CMS 3D CMS Logo

RemoteFile.cc
Go to the documentation of this file.
4 #include <sys/wait.h>
5 #include <sys/types.h>
6 #include <cerrno>
7 #include <cassert>
8 #include <spawn.h>
9 #include <unistd.h>
10 #include <ostream>
11 #include <cstring>
12 #if __APPLE__
13 #include <crt_externs.h>
14 #define environ (*_NSGetEnviron())
15 #endif
16 
17 using namespace edm::storage;
18 
19 static std::string join(char **cmd) {
20  size_t size = 0;
21  for (char **p = cmd; p && p[0]; ++p)
22  size += 1 + strlen(*p);
23 
25  result.reserve(size);
26 
27  for (char **p = cmd; p && p[0]; ++p) {
28  if (p != cmd)
29  result += ' ';
30  result += *p;
31  }
32 
33  return result;
34 }
35 
37 
38 void RemoteFile::remove(void) { unlink(name_.c_str()); }
39 
40 void RemoteFile::close(void) {
41  remove();
42  File::close();
43 }
44 
45 void RemoteFile::abort(void) {
46  remove();
47  File::abort();
48 }
49 
51  // Download temporary files to the current directory by default.
52  // This is better for grid jobs as the current directory is
53  // likely to have more space, and is more optimised for
54  // large files, and is cleaned up after the job.
55  if (tmpdir.empty() || tmpdir == ".") {
56  size_t len = pathconf(".", _PC_PATH_MAX);
57  char *buf = (char *)malloc(len);
58  getcwd(buf, len);
59 
60  temp.reserve(len + 32);
61  temp = buf;
62  free(buf);
63  } else {
64  temp.reserve(tmpdir.size() + 32);
65  temp = tmpdir;
66  }
67  if (temp[temp.size() - 1] != '/')
68  temp += '/';
69 
70  temp += "storage-factory-local-XXXXXX";
71  temp.c_str(); // null terminate for mkstemp
72 
73  int fd = mkstemp(&temp[0]);
74  if (fd == -1)
75  throwStorageError("RemoteFile", "Calling RemoteFile::local()", "mkstemp()", errno);
76 
77  return fd;
78 }
79 
80 std::unique_ptr<Storage> RemoteFile::get(int localfd, const std::string &name, char **cmd, int mode) {
81  // FIXME: On write, create a temporary local file open for write;
82  // on close, trigger transfer to destination. If opening existing
83  // file for write, may need to first download.
85 
86  pid_t pid = -1;
87  int rc = posix_spawnp(&pid, cmd[0], nullptr, nullptr, cmd, environ);
88 
89  if (rc == -1) {
90  int errsave = errno;
91  ::close(localfd);
92  unlink(name.c_str());
93  throwStorageError("RemoteFile", "Calling RemoteFile::get()", "posix_spawnp()", errsave);
94  }
95 
96  pid_t rcpid;
97  do
98  rcpid = waitpid(pid, &rc, 0);
99  while (rcpid == (pid_t)-1 && errno == EINTR);
100 
101  if (rcpid == (pid_t)-1) {
102  int errsave = errno;
103  ::close(localfd);
104  unlink(name.c_str());
105  throwStorageError("RemoteFile", "Calling RemoteFile::get()", "waitpid()", errsave);
106  }
107 
108  if (WIFEXITED(rc) && WEXITSTATUS(rc) == 0)
109  return std::unique_ptr<Storage>(static_cast<Storage *>(new RemoteFile(localfd, name)));
110  else {
111  ::close(localfd);
112  unlink(name.c_str());
113  cms::Exception ex("RemoteFile");
114  ex << "'" << join(cmd) << "'"
115  << (WIFEXITED(rc) ? " exited with exit code "
116  : WIFSIGNALED(rc) ? " died from signal "
117  : " died for an obscure unknown reason with exit status ")
118  << (WIFEXITED(rc) ? WEXITSTATUS(rc)
119  : WIFSIGNALED(rc) ? WTERMSIG(rc)
120  : rc);
121  ex.addContext("Calling RemoteFile::get()");
122  throw ex;
123  }
124 }
IOFD fd() const
Definition: File.h:34
size
Write out results.
static std::unique_ptr< Storage > get(int localfd, const std::string &name, char **cmd, int mode)
Definition: RemoteFile.cc:80
void throwStorageError(const char *category, const char *context, const char *call, int error)
Definition: Throw.cc:6
assert(be >=bs)
void abort(void) override
Definition: RemoteFile.cc:45
virtual void abort()
Definition: File.cc:240
void close() override
Definition: File.cc:227
static int local(const std::string &tmpdir, std::string &temp)
Definition: RemoteFile.cc:50
static std::string join(char **cmd)
Definition: RemoteFile.cc:19
list cmd
Definition: mps_setup.py:244
int IOFD
Definition: IOTypes.h:23
RemoteFile(IOFD fd, const std::string &name)
Definition: RemoteFile.cc:36
fd
Definition: ztee.py:136
void close(void) override
Definition: RemoteFile.cc:40