CMS 3D CMS Logo

RFIOFile Class Reference

RFIO Storage object. More...

#include <Utilities/RFIOAdaptor/interface/RFIOFile.h>

Inheritance diagram for RFIOFile:

Storage IOInput IOOutput

List of all members.

Public Member Functions

virtual void abort (void)
virtual void close (void)
virtual void create (const std::string &name, bool exclusive=false, int perms=0666)
virtual void create (const char *name, bool exclusive=false, int perms=0666)
virtual void open (const std::string &name, int flags=IOFlags::OpenRead, int perms=0666)
virtual void open (const char *name, int flags=IOFlags::OpenRead, int perms=0666)
virtual IOOffset position (IOOffset offset, Relative whence=SET)
virtual bool prefetch (const IOPosBuffer *what, IOSize n)
virtual IOSize read (void *into, IOSize n)
 Read into into at most n number of bytes.
virtual IOSize readv (IOPosBuffer *into, IOSize buffers)
virtual void resize (IOOffset size)
 RFIOFile (const std::string &name, int flags=IOFlags::OpenRead, int perms=0666)
 RFIOFile (const char *name, int flags=IOFlags::OpenRead, int perms=0666)
 RFIOFile (IOFD fd)
 RFIOFile (void)
virtual IOSize write (const void *from, IOSize n)
 Write n bytes of data starting at address from.
 ~RFIOFile (void)

Private Member Functions

void reopen ()
ssize_t retryRead (void *into, IOSize n, int maxRetry=10)

Private Attributes

bool m_close
IOOffset m_curpos
IOFD m_fd
int m_flags
std::string m_name
int m_perms


Detailed Description

RFIO Storage object.

Definition at line 10 of file RFIOFile.h.


Constructor & Destructor Documentation

RFIOFile::RFIOFile ( void   ) 

Definition at line 19 of file RFIOFile.cc.

00020   : m_fd (EDM_IOFD_INVALID),
00021     m_close (false),
00022     m_flags (0),
00023     m_perms (0),
00024     m_curpos (0)
00025 {}

RFIOFile::RFIOFile ( IOFD  fd  ) 

Definition at line 27 of file RFIOFile.cc.

00028   : m_fd (fd),
00029     m_close (true),
00030     m_flags (0),
00031     m_perms (0),
00032     m_curpos (0)
00033 {}

RFIOFile::RFIOFile ( const char *  name,
int  flags = IOFlags::OpenRead,
int  perms = 0666 
)

Definition at line 35 of file RFIOFile.cc.

References open().

00038   : m_fd (EDM_IOFD_INVALID),
00039     m_close (false),
00040     m_flags (0),
00041     m_perms (0),
00042     m_curpos (0)
00043 { open (name, flags, perms); }

RFIOFile::RFIOFile ( const std::string &  name,
int  flags = IOFlags::OpenRead,
int  perms = 0666 
)

Definition at line 45 of file RFIOFile.cc.

References open().

00048   : m_fd (EDM_IOFD_INVALID),
00049     m_close (false),
00050     m_flags (0),
00051     m_perms (0),
00052     m_curpos (0)
00053 { open (name.c_str (), flags, perms); }

RFIOFile::~RFIOFile ( void   ) 

Definition at line 55 of file RFIOFile.cc.

References m_close, and m_name.

00056 {
00057   if (m_close)
00058     edm::LogError("RFIOFileError")
00059       << "Destructor called on RFIO file '" << m_name
00060       << "' but the file is still open";
00061 }


Member Function Documentation

void RFIOFile::abort ( void   )  [virtual]

Definition at line 224 of file RFIOFile.cc.

References EDM_IOFD_INVALID, m_close, m_fd, rfio_close64(), and serrno.

00225 {
00226   serrno = 0;
00227   if (m_fd != EDM_IOFD_INVALID)
00228     rfio_close64 (m_fd);
00229 
00230   m_close = false;
00231   m_fd = EDM_IOFD_INVALID;
00232 }

