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