Back to home page

Project CMSSW displayed by LXR

 
 

    


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

0001 #include "Utilities/StorageFactory/interface/File.h"
0002 #include "Utilities/StorageFactory/src/SysFile.h"
0003 #include "Utilities/StorageFactory/src/Throw.h"
0004 #include <cassert>
0005 
0006 using namespace edm::storage;
0007 using namespace edm::storage::IOFlags;
0008 
0009 //<<<<<< PRIVATE DEFINES                                                >>>>>>
0010 //<<<<<< PRIVATE CONSTANTS                                              >>>>>>
0011 //<<<<<< PRIVATE TYPES                                                  >>>>>>
0012 //<<<<<< PUBLIC VARIABLE DEFINITIONS                                    >>>>>>
0013 //<<<<<< PRIVATE VARIABLE DEFINITIONS                                   >>>>>>
0014 //<<<<<< CLASS STRUCTURE INITIALIZATION                                 >>>>>>
0015 //<<<<<< PUBLIC FUNCTION DEFINITIONS                                    >>>>>>
0016 //<<<<<< PRIVATE FUNCTION DEFINITIONS                                   >>>>>>
0017 //<<<<<< MEMBER FUNCTION DEFINITIONS                                    >>>>>>
0018 
0019 /** @fn IOSize File::read (IOBuffer into, IOOffset pos)
0020     Read from the file at the specified position.  */
0021 
0022 /** @fn IOSize File::write (IOBuffer from, IOOffset pos)
0023     Write to the file at the specified position.  */
0024 
0025 /** @fn IOOffset File::size (void) const
0026     Get the size of the file.  */
0027 
0028 /** @fn IOOffset File::position (void) const
0029     Return the current file pointer position.  */
0030 
0031 /** @fn IOOffset File::position (IOOffset offset, Relative whence = SET)
0032     Move the current file pointer to @a offset relative to @a whence.
0033     Returns the new file offset relative to the beginning of the file. */
0034 
0035 /** @fn void  File::resize (IOOffset size)
0036     Resize to the file to @a size.  If @a size is less than the file's
0037     current size, the file is truncated.  If @a size is larger than
0038     the file's current size, the file is extended with zero bytes.
0039     Does not change the current file pointer.  */
0040 
0041 /** @fn void File::flush (void)
0042     Flush the system's file system buffers for this file.  */
0043 
0044 /** @fn bool File::sysclose (IOFD fd, int *error)
0045     Actually close a file handle and return error code.  */
0046 
0047 /** @fn void File::times (Time *ctime, Time *mtime, Time *atime) const
0048     Get the file's creation, modification and access times.  Fills in
0049     non-null #Time parameters.  */
0050 
0051 /** @fn bool File::status (IOStatus &s) const
0052     Get the full #IOStatus description of the file.  */
0053 
0054 //////////////////////////////////////////////////////////////////////
0055 //////////////////////////////////////////////////////////////////////
0056 //////////////////////////////////////////////////////////////////////
0057 /** Create a new file object without a file attached to it.  */
0058 File::File() : m_fd(EDM_IOFD_INVALID) { m_flags = 0; }
0059 
0060 /** Create a new file object from a file descriptor.  The descriptor
0061     will be closed automatically when the file object is destructed
0062     if @a autoclose is @c true (the default).  */
0063 File::File(IOFD fd, bool autoclose /* = true */) : m_fd(fd) { m_flags = autoclose ? InternalAutoClose : 0; }
0064 
0065 /** Internal function for copying file objects to retain the state flags. */
0066 File::File(IOFD fd, unsigned flags) : m_fd(fd) { m_flags = flags; }
0067 
0068 /** Create a new file object by calling #open() with the given arguments.  */
0069 File::File(const char *name, int flags /*= OpenRead*/, int perms /*= 0666*/) { open(name, flags, perms); }
0070 
0071 /** Create a new file object by calling #open() with the given arguments.  */
0072 File::File(const std::string &name, int flags /*= OpenRead*/, int perms /*= 0666*/) {
0073   open(name.c_str(), flags, perms);
0074 }
0075 
0076 /** Release the resources held by the file object.  If the object
0077     holds a valid file descriptor given to it through the constructor
0078     or obtained by calling #open(), the descriptor will be closed.  */
0079 File::~File(void) {
0080   if (m_flags & InternalAutoClose)
0081     abort();
0082 }
0083 
0084 //////////////////////////////////////////////////////////////////////
0085 /** Set the autoclose flag of the file.  If @a autoclose is @c true,
0086     the destructor will automatically try to close the underlying file
0087     descriptor.  Otherwise the file descriptor will be left open.  Set
0088     the flag off if the file descriptor is originally owned by someone
0089     else.  */
0090 void File::setAutoClose(bool autoclose) {
0091   m_flags &= ~InternalAutoClose;
0092   if (autoclose)
0093     m_flags |= InternalAutoClose;
0094 }
0095 
0096 //////////////////////////////////////////////////////////////////////
0097 /** Duplicate the file object.  If @a copy, also duplicates the
0098     underlying file descriptor, otherwise the two will point to the
0099     same descriptor.  If the file descriptor is not copied, the copy
0100     will not close its file descriptor on destruction, the original
0101     object (@c this) will. */
0102 File *File::duplicate(bool copy) const {
0103   File *dup = new File(fd(), copy ? m_flags : 0);
0104   return copy ? this->duplicate(dup) : dup;
0105 }
0106 
0107 /** Internal implementation of #duplicate() to actually duplicate the
0108     file handle into @a child. */
0109 File *File::duplicate(File *child) const {
0110   IOFD fd = m_fd;
0111   assert(fd != EDM_IOFD_INVALID);
0112   assert(child);
0113   child->m_fd = sysduplicate(fd);
0114   child->m_flags = m_flags;
0115   return child;
0116 }
0117 
0118 //////////////////////////////////////////////////////////////////////
0119 /** Create and open the file @a name in write mode.  If @a exclusive,
0120     the creation fails if the file already exists, otherwise if the
0121     file exists, it will be truncated.  The new file will have the
0122     permissions @a perms. */
0123 void File::create(const char *name, bool exclusive /*=false*/, int perms /*=0666*/) {
0124   open(name, (OpenCreate | OpenWrite | OpenTruncate | (exclusive ? OpenExclusive : 0)), perms);
0125 }
0126 
0127 /** Create and open the file @a name in write mode.  If @a exclusive,
0128     the creation fails if the file already exists, otherwise if the
0129     file exists, it will be truncated.  The new file will have the
0130     permissions @a perms. */
0131 void File::create(const std::string &name, bool exclusive /*=false*/, int perms /*=0666*/) {
0132   open(name.c_str(), (OpenCreate | OpenWrite | OpenTruncate | (exclusive ? OpenExclusive : 0)), perms);
0133 }
0134 
0135 /** Open or possibly create the file @a name with options specified in
0136     @a flags.  If the file is to be created, it will be given the
0137     permissions @a perms.  If this object already has a file open,
0138     it is closed first.  Redirected to the overloaded method taking
0139     a "const char *" argument.  */
0140 void File::open(const std::string &name, int flags /*= OpenRead*/, int perms /*= 0666*/) {
0141   open(name.c_str(), flags, perms);
0142 }
0143 
0144 /** Open or possibly create the file @a name with options specified in
0145     @a flags.  If the file is to be created, it will be given the
0146     permissions @a perms.  If this object already has a file open,
0147     it is closed first.  */
0148 void File::open(const char *name, int flags /*= OpenRead*/, int perms /*= 0666*/) {
0149   // is zero and always implied.  OTOH, existence check should be
0150   // done with Filename::exists() -- see comments there about what
0151   // can happen on a WIN32 remote share even if the file doesn't
0152   // exist.  For now make sure that read or write was asked for.
0153 
0154   assert(name && *name);
0155   assert(flags & (OpenRead | OpenWrite));
0156 
0157   // If I am already open, close the old file first.
0158   if (fd() != EDM_IOFD_INVALID && (m_flags & InternalAutoClose))
0159     close();
0160 
0161   IOFD newfd = EDM_IOFD_INVALID;
0162   unsigned newflags = InternalAutoClose;
0163 
0164   sysopen(name, flags, perms, newfd, newflags);
0165 
0166   m_fd = newfd;
0167   m_flags = newflags;
0168 }
0169 
0170 void File::attach(IOFD fd) {
0171   m_fd = fd;
0172   m_flags = 0;
0173 }
0174 
0175 //////////////////////////////////////////////////////////////////////
0176 /** Prefetch data for the file.  */
0177 bool File::prefetch(const IOPosBuffer *what, IOSize n) {
0178   IOFD fd = m_fd;
0179   for (IOSize i = 0; i < n; ++i) {
0180 #if F_RDADVISE
0181     radvisory info;
0182     info.ra_offset = what[i].offset();
0183     info.ra_count = what[i].size();
0184     fcntl(fd, F_RDADVISE, &info);
0185 #elif _POSIX_ADVISORY_INFO > 0
0186     posix_fadvise(fd, what[i].offset(), what[i].size(), POSIX_FADV_WILLNEED);
0187 #else
0188 #error advisory read ahead not available on this platform
0189 #endif
0190   }
0191   return true;
0192 }
0193 
0194 /** Write to the file.  */
0195 IOSize File::write(const void *from, IOSize n) {
0196   // FIXME: This may create a race condition or cause trouble on
0197   // remote files.  Should be currently needed only on WIN32.
0198   if (m_flags & OpenAppend)
0199     position(0, END);
0200 
0201   IOSize s = syswrite(from, n);
0202 
0203   if (m_flags & OpenUnbuffered)
0204     // FIXME: Exception handling?
0205     flush();
0206 
0207   return s;
0208 }
0209 
0210 /** Write to the file.  */
0211 IOSize File::writev(const IOBuffer *from, IOSize length) {
0212   // FIXME: This may create a race condition or cause trouble on
0213   // remote files.  Should be currently needed only on WIN32.
0214   if (m_flags & OpenAppend)
0215     position(0, END);
0216 
0217   IOSize s = syswritev(from, length);
0218 
0219   if (m_flags & OpenUnbuffered)
0220     // FIXME: Exception handling?
0221     flush();
0222 
0223   return s;
0224 }
0225 
0226 /** Close the file.  */
0227 void File::close() {
0228   IOFD fd = m_fd;
0229   assert(fd != EDM_IOFD_INVALID);
0230 
0231   int error;
0232   if (!sysclose(fd, &error))
0233     throwStorageError("FileCloseError", "Calling File::close()", "sysclose", error);
0234 
0235   m_flags &= ~InternalAutoClose;
0236   m_fd = EDM_IOFD_INVALID;
0237 }
0238 
0239 /** Close the file and ignore all errors.  */
0240 void File::abort() {
0241   IOFD fd = m_fd;
0242   if (fd != EDM_IOFD_INVALID) {
0243     sysclose(fd);
0244     m_flags &= ~InternalAutoClose;
0245     m_fd = EDM_IOFD_INVALID;
0246   }
0247 }