XrdOssMio.cc

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /*                                                                            */
00003 /*                          X r d O s s M i o . c c                           */
00004 /*                                                                            */
00005 /* (c) 2005 by the Board of Trustees of the Leland Stanford, Jr., University  */
00006 /*                            All Rights Reserved                             */
00007 /*   Produced by Andrew Hanushevsky for Stanford University under contract    */
00008 /*              DE-AC02-76-SFO0515 with the Department of Energy              */
00009 /******************************************************************************/
00010 
00011 //         $Id: XrdOssMio.cc 30949 2009-11-02 16:37:58Z ganis $
00012 
00013 const char *XrdOssMioCVSID = "$Id: XrdOssMio.cc 30949 2009-11-02 16:37:58Z ganis $";
00014   
00015 #include <unistd.h>
00016 #include <stdio.h>
00017 #include <sys/param.h>
00018 #include <sys/types.h>
00019 #include <sys/stat.h>
00020 
00021 #if defined(_POSIX_MAPPED_FILES)
00022 #include <sys/mman.h>
00023 #endif
00024 
00025 #include "XrdSys/XrdSysPthread.hh"
00026 #include "XrdOss/XrdOssMio.hh"
00027 #include "XrdOss/XrdOssMioFile.hh"
00028 #include "XrdOss/XrdOssTrace.hh"
00029 
00030 /******************************************************************************/
00031 /*                      S t a t i c   V a r i a b l e s                       */
00032 /******************************************************************************/
00033 
00034 XrdOucHash<XrdOssMioFile> XrdOssMio::MM_Hash;
00035 
00036 XrdSysMutex    XrdOssMio::MM_Mutex;
00037 
00038 XrdOssMioFile *XrdOssMio::MM_Perm     = 0;
00039 XrdOssMioFile *XrdOssMio::MM_Idle     = 0;
00040 XrdOssMioFile *XrdOssMio::MM_IdleLast = 0;
00041 
00042 char           XrdOssMio::MM_on       = 1;
00043 char           XrdOssMio::MM_chkmap   = 0;
00044 char           XrdOssMio::MM_chklok   = 0;
00045 char           XrdOssMio::MM_chkkeep  = 0;
00046 char           XrdOssMio::MM_chk      = 0;
00047 char           XrdOssMio::MM_okmlock  = 1;
00048 char           XrdOssMio::MM_preld    = 0;
00049 long long      XrdOssMio::MM_pagsz    = (long long)sysconf(_SC_PAGESIZE);
00050 #ifdef __macos__
00051 long long      XrdOssMio::MM_pages    = 1024*1024*1024;
00052 #else
00053 long long      XrdOssMio::MM_pages    = (long long)sysconf(_SC_PHYS_PAGES);
00054 #endif
00055 long long      XrdOssMio::MM_max      = MM_pagsz*MM_pages/2;
00056 long long      XrdOssMio::MM_inuse    = 0;
00057 
00058 extern XrdSysError OssEroute;
00059 
00060 extern XrdOucTrace OssTrace;
00061   
00062 /******************************************************************************/
00063 /*                               D i s p l a y                                */
00064 /******************************************************************************/
00065 
00066 void XrdOssMio::Display(XrdSysError &Eroute)
00067 {
00068      char buff[1080];
00069      snprintf(buff, sizeof(buff), "       oss.memfile %s%s%s%s%s max %lld",
00070              (MM_on      ? ""            : "off "),
00071              (MM_preld   ? "preload"     : ""),
00072              (MM_chklok  ? "check lock " : ""),
00073              (MM_chkmap  ? "check map "  : ""),
00074              (MM_chkkeep ? "check keep"  : ""), MM_max);
00075      Eroute.Say(buff);
00076 }
00077 
00078 /******************************************************************************/
00079 /*                               g e t O p t s                                */
00080 /******************************************************************************/
00081   
00082 int XrdOssMio::getOpts(char *path, int popts)
00083 {
00084     struct stat statb;
00085     char buff[MAXPATHLEN+16], *bsfx = buff+strlen(path);
00086 
00087 // Generate new options, as needed
00088 //
00089    if (MM_chklok && !(popts & OSSMIO_MLOK))
00090       {strcpy(bsfx, ".mlock");
00091        if (!stat(buff, &statb)) popts |= OSSMIO_MLOK;
00092       }
00093       else if (MM_chkmap && !(popts & OSSMIO_MMAP))
00094               {strcpy(bsfx, ".mmap");
00095                if (!stat(buff, &statb)) popts |= OSSMIO_MMAP;
00096               }
00097       if (MM_chkkeep && !(popts & OSSMIO_MPRM))
00098               {strcpy(bsfx, ".mkeep");
00099                if (!stat(buff, &statb)) popts |= OSSMIO_MPRM;
00100               }
00101 
00102    return popts;
00103 }
00104 
00105 /******************************************************************************/
00106 /*                                   M a p                                    */
00107 /******************************************************************************/
00108   
00109 XrdOssMioFile *XrdOssMio::Map(char *path, int fd, int opts)
00110 {
00111 #if defined(_POSIX_MAPPED_FILES)
00112    EPNAME("MioMap");
00113    XrdSysMutexHelper mapMutex;
00114    struct stat statb;
00115    XrdOssMioFile *mp;
00116    void *thefile;
00117    char hashname[64];
00118 
00119 // Get the size of the file
00120 //
00121    if (fstat(fd, &statb))
00122       {OssEroute.Emsg("Mio", errno, "fstat file", path);
00123        return 0;
00124       }
00125 
00126 // Develop hash name for this file
00127 //
00128    XrdOucTrace::bin2hex((char *)&statb.st_dev,
00129                          int(sizeof(statb.st_dev)), hashname);
00130    XrdOucTrace::bin2hex((char *)&statb.st_ino, int(sizeof(statb.st_ino)),
00131                                          hashname+(sizeof(statb.st_dev)*2));
00132 
00133 // Because of potntial race conditions, we must serialize execution
00134 //
00135    mapMutex.Lock(&MM_Mutex);
00136 
00137 // Check if we already have this mapping
00138 //
00139    if ((mp = MM_Hash.Find(hashname)))
00140       {DEBUG("Reusing mmap; usecnt=" <<mp->inUse <<" path=" <<path);
00141        if (!(mp->Status & OSSMIO_MPRM) && !mp->inUse) Reclaim(mp);
00142        mp->inUse++;
00143        return mp;
00144       }
00145 
00146 // Check if memory will be over committed
00147 //
00148    if (MM_inuse + statb.st_size > MM_max)
00149       {if (!Reclaim(statb.st_size))
00150           {OssEroute.Emsg("Mio", "Unable to reclaim enough storage to mmap",path);
00151            return 0;
00152           }
00153       }
00154    MM_inuse += statb.st_size;
00155 
00156 // Memory map the file
00157 //
00158    if ((thefile = mmap(0,statb.st_size,PROT_READ,MAP_PRIVATE,fd,0))==MAP_FAILED)
00159       {OssEroute.Emsg("Mio", errno, "mmap file", path);
00160        return 0;
00161       } else {DEBUG("mmap " <<statb.st_size <<" bytes for " <<path);}
00162 
00163 // Lock the file, if need be. Turn off locking if we don't have privs
00164 //
00165    if (MM_okmlock && (opts & OSSMIO_MLOK))
00166       {if (mlock((char *)thefile, statb.st_size))
00167           {     if (errno == ENOSYS)
00168                    {OssEroute.Emsg("Mio","mlock() not supported; feature disabled.");
00169                     MM_okmlock = 0;
00170                    }
00171            else if (errno == EPERM)
00172                    {OssEroute.Emsg("Mio","Not privileged for mlock(); feature disabled.");
00173                     MM_okmlock = 0;
00174                    }
00175            else  OssEroute.Emsg("Mio", errno, "mlock file", path);
00176           } else {DEBUG("Locked " <<statb.st_size <<" bytes for " <<path);}
00177       }
00178 
00179 // get a new file object
00180 //
00181    if (!(mp = new XrdOssMioFile(hashname)))
00182       {OssEroute.Emsg("Mio", "Unable to allocate mmap file object for", path);
00183        munmap((char *)thefile, statb.st_size);
00184        return 0;
00185       }
00186 
00187 // Complete the object here
00188 //
00189    mp->Base   = thefile;
00190    mp->Size   = statb.st_size;
00191    mp->Dev    = statb.st_dev;
00192    mp->Ino    = statb.st_ino;
00193    mp->Status = opts;
00194 
00195 // Add the mapping to our hash table
00196 //
00197    if (MM_Hash.Add(hashname, mp))
00198       {OssEroute.Emsg("Mio", "Hash add failed for", path);
00199        munmap((char *)thefile, statb.st_size);
00200        delete mp;
00201        return 0;
00202       }
00203 
00204 // If this is a permanent file, place it on the permanent queue
00205 //
00206    if (opts & OSSMIO_MPRM)
00207       {mp->Next = MM_Perm; MM_Perm = mp;
00208        DEBUG("Placed file on permanent queue " <<path);
00209       }
00210 
00211 // If this file is to be preloaded, start it now
00212 //
00213    if (MM_preld && mp->inUse == 1)
00214       {pthread_t tid;
00215        int retc;
00216        mp->inUse++;
00217        if ((retc = XrdSysThread::Run(&tid, preLoad, (void *)mp)) < 0)
00218           {OssEroute.Emsg("Mio", retc, "creating mmap preload thread");
00219            mp->inUse--;
00220           }
00221           else DEBUG("started mmap preload thread; tid=" <<(unsigned long)tid);
00222       }
00223 
00224 // All done
00225 //
00226    return mp;
00227 #else
00228    return 0;
00229 #endif
00230 }
00231 
00232 /******************************************************************************/
00233 /*                               p r e L o a d                                */
00234 /******************************************************************************/
00235   
00236 void *XrdOssMio::preLoad(void *arg)
00237 {
00238    XrdOssMioFile *mp = (XrdOssMioFile *)arg;
00239    char *Base = (char *)(mp->Base);
00240    char *Bend = Base + mp->Size;
00241    char  Byte;
00242 
00243 // Reference each page until we are done
00244 //
00245    while(Base < Bend) {Byte = *Base; Base += MM_pagsz;}
00246 
00247 // All done
00248 //
00249    Recycle(mp);
00250    return (void *)0;
00251 }
00252 
00253 /******************************************************************************/
00254 /*                               R e c l a i m                                */
00255 /******************************************************************************/
00256   
00257 // Reclaim() can only be called if the caller has the MM_Mutex lock!
00258 //
00259 int XrdOssMio::Reclaim(off_t amount)
00260 {
00261    EPNAME("MioReclaim");
00262    XrdOssMioFile *mp;
00263    DEBUG("Trying to reclaim " <<amount <<" bytes.");
00264 
00265 // Try to reclaim memory
00266 //
00267    while((mp = MM_Idle) && amount > 0)
00268         {MM_Idle = mp->Next;
00269          MM_inuse -= mp->Size;
00270          amount   -= mp->Size;
00271          MM_Hash.Del(mp->HashName);  // This will delete the object
00272         }
00273 
00274 // Indicate whether we cleared enough
00275 //
00276    return amount <= 0;
00277 }
00278 
00279 /******************************************************************************/
00280 
00281 int XrdOssMio::Reclaim(XrdOssMioFile *mp)
00282 {
00283    EPNAME("MioReclaim");
00284    XrdOssMioFile *pmp = 0, *cmp = MM_Idle;
00285 
00286 // Try to find the mapping
00287 //
00288    while(cmp && mp != cmp) {pmp = cmp; cmp = cmp->Next;}
00289 
00290 // Remove mapping from the idle list
00291 //
00292    if (cmp)
00293       {if (pmp) pmp->Next = mp->Next;
00294           else  MM_Idle   = mp->Next;
00295        if (MM_IdleLast == cmp) MM_IdleLast = pmp;
00296       }
00297       else {DEBUG("Cannot find mapping for " <<mp->Dev <<':' <<mp->Ino);}
00298 
00299    return (cmp != 0);
00300 }
00301  
00302 /******************************************************************************/
00303 /*                               R e c y c l e                                */
00304 /******************************************************************************/
00305   
00306 void XrdOssMio::Recycle(XrdOssMioFile *mp)
00307 {
00308    XrdSysMutexHelper mmMutex(&MM_Mutex);
00309 
00310 // Decrement the use count
00311 //
00312    mp->inUse--;
00313    if (mp->inUse < 0)
00314       {OssEroute.Emsg("Mio", "MM usecount underflow for ", mp->HashName);
00315        mp->inUse = 0;
00316       } else if (mp->inUse > 0) return;
00317 
00318 // If this is not a kept mapping, put it on the reclaim list
00319 //
00320    if (!(mp->Status & OSSMIO_MPRM))
00321       {if (MM_IdleLast) MM_IdleLast->Next = mp;
00322           else MM_Idle = mp;
00323        MM_IdleLast = mp;
00324        mp->Next = 0;
00325       }
00326 }
00327   
00328 /******************************************************************************/
00329 /*                                   S e t                                    */
00330 /******************************************************************************/
00331   
00332 void XrdOssMio::Set(int V_on, int V_preld,  int V_chklok,
00333                               int V_chkmap, int V_chkkeep)
00334 {
00335    if (V_on      >= 0) MM_on      = (char)V_on;
00336    if (V_preld   >= 0) MM_preld   = (char)V_preld;
00337    if (V_chklok  >= 0) MM_chklok  = (char)V_chklok;
00338    if (V_chkmap  >= 0) MM_chkmap  = (char)V_chkmap;
00339    if (V_chkkeep >= 0) MM_chkkeep = (char)V_chkkeep;
00340    MM_chk = MM_chklok | MM_chkmap | MM_chkkeep;
00341 }
00342 
00343 void XrdOssMio::Set(long long V_max)
00344 {
00345    if (V_max > 0) MM_max = V_max;
00346       else if (V_max < 0) MM_max = MM_pagsz*MM_pages*(-V_max)/100;
00347 }
00348  
00349 /******************************************************************************/
00350 /*             X r d O s s d M i o F i l e   D e s t r u c t o r              */
00351 /******************************************************************************/
00352   
00353 XrdOssMioFile::~XrdOssMioFile()
00354 {
00355 #if defined(_POSIX_MAPPED_FILES)
00356     munmap((char *)Base, Size);
00357 #endif
00358 }

Generated on Tue Jul 5 14:46:47 2011 for ROOT_528-00b_version by  doxygen 1.5.1