CMS 3D CMS Logo

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