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 int errsave = errno;
00103 ::close (localfd);
00104 unlink (name.c_str());
00105 throwStorageError ("RemoteFile", "Calling RemoteFile::get()", "posix_spawnp()", errsave);
00106 }
00107
00108 pid_t rcpid;
00109 do
00110 rcpid = waitpid(pid, &rc, 0);
00111 while (rcpid == (pid_t) -1 && errno == EINTR);
00112
00113 if (rcpid == (pid_t) -1)
00114 {
00115 int errsave = errno;
00116 ::close (localfd);
00117 unlink (name.c_str());
00118 throwStorageError ("RemoteFile", "Calling RemoteFile::get()", "waitpid()", errsave);
00119 }
00120
00121 if (WIFEXITED(rc) && WEXITSTATUS(rc) == 0)
00122 return new RemoteFile (localfd, name);
00123 else
00124 {
00125 ::close (localfd);
00126 unlink (name.c_str());
00127 cms::Exception ex("RemoteFile");
00128 ex << "'" << join(cmd) << "'"
00129 << (WIFEXITED(rc) ? " exited with exit code "
00130 : WIFSIGNALED(rc) ? " died from signal "
00131 : " died for an obscure unknown reason with exit status ")
00132 << (WIFEXITED(rc) ? WEXITSTATUS(rc)
00133 : WIFSIGNALED(rc) ? WTERMSIG(rc)
00134 : rc);
00135 ex.addContext("Calling RemoteFile::get()");
00136 throw ex;
00137 }
00138 }