void RFIOFile::close ( void   )  [virtual]

Reimplemented from Storage.

Definition at line 180 of file RFIOFile.cc.

References EDM_IOFD_INVALID, m_close, m_fd, m_name, rfio_close64(), rfio_errno, rfio_serror(), serrno, and StDecayID::status.

Referenced by open(), and reopen().

00181 {
00182   if (m_fd == EDM_IOFD_INVALID)
00183   {
00184     edm::LogError("RFIOFileError")
00185       << "RFIOFile::close(name='" << m_name
00186       << "') called but the file is not open";
00187     m_close = false;
00188     return;
00189   }
00190 
00191   serrno = 0;
00192   if (rfio_close64 (m_fd) == -1)
00193   {
00194     // If we fail to close the file, report a warning.
00195     edm::LogWarning("RFIOFileWarning")
00196       << "rfio_close64(name='" << m_name
00197       << "') failed with error '" << rfio_serror()
00198       << "' (rfio_errno=" << rfio_errno << ", serrno=" << serrno << ")";
00199 
00200     // When rfio_close64 fails then try the system close function as
00201     // per the advice from Olof Barring from the Castor operations.
00202     int status = ::close(m_fd);
00203     if (status < 0)
00204       edm::LogWarning("RFIOFileWarning")
00205         << "RFIOFile::close(): system level close after a failed"
00206         << " rfio_close64 also failed with error '" << strerror (errno)
00207         << "' (error code " << errno << ")";
00208     else
00209       edm::LogWarning("RFIOFileWarning")
00210         << "RFIOFile::close(): system level close after a failed"
00211         << " rfio_close64 succeeded";
00212 
00213     sleep(5);
00214   }
00215 
00216   m_close = false;
00217   m_fd = EDM_IOFD_INVALID;
00218 
00219   // Caused hang.  Will be added back after problem is fix
00220   // edm::LogInfo("RFIOFileInfo") << "Closed " << m_name;
00221 }

void RFIOFile::create ( const std::string &  name,
bool  exclusive = false,
int  perms = 0666 
) [virtual]

Definition at line 77 of file RFIOFile.cc.

References open(), IOFlags::OpenCreate, IOFlags::OpenExclusive, IOFlags::OpenTruncate, and IOFlags::OpenWrite.

00080 {
00081   open (name.c_str (),
00082         (IOFlags::OpenCreate | IOFlags::OpenWrite | IOFlags::OpenTruncate
00083          | (exclusive ? IOFlags::OpenExclusive : 0)),
00084         perms);
00085 }

void RFIOFile::create ( const char *  name,
bool  exclusive = false,
int  perms = 0666 
) [virtual]

Definition at line 66 of file RFIOFile.cc.

References open(), IOFlags::OpenCreate, IOFlags::OpenExclusive, IOFlags::OpenTruncate, and IOFlags::OpenWrite.

00069 {
00070   open (name,
00071         (IOFlags::OpenCreate | IOFlags::OpenWrite | IOFlags::OpenTruncate
00072          | (exclusive ? IOFlags::OpenExclusive : 0)),
00073         perms);
00074 }

void RFIOFile::open ( const std::string &  name,
int  flags = IOFlags::OpenRead,
int  perms = 0666 
) [virtual]

Definition at line 88 of file RFIOFile.cc.

References open().

00091 { open (name.c_str (), flags, perms); }

void RFIOFile::open ( const char *  name,
int  flags = IOFlags::OpenRead,
int  perms = 0666 
) [virtual]

Definition at line 94 of file RFIOFile.cc.

