00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifdef WIN32
00012 #pragma optimize("",off)
00013 #endif
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 #ifdef WIN32
00060 # include <windows.h>
00061 # include <process.h>
00062 # ifdef GetObject
00063 # undef GetObject
00064 # endif
00065 # define HAVE_SEMOP
00066
00067 # ifdef CreateSemaphore
00068 # undef CreateSemaphore
00069 # endif
00070
00071 # ifdef AcquireSemaphore
00072 # undef AcquireSemaphore;
00073 # endif
00074
00075 # ifdef ReleaseSemaphore
00076 # undef ReleaseSemaphore
00077 # endif
00078
00079 # ifdef DeleteSemaphore
00080 # undef DeleteSemaphore
00081 # endif
00082
00083 #else
00084 # define INVALID_HANDLE_VALUE -1
00085 #endif
00086
00087 #include <fcntl.h>
00088 #include <errno.h>
00089
00090 #include "TMapFile.h"
00091 #include "TKeyMapFile.h"
00092 #include "TDirectoryFile.h"
00093 #include "TBrowser.h"
00094 #include "TString.h"
00095 #include "TSystem.h"
00096 #include "TClass.h"
00097 #include "TBufferFile.h"
00098 #include "TVirtualMutex.h"
00099 #include <cmath>
00100
00101 #if defined(R__UNIX) && !defined(R__MACOSX) && !defined(R__WINGCC)
00102 #define HAVE_SEMOP
00103 #include <sys/types.h>
00104 #include <sys/ipc.h>
00105 #include <sys/sem.h>
00106 #if defined(R__HPUX) || (defined (R__ALPHA) && !defined(R__FBSD)) || \
00107 defined (R__SOLARIS) || defined(R__AIX) || defined(R__HIUX) || \
00108 __GLIBC_MINOR__ > 0
00109 union semun {
00110 int val;
00111 struct semid_ds *buf;
00112 ushort *array;
00113 };
00114 #endif
00115 #if defined(R__LINUX) || defined(R__LYNXOS) || defined(R__HURD)
00116 # define SEM_A 0200 // alter permission
00117 # define SEM_R 0400 // read permission
00118 #endif
00119 #endif
00120
00121
00122 Long_t TMapFile::fgMapAddress = 0;
00123 void *TMapFile::fgMmallocDesc = 0;
00124
00125
00126
00127
00128
00129
00130 TMapRec::TMapRec(const char *name, const TObject *obj, Int_t size, void *buf)
00131 {
00132
00133 fName = StrDup(name);
00134 fClassName = 0;
00135 fObject = (TObject*)obj;
00136 fBuffer = buf;
00137 fBufSize = size;
00138 fNext = 0;
00139 }
00140
00141
00142 TMapRec::~TMapRec()
00143 {
00144
00145 delete [] fName;
00146 delete [] fClassName;
00147 }
00148
00149
00150 TObject *TMapRec::GetObject() const
00151 {
00152
00153
00154
00155
00156 return fObject;
00157 }
00158
00159
00160
00161
00162 ClassImp(TMapFile)
00163
00164
00165 TMapFile::TMapFile()
00166 {
00167
00168
00169 fFd = -1;
00170 fVersion = 0;
00171 fName = 0;
00172 fTitle = 0;
00173 fOption = 0;
00174 fMmallocDesc = 0;
00175 fBaseAddr = 0;
00176 fSize = 0;
00177 fFirst = 0;
00178 fLast = 0;
00179 fOffset = 0;
00180 fDirectory = 0;
00181 fBrowseList = 0;
00182 fWritable = kFALSE;
00183 fSemaphore = -1;
00184 fhSemaphore = 0;
00185 fGetting = 0;
00186 fWritten = 0;
00187 fSumBuffer = 0;
00188 fSum2Buffer = 0;
00189 }
00190
00191
00192 TMapFile::TMapFile(const char *name, const char *title, Option_t *option,
00193 Int_t size, TMapFile *&newMapFile)
00194 {
00195
00196
00197
00198
00199
00200
00201
00202 #ifndef WIN32
00203 fFd = -1;
00204 fSemaphore = -1;
00205 fhSemaphore = 0;
00206 #else
00207 fFd = (Int_t) INVALID_HANDLE_VALUE;
00208 fSemaphore = (Int_t) INVALID_HANDLE_VALUE;
00209 #endif
00210 fMmallocDesc = 0;
00211 fSize = size;
00212 fFirst = 0;
00213 fOffset = 0;
00214 fVersion = gROOT->GetVersionInt();
00215 fTitle = StrDup(title);
00216 fOption = StrDup(option);
00217 fDirectory = 0;
00218 fBrowseList = 0;
00219 fGetting = 0;
00220 fWritten = 0;
00221 fSumBuffer = 0;
00222 fSum2Buffer = 0;
00223
00224 char *cleanup = 0;
00225 Bool_t create = kFALSE;
00226 Bool_t recreate, update, read;
00227
00228 {
00229 TString opt = option;
00230
00231 if (!opt.CompareTo("NEW", TString::kIgnoreCase) ||
00232 !opt.CompareTo("CREATE", TString::kIgnoreCase))
00233 create = kTRUE;
00234 recreate = opt.CompareTo("RECREATE", TString::kIgnoreCase)
00235 ? kFALSE : kTRUE;
00236 update = opt.CompareTo("UPDATE", TString::kIgnoreCase)
00237 ? kFALSE : kTRUE;
00238 read = opt.CompareTo("READ", TString::kIgnoreCase)
00239 ? kFALSE : kTRUE;
00240 if (!create && !recreate && !update && !read) {
00241 read = kTRUE;
00242 delete [] fOption;
00243 fOption = StrDup("READ");
00244 }
00245 }
00246
00247 const char *fname;
00248 if ((fname = gSystem->ExpandPathName(name))) {
00249 fName = StrDup(fname);
00250 delete [] (char*)fname;
00251 fname = fName;
00252 } else {
00253 Error("TMapFile", "error expanding path %s", fname);
00254 goto zombie;
00255 }
00256
00257 if (recreate) {
00258 if (!gSystem->AccessPathName(fname, kFileExists))
00259 gSystem->Unlink(fname);
00260 recreate = kFALSE;
00261 create = kTRUE;
00262 delete [] fOption;
00263 fOption = StrDup("CREATE");
00264 }
00265 if (create && !gSystem->AccessPathName(fname, kFileExists)) {
00266 Error("TMapFile", "file %s already exists", fname);
00267 goto zombie;
00268 }
00269 if (update) {
00270 if (gSystem->AccessPathName(fname, kFileExists)) {
00271 update = kFALSE;
00272 create = kTRUE;
00273 }
00274 if (update && gSystem->AccessPathName(fname, kWritePermission)) {
00275 Error("TMapFile", "no write permission, could not open file %s", fname);
00276 goto zombie;
00277 }
00278 }
00279 if (read) {
00280 if (gSystem->AccessPathName(fname, kFileExists)) {
00281 Error("TMapFile", "file %s does not exist", fname);
00282 goto zombie;
00283 }
00284 if (gSystem->AccessPathName(fname, kReadPermission)) {
00285 Error("TMapFile", "no read permission, could not open file %s", fname);
00286 goto zombie;
00287 }
00288 }
00289
00290
00291 if (create || update) {
00292 #ifndef WIN32
00293 fFd = open(fname, O_RDWR | O_CREAT, 0644);
00294 #else
00295 fFd = (Int_t) CreateFile(fname,
00296 GENERIC_WRITE | GENERIC_READ,
00297 FILE_SHARE_WRITE | FILE_SHARE_READ,
00298 NULL,
00299 OPEN_ALWAYS,
00300 FILE_ATTRIBUTE_TEMPORARY,
00301 (HANDLE) NULL);
00302 #endif
00303 if (fFd == (Int_t)INVALID_HANDLE_VALUE) {
00304 SysError("TMapFile", "file %s can not be opened", fname);
00305 goto zombie;
00306 }
00307 fWritable = kTRUE;
00308 } else {
00309 #ifndef WIN32
00310 fFd = open(fname, O_RDONLY);
00311 #else
00312 fFd = (Int_t) CreateFile(fname,
00313 GENERIC_READ,
00314 FILE_SHARE_WRITE | FILE_SHARE_READ,
00315 NULL,
00316 OPEN_EXISTING,
00317 FILE_ATTRIBUTE_TEMPORARY,
00318 (HANDLE) NULL);
00319 #endif
00320 if (fFd == (Int_t)INVALID_HANDLE_VALUE) {
00321 SysError("TMapFile", "file %s can not be opened for reading", fname);
00322 goto zombie;
00323 }
00324 fWritable = kFALSE;
00325 }
00326
00327
00328 void *mapto;
00329 TMapFile *mapfil;
00330
00331 if (((mapto = MapToAddress()) == (void *)-1) ||
00332 #ifndef WIN32
00333 ((fMmallocDesc = mmalloc_attach(fFd, mapto, fSize)) == 0)) {
00334 #else
00335 ((fMmallocDesc = mmalloc_attach((HANDLE) fFd, mapto, fSize)) == 0)) {
00336 #endif
00337
00338 if (mapto == (void *)-1) {
00339 Error("TMapFile", "no memory mapped file capability available\n"
00340 "Use rootn.exe or link application against \"-lNew\"");
00341 } else {
00342 if (fMmallocDesc == 0 && fWritable)
00343 Error("TMapFile", "mapped file not in mmalloc format or\n"
00344 "already open in RW mode by another process");
00345 if (fMmallocDesc == 0 && !fWritable)
00346 Error("TMapFile", "mapped file not in mmalloc format");
00347 }
00348 #ifndef WIN32
00349 close(fFd);
00350 #else
00351 CloseHandle((HANDLE) fFd);
00352 #endif
00353 fFd = -1;
00354 if (create)
00355 gSystem->Unlink(fname);
00356 goto zombie;
00357
00358 } else if ((mapfil = (TMapFile *) mmalloc_getkey(fMmallocDesc, 0)) != 0) {
00359
00360
00361
00362
00363
00364
00365 if (mapfil->fVersion != fVersion) {
00366 Error("TMapFile", "map file %s (%d) incompatible with current ROOT version (%d)",
00367 fname, mapfil->fVersion, fVersion);
00368 mmalloc_detach(fMmallocDesc);
00369 #ifndef WIN32
00370 close(fFd);
00371 #else
00372 CloseHandle((HANDLE) fFd);
00373 #endif
00374 fFd = -1;
00375 fMmallocDesc = 0;
00376 goto zombie;
00377 }
00378
00379 if (mapfil->fWritable && fWritable) {
00380 Warning("TMapFile", "map file already open in write mode, opening in read-only mode");
00381 fWritable = kFALSE;
00382 }
00383
00384 fBaseAddr = mapfil->fBaseAddr;
00385 fSize = mapfil->fSize;
00386
00387 if (fWritable) {
00388
00389 CreateSemaphore();
00390 gMmallocDesc = fMmallocDesc;
00391 TMapFile *mf = new TMapFile(*mapfil);
00392 mf->fFd = fFd;
00393 mf->fWritable = kTRUE;
00394 cleanup = mf->fOption;
00395 mf->fOption = StrDup(fOption);
00396 mf->fSemaphore = fSemaphore;
00397 #ifdef WIN32
00398 mf->CreateSemaphore(fSemaphore);
00399 #endif
00400 mmalloc_setkey(fMmallocDesc, 0, mf);
00401 gMmallocDesc = 0;
00402 mapfil = mf;
00403 } else {
00404 gMmallocDesc = 0;
00405 fOffset = ((struct mdesc *) fMmallocDesc)->offset;
00406 TMapFile *mf = new TMapFile(*mapfil, fOffset);
00407 delete [] mf->fOption;
00408 mf->fFd = fFd;
00409 mf->fOption = StrDup("READ");
00410 mf->fMmallocDesc = fMmallocDesc;
00411 mf->fWritable = kFALSE;
00412 mapfil = mf;
00413 }
00414
00415
00416
00417 fVersion = -1;
00418 R__LOCKGUARD2(gROOTMutex);
00419 gROOT->GetListOfMappedFiles()->AddLast(this);
00420
00421 } else {
00422
00423
00424
00425 if (!fWritable) {
00426 Error("TMapFile", "map file is not writable");
00427 mmalloc_detach(fMmallocDesc);
00428 #ifndef WIN32
00429 close(fFd);
00430 #else
00431 CloseHandle((HANDLE) fFd);
00432 #endif
00433 fFd = -1;
00434 fMmallocDesc = 0;
00435 goto zombie;
00436 }
00437
00438 fBaseAddr = (ULong_t)((struct mdesc *) fMmallocDesc)->base;
00439
00440 CreateSemaphore();
00441
00442 gMmallocDesc = fMmallocDesc;
00443
00444 mapfil = new TMapFile(*this);
00445 mmalloc_setkey(fMmallocDesc, 0, mapfil);
00446
00447 gMmallocDesc = 0;
00448
00449
00450 fVersion = -1;
00451 R__LOCKGUARD2(gROOTMutex);
00452 gROOT->GetListOfMappedFiles()->AddLast(this);
00453
00454 }
00455
00456 mapfil->InitDirectory();
00457 {
00458 R__LOCKGUARD2(gROOTMutex);
00459 gROOT->GetListOfMappedFiles()->AddFirst(mapfil);
00460 }
00461
00462 if (cleanup) delete [] cleanup;
00463
00464 newMapFile = mapfil;
00465
00466 return;
00467
00468 zombie:
00469
00470 MakeZombie();
00471 newMapFile = this;
00472 gMmallocDesc = 0;
00473 }
00474
00475
00476 TMapFile::TMapFile(const TMapFile &f, Long_t offset) : TObject(f)
00477 {
00478
00479
00480
00481
00482 fFd = f.fFd;
00483 fVersion = f.fVersion;
00484 fName = StrDup((char *)((long)f.fName + offset));
00485 fTitle = StrDup((char *)((long)f.fTitle + offset));
00486 fOption = StrDup((char *)((long)f.fOption + offset));
00487 fMmallocDesc = f.fMmallocDesc;
00488 fBaseAddr = f.fBaseAddr;
00489 fSize = f.fSize;
00490 fFirst = f.fFirst;
00491 fLast = f.fLast;
00492 fWritable = f.fWritable;
00493 fSemaphore = f.fSemaphore;
00494 fOffset = offset;
00495 fDirectory = 0;
00496 fBrowseList = 0;
00497 fGetting = 0;
00498 fWritten = f.fWritten;
00499 fSumBuffer = f.fSumBuffer;
00500 fSum2Buffer = f.fSum2Buffer;
00501 #ifdef WIN32
00502 CreateSemaphore(fSemaphore);
00503 #else
00504 fhSemaphore = f.fhSemaphore;
00505 #endif
00506 }
00507
00508
00509 TMapFile::~TMapFile()
00510 {
00511
00512
00513
00514
00515
00516 if (fDirectory == gDirectory) gDirectory = gROOT;
00517 delete fDirectory; fDirectory = 0;
00518 if (fBrowseList) fBrowseList->Delete();
00519 delete fBrowseList; fBrowseList = 0;
00520
00521
00522 if (fVersion == -1)
00523 return;
00524
00525
00526
00527
00528 if (fWritable)
00529 TObject::SetDtorOnly(this);
00530
00531 Close("dtor");
00532
00533 fgMmallocDesc = fMmallocDesc;
00534 }
00535
00536
00537 void TMapFile::InitDirectory()
00538 {
00539
00540
00541 gDirectory = 0;
00542 fDirectory = new TDirectoryFile();
00543 fDirectory->SetName(GetName());
00544 fDirectory->SetTitle(GetTitle());
00545 fDirectory->Build();
00546 fDirectory->SetMother(this);
00547 gDirectory = fDirectory;
00548 }
00549
00550
00551 void TMapFile::Add(const TObject *obj, const char *name)
00552 {
00553
00554
00555
00556 if (!fWritable || !fMmallocDesc) return;
00557
00558 Bool_t lock = fGetting != obj ? kTRUE : kFALSE;
00559
00560 if (lock)
00561 AcquireSemaphore();
00562
00563 gMmallocDesc = fMmallocDesc;
00564
00565 const char *n;
00566 if (name && *name)
00567 n = name;
00568 else
00569 n = obj->GetName();
00570
00571 if (Remove(n, kFALSE)) {
00572
00573 }
00574
00575 TMapRec *mr = new TMapRec(n, obj, 0, 0);
00576 if (!fFirst) {
00577 fFirst = mr;
00578 fLast = mr;
00579 } else {
00580 fLast->fNext = mr;
00581 fLast = mr;
00582 }
00583
00584 gMmallocDesc = 0;
00585
00586 if (lock)
00587 ReleaseSemaphore();
00588 }
00589
00590
00591 void TMapFile::Update(TObject *obj)
00592 {
00593
00594
00595 if (!fWritable || !fMmallocDesc) return;
00596
00597 AcquireSemaphore();
00598
00599 gMmallocDesc = fMmallocDesc;
00600
00601 Bool_t all = (obj == 0) ? kTRUE : kFALSE;
00602
00603 TMapRec *mr = fFirst;
00604 while (mr) {
00605 if (all || mr->fObject == obj) {
00606 TBufferFile *b;
00607 if (!mr->fBufSize) {
00608 b = new TBufferFile(TBuffer::kWrite, GetBestBuffer());
00609 mr->fClassName = StrDup(mr->fObject->ClassName());
00610 } else
00611 b = new TBufferFile(TBuffer::kWrite, mr->fBufSize, mr->fBuffer);
00612 b->MapObject(mr->fObject);
00613 mr->fObject->Streamer(*b);
00614 mr->fBufSize = b->BufferSize();
00615 mr->fBuffer = b->Buffer();
00616 SumBuffer(b->Length());
00617 b->DetachBuffer();
00618 delete b;
00619 }
00620 mr = mr->fNext;
00621 }
00622
00623 gMmallocDesc = 0;
00624
00625 ReleaseSemaphore();
00626 }
00627
00628
00629 TObject *TMapFile::Remove(TObject *obj, Bool_t lock)
00630 {
00631
00632
00633
00634 if (!fWritable || !fMmallocDesc) return 0;
00635
00636 if (lock)
00637 AcquireSemaphore();
00638
00639 TObject *retObj = 0;
00640 TMapRec *prev = 0, *mr = fFirst;
00641 while (mr) {
00642 if (mr->fObject == obj) {
00643 if (mr == fFirst) {
00644 fFirst = mr->fNext;
00645 if (mr == fLast)
00646 fLast = 0;
00647 } else {
00648 prev->fNext = mr->fNext;
00649 if (mr == fLast)
00650 fLast = prev;
00651 }
00652 retObj = obj;
00653 delete mr;
00654 break;
00655 }
00656 prev = mr;
00657 mr = mr->fNext;
00658 }
00659
00660 if (lock)
00661 ReleaseSemaphore();
00662
00663 return retObj;
00664 }
00665
00666
00667 TObject *TMapFile::Remove(const char *name, Bool_t lock)
00668 {
00669
00670
00671
00672 if (!fWritable || !fMmallocDesc) return 0;
00673
00674 if (lock)
00675 AcquireSemaphore();
00676
00677 TObject *retObj = 0;
00678 TMapRec *prev = 0, *mr = fFirst;
00679 while (mr) {
00680 if (!strcmp(mr->fName, name)) {
00681 if (mr == fFirst) {
00682 fFirst = mr->fNext;
00683 if (mr == fLast)
00684 fLast = 0;
00685 } else {
00686 prev->fNext = mr->fNext;
00687 if (mr == fLast)
00688 fLast = prev;
00689 }
00690 retObj = mr->fObject;
00691 delete mr;
00692 break;
00693 }
00694 prev = mr;
00695 mr = mr->fNext;
00696 }
00697
00698 if (lock)
00699 ReleaseSemaphore();
00700
00701 return retObj;
00702 }
00703
00704
00705 void TMapFile::RemoveAll()
00706 {
00707
00708
00709 if (!fWritable || !fMmallocDesc) return;
00710
00711 AcquireSemaphore();
00712
00713 TMapRec *mr = fFirst;
00714 while (mr) {
00715 TMapRec *t = mr;
00716 mr = mr->fNext;
00717 delete t;
00718 }
00719 fFirst = fLast = 0;
00720
00721 ReleaseSemaphore();
00722 }
00723
00724
00725 TObject *TMapFile::Get(const char *name, TObject *delObj)
00726 {
00727
00728
00729
00730
00731
00732 if (!fMmallocDesc) return 0;
00733
00734 AcquireSemaphore();
00735
00736 delete delObj;
00737
00738 TObject *obj = 0;
00739 TMapRec *mr = GetFirst();
00740 while (OrgAddress(mr)) {
00741 if (!strcmp(mr->GetName(fOffset), name)) {
00742 if (!mr->fBufSize) goto release;
00743 TClass *cl = TClass::GetClass(mr->GetClassName(fOffset));
00744 if (!cl) {
00745 Error("Get", "unknown class %s", mr->GetClassName(fOffset));
00746 goto release;
00747 }
00748
00749 obj = (TObject *)cl->New();
00750 if (!obj) {
00751 Error("Get", "cannot create new object of class %s", mr->GetClassName(fOffset));
00752 goto release;
00753 }
00754
00755 fGetting = obj;
00756 TBufferFile *b = new TBufferFile(TBuffer::kRead, mr->fBufSize, mr->GetBuffer(fOffset));
00757 b->MapObject(obj);
00758 obj->Streamer(*b);
00759 b->DetachBuffer();
00760 delete b;
00761 fGetting = 0;
00762 goto release;
00763 }
00764 mr = mr->GetNext(fOffset);
00765 }
00766
00767 release:
00768 ReleaseSemaphore();
00769
00770 return obj;
00771 }
00772
00773
00774 #ifndef WIN32
00775 void TMapFile::CreateSemaphore(int)
00776 #else
00777 void TMapFile::CreateSemaphore(int pid)
00778 #endif
00779 {
00780
00781
00782 #ifdef HAVE_SEMOP
00783 #ifndef WIN32
00784
00785 fSemaphore = semget(IPC_PRIVATE, 1, SEM_R|SEM_A|(SEM_R>>3)|(SEM_A>>3)|
00786 (SEM_R>>6)|(SEM_A>>6));
00787
00788
00789 if (fSemaphore != -1) {
00790 union semun set;
00791 set.val = 1;
00792 semctl(fSemaphore, 0, SETVAL, set);
00793 }
00794 #else
00795 char buffer[] ="ROOT_Semaphore_xxxxxxxx";
00796 int lbuf = strlen(buffer);
00797 if (!pid) fSemaphore = getpid();
00798 fhSemaphore = (ULong_t)CreateMutex(NULL,FALSE,itoa(fSemaphore,&buffer[lbuf-8],16));
00799 if (fhSemaphore == 0) fSemaphore = (Int_t)INVALID_HANDLE_VALUE;
00800 #endif
00801 #endif
00802 }
00803
00804
00805 void TMapFile::DeleteSemaphore()
00806 {
00807
00808
00809 #ifdef HAVE_SEMOP
00810
00811 #ifndef WIN32
00812 if (fSemaphore != -1) {
00813 int semid = fSemaphore;
00814 fSemaphore = -1;
00815 union semun set;
00816 set.val = 0;
00817 semctl(semid, 0, IPC_RMID, set);
00818 }
00819 #else
00820 if (fSemaphore != (Int_t)INVALID_HANDLE_VALUE) {
00821 CloseHandle((HANDLE)fhSemaphore);
00822 fhSemaphore = 0;
00823 fSemaphore = (Int_t)INVALID_HANDLE_VALUE;
00824 }
00825 #endif
00826 #endif
00827 }
00828
00829
00830 Int_t TMapFile::AcquireSemaphore()
00831 {
00832
00833
00834 #ifdef HAVE_SEMOP
00835 #ifndef WIN32
00836 if (fSemaphore != -1) {
00837 struct sembuf buf = { 0, -1, SEM_UNDO };
00838 int intr = 0;
00839 again:
00840 if (semop(fSemaphore, &buf, 1) == -1) {
00841 #if defined(R__FBSD) || defined(R__OBSD)
00842 if (TSystem::GetErrno() == EINVAL)
00843 #else
00844 if (TSystem::GetErrno() == EIDRM)
00845 #endif
00846 fSemaphore = -1;
00847 #if !defined(R__FBSD)
00848 if (TSystem::GetErrno() == EINTR) {
00849 if (intr > 2)
00850 return -1;
00851 TSystem::ResetErrno();
00852 intr++;
00853 goto again;
00854 }
00855 #endif
00856 }
00857 }
00858 #else
00859
00860 if (fSemaphore != (Int_t)INVALID_HANDLE_VALUE)
00861 WaitForSingleObject((HANDLE)fhSemaphore,INFINITE);
00862 #endif
00863 #endif
00864
00865
00866 if (!fWritable && fMmallocDesc) {
00867 if (mmalloc_update_mapping(fMmallocDesc) == -1)
00868 Error("AcquireSemaphore", "cannot update mapping");
00869 }
00870
00871 return 0;
00872 }
00873
00874
00875 Int_t TMapFile::ReleaseSemaphore()
00876 {
00877
00878
00879 #ifdef HAVE_SEMOP
00880 #ifndef WIN32
00881 if (fSemaphore != -1) {
00882 struct sembuf buf = { 0, 1, SEM_UNDO };
00883 if (semop(fSemaphore, &buf, 1) == -1) {
00884 #if defined(R__FBSD) || defined(R__OBSD)
00885 if (TSystem::GetErrno() == EINVAL)
00886 #else
00887 if (TSystem::GetErrno() == EIDRM)
00888 #endif
00889 fSemaphore = -1;
00890 }
00891 }
00892 #else
00893 if (fSemaphore != (Int_t)INVALID_HANDLE_VALUE)
00894 ReleaseMutex((HANDLE)fhSemaphore);
00895 #endif
00896 #endif
00897 return 0;
00898 }
00899
00900
00901 void TMapFile::Close(Option_t *option)
00902 {
00903
00904
00905
00906
00907
00908
00909 if (!fMmallocDesc) return;
00910
00911 TMapFile *shadow = FindShadowMapFile();
00912 if (!shadow) {
00913 Error("Close", "shadow map == 0, should never happen!");
00914 return;
00915 }
00916
00917 {
00918 R__LOCKGUARD2(gROOTMutex);
00919 gROOT->GetListOfMappedFiles()->Remove(shadow);
00920 gROOT->GetListOfMappedFiles()->Remove(this);
00921 }
00922
00923 if (shadow->fWritable) {
00924 fWritable = kFALSE;
00925 DeleteSemaphore();
00926 }
00927
00928 if (fMmallocDesc) {
00929 if (strcmp(option, "dtor"))
00930 mmalloc_detach(fMmallocDesc);
00931
00932
00933
00934
00935 if (!shadow->fWritable)
00936 fMmallocDesc = 0;
00937 }
00938
00939 if (shadow->fFd != -1)
00940 #ifndef WIN32
00941 close(shadow->fFd);
00942 #else
00943 CloseHandle((HANDLE)shadow->fFd);
00944 #endif
00945
00946 delete shadow;
00947 }
00948
00949
00950 TMapFile *TMapFile::FindShadowMapFile()
00951 {
00952
00953
00954 R__LOCKGUARD2(gROOTMutex);
00955 TObjLink *lnk = ((TList *)gROOT->GetListOfMappedFiles())->LastLink();
00956 while (lnk) {
00957 TMapFile *mf = (TMapFile*)lnk->GetObject();
00958 if (mf->fVersion == -1 && fBaseAddr == mf->fBaseAddr && fSize == mf->fSize)
00959 return mf;
00960 lnk = lnk->Prev();
00961 }
00962 return 0;
00963 }
00964
00965
00966 void TMapFile::Print(Option_t *) const
00967 {
00968
00969
00970 Printf("Memory mapped file: %s", fName);
00971 Printf("Title: %s", fTitle);
00972 if (fMmallocDesc) {
00973 Printf("Option: %s", fOption);
00974 ULong_t size = (ULong_t)((struct mdesc *)fMmallocDesc)->top - fBaseAddr;
00975 Printf("Mapped Memory region: 0x%lx - 0x%lx (%.2f MB)", fBaseAddr, fBaseAddr + size,
00976 (float)size/1048576);
00977 Printf("Current breakval: 0x%lx", (ULong_t)GetBreakval());
00978 } else
00979 Printf("Option: file closed");
00980 }
00981
00982
00983 Bool_t TMapFile::IsFolder() const
00984 {
00985
00986
00987 if (fMmallocDesc && fVersion > 0) return kTRUE;
00988 return kFALSE;
00989 }
00990
00991
00992 void TMapFile::Browse(TBrowser *b)
00993 {
00994
00995
00996 if (b && fMmallocDesc) {
00997
00998 AcquireSemaphore();
00999
01000 TMapRec *mr = GetFirst();
01001 TKeyMapFile *keymap;
01002 if (!fBrowseList) fBrowseList = new TList();
01003 while (OrgAddress(mr)) {
01004 keymap = (TKeyMapFile*)fBrowseList->FindObject(mr->GetName(fOffset));
01005 if (!keymap) {
01006 keymap = new TKeyMapFile(mr->GetName(fOffset),mr->GetClassName(fOffset),this);
01007 fBrowseList->Add(keymap);
01008 }
01009 b->Add(keymap, keymap->GetName());
01010 mr = mr->GetNext(fOffset);
01011 }
01012
01013 ReleaseSemaphore();
01014
01015 }
01016 }
01017
01018
01019 Bool_t TMapFile::cd(const char *path)
01020 {
01021
01022
01023 if (fDirectory)
01024 return fDirectory->cd(path);
01025 return kFALSE;
01026 }
01027
01028
01029 void TMapFile::ls(Option_t *) const
01030 {
01031
01032
01033 if (fMmallocDesc) {
01034
01035 ((TMapFile*)this)->AcquireSemaphore();
01036
01037 Printf("%-20s %-20s %-10s", "Object", "Class", "Size");
01038 if (!fFirst)
01039 Printf("*** no objects stored in memory mapped file ***");
01040
01041 TMapRec *mr = GetFirst();
01042 while (OrgAddress(mr)) {
01043 Printf("%-20s %-20s %-10d", mr->GetName(fOffset),
01044 mr->GetClassName(fOffset), mr->fBufSize);
01045 mr = mr->GetNext(fOffset);
01046 }
01047
01048 ((TMapFile*)this)->ReleaseSemaphore();
01049
01050 }
01051 }
01052
01053
01054 void TMapFile::SumBuffer(Int_t bufsize)
01055 {
01056
01057
01058 fWritten++;
01059 fSumBuffer += bufsize;
01060 fSum2Buffer += bufsize*bufsize;
01061 }
01062
01063
01064 Int_t TMapFile::GetBestBuffer()
01065 {
01066
01067
01068
01069
01070
01071
01072 if (!fWritten) return TBuffer::kMinimalSize;
01073 Double_t mean = fSumBuffer/fWritten;
01074 Double_t rms2 = TMath::Abs(fSum2Buffer/fSumBuffer - mean*mean);
01075 return (Int_t)(mean + std::sqrt(rms2));
01076 }
01077
01078
01079
01080 TMapFile *TMapFile::Create(const char *name, Option_t *option, Int_t size,
01081 const char *title)
01082 {
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092 TMapFile *newMapFile;
01093 new TMapFile(name, title, option, size, newMapFile);
01094
01095 return newMapFile;
01096 }
01097
01098
01099 void TMapFile::SetMapAddress(Long_t addr)
01100 {
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127 fgMapAddress = addr;
01128 }
01129
01130
01131 void *TMapFile::MapToAddress()
01132 {
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152 #ifdef R__HAVE_MMAP
01153 if (TStorage::HasCustomNewDelete())
01154 return (void *)fgMapAddress;
01155 else
01156 return (void *)-1;
01157 #else
01158 return (void *)-1;
01159 #endif
01160 }
01161
01162
01163 void TMapFile::operator delete(void *ptr)
01164 {
01165
01166
01167
01168 mmalloc_detach(fgMmallocDesc);
01169 fgMmallocDesc = 0;
01170
01171 TObject::operator delete(ptr);
01172 }