Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:31:52

0001 #include "Utilities/StorageFactory/interface/RemoteFile.h"
0002 #include "Utilities/StorageFactory/src/Throw.h"
0003 #include "FWCore/Utilities/interface/Exception.h"
0004 #include <sys/wait.h>
0005 #include <sys/types.h>
0006 #include <cerrno>
0007 #include <cassert>
0008 #include <spawn.h>
0009 #include <unistd.h>
0010 #include <ostream>
0011 #include <cstring>
0012 #if __APPLE__
0013 #include <crt_externs.h>
0014 #define environ (*_NSGetEnviron())
0015 #endif
0016 
0017 using namespace edm::storage;
0018 
0019 static std::string join(char **cmd) {
0020   size_t size = 0;
0021   for (char **p = cmd; p && p[0]; ++p)
0022     size += 1 + strlen(*p);
0023 
0024   std::string result;
0025   result.reserve(size);
0026 
0027   for (char **p = cmd; p && p[0]; ++p) {
0028     if (p != cmd)
0029       result += ' ';
0030     result += *p;
0031   }
0032 
0033   return result;
0034 }
0035 
0036 RemoteFile::RemoteFile(IOFD fd, const std::string &name) : File(fd), name_(name) {}
0037 
0038 void RemoteFile::remove(void) { unlink(name_.c_str()); }
0039 
0040 void RemoteFile::close(void) {
0041   remove();
0042   File::close();
0043 }
0044 
0045 void RemoteFile::abort(void) {
0046   remove();
0047   File::abort();
0048 }
0049 
0050 int RemoteFile::local(const std::string &tmpdir, std::string &temp) {
0051   // Download temporary files to the current directory by default.
0052   // This is better for grid jobs as the current directory is
0053   // likely to have more space, and is more optimised for
0054   // large files, and is cleaned up after the job.
0055   if (tmpdir.empty() || tmpdir == ".") {
0056     size_t len = pathconf(".", _PC_PATH_MAX);
0057     char *buf = (char *)malloc(len);
0058     getcwd(buf, len);
0059 
0060     temp.reserve(len + 32);
0061     temp = buf;
0062     free(buf);
0063   } else {
0064     temp.reserve(tmpdir.size() + 32);
0065     temp = tmpdir;
0066   }
0067   if (temp[temp.size() - 1] != '/')
0068     temp += '/';
0069 
0070   temp += "storage-factory-local-XXXXXX";
0071   temp.c_str();  // null terminate for mkstemp
0072 
0073   int fd = mkstemp(&temp[0]);
0074   if (fd == -1)
0075     throwStorageError("RemoteFile", "Calling RemoteFile::local()", "mkstemp()", errno);
0076 
0077   return fd;
0078 }
0079 
0080 std::unique_ptr<Storage> RemoteFile::get(int localfd, const std::string &name, char **cmd, int mode) {
0081   // FIXME: On write, create a temporary local file open for write;
0082   // on close, trigger transfer to destination.  If opening existing
0083   // file for write, may need to first download.
0084   assert(!(mode & (IOFlags::OpenWrite | IOFlags::OpenCreate)));
0085 
0086   pid_t pid = -1;
0087   int rc = posix_spawnp(&pid, cmd[0], nullptr, nullptr, cmd, environ);
0088 
0089   if (rc == -1) {
0090     int errsave = errno;
0091     ::close(localfd);
0092     unlink(name.c_str());
0093     throwStorageError("RemoteFile", "Calling RemoteFile::get()", "posix_spawnp()", errsave);
0094   }
0095 
0096   pid_t rcpid;
0097   do
0098     rcpid = waitpid(pid, &rc, 0);
0099   while (rcpid == (pid_t)-1 && errno == EINTR);
0100 
0101   if (rcpid == (pid_t)-1) {
0102     int errsave = errno;
0103     ::close(localfd);
0104     unlink(name.c_str());
0105     throwStorageError("RemoteFile", "Calling RemoteFile::get()", "waitpid()", errsave);
0106   }
0107 
0108   if (WIFEXITED(rc) && WEXITSTATUS(rc) == 0)
0109     return std::unique_ptr<Storage>(static_cast<Storage *>(new RemoteFile(localfd, name)));
0110   else {
0111     ::close(localfd);
0112     unlink(name.c_str());
0113     cms::Exception ex("RemoteFile");
0114     ex << "'" << join(cmd) << "'"
0115        << (WIFEXITED(rc)     ? " exited with exit code "
0116            : WIFSIGNALED(rc) ? " died from signal "
0117                              : " died for an obscure unknown reason with exit status ")
0118        << (WIFEXITED(rc)     ? WEXITSTATUS(rc)
0119            : WIFSIGNALED(rc) ? WTERMSIG(rc)
0120                              : rc);
0121     ex.addContext("Calling RemoteFile::get()");
0122     throw ex;
0123   }
0124 }