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 #include <filesystem>
13 #include <vector>
14 #if __APPLE__
15 #include <crt_externs.h>
16 #define environ (*_NSGetEnviron())
17 #endif
18 
19 using namespace edm::storage;
20 
21 static std::string join(char **cmd) {
22  size_t size = 0;
23  for (char **p = cmd; p && p[0]; ++p)
24  size += 1 + strlen(*p);
25 
27  result.reserve(size);
28 
29  for (char **p = cmd; p && p[0]; ++p) {
30  if (p != cmd)
31  result += ' ';
32  result += *p;
33  }
34 
35  return result;
36 }
37 
39 
40 void RemoteFile::remove(void) { unlink(name_.c_str()); }
41 
42 void RemoteFile::close(void) {
43  remove();
44  File::close();
45 }
46 
47 void RemoteFile::abort(void) {
48  remove();
49  File::abort();
50 }
51 
53  // Download temporary files to the current directory by default.
54  // This is better for grid jobs as the current directory is
55  // likely to have more space, and is more optimised for
56  // large files, and is cleaned up after the job.
57  std::vector<char> temp_chars;
58 
59  if (tmpdir.empty() || tmpdir == ".") {
60  std::filesystem::path current_path = std::filesystem::current_path();
61  auto spath = current_path.string();
62  temp_chars.reserve(spath.size() + 30);
63  temp_chars.assign(spath.begin(), spath.end());
64  } else {
65  temp_chars.reserve(tmpdir.size() + 30);
66  temp_chars.assign(tmpdir.begin(), tmpdir.end());
67  }
68 
69  if (temp_chars.back() != '/')
70  temp_chars.push_back('/');
71 
72  std::string suffix = "storage-factory-local-XXXXXX";
73  temp_chars.insert(temp_chars.end(), suffix.begin(), suffix.end());
74 
75  // Ensure the vector is null-terminated
76  temp_chars.push_back('\0');
77 
78  int fd = mkstemp(temp_chars.data());
79  if (fd == -1)
80  throwStorageError("RemoteFile", "Calling RemoteFile::local()", "mkstemp()", errno);
81  // Copy temp_chars to temp
82  temp.assign(temp_chars.begin(), temp_chars.end() - 1); // Exclude the null terminator
83 
84  return fd;
85 }
86 
87 std::unique_ptr<Storage> RemoteFile::get(int localfd, const std::string &name, char **cmd, int mode) {
88  // FIXME: On write, create a temporary local file open for write;
89  // on close, trigger transfer to destination. If opening existing
90  // file for write, may need to first download.
92 
93  pid_t pid = -1;
94  int rc = posix_spawnp(&pid, cmd[0], nullptr, nullptr, cmd, environ);
95 
96  if (rc == -1) {
97  int errsave = errno;
98  ::close(localfd);
99  unlink(name.c_str());
100  throwStorageError("RemoteFile", "Calling RemoteFile::get()", "posix_spawnp()", errsave);
101  }
102 
103  pid_t rcpid;
104  do
105  rcpid = waitpid(pid, &rc, 0);
106  while (rcpid == (pid_t)-1 && errno == EINTR);
107 
108  if (rcpid == (pid_t)-1) {
109  int errsave = errno;
110  ::close(localfd);
111  unlink(name.c_str());
112  throwStorageError("RemoteFile", "Calling RemoteFile::get()", "waitpid()", errsave);
113  }
114 
115  if (WIFEXITED(rc) && WEXITSTATUS(rc) == 0)
116  return std::unique_ptr<Storage>(static_cast<Storage *>(new RemoteFile(localfd, name)));
117  else {
118  ::close(localfd);
119  unlink(name.c_str());
120  cms::Exception ex("RemoteFile");
121  ex << "'" << join(cmd) << "'"
122  << (WIFEXITED(rc) ? " exited with exit code "
123  : WIFSIGNALED(rc) ? " died from signal "
124  : " died for an obscure unknown reason with exit status ")
125  << (WIFEXITED(rc) ? WEXITSTATUS(rc)
126  : WIFSIGNALED(rc) ? WTERMSIG(rc)
127  : rc);
128  ex.addContext("Calling RemoteFile::get()");
129  throw ex;
130  }
131 }
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:87
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:47
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:52
static std::string join(char **cmd)
Definition: RemoteFile.cc:21
list cmd
Definition: mps_setup.py:244
int IOFD
Definition: IOTypes.h:23
RemoteFile(IOFD fd, const std::string &name)
Definition: RemoteFile.cc:38
fd
Definition: ztee.py:136
void close(void) override
Definition: RemoteFile.cc:42