CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_2_9_HLT1_bphpatch4/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/Exception.h"
00003 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00004 #include <vector>
00005 
00006 XrdFile::XrdFile (void)
00007   : m_client (0),
00008     m_offset (0),
00009     m_close (false)
00010 {}
00011 
00012 XrdFile::XrdFile (const char *name,
00013                   int flags /* = IOFlags::OpenRead */,
00014                   int perms /* = 066 */)
00015   : m_client (0),
00016     m_offset (0),
00017     m_close (false)
00018 { open (name, flags, perms); }
00019 
00020 XrdFile::XrdFile (const std::string &name,
00021                   int flags /* = IOFlags::OpenRead */,
00022                   int perms /* = 066 */)
00023   : m_client (0),
00024     m_offset (0),
00025     m_close (false)
00026 { open (name.c_str (), flags, perms); }
00027 
00028 XrdFile::~XrdFile (void)
00029 {
00030   if (m_close)
00031     edm::LogError("XrdFileError")
00032       << "Destructor called on XROOTD file '" << m_name
00033       << "' but the file is still open";
00034 }
00035 
00037 void
00038 XrdFile::create (const char *name,
00039                  bool exclusive /* = false */,
00040                  int perms /* = 066 */)
00041 {
00042   open (name,
00043         (IOFlags::OpenCreate | IOFlags::OpenWrite | IOFlags::OpenTruncate
00044          | (exclusive ? IOFlags::OpenExclusive : 0)),
00045         perms);
00046 }
00047 
00048 void
00049 XrdFile::create (const std::string &name,
00050                  bool exclusive /* = false */,
00051                  int perms /* = 066 */)
00052 {
00053   open (name.c_str (),
00054         (IOFlags::OpenCreate | IOFlags::OpenWrite | IOFlags::OpenTruncate
00055          | (exclusive ? IOFlags::OpenExclusive : 0)),
00056         perms);
00057 }
00058 
00059 void
00060 XrdFile::open (const std::string &name,
00061                int flags /* = IOFlags::OpenRead */,
00062                int perms /* = 066 */)
00063 { open (name.c_str (), flags, perms); }
00064 
00065 void
00066 XrdFile::open (const char *name,
00067                int flags /* = IOFlags::OpenRead */,
00068                int perms /* = 066 */)
00069 {
00070   m_name = name;
00071 
00072   // Actual open
00073   if ((name == 0) || (*name == 0))
00074     throw cms::Exception("XrdFile::open()")
00075       << "Cannot open a file without a name";
00076 
00077   if ((flags & (IOFlags::OpenRead | IOFlags::OpenWrite)) == 0)
00078     throw cms::Exception("XrdFile::open()")
00079       << "Must open file '" << name << "' at least for read or write";
00080 
00081   // If I am already open, close old file first
00082   if (m_client && m_close)
00083     close();
00084   else
00085     abort();
00086 
00087   // Translate our flags to system flags
00088   int openflags = 0;
00089 
00090   if (flags & IOFlags::OpenWrite)
00091     openflags |= kXR_open_updt;
00092   else if (flags & IOFlags::OpenRead)
00093     openflags |= kXR_open_read;
00094 
00095   if (flags & IOFlags::OpenAppend)
00096     throw cms::Exception("XrdFile::open()")
00097       << "Opening file '" << name << "' in append mode not supported";
00098 
00099   if (flags & IOFlags::OpenCreate)
00100   {
00101     if (! (flags & IOFlags::OpenExclusive))
00102       openflags |= kXR_delete;
00103     openflags |= kXR_new;
00104     openflags |= kXR_mkpath;
00105   }
00106 
00107   if ((flags & IOFlags::OpenTruncate) && (flags & IOFlags::OpenWrite))
00108     openflags |= kXR_delete;
00109 
00110   m_client = new XrdClient(name);
00111   if (! m_client->Open(perms, openflags)
00112       || m_client->LastServerResp()->status != kXR_ok)
00113     throw cms::Exception("XrdFile::open()")
00114       << "XrdClient::Open(name='" << name
00115       << "', flags=0x" << std::hex << openflags
00116       << ", permissions=0" << std::oct << perms << std::dec
00117       << ") => error '" << m_client->LastServerError()->errmsg
00118       << "' (errno=" << m_client->LastServerError()->errnum << ")";
00119 
00120   if (! m_client->Stat(&m_stat))
00121     throw cms::Exception("XrdFile::open()")
00122       << "XrdClient::Stat(name='" << name
00123       << ") => error '" << m_client->LastServerError()->errmsg
00124       << "' (errno=" << m_client->LastServerError()->errnum << ")";
00125 
00126   m_offset = 0;
00127   m_close = true;
00128   edm::LogInfo("XrdFileInfo") << "Opened " << m_name;
00129 }
00130 
00131 void
00132 XrdFile::close (void)
00133 {
00134   if (! m_client)
00135   {
00136     edm::LogError("XrdFileError")
00137       << "XrdFile::close(name='" << m_name
00138       << "') called but the file is not open";
00139     m_close = false;
00140     return;
00141   }
00142 
00143   if (! m_client->Close())
00144     edm::LogWarning("XrdFileWarning")
00145       << "XrdFile::close(name='" << m_name
00146       << "') failed with error '" << m_client->LastServerError()->errmsg
00147       << "' (errno=" << m_client->LastServerError()->errnum << ")";
00148   delete m_client;
00149   m_client = 0;
00150 
00151   m_close = false;
00152   m_offset = 0;
00153   memset(&m_stat, 0, sizeof (m_stat));
00154   edm::LogInfo("XrdFileInfo") << "Closed " << m_name;
00155 }
00156 
00157 void
00158 XrdFile::abort (void)
00159 {
00160   delete m_client;
00161   m_client = 0;
00162   m_close = false;
00163   m_offset = 0;
00164   memset(&m_stat, 0, sizeof (m_stat));
00165 }
00166 
00168 IOSize
00169 XrdFile::read (void *into, IOSize n)
00170 {
00171   if (n > 0x7fffffff)
00172     throw cms::Exception("XrdFile::read()")
00173       << "XrdFile::read(name='" << m_name << "', n=" << n
00174       << ") too many bytes, limit is 0x7fffffff";
00175 
00176   int s = m_client->Read(into, m_offset, n);
00177   if (s < 0)
00178     throw cms::Exception("XrdFile::read()")
00179       << "XrdClient::Read(name='" << m_name
00180       << "', offset=" << m_offset << ", n=" << n
00181       << ") failed with error '" << m_client->LastServerError()->errmsg
00182       << "' (errno=" << m_client->LastServerError()->errnum << ")";
00183   m_offset += s;
00184   return s;
00185 }
00186 
00187 IOSize
00188 XrdFile::read (void *into, IOSize n, IOOffset pos)
00189 {
00190   if (n > 0x7fffffff)
00191     throw cms::Exception("XrdFile::read()")
00192       << "XrdFile::read(name='" << m_name << "', n=" << n
00193       << ") exceeds read size limit 0x7fffffff";
00194 
00195   int s = m_client->Read(into, pos, n);
00196   if (s < 0)
00197     throw cms::Exception("XrdFile::read()")
00198       << "XrdClient::Read(name='" << m_name
00199       << "', offset=" << m_offset << ", n=" << n
00200       << ") failed with error '" << m_client->LastServerError()->errmsg
00201       << "' (errno=" << m_client->LastServerError()->errnum << ")";
00202   return s;
00203 }
00204 
00205 IOSize
00206 XrdFile::readv (IOBuffer *into, IOSize n)
00207 {
00208   // Note that the XROOTD and our interfaces do not match.
00209   // XROOTD expects readv() into a single monolithic buffer
00210   // from multiple file locations, whereas we expect scatter
00211   // gather buffers read from a single file location.
00212   //
00213   // We work around this mismatch for now by issuing a cache
00214   // read on the background, and then individual reads.
00215   IOOffset pos = m_offset;
00216   std::vector<long long> offsets (n);
00217   std::vector<int> lengths (n);
00218   for (IOSize i = 0; i < n; ++i)
00219   {
00220     IOSize len = into[i].size();
00221     if (len > 0x7fffffff)
00222       throw cms::Exception("XrdFile::readv()")
00223         << "XrdFile::readv(name='" << m_name << "')[" << i
00224         << "].size=" << len << " exceeds read size limit 0x7fffffff";
00225     offsets[i] = pos;
00226     lengths[i] = len;
00227     pos += len;
00228   }
00229 
00230   // Prefetch into the cache (if any).
00231   if (m_client->ReadV(0, &offsets[0], &lengths[0], n) < 0)
00232     throw cms::Exception("XrdFile::readv()")
00233       << "XrdClient::ReadV(name='" << m_name
00234       << "') failed with error '" << m_client->LastServerError()->errmsg
00235       << "' (errno=" << m_client->LastServerError()->errnum << ")";
00236 
00237   // Issue actual reads.
00238   IOSize total = 0;
00239   for (IOSize i = 0; i < n; ++i)
00240   {
00241     int s = m_client->Read(into[i].data(), offsets[i], lengths[i]);
00242     if (s < 0)
00243     {
00244       if (i > 0)
00245         break;
00246       throw cms::Exception("XrdFile::readv()")
00247         << "XrdClient::Read(name='" << m_name
00248         << "', offset=" << offsets[i] << ", n=" << lengths[i]
00249         << ") failed with error '" << m_client->LastServerError()->errmsg
00250         << "' (errno=" << m_client->LastServerError()->errnum << ")";
00251     }
00252     total += s;
00253     m_offset += s;
00254   }
00255 
00256   return total;
00257 }
00258 
00259 IOSize
00260 XrdFile::readv (IOPosBuffer *into, IOSize n)
00261 {
00262   // See comments in readv() above.
00263   std::vector<long long> offsets (n);
00264   std::vector<int> lengths (n);
00265   for (IOSize i = 0; i < n; ++i)
00266   {
00267     IOSize len = into[i].size();
00268     if (len > 0x7fffffff)
00269       throw cms::Exception("XrdFile::readv()")
00270         << "XrdFile::readv(name='" << m_name << "')[" << i
00271         << "].size=" << len << " exceeds read size limit 0x7fffffff";
00272     offsets[i] = into[i].offset();
00273     lengths[i] = len;
00274   }
00275 
00276   // Prefetch into the cache (if any).
00277   if (m_client->ReadV(0, &offsets[0], &lengths[0], n) < 0)
00278     throw cms::Exception("XrdFile::readv()")
00279       << "XrdClient::ReadV(name='" << m_name
00280       << "') failed with error '" << m_client->LastServerError()->errmsg
00281       << "' (errno=" << m_client->LastServerError()->errnum << ")";
00282 
00283   // Issue actual reads.
00284   IOSize total = 0;
00285   for (IOSize i = 0; i < n; ++i)
00286   {
00287     int s = m_client->Read(into[i].data(), offsets[i], lengths[i]);
00288     if (s < 0)
00289     {
00290       if (i > 0)
00291         break;
00292       throw cms::Exception("XrdFile::readv()")
00293         << "XrdClient::Read(name='" << m_name
00294         << "', offset=" << offsets[i] << ", n=" << lengths[i]
00295         << ") failed with error '" << m_client->LastServerError()->errmsg
00296         << "' (errno=" << m_client->LastServerError()->errnum << ")";
00297     }
00298     total += s;
00299   }
00300 
00301   return total;
00302 }
00303 
00304 IOSize
00305 XrdFile::write (const void *from, IOSize n)
00306 {
00307   if (n > 0x7fffffff)
00308     throw cms::Exception("XrdFile::write()")
00309       << "XrdFile::write(name='" << m_name << "', n=" << n
00310       << ") too many bytes, limit is 0x7fffffff";
00311 
00312   ssize_t s = m_client->Write(from, m_offset, n);
00313   if (s < 0)
00314     throw cms::Exception("XrdFile::write()")
00315       << "XrdFile::write(name='" << m_name << "', n=" << n
00316       << ") failed with error '" << m_client->LastServerError()->errmsg
00317       << "' (errno=" << m_client->LastServerError()->errnum << ")";
00318 
00319   m_offset += s;
00320   if (m_offset > m_stat.size)
00321     m_stat.size = m_offset;
00322 
00323   return s;
00324 }
00325 
00326 IOSize
00327 XrdFile::write (const void *from, IOSize n, IOOffset pos)
00328 {
00329   if (n > 0x7fffffff)
00330     throw cms::Exception("XrdFile::write()")
00331       << "XrdFile::write(name='" << m_name << "', n=" << n
00332       << ") too many bytes, limit is 0x7fffffff";
00333 
00334   ssize_t s = m_client->Write(from, pos, n);
00335   if (s < 0)
00336     throw cms::Exception("XrdFile::write()")
00337       << "XrdFile::write(name='" << m_name << "', n=" << n
00338       << ") failed with error '" << m_client->LastServerError()->errmsg
00339       << "' (errno=" << m_client->LastServerError()->errnum << ")";
00340 
00341   if (pos + s > m_stat.size)
00342     m_stat.size = pos + s;
00343 
00344   return s;
00345 }
00346 
00347 bool
00348 XrdFile::prefetch (const IOPosBuffer *what, IOSize n)
00349 {
00350   XReqErrorType r = kOK;
00351   for (IOSize i = 0; i < n && r == kOK; ++i)
00352     r = m_client->Read_Async(what[i].offset(), what[i].size());
00353   return r == kOK;
00354 }
00355 
00359 IOOffset
00360 XrdFile::position (IOOffset offset, Relative whence /* = SET */)
00361 {
00362   if (! m_client)
00363     throw cms::Exception("XrdFile::position()")
00364       << "XrdFile::position() called on a closed file";
00365 
00366   switch (whence)
00367   {
00368   case SET:
00369     m_offset = offset;
00370     break;
00371 
00372   case CURRENT:
00373     m_offset += offset;
00374     break;
00375 
00376   case END:
00377     m_offset = m_stat.size + offset;
00378     break;
00379 
00380   default:
00381     throw cms::Exception("XrdFile::position()")
00382       << "XrdFile::position() called with incorrect 'whence' parameter";
00383   }
00384 
00385   if (m_offset < 0)
00386     m_offset = 0;
00387   if (m_offset > m_stat.size)
00388     m_stat.size = m_offset;
00389 
00390   return m_offset;
00391 }
00392 
00393 void
00394 XrdFile::resize (IOOffset /* size */)
00395 {
00396   throw cms::Exception("XrdFile::resize()")
00397     << "XrdFile::resize(name='" << m_name << "') not implemented";
00398 }