References close(), EDM_IOFD_INVALID, Exception, m_close, m_curpos, m_fd, m_flags, m_name, m_perms, O_NONBLOCK, IOFlags::OpenAppend, IOFlags::OpenCreate, IOFlags::OpenExclusive, IOFlags::OpenNonBlock, IOFlags::OpenRead, IOFlags::OpenTruncate, IOFlags::OpenUnbuffered, IOFlags::OpenWrite, rfio_errno, rfio_open64(), RFIO_READOPT, rfio_serror(), rfiosetopt(), and serrno.

Referenced by create(), open(), reopen(), and RFIOFile().

00097 {
00098   // Save parameters for error recovery.
00099   m_name = name;
00100   m_flags = flags;
00101   m_perms = perms;
00102 
00103   // Reset RFIO error code.
00104   serrno = 0;
00105 
00106   // Disable buffering in rfio library?  Note that doing this on
00107   // one file disables it for everything.  Not much we can do...
00108   // but it does make a significant performance difference to the
00109   // clients.  Note also that docs say the flag turns off write
00110   // buffering -- this turns off all buffering.
00111   if (flags & IOFlags::OpenUnbuffered)
00112   {
00113     int readopt = 0;
00114     rfiosetopt (RFIO_READOPT, &readopt, sizeof (readopt));
00115   }
00116   else 
00117   {
00118     int readopt = 1;
00119     rfiosetopt (RFIO_READOPT, &readopt, sizeof (readopt));
00120   }
00121 
00122   if ((name == 0) || (*name == 0))
00123     throw cms::Exception("RFIOFile::open()")
00124       << "Cannot open a file without a name";
00125 
00126   if ((flags & (IOFlags::OpenRead | IOFlags::OpenWrite)) == 0)
00127     throw cms::Exception("RFIOFile::open()")
00128       << "Must open file '" << name << "' at least for read or write";
00129 
00130   std::string lname (name);
00131   if (lname.find ("//") == 0)
00132     lname.erase(0, 1);
00133 
00134   // If I am already open, close old file first
00135   if (m_fd != EDM_IOFD_INVALID && m_close)
00136     close ();
00137 
00138   // Translate our flags to system flags
00139   int openflags = 0;
00140 
00141   if ((flags & IOFlags::OpenRead) && (flags & IOFlags::OpenWrite))
00142     openflags |= O_RDWR;
00143   else if (flags & IOFlags::OpenRead)
00144     openflags |= O_RDONLY;
00145   else if (flags & IOFlags::OpenWrite)
00146     openflags |= O_WRONLY;
00147 
00148   if (flags & IOFlags::OpenNonBlock)
00149     openflags |= O_NONBLOCK;
00150 
00151   if (flags & IOFlags::OpenAppend)
00152     openflags |= O_APPEND;
00153 
00154   if (flags & IOFlags::OpenCreate)
00155     openflags |= O_CREAT;
00156 
00157   if (flags & IOFlags::OpenExclusive)
00158     openflags |= O_EXCL;
00159 
00160   if (flags & IOFlags::OpenTruncate)
00161     openflags |= O_TRUNC;
00162 
00163   IOFD newfd = EDM_IOFD_INVALID;
00164   if ((newfd = rfio_open64 (lname.c_str(), openflags, perms)) == -1)
00165     throw cms::Exception("RFIOFile::open()")
00166       << "rfio_open(name='" << lname
00167       << "', flags=0x" << std::hex << openflags
00168       << ", permissions=0" << std::oct << perms << std::dec
00169       << ") => error '" << rfio_serror ()
00170       << "' (rfio_errno=" << rfio_errno << ", serrno=" << serrno << ")";
00171 
00172   m_fd = newfd;
00173   m_close = true;
00174   m_curpos = 0;
00175 
00176   edm::LogInfo("RFIOFileInfo") << "Opened " << lname;
00177 }

IOOffset RFIOFile::position ( IOOffset  offset,
Relative  whence = SET 
) [virtual]

Implements Storage.

Definition at line 356 of file RFIOFile.cc.

