CMS 3D CMS Logo

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

Generated on Tue Jun 9 17:48:58 2009 for CMSSW by  doxygen 1.5.4