CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_1/src/Utilities/XrdAdaptor/src/XrdFile.cc

Go to the documentation of this file.
00001 #include "Utilities/XrdAdaptor/src/XrdFile.h"
00002 #include "FWCore/Utilities/interface/EDMException.h"
00003 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00004 #include <vector>
00005 #include <sstream>
00006 
00007 XrdFile::XrdFile (void)
00008   : m_client (0),
00009     m_offset (0),
00010     m_stat(),
00011     m_close (false),
00012     m_name()
00013 {
00014   memset(&m_stat, 0, sizeof (m_stat));
00015 }
00016 
00017 XrdFile::XrdFile (const char *name,
00018                   int flags /* = IOFlags::OpenRead */,
00019                   int perms /* = 066 */)
00020   : m_client (0),
00021     m_offset (0),
00022     m_stat(),
00023     m_close (false),
00024     m_name()
00025 {
00026   memset(&m_stat, 0, sizeof (m_stat));
00027   open (name, flags, perms);
00028 }
00029 
00030 XrdFile::XrdFile (const std::string &name,
00031                   int flags /* = IOFlags::OpenRead */,
00032                   int perms /* = 066 */)
00033   : m_client (0),
00034     m_offset (0),
00035     m_stat(),
00036     m_close (false),
00037     m_name()
00038 {
00039   memset(&m_stat, 0, sizeof (m_stat));
00040   open (name.c_str (), flags, perms);
00041 }
00042 
00043 XrdFile::~XrdFile (void)
00044 {
00045   if (m_close)
00046     edm::LogError("XrdFileError")
00047       << "Destructor called on XROOTD file '" << m_name
00048       << "' but the file is still open";
00049 }
00050 
00052 void
00053 XrdFile::create (const char *name,
00054                  bool exclusive /* = false */,
00055                  int perms /* = 066 */)
00056 {
00057   open (name,
00058         (IOFlags::OpenCreate | IOFlags::OpenWrite | IOFlags::OpenTruncate
00059          | (exclusive ? IOFlags::OpenExclusive : 0)),
00060         perms);
00061 }
00062 
00063 void
00064 XrdFile::create (const std::string &name,
00065                  bool exclusive /* = false */,
00066                  int perms /* = 066 */)
00067 {
00068   open (name.c_str (),
00069         (IOFlags::OpenCreate | IOFlags::OpenWrite | IOFlags::OpenTruncate
00070          | (exclusive ? IOFlags::OpenExclusive : 0)),
00071         perms);
00072 }
00073 
00074 void
00075 XrdFile::open (const std::string &name,
00076                int flags /* = IOFlags::OpenRead */,
00077                int perms /* = 066 */)
00078 { open (name.c_str (), flags, perms); }
00079 
00080 void
00081 XrdFile::open (const char *name,
00082                int flags /* = IOFlags::OpenRead */,
00083                int perms /* = 066 */)
00084 {
00085   // Actual open
00086   if ((name == 0) || (*name == 0)) {
00087     edm::Exception ex(edm::errors::FileOpenError);
00088     ex << "Cannot open a file without a name";
00089     ex.addContext("Calling XrdFile::open()");
00090     throw ex;
00091   }
00092   if ((flags & (IOFlags::OpenRead | IOFlags::OpenWrite)) == 0) {
00093     edm::Exception ex(edm::errors::FileOpenError);
00094     ex << "Must open file '" << name << "' at least for read or write";
00095     ex.addContext("Calling XrdFile::open()");
00096     throw ex;
00097   }
00098   // If I am already open, close old file first
00099   if (m_client && m_close)
00100     close();
00101   else
00102     abort();
00103 
00104   // Translate our flags to system flags
00105   int openflags = 0;
00106 
00107   if (flags & IOFlags::OpenWrite)
00108     openflags |= kXR_open_updt;
00109   else if (flags & IOFlags::OpenRead)
00110     openflags |= kXR_open_read;
00111 
00112   if (flags & IOFlags::OpenAppend) {
00113     edm::Exception ex(edm::errors::FileOpenError);
00114     ex << "Opening file '" << name << "' in append mode not supported";
00115     ex.addContext("Calling XrdFile::open()");
00116     throw ex;
00117   }
00118 
00119   if (flags & IOFlags::OpenCreate)
00120   {
00121     if (! (flags & IOFlags::OpenExclusive))
00122       openflags |= kXR_delete;
00123     openflags |= kXR_new;
00124     openflags |= kXR_mkpath;
00125   }
00126 
00127   if ((flags & IOFlags::OpenTruncate) && (flags & IOFlags::OpenWrite))
00128     openflags |= kXR_delete;
00129 
00130   m_name = name;
00131   m_client = new XrdClient(name);
00132   if (! m_client->Open(perms, openflags)
00133       || m_client->LastServerResp()->status != kXR_ok) {
00134     edm::Exception ex(edm::errors::FileOpenError);
00135     ex << "XrdClient::Open(name='" << name
00136        << "', flags=0x" << std::hex << openflags
00137        << ", permissions=0" << std::oct << perms << std::dec
00138        << ") => error '" << m_client->LastServerError()->errmsg
00139        << "' (errno=" << m_client->LastServerError()->errnum << ")";
00140     ex.addContext("Calling XrdFile::open()");
00141     addConnection(ex);
00142     throw ex;
00143   }
00144   if (! m_client->Stat(&m_stat)) {
00145     edm::Exception ex(edm::errors::FileOpenError);
00146     ex << "XrdClient::Stat(name='" << name
00147       << ") => error '" << m_client->LastServerError()->errmsg
00148       << "' (errno=" << m_client->LastServerError()->errnum << ")";
00149     ex.addContext("Calling XrdFile::open()");
00150     addConnection(ex);
00151     throw ex;
00152   }
00153   m_offset = 0;
00154   m_close = true;
00155   edm::LogInfo("XrdFileInfo") << "Opened " << m_name;
00156 
00157   XrdClientConn *conn = m_client->GetClientConn();
00158   edm::LogInfo("XrdFileInfo") << "Connection URL " << conn->GetCurrentUrl().GetUrl().c_str();
00159 }
00160 
00161 void
00162 XrdFile::close (void)
00163 {
00164   if (! m_client)
00165   {
00166     edm::LogError("XrdFileError")
00167       << "XrdFile::close(name='" << m_name
00168       << "') called but the file is not open";
00169     m_close = false;
00170     return;
00171   }
00172 
00173   if (! m_client->Close())
00174     edm::LogWarning("XrdFileWarning")
00175       << "XrdFile::close(name='" << m_name
00176       << "') failed with error '" << m_client->LastServerError()->errmsg
00177       << "' (errno=" << m_client->LastServerError()->errnum << ")";
00178   delete m_client;
00179   m_client = 0;
00180 
00181   m_close = false;
00182   m_offset = 0;
00183   memset(&m_stat, 0, sizeof (m_stat));
00184   edm::LogInfo("XrdFileInfo") << "Closed " << m_name;
00185 }
00186 
00187 void
00188 XrdFile::abort (void)
00189 {
00190   delete m_client;
00191   m_client = 0;
00192   m_close = false;
00193   m_offset = 0;
00194   memset(&m_stat, 0, sizeof (m_stat));
00195 }
00196 
00198 IOSize
00199 XrdFile::read (void *into, IOSize n)
00200 {
00201   if (n > 0x7fffffff) {
00202     edm::Exception ex(edm::errors::FileReadError);
00203     ex << "XrdFile::read(name='" << m_name << "', n=" << n
00204        << ") too many bytes, limit is 0x7fffffff";
00205     ex.addContext("Calling XrdFile::read()");
00206     addConnection(ex);
00207     throw ex;
00208   }
00209   int s = m_client->Read(into, m_offset, n);
00210   if (s < 0) {
00211     edm::Exception ex(edm::errors::FileReadError);
00212     ex << "XrdClient::Read(name='" << m_name
00213        << "', offset=" << m_offset << ", n=" << n
00214        << ") failed with error '" << m_client->LastServerError()->errmsg
00215        << "' (errno=" << m_client->LastServerError()->errnum << ")";
00216     ex.addContext("Calling XrdFile::read()");
00217     addConnection(ex);
00218     throw ex;
00219   }
00220   m_offset += s;
00221   return s;
00222 }
00223 
00224 IOSize
00225 XrdFile::read (void *into, IOSize n, IOOffset pos)
00226 {
00227   if (n > 0x7fffffff) {
00228     edm::Exception ex(edm::errors::FileReadError);
00229     ex << "XrdFile::read(name='" << m_name << "', n=" << n
00230        << ") exceeds read size limit 0x7fffffff";
00231     ex.addContext("Calling XrdFile::read()");
00232     addConnection(ex);
00233     throw ex;
00234   }
00235   int s = m_client->Read(into, pos, n);
00236   if (s < 0) {
00237     edm::Exception ex(edm::errors::FileReadError);
00238     ex << "XrdClient::Read(name='" << m_name
00239        << "', offset=" << m_offset << ", n=" << n
00240        << ") failed with error '" << m_client->LastServerError()->errmsg
00241        << "' (errno=" << m_client->LastServerError()->errnum << ")";
00242     ex.addContext("Calling XrdFile::read()");
00243     addConnection(ex);
00244     throw ex;
00245   }
00246   return s;
00247 }
00248 
00249 IOSize
00250 XrdFile::readv (IOBuffer *into, IOSize n)
00251 {
00252   // Note that the XROOTD and our interfaces do not match.
00253   // XROOTD expects readv() into a single monolithic buffer
00254   // from multiple file locations, whereas we expect scatter
00255   // gather buffers read from a single file location.
00256   //
00257   // We work around this mismatch for now by issuing a cache
00258   // read on the background, and then individual reads.
00259   IOOffset pos = m_offset;
00260   std::vector<long long> offsets (n);
00261   std::vector<int> lengths (n);
00262   for (IOSize i = 0; i < n; ++i)
00263   {
00264     IOSize len = into[i].size();
00265     if (len > 0x7fffffff) {
00266       edm::Exception ex(edm::errors::FileReadError);
00267       ex << "XrdFile::readv(name='" << m_name << "')[" << i
00268          << "].size=" << len << " exceeds read size limit 0x7fffffff";
00269       ex.addContext("Calling XrdFile::readv()");
00270       addConnection(ex);
00271       throw ex;
00272     }
00273     offsets[i] = pos;
00274     lengths[i] = len;
00275     pos += len;
00276   }
00277 
00278   // Prefetch into the cache (if any).
00279   if (m_client->ReadV(0, &offsets[0], &lengths[0], n) < 0) {
00280     edm::Exception ex(edm::errors::FileReadError);
00281     ex << "XrdClient::ReadV(name='" << m_name
00282        << "') failed with error '" << m_client->LastServerError()->errmsg
00283        << "' (errno=" << m_client->LastServerError()->errnum << ")";
00284     ex.addContext("Calling XrdFile::readv()");
00285     addConnection(ex);
00286     throw ex;
00287   }
00288 
00289   // Issue actual reads.
00290   IOSize total = 0;
00291   for (IOSize i = 0; i < n; ++i)
00292   {
00293     int s = m_client->Read(into[i].data(), offsets[i], lengths[i]);
00294     if (s < 0)
00295     {
00296       if (i > 0)
00297         break;
00298       edm::Exception ex(edm::errors::FileReadError);
00299       ex << "XrdClient::Read(name='" << m_name
00300          << "', offset=" << offsets[i] << ", n=" << lengths[i]
00301          << ") failed with error '" << m_client->LastServerError()->errmsg
00302          << "' (errno=" << m_client->LastServerError()->errnum << ")";
00303       ex.addContext("Calling XrdFile::readv()");
00304       addConnection(ex);
00305       throw ex;
00306     }
00307     total += s;
00308     m_offset += s;
00309   }
00310 
00311   return total;
00312 }
00313 
00314 IOSize
00315 XrdFile::readv (IOPosBuffer *into, IOSize n)
00316 {
00317   // See comments in readv() above.
00318   std::vector<long long> offsets (n);
00319   std::vector<int> lengths (n);
00320   for (IOSize i = 0; i < n; ++i)
00321   {
00322     IOSize len = into[i].size();
00323     if (len > 0x7fffffff) {
00324       edm::Exception ex(edm::errors::FileReadError);
00325       ex << "XrdFile::readv(name='" << m_name << "')[" << i
00326          << "].size=" << len << " exceeds read size limit 0x7fffffff";
00327       ex.addContext("Calling XrdFile::readv()");
00328       addConnection(ex);
00329       throw ex;
00330     }
00331     offsets[i] = into[i].offset();
00332     lengths[i] = len;
00333   }
00334 
00335   // Prefetch into the cache (if any).
00336   if (m_client->ReadV(0, &offsets[0], &lengths[0], n) < 0) {
00337     edm::Exception ex(edm::errors::FileReadError);
00338     ex << "XrdClient::ReadV(name='" << m_name
00339        << "') failed with error '" << m_client->LastServerError()->errmsg
00340        << "' (errno=" << m_client->LastServerError()->errnum << ")";
00341     ex.addContext("Calling XrdFile::readv()");
00342     addConnection(ex);
00343     throw ex;
00344   }
00345   // Issue actual reads.
00346   IOSize total = 0;
00347   for (IOSize i = 0; i < n; ++i)
00348   {
00349     int s = m_client->Read(into[i].data(), offsets[i], lengths[i]);
00350     if (s < 0)
00351     {
00352       if (i > 0)
00353         break;
00354       edm::Exception ex(edm::errors::FileReadError);
00355       ex << "XrdClient::Read(name='" << m_name
00356          << "', offset=" << offsets[i] << ", n=" << lengths[i]
00357          << ") failed with error '" << m_client->LastServerError()->errmsg
00358          << "' (errno=" << m_client->LastServerError()->errnum << ")";
00359       ex.addContext("Calling XrdFile::readv()");
00360       addConnection(ex);
00361       throw ex;
00362     }
00363     total += s;
00364   }
00365 
00366   return total;
00367 }
00368 
00369 IOSize
00370 XrdFile::write (const void *from, IOSize n)
00371 {
00372   if (n > 0x7fffffff) {
00373     cms::Exception ex("FileWriteError");
00374     ex << "XrdFile::write(name='" << m_name << "', n=" << n
00375        << ") too many bytes, limit is 0x7fffffff";
00376     ex.addContext("Calling XrdFile::write()");
00377     addConnection(ex);
00378     throw ex;
00379   }
00380   ssize_t s = m_client->Write(from, m_offset, n);
00381   if (s < 0) {
00382     cms::Exception ex("FileWriteError");
00383     ex << "XrdFile::write(name='" << m_name << "', n=" << n
00384        << ") failed with error '" << m_client->LastServerError()->errmsg
00385        << "' (errno=" << m_client->LastServerError()->errnum << ")";
00386     ex.addContext("Calling XrdFile::write()");
00387     addConnection(ex);
00388     throw ex;
00389   }
00390   m_offset += s;
00391   if (m_offset > m_stat.size)
00392     m_stat.size = m_offset;
00393 
00394   return s;
00395 }
00396 
00397 IOSize
00398 XrdFile::write (const void *from, IOSize n, IOOffset pos)
00399 {
00400   if (n > 0x7fffffff) {
00401     cms::Exception ex("FileWriteError");
00402     ex << "XrdFile::write(name='" << m_name << "', n=" << n
00403        << ") too many bytes, limit is 0x7fffffff";
00404     ex.addContext("Calling XrdFile::write()");
00405     addConnection(ex);
00406     throw ex;
00407   }
00408   ssize_t s = m_client->Write(from, pos, n);
00409   if (s < 0) {
00410     cms::Exception ex("FileWriteError");
00411     ex << "XrdFile::write(name='" << m_name << "', n=" << n
00412        << ") failed with error '" << m_client->LastServerError()->errmsg
00413        << "' (errno=" << m_client->LastServerError()->errnum << ")";
00414     ex.addContext("Calling XrdFile::write()");
00415     addConnection(ex);
00416     throw ex;
00417   }
00418   if (pos + s > m_stat.size)
00419     m_stat.size = pos + s;
00420 
00421   return s;
00422 }
00423 
00424 bool
00425 XrdFile::prefetch (const IOPosBuffer *what, IOSize n)
00426 {
00427   std::vector<long long> offsets; offsets.resize(n);
00428   std::vector<int> lens; lens.resize(n);
00429   kXR_int64 total = 0;
00430   for (IOSize i = 0; i < n; ++i) {
00431     offsets[i] = what[i].offset();
00432     lens[i] = what[i].size();
00433     total += what[i].size();
00434   }
00435 
00436   kXR_int64 r = m_client->ReadV(NULL, &offsets[0], &lens[0], n);
00437   return r == total;
00438 }
00439 
00443 IOOffset
00444 XrdFile::position (IOOffset offset, Relative whence /* = SET */)
00445 {
00446   if (! m_client) {
00447     cms::Exception ex("FilePositionError");
00448     ex << "XrdFile::position() called on a closed file";
00449     ex.addContext("Calling XrdFile::position()");
00450     addConnection(ex);
00451     throw ex;
00452   }
00453   switch (whence)
00454   {
00455   case SET:
00456     m_offset = offset;
00457     break;
00458 
00459   case CURRENT:
00460     m_offset += offset;
00461     break;
00462 
00463   case END:
00464     m_offset = m_stat.size + offset;
00465     break;
00466 
00467   default:
00468     cms::Exception ex("FilePositionError");
00469     ex << "XrdFile::position() called with incorrect 'whence' parameter";
00470     ex.addContext("Calling XrdFile::position()");
00471     addConnection(ex);
00472     throw ex;
00473   }
00474 
00475   if (m_offset < 0)
00476     m_offset = 0;
00477   if (m_offset > m_stat.size)
00478     m_stat.size = m_offset;
00479 
00480   return m_offset;
00481 }
00482 
00483 void
00484 XrdFile::resize (IOOffset /* size */)
00485 {
00486   cms::Exception ex("FileResizeError");
00487   ex << "XrdFile::resize(name='" << m_name << "') not implemented";
00488   ex.addContext("Calling XrdFile::resize()");
00489   addConnection(ex);
00490   throw ex;
00491 }
00492 
00493 void
00494 XrdFile::addConnection (cms::Exception &ex)
00495 {
00496   XrdClientConn *conn = m_client->GetClientConn();
00497   if (conn) {
00498     std::stringstream ss;
00499     ss << "Current server connection: " << conn->GetCurrentUrl().GetUrl().c_str();
00500     ex.addAdditionalInfo(ss.str());
00501   }
00502 }
00503