References Storage::CURRENT, EDM_IOFD_INVALID, Storage::END, Exception, m_curpos, m_fd, m_name, HLT_VtxMuL3::result, rfio_errno, rfio_lseek64(), rfio_serror(), serrno, and Storage::SET.

00357 {
00358   if (m_fd == EDM_IOFD_INVALID)
00359     throw cms::Exception("RFIOFile::position()")
00360       << "RFIOFile::position() called on a closed file";
00361   if (whence != CURRENT && whence != SET && whence != END)
00362     throw cms::Exception("RFIOFile::position()")
00363       << "RFIOFile::position() called with incorrect 'whence' parameter";
00364 
00365   IOOffset      result;
00366   int           mywhence = (whence == SET ? SEEK_SET
00367                             : whence == CURRENT ? SEEK_CUR
00368                             : SEEK_END);
00369 
00370   serrno = 0;
00371   if ((result = rfio_lseek64 (m_fd, offset, mywhence)) == -1)
00372     throw cms::Exception("RFIOFile::position()")
00373       << "rfio_lseek(name='" << m_name << "', offset=" << offset
00374       << ", whence=" << mywhence << ") failed at position "
00375       << m_curpos << " with error '" << rfio_serror()
00376       << "' (rfio_errno=" << rfio_errno << ", serrno=" << serrno << ")";
00377 
00378   m_curpos = result;
00379   return result;
00380 }

bool RFIOFile::prefetch ( const IOPosBuffer what,
IOSize  n 
) [virtual]

Reimplemented from Storage.

Definition at line 390 of file RFIOFile.cc.

References Exception, i, m_curpos, m_fd, m_name, IOPosBuffer::offset(), HLT_VtxMuL3::result, rfio_errno, rfio_preseek64(), RFIO_READOPT, rfio_serror(), rfioreadopt(), serrno, and IOPosBuffer::size().

Referenced by readv().

00391 {
00392   if (rfioreadopt (RFIO_READOPT) != 1)
00393     throw cms::Exception("RFIOFile::preseek()")
00394       << "RFIOFile::prefetch() called but RFIO_READOPT="
00395       << rfioreadopt (RFIO_READOPT) << " (must be 1)";
00396 
00397   std::vector<iovec64> iov (n);
00398   for (IOSize i = 0; i < n; ++i)
00399   {
00400     iov[i].iov_base = what[i].offset();
00401     iov[i].iov_len = what[i].size();
00402   }
00403 
00404   serrno = 0;
00405   int retry = 5;
00406   int result;
00407   while ((result = rfio_preseek64(m_fd, &iov[0], n)) == -1)
00408   {
00409     if (--retry <= 0)
00410     {
00411       edm::LogError("RFIOFile::prefetch")
00412         << "RFIOFile::prefetch(name='" << m_name << "') failed with error '"
00413         << rfio_serror() << "' (rfio_errno=" << rfio_errno
00414         << ", serrno=" << serrno << ")";
00415       return false;
00416     }
00417     else
00418     {
00419       edm::LogWarning("RFIOFileRetry")
00420         << "RFIOFile::prefetch(name='" << m_name << "') failed at position "
00421         << m_curpos << " with error '" << rfio_serror()
00422         << "' (rfio_errno=" << rfio_errno << ", serrno=" << serrno
00423         << "); retrying " << (retry+1) << " times";
00424       serrno = 0;
00425       sleep(5);
00426     }
00427   }
00428 
00429   return true;
00430 }

IOSize RFIOFile::read ( void into,
IOSize  n 
) [virtual]

Read into into at most n number of bytes.

If this is a blocking stream, the call will block until some data can be read, end of input is reached, or an exception is thrown. For a non-blocking stream the available input is returned. If none is available, an exception is thrown.

Returns:
The number of bytes actually read. This is less or equal to the size of the buffer. Zero indicates that the end of the input has been reached: end of file, or remote end closing for a connected channel like a pipe or a socket. Otherwise the value can be less than requested if limited amount of input is currently available for platform or implementation reasons.
Exceptions:
In case of error, a IOError exception is thrown. This includes the situation where the input stream is in non-blocking mode and no input is currently available (FIXME: make this simpler; clarify which exception).

Implements IOInput.

Definition at line 305 of file RFIOFile.cc.

References end, Exception, LogDebug, m_curpos, m_name, realNanoSecs(), retryRead(), rfio_errno, rfio_serror(), s, and serrno.

00306 {
00307   // Be aware that when enabled these LogDebug prints
00308   // will take more time than the read itself unless the reads
00309   // are proceeding slower than under optimal conditions.
00310   LogDebug("RFIOFileDebug") << "Entering RFIOFile read()";
00311   double start = realNanoSecs();
00312 
00313   ssize_t s;
00314   serrno = 0;
00315   if ((s = retryRead (into, n, 3)) < 0)
00316     throw cms::Exception("RFIOFile::read()")
00317       << "rfio_read(name='" << m_name << "', n=" << n << ") failed"
00318       << " at position " << m_curpos << " with error '" << rfio_serror()
00319       << "' (rfio_errno=" << rfio_errno << ", serrno=" << serrno << ")";
00320 
00321   m_curpos += s;
00322 
00323   double end = realNanoSecs();
00324   LogDebug("RFIOFileDebug")
00325     << "Exiting RFIOFile read(), elapsed time = " << end - start
00326     << " ns, bytes read = " << s << ", file position = " << m_curpos;
00327 
00328   return s;
00329 }

IOSize RFIOFile::readv ( IOPosBuffer into,
IOSize  buffers 
) [virtual]

Reimplemented from Storage.

Definition at line 332 of file RFIOFile.cc.

References m_flags, IOFlags::OpenUnbuffered, prefetch(), and Storage::readv().

00333 {
00334   if (! (m_flags & IOFlags::OpenUnbuffered))
00335     prefetch(into, buffers);
00336   return Storage::readv(into, buffers);
00337 }

void RFIOFile::reopen ( void   )  [private]

Definition at line 234 of file RFIOFile.cc.

References close(), m_curpos, m_flags, m_name, m_perms, open(), and Storage::position().

Referenced by retryRead().

00235 {
00236   // Remember the current position in the file
00237   IOOffset lastpos = m_curpos;
00238   close();
00239   sleep(5);
00240   open(m_name, m_flags, m_perms);
00241 
00242   // Set the position back to the same place it was
00243   // before the file closed and opened.
00244   position(lastpos);
00245 }

void RFIOFile::resize ( IOOffset  size  )  [virtual]

Implements Storage.

Definition at line 383 of file RFIOFile.cc.

References Exception, and m_name.

00384 {
00385   throw cms::Exception("RFIOFile::resize()")
00386     << "RFIOFile::resize(name='" << m_name << "') not implemented";
00387 }

ssize_t RFIOFile::retryRead ( void into,
IOSize  n,
int  maxRetry = 10 
) [private]

Definition at line 248 of file RFIOFile.cc.

References edm::FlushMessageLog(), m_curpos, m_fd, m_name, reopen(), rfio_errno, rfio_read64(), rfio_serror(), s, and serrno.

Referenced by read().

00249 {
00250   // Attempt to read up to maxRetry times.
00251   ssize_t s;
00252   do
00253   {
00254     serrno = 0;
00255     s = rfio_read64 (m_fd, into, n);
00256     if ((s == -1 && serrno == 1004) || (s > ssize_t (n)))
00257     {
00258       // Wait a little while to allow Castor to recover from the timeout.
00259       const char *sleepTimeMsg;
00260       int secondsToSleep = 5;
00261       switch (maxRetry)
00262       {
00263       case 1:
00264         sleepTimeMsg = "10 minutes";
00265         secondsToSleep = 600;
00266         break;
00267 
00268       case 2:
00269         sleepTimeMsg = "5 minutes";
00270         secondsToSleep = 300;
00271         break;
00272 
00273       default:
00274         sleepTimeMsg = "1 minute";
00275         secondsToSleep = 60;
00276       }
00277 
00278       edm::LogWarning("RFIOFileRetry")
00279         << "RFIOFile retrying read\n"
00280         << "  return value from rfio_read64 = " << s << " (normally this is bytes read, -1 for error)\n"
00281         << "  bytes requested = " << n << "  (this and bytes read are equal unless error or EOF)\n"
00282         << "  rfio error message = " << rfio_serror() << " (explanation from server, if possible)\n"
00283         << "  serrno = " << serrno << " (rfio server error code, 0 = OK, 1004 = timeout, ...)\n"
00284         << "  rfio_errno = " << rfio_errno << " (rfio error from actually accessing the file)\n"
00285         << "  current position = " << m_curpos << " (in bytes, beginning of file is 0)\n"
00286         << "  retries left before quitting = " << maxRetry << "\n"
00287         << "  will close and reopen file " << m_name << "\n"
00288         << "  will sleep for " << sleepTimeMsg << " before attempting retry";
00289       edm::FlushMessageLog();
00290       sleep(secondsToSleep);
00291 
00292       // Improve the chances of success by closing and reopening
00293       // the file before retrying the read.  This also resets
00294       // the position in the file to the correct place.
00295       reopen();
00296     }
00297     else
00298       break;
00299   } while (--maxRetry > 0);
00300 
00301   return s;
00302 }

IOSize RFIOFile::write ( const void from,
IOSize  n 
) [virtual]

Write n bytes of data starting at address from.

Returns:
The number of bytes written. Normally this will be n, but can be less, even zero, for example if the stream is non-blocking mode and cannot accept input at this time.
Exceptions:
In case of error, an exception is thrown. However if the stream is in non-blocking mode and cannot accept output, it will not throw an exception -- the return value will be less than requested.

Implements IOOutput.

Definition at line 340 of file RFIOFile.cc.

References Exception, m_curpos, m_fd, m_name, rfio_errno, rfio_serror(), rfio_write64(), s, and serrno.

00341 {
00342   serrno = 0;
00343   ssize_t s = rfio_write64 (m_fd, from, n);
00344   if (s < 0)
00345     throw cms::Exception("RFIOFile::write()")
00346       << "rfio_write(name='" << m_name << "', n=" << n << ") failed"
00347       << " at position " << m_curpos << " with error '" << rfio_serror()
00348       << "' (rfio_errno=" << rfio_errno << ", serrno=" << serrno << ")";
00349   return s;
00350 }


Member Data Documentation

bool RFIOFile::m_close [private]

Definition at line 52 of file RFIOFile.h.

Referenced by abort(), close(), open(), and ~RFIOFile().

IOOffset RFIOFile::m_curpos [private]

Definition at line 56 of file RFIOFile.h.

Referenced by open(), position(), prefetch(), read(), reopen(), retryRead(), and write().

IOFD RFIOFile::m_fd [private]

Definition at line 51 of file RFIOFile.h.

Referenced by abort(), close(), open(), position(), prefetch(), retryRead(), and write().

int RFIOFile::m_flags [private]

Definition at line 54 of file RFIOFile.h.

Referenced by open(), readv(), and reopen().

std::string RFIOFile::m_name [private]

Definition at line 53 of file RFIOFile.h.

Referenced by close(), open(), position(), prefetch(), read(), reopen(), resize(), retryRead(), write(), and ~RFIOFile().

int RFIOFile::m_perms [private]

Definition at line 55 of file RFIOFile.h.

Referenced by open(), and reopen().


The documentation for this class was generated from the following files:
Generated on Tue Jun 9 18:30:45 2009 for CMSSW by  doxygen 1.5.4