diff --git a/src/XrdOuc/XrdOucCache2.hh b/src/XrdOuc/XrdOucCache2.hh index 4439e641c0d..a27396f5e28 100644 --- a/src/XrdOuc/XrdOucCache2.hh +++ b/src/XrdOuc/XrdOucCache2.hh @@ -61,6 +61,21 @@ class XrdOucCacheIO2 : public virtual XrdOucCacheIO { public: +//------------------------------------------------------------------------------ +//! Perform an fstat() operation (defaults to passthrough). +//! +//! @param sbuff reference to the stat buffer to be filled in. Only fields +//! st_size, st_blocks, st_mtime (st_atime and st_ctime may be +//! set to st_mtime), st_ino, and st_mode need to be set. All +//! other fields are preset and should not be changed. +//! +//! @return <0 - fstat failed, value is -errno. +//! =0 - fstat succeeded, sbuff holds stat information. +//! >0 - fstat could not be done, forward operation to next level. +//------------------------------------------------------------------------------ + +virtual int Fstat(struct stat &sbuff) {(void)sbuff; return 1;} + //------------------------------------------------------------------------------ //! Perform an asynchronous read (defaults to synchrnous). //! @@ -227,8 +242,8 @@ int Prepare(const char *url, int oflags, mode_t mode) //! @param url pointer to the url whose stat information is wanted. //! @param sbuff reference to the stat buffer to be filled in. Only fields //! st_size, st_blocks, st_mtime (st_atime and st_ctime may be -//! set to st_mtime), st_ino, st_rdev, and st_mode need to be -//! set. All other fields should be set to zero. +//! set to st_mtime), st_ino, and st_mode need to be set. All +//! other fields are preset and should not be changed. //! //! @return <0 - Stat failed, value is -errno. //! =0 - Stat succeeded, sbuff holds stat information. diff --git a/src/XrdPosix/XrdPosixCacheBC.hh b/src/XrdPosix/XrdPosixCacheBC.hh index 5694b9ef42d..54d05125876 100644 --- a/src/XrdPosix/XrdPosixCacheBC.hh +++ b/src/XrdPosix/XrdPosixCacheBC.hh @@ -53,6 +53,8 @@ XrdOucCacheIO2 *Detach() {XrdOucCacheIO2 *theCIO = cacheIO2; virtual long long FSize() {return cacheIO1->FSize();} +virtual int Fstat(struct stat &buf) {return cacheIO2->Fstat(buf);} + virtual const char *Path() {return cacheIO1->Path();} diff --git a/src/XrdPosix/XrdPosixFile.cc b/src/XrdPosix/XrdPosixFile.cc index 92ebe77722d..988af11d8e3 100644 --- a/src/XrdPosix/XrdPosixFile.cc +++ b/src/XrdPosix/XrdPosixFile.cc @@ -248,6 +248,31 @@ bool XrdPosixFile::Finalize(XrdCl::XRootDStatus *Status) return true; } +/******************************************************************************/ +/* F s t a t */ +/******************************************************************************/ + +int XrdPosixFile::Fstat(struct stat &buf) +{ + long long theSize; + +// The size is treated differently here as it may come from a cache and may +// actually trigger a file open if the open was deferred. +// + theSize = XCio->FSize(); + if (theSize < 0) return static_cast(theSize); + +// Return what little we can +// + buf.st_size = theSize; + buf.st_atime = buf.st_mtime = buf.st_ctime = myMtime; + buf.st_blocks = buf.st_size/512+1; + buf.st_ino = myInode; + buf.st_rdev = myRdev; + buf.st_mode = myMode; + return 0; +} + /******************************************************************************/ /* H a n d l e R e s p o n s e */ /******************************************************************************/ diff --git a/src/XrdPosix/XrdPosixFile.hh b/src/XrdPosix/XrdPosixFile.hh index 116c52ac536..1f12025494b 100644 --- a/src/XrdPosix/XrdPosixFile.hh +++ b/src/XrdPosix/XrdPosixFile.hh @@ -92,6 +92,8 @@ static void DelayedDestroy(XrdPosixFile *fp); return retSize; } + int Fstat(struct stat &buf); + void HandleResponse(XrdCl::XRootDStatus *status, XrdCl::AnyObject *response); diff --git a/src/XrdPosix/XrdPosixPrepIO.hh b/src/XrdPosix/XrdPosixPrepIO.hh index ff3f7402113..42d601b91ea 100644 --- a/src/XrdPosix/XrdPosixPrepIO.hh +++ b/src/XrdPosix/XrdPosixPrepIO.hh @@ -43,8 +43,13 @@ XrdOucCacheIO *Detach() {return this;} // Already defined long long FSize() {return (Init() ? fileP->FSize() : openRC);} +int Fstat(struct stat &buf) + {return (Init() ? fileP->Fstat(buf) : openRC);} + bool ioActive() { return false; } // Already defined +int Open() {Init(); return openRC;} + const char *Path() {return fileP->Path();} int Read (char *Buffer, long long Offset, int Length) diff --git a/src/XrdPosix/XrdPosixXrootd.cc b/src/XrdPosix/XrdPosixXrootd.cc index 77f83299a4d..1658419ff49 100644 --- a/src/XrdPosix/XrdPosixXrootd.cc +++ b/src/XrdPosix/XrdPosixXrootd.cc @@ -294,7 +294,7 @@ int XrdPosixXrootd::endPoint(int FD, char *Buff, int Blen) int XrdPosixXrootd::Fstat(int fildes, struct stat *buf) { XrdPosixFile *fp; - long long theSize; + int rc; // Find the file object // @@ -306,40 +306,21 @@ int XrdPosixXrootd::Fstat(int fildes, struct stat *buf) // Check if we can get the stat information from the cache. // - if (myCache2) - {int rc = myCache2->Stat(fp->Path(), *buf); - if (rc <= 0) - {fp->UnLock(); - if (!rc) return 0; - errno = -rc; - return -1; - } - } - -// We need to trat getting the size separately as this file may still not be -// open. This gets resolved via the cache layer. -// - theSize = fp->XCio->FSize(); - if (theSize < 0) + rc = fp->XCio->Fstat(*buf); + if (rc <= 0) {fp->UnLock(); - errno = static_cast(-theSize); + if (!rc) return 0; + errno = -rc; return -1; } - -// Return what little we can -// - buf->st_size = theSize; - buf->st_atime = buf->st_mtime = buf->st_ctime = fp->myMtime; - buf->st_blocks = buf->st_size/512+1; - buf->st_ino = fp->myInode; - buf->st_rdev = fp->myRdev; - buf->st_mode = fp->myMode; - -// All done +// At this point we can call the file's Fstat() and if the file is not open +// it will be opened. // + rc = fp->Fstat(*buf); fp->UnLock(); - return 0; + if (rc < 0) {errno = -rc; rc = -1;} + return rc; } /******************************************************************************/ @@ -445,13 +426,17 @@ off_t XrdPosixXrootd::Lseek(int fildes, off_t offset, int whence) // if (!(fp = XrdPosixObject::File(fildes))) return -1; -// Set the new offset +// Set the new offset. Note that SEEK_END requires that the file be opened. +// An open may occur by calling the FSize() method via the cache pointer. // - if (whence == SEEK_SET) curroffset = fp->setOffset(offset); - else if (whence == SEEK_CUR) curroffset = fp->addOffset(offset); - else if (whence == SEEK_END) - curroffset = fp->setOffset(fp->FSize()+offset); - else return Fault(fp, EINVAL); + if (whence == SEEK_SET) curroffset = fp->setOffset(offset); + else if (whence == SEEK_CUR) curroffset = fp->addOffset(offset); + else if (whence == SEEK_END) + {curroffset = fp->XCio->FSize(); + if (curroffset < 0) return Fault(fp,static_cast(-curroffset)); + curroffset = fp->setOffset(curroffset+offset); + } + else return Fault(fp, EINVAL); // All done // @@ -1395,7 +1380,7 @@ void XrdPosixXrootd::initEnv(char *eData) myParms.Options |= XrdOucCache::Serialized; if (!(v1Cache = myCache->Create(myParms, &apParms))) cerr <<"XrdPosix: " <