Go to the documentation of this file.00001 #include "Utilities/StorageFactory/interface/RemoteFile.h"
00002 #include "Utilities/StorageFactory/src/Throw.h"
00003 #include "FWCore/Utilities/interface/Exception.h"
00004 #include <sys/wait.h>
00005 #include <sys/types.h>
00006 #include <cerrno>
00007 #include <cassert>
00008 #include <spawn.h>
00009 #include <unistd.h>
00010 #include <ostream>
00011 #include <cstring>
00012 #if __APPLE__
00013 # include <crt_externs.h>
00014 # define environ (*_NSGetEnviron())
00015 #endif
00016
00017 static std::string
00018 join (char **cmd)
00019 {
00020 size_t size = 0;
00021 for (char **p = cmd; p && p[0]; ++p)
00022 size += 1 + strlen(*p);
00023
00024 std::string result;
00025 result.reserve (size);
00026
00027 for (char **p = cmd; p && p[0]; ++p)
00028 {
00029 if (p != cmd)
00030 result += ' ';
00031 result += *p;
00032 }
00033
00034 return result;
00035 }
00036
00037 RemoteFile::RemoteFile (IOFD fd, const std::string &name)
00038 : File (fd),
00039 name_ (name)
00040 {}
00041
00042 void
00043 RemoteFile::remove (void)
00044 { unlink (name_.c_str()); }
00045
00046 void
00047 RemoteFile::close (void)
00048 { remove(); File::close (); }
00049
00050 void
00051 RemoteFile::abort (void)
00052 { remove(); File::abort (); }
00053
00054 int
00055 RemoteFile::local (const std::string &tmpdir, std::string &temp)
00056 {
00057
00058
00059
00060
00061 if (tmpdir.empty () || tmpdir == ".")
00062 {
00063 size_t len = pathconf (".", _PC_PATH_MAX);
00064 char *buf = (char *) malloc (len);
00065 getcwd (buf, len);
00066
00067 temp.reserve (len + 32);
00068 temp = buf;
00069 free (buf);
00070 }
00071 else
00072 {
00073 temp.reserve (tmpdir.size() + 32);
00074 temp = tmpdir;
00075 }
00076 if (temp[temp.size()-1] != '/')
00077 temp += '/';
00078
00079 temp += "storage-factory-local-XXXXXX";
00080 temp.c_str();
00081
00082 int fd = mkstemp (&temp[0]);
00083 if (fd == -1)
00084 throwStorageError("RemoteFile", "Calling RemoteFile::local()", "mkstemp()", errno);
00085
00086 return fd;
00087 }
00088
00089 Storage *
00090 RemoteFile::get (int localfd, const std::string &name, char **cmd, int mode)
00091 {
00092
00093
00094
00095 assert (! (mode & (IOFlags::OpenWrite | IOFlags::OpenCreate)));
00096
00097 pid_t pid = -1;
00098 int rc = posix_spawnp (&pid, cmd[0], 0, 0, cmd, environ);
00099
00100 if (rc == -1)
00101 {
00102 ::close (localfd);
00103 unlink (name.c_str());
00104 throwStorageError ("RemoteFile", "Calling RemoteFile::get()", "posix_spawnp()", rc);
00105 }
00106
00107 pid_t rcpid;
00108 do
00109 rcpid = waitpid(pid, &rc, 0);
00110 while (rcpid == (pid_t) -1 && errno == EINTR);
00111
00112 if (rcpid == (pid_t) -1)
00113 {
00114 ::close (localfd);
00115 unlink (name.c_str());
00116 throwStorageError ("RemoteFile", "Calling RemoteFile::get()", "waitpid()", errno);
00117 }
00118
00119 if (WIFEXITED(rc) && WEXITSTATUS(rc) == 0)
00120 return new RemoteFile (localfd, name);
00121 else
00122 {
00123 ::close (localfd);
00124 unlink (name.c_str());
00125 cms::Exception ex("RemoteFile");
00126 ex << "'" << join(cmd) << "'"
00127 << (WIFEXITED(rc) ? " exited with exit code "
00128 : WIFSIGNALED(rc) ? " died from signal "
00129 : " died for an obscure unknown reason with exit status ")
00130 << (WIFEXITED(rc) ? WEXITSTATUS(rc)
00131 : WIFSIGNALED(rc) ? WTERMSIG(rc)
00132 : rc);
00133 ex.addContext("Calling RemoteFile::get()");
00134 throw ex;
00135 }
00136 }