12 #pragma optimize("",off)
67 # ifdef CreateSemaphore
68 # undef CreateSemaphore
71 # ifdef AcquireSemaphore
72 # undef AcquireSemaphore;
75 # ifdef ReleaseSemaphore
76 # undef ReleaseSemaphore
79 # ifdef DeleteSemaphore
80 # undef DeleteSemaphore
84 # define INVALID_HANDLE_VALUE -1
100 #include "mmprivate.h"
104 #if defined(R__UNIX) && !defined(R__MACOSX) && !defined(R__WINGCC)
106 #include <sys/types.h>
109 #if defined(R__HPUX) || \
110 defined (R__SOLARIS) || defined(R__AIX) || defined(R__HIUX) || \
114 struct semid_ds *buf;
118 #if defined(R__LINUX) || defined(R__LYNXOS) || defined(R__HURD)
119 # define SEM_A 0200 // alter permission
120 # define SEM_R 0400 // read permission
125 Long_t TMapFile::fgMapAddress = 0;
126 void *TMapFile::fgMmallocDesc = 0;
134 static bool FreeIfTMapFile(
void* ptr) {
135 if (TMapFile *mf = TMapFile::WhichMapFile(ptr)) {
136 if (mf->IsWritable())
137 ::mfree(mf->GetMmallocDesc(), ptr);
148 struct SetFreeIfTMapFile_t {
149 SetFreeIfTMapFile_t() {
150 ROOT::Internal::gFreeIfTMapFile = FreeIfTMapFile;
152 ~SetFreeIfTMapFile_t() {
153 ROOT::Internal::gFreeIfTMapFile =
nullptr;
155 } gSetFreeIfTMapFile;
161 TMapRec::TMapRec(
const char *name,
const TObject *obj, Int_t size,
void *buf)
163 fName = StrDup(name);
165 fObject = (TObject*)obj;
177 delete [] fClassName;
186 TObject *TMapRec::GetObject()
const
233 TMapFile::TMapFile(
const char *name,
const char *title, Option_t *option,
234 Int_t size, TMapFile *&newMapFile)
241 fFd = (Int_t) INVALID_HANDLE_VALUE;
242 fSemaphore = (Int_t) INVALID_HANDLE_VALUE;
248 fVersion = gROOT->GetVersionInt();
249 fTitle = StrDup(title);
250 fOption = StrDup(option);
259 Bool_t create = kFALSE;
260 Bool_t recreate, update, read;
263 TString opt = option;
265 if (!opt.CompareTo(
"NEW", TString::kIgnoreCase) ||
266 !opt.CompareTo(
"CREATE", TString::kIgnoreCase))
268 recreate = opt.CompareTo(
"RECREATE", TString::kIgnoreCase)
270 update = opt.CompareTo(
"UPDATE", TString::kIgnoreCase)
272 read = opt.CompareTo(
"READ", TString::kIgnoreCase)
274 if (!create && !recreate && !update && !read) {
277 fOption = StrDup(
"READ");
282 if ((fname = gSystem->ExpandPathName(name))) {
283 fName = StrDup(fname);
284 delete [] (
char*)fname;
287 Error(
"TMapFile",
"error expanding path %s", name);
292 if (!gSystem->AccessPathName(fname, kFileExists))
293 gSystem->Unlink(fname);
297 fOption = StrDup(
"CREATE");
299 if (create && !gSystem->AccessPathName(fname, kFileExists)) {
300 Error(
"TMapFile",
"file %s already exists", fname);
304 if (gSystem->AccessPathName(fname, kFileExists)) {
308 if (update && gSystem->AccessPathName(fname, kWritePermission)) {
309 Error(
"TMapFile",
"no write permission, could not open file %s", fname);
314 if (gSystem->AccessPathName(fname, kFileExists)) {
315 Error(
"TMapFile",
"file %s does not exist", fname);
318 if (gSystem->AccessPathName(fname, kReadPermission)) {
319 Error(
"TMapFile",
"no read permission, could not open file %s", fname);
325 if (create || update) {
327 fFd = open(fname, O_RDWR | O_CREAT, 0644);
329 fFd = (Int_t) CreateFile(fname,
330 GENERIC_WRITE | GENERIC_READ,
331 FILE_SHARE_WRITE | FILE_SHARE_READ,
334 FILE_ATTRIBUTE_TEMPORARY,
337 if (fFd == (Int_t)INVALID_HANDLE_VALUE) {
338 SysError(
"TMapFile",
"file %s can not be opened", fname);
344 fFd = open(fname, O_RDONLY);
346 fFd = (Int_t) CreateFile(fname,
348 FILE_SHARE_WRITE | FILE_SHARE_READ,
351 FILE_ATTRIBUTE_TEMPORARY,
354 if (fFd == (Int_t)INVALID_HANDLE_VALUE) {
355 SysError(
"TMapFile",
"file %s can not be opened for reading", fname);
365 if (((mapto = MapToAddress()) == (
void *)-1) ||
367 ((fMmallocDesc = mmalloc_attach(fFd, mapto, fSize)) == 0)) {
369 ((fMmallocDesc = mmalloc_attach((HANDLE) fFd, mapto, fSize)) == 0)) {
372 if (mapto == (
void *)-1) {
373 Error(
"TMapFile",
"no memory mapped file capability available\n"
374 "Use rootn.exe or link application against \"-lNew\"");
376 if (fMmallocDesc == 0 && fWritable)
377 Error(
"TMapFile",
"mapped file not in mmalloc format or\n"
378 "already open in RW mode by another process");
379 if (fMmallocDesc == 0 && !fWritable)
380 Error(
"TMapFile",
"mapped file not in mmalloc format");
385 CloseHandle((HANDLE) fFd);
389 gSystem->Unlink(fname);
392 }
else if ((mapfil = (TMapFile *) mmalloc_getkey(fMmallocDesc, 0)) != 0) {
399 if (mapfil->fVersion != fVersion) {
400 Error(
"TMapFile",
"map file %s (%d) incompatible with current ROOT version (%d)",
401 fname, mapfil->fVersion, fVersion);
402 mmalloc_detach(fMmallocDesc);
406 CloseHandle((HANDLE) fFd);
413 if (mapfil->fWritable && fWritable) {
414 Warning(
"TMapFile",
"map file already open in write mode, opening in read-only mode");
418 fBaseAddr = mapfil->fBaseAddr;
419 fSize = mapfil->fSize;
424 ROOT::Internal::gMmallocDesc = fMmallocDesc;
425 TMapFile *mf =
new TMapFile(*mapfil);
427 mf->fWritable = kTRUE;
428 cleanup = mf->fOption;
429 mf->fOption = StrDup(fOption);
430 mf->fSemaphore = fSemaphore;
432 mf->CreateSemaphore(fSemaphore);
434 mmalloc_setkey(fMmallocDesc, 0, mf);
435 ROOT::Internal::gMmallocDesc = 0;
438 ROOT::Internal::gMmallocDesc = 0;
439 fOffset = ((
struct mdesc *) fMmallocDesc)->offset;
440 TMapFile *mf =
new TMapFile(*mapfil, fOffset);
441 delete [] mf->fOption;
443 mf->fOption = StrDup(
"READ");
444 mf->fMmallocDesc = fMmallocDesc;
445 mf->fWritable = kFALSE;
452 R__LOCKGUARD(gROOTMutex);
453 gROOT->GetListOfMappedFiles()->AddLast(
this);
460 Error(
"TMapFile",
"map file is not writable");
461 mmalloc_detach(fMmallocDesc);
465 CloseHandle((HANDLE) fFd);
472 fBaseAddr = (ULong_t)((
struct mdesc *) fMmallocDesc)->base;
476 ROOT::Internal::gMmallocDesc = fMmallocDesc;
478 mapfil =
new TMapFile(*
this);
479 mmalloc_setkey(fMmallocDesc, 0, mapfil);
481 ROOT::Internal::gMmallocDesc = 0;
485 R__LOCKGUARD(gROOTMutex);
486 gROOT->GetListOfMappedFiles()->AddLast(
this);
490 mapfil->InitDirectory();
492 R__LOCKGUARD(gROOTMutex);
493 gROOT->GetListOfMappedFiles()->AddFirst(mapfil);
496 if (cleanup)
delete [] cleanup;
506 ROOT::Internal::gMmallocDesc = 0;
516 TMapFile::TMapFile(
const TMapFile &f, Long_t offset) : TObject(f)
519 fVersion = f.fVersion;
520 fName = StrDup((
char *)((Long_t)f.fName + offset));
521 fTitle = StrDup((
char *)((Long_t)f.fTitle + offset));
522 fOption = StrDup((
char *)((Long_t)f.fOption + offset));
523 fMmallocDesc = f.fMmallocDesc;
524 fBaseAddr = f.fBaseAddr;
528 fWritable = f.fWritable;
529 fSemaphore = f.fSemaphore;
534 fWritten = f.fWritten;
535 fSumBuffer = f.fSumBuffer;
536 fSum2Buffer = f.fSum2Buffer;
538 CreateSemaphore(fSemaphore);
540 fhSemaphore = f.fhSemaphore;
550 TMapFile::~TMapFile()
552 if (fDirectory == gDirectory) gDirectory = gROOT;
553 delete fDirectory; fDirectory = 0;
554 if (fBrowseList) fBrowseList->Delete();
555 delete fBrowseList; fBrowseList = 0;
565 TObject::SetDtorOnly(
this);
569 fgMmallocDesc = fMmallocDesc;
575 void TMapFile::InitDirectory()
578 fDirectory =
new TDirectoryFile();
579 fDirectory->SetName(GetName());
580 fDirectory->SetTitle(GetTitle());
582 fDirectory->SetMother(
this);
583 gDirectory = fDirectory;
590 void TMapFile::Add(
const TObject *obj,
const char *name)
592 if (!fWritable || !fMmallocDesc)
return;
594 Bool_t lock = fGetting != obj ? kTRUE : kFALSE;
599 ROOT::Internal::gMmallocDesc = fMmallocDesc;
607 if (Remove(n, kFALSE)) {
611 TMapRec *mr =
new TMapRec(n, obj, 0, 0);
620 ROOT::Internal::gMmallocDesc = 0;
629 void TMapFile::Update(TObject *obj)
631 if (!fWritable || !fMmallocDesc)
return;
635 ROOT::Internal::gMmallocDesc = fMmallocDesc;
637 Bool_t all = (obj == 0) ? kTRUE : kFALSE;
639 TMapRec *mr = fFirst;
641 if (all || mr->fObject == obj) {
644 b =
new TBufferFile(TBuffer::kWrite, GetBestBuffer());
645 mr->fClassName = StrDup(mr->fObject->ClassName());
647 b =
new TBufferFile(TBuffer::kWrite, mr->fBufSize, mr->fBuffer);
648 b->MapObject(mr->fObject);
649 mr->fObject->Streamer(*b);
650 mr->fBufSize = b->BufferSize();
651 mr->fBuffer = b->Buffer();
652 SumBuffer(b->Length());
659 ROOT::Internal::gMmallocDesc = 0;
669 TObject *TMapFile::Remove(TObject *obj, Bool_t lock)
671 if (!fWritable || !fMmallocDesc)
return 0;
677 TMapRec *prev = 0, *mr = fFirst;
679 if (mr->fObject == obj) {
685 prev->fNext = mr->fNext;
708 TObject *TMapFile::Remove(
const char *name, Bool_t lock)
710 if (!fWritable || !fMmallocDesc)
return 0;
716 TMapRec *prev = 0, *mr = fFirst;
718 if (!strcmp(mr->fName, name)) {
724 prev->fNext = mr->fNext;
728 retObj = mr->fObject;
745 void TMapFile::RemoveAll()
747 if (!fWritable || !fMmallocDesc)
return;
751 TMapRec *mr = fFirst;
770 TObject *TMapFile::Get(
const char *name, TObject *delObj)
772 if (!fMmallocDesc)
return 0;
779 TMapRec *mr = GetFirst();
780 while (OrgAddress(mr)) {
781 if (!strcmp(mr->GetName(fOffset), name)) {
782 if (!mr->fBufSize)
goto release;
783 TClass *cl = TClass::GetClass(mr->GetClassName(fOffset));
785 Error(
"Get",
"unknown class %s", mr->GetClassName(fOffset));
789 obj = (TObject *)cl->New();
791 Error(
"Get",
"cannot create new object of class %s", mr->GetClassName(fOffset));
796 TBufferFile *b =
new TBufferFile(TBuffer::kRead, mr->fBufSize, mr->GetBuffer(fOffset));
804 mr = mr->GetNext(fOffset);
817 void TMapFile::CreateSemaphore(
int)
819 void TMapFile::CreateSemaphore(
int pid)
825 fSemaphore = semget(IPC_PRIVATE, 1, SEM_R|SEM_A|(SEM_R>>3)|(SEM_A>>3)|
826 (SEM_R>>6)|(SEM_A>>6));
829 if (fSemaphore != -1) {
832 semctl(fSemaphore, 0, SETVAL, set);
835 char buffer[] =
"ROOT_Semaphore_xxxxxxxx";
836 int lbuf = strlen(buffer);
837 if (!pid) fSemaphore = getpid();
838 fhSemaphore = (ULong_t)CreateMutex(NULL,FALSE,itoa(fSemaphore,&buffer[lbuf-8],16));
839 if (fhSemaphore == 0) fSemaphore = (Int_t)INVALID_HANDLE_VALUE;
847 void TMapFile::DeleteSemaphore()
852 if (fSemaphore != -1) {
853 int semid = fSemaphore;
857 semctl(semid, 0, IPC_RMID, set);
860 if (fSemaphore != (Int_t)INVALID_HANDLE_VALUE) {
861 CloseHandle((HANDLE)fhSemaphore);
863 fSemaphore = (Int_t)INVALID_HANDLE_VALUE;
872 Int_t TMapFile::AcquireSemaphore()
876 if (fSemaphore != -1) {
877 struct sembuf buf = { 0, -1, SEM_UNDO };
880 if (semop(fSemaphore, &buf, 1) == -1) {
881 #if defined(R__FBSD) || defined(R__OBSD)
882 if (TSystem::GetErrno() == EINVAL)
884 if (TSystem::GetErrno() == EIDRM)
887 #if !defined(R__FBSD)
888 if (TSystem::GetErrno() == EINTR) {
891 TSystem::ResetErrno();
900 if (fSemaphore != (Int_t)INVALID_HANDLE_VALUE)
901 WaitForSingleObject((HANDLE)fhSemaphore,INFINITE);
906 if (!fWritable && fMmallocDesc) {
907 if (mmalloc_update_mapping(fMmallocDesc) == -1)
908 Error(
"AcquireSemaphore",
"cannot update mapping");
917 Int_t TMapFile::ReleaseSemaphore()
921 if (fSemaphore != -1) {
922 struct sembuf buf = { 0, 1, SEM_UNDO };
923 if (semop(fSemaphore, &buf, 1) == -1) {
924 #if defined(R__FBSD) || defined(R__OBSD)
925 if (TSystem::GetErrno() == EINVAL)
927 if (TSystem::GetErrno() == EIDRM)
933 if (fSemaphore != (Int_t)INVALID_HANDLE_VALUE)
934 ReleaseMutex((HANDLE)fhSemaphore);
949 void TMapFile::Close(Option_t *option)
951 if (!fMmallocDesc)
return;
953 TMapFile *shadow = FindShadowMapFile();
955 Error(
"Close",
"shadow map == 0, should never happen!");
960 R__LOCKGUARD(gROOTMutex);
961 gROOT->GetListOfMappedFiles()->Remove(shadow);
962 gROOT->GetListOfMappedFiles()->Remove(
this);
965 if (shadow->fWritable) {
971 if (strcmp(option,
"dtor"))
972 mmalloc_detach(fMmallocDesc);
977 if (!shadow->fWritable)
981 if (shadow->fFd != -1)
985 CloseHandle((HANDLE)shadow->fFd);
994 TMapFile *TMapFile::FindShadowMapFile()
996 R__LOCKGUARD(gROOTMutex);
997 TObjLink *lnk = ((TList *)gROOT->GetListOfMappedFiles())->LastLink();
999 TMapFile *mf = (TMapFile*)lnk->GetObject();
1000 if (mf->fVersion == -1 && fBaseAddr == mf->fBaseAddr && fSize == mf->fSize)
1010 void TMapFile::Print(Option_t *)
const
1012 Printf(
"Memory mapped file: %s", fName);
1013 Printf(
"Title: %s", fTitle);
1015 Printf(
"Option: %s", fOption);
1016 ULong_t size = (ULong_t)((
struct mdesc *)fMmallocDesc)->top - fBaseAddr;
1017 Printf(
"Mapped Memory region: 0x%lx - 0x%lx (%.2f MB)", fBaseAddr, fBaseAddr + size,
1018 (
float)size/1048576);
1019 Printf(
"Current breakval: 0x%lx", (ULong_t)GetBreakval());
1021 Printf(
"Option: file closed");
1027 Bool_t TMapFile::IsFolder()
const
1029 if (fMmallocDesc && fVersion > 0)
return kTRUE;
1036 void TMapFile::Browse(TBrowser *b)
1038 if (b && fMmallocDesc) {
1042 TMapRec *mr = GetFirst();
1043 TKeyMapFile *keymap;
1044 if (!fBrowseList) fBrowseList =
new TList();
1045 while (OrgAddress(mr)) {
1046 keymap = (TKeyMapFile*)fBrowseList->FindObject(mr->GetName(fOffset));
1048 keymap =
new TKeyMapFile(mr->GetName(fOffset),mr->GetClassName(fOffset),
this);
1049 fBrowseList->Add(keymap);
1051 b->Add(keymap, keymap->GetName());
1052 mr = mr->GetNext(fOffset);
1063 Bool_t TMapFile::cd(
const char *path)
1066 return fDirectory->cd(path);
1073 void TMapFile::ls(Option_t *)
const
1077 ((TMapFile*)
this)->AcquireSemaphore();
1079 Printf(
"%-20s %-20s %-10s",
"Object",
"Class",
"Size");
1081 Printf(
"*** no objects stored in memory mapped file ***");
1083 TMapRec *mr = GetFirst();
1084 while (OrgAddress(mr)) {
1085 Printf(
"%-20s %-20s %-10d", mr->GetName(fOffset),
1086 mr->GetClassName(fOffset), mr->fBufSize);
1087 mr = mr->GetNext(fOffset);
1090 ((TMapFile*)
this)->ReleaseSemaphore();
1098 void TMapFile::SumBuffer(Int_t bufsize)
1101 fSumBuffer += bufsize;
1102 fSum2Buffer += bufsize*bufsize;
1112 Int_t TMapFile::GetBestBuffer()
1114 if (!fWritten)
return TBuffer::kMinimalSize;
1115 Double_t mean = fSumBuffer/fWritten;
1116 Double_t rms2 = TMath::Abs(fSum2Buffer/fSumBuffer - mean*mean);
1117 return (Int_t)(mean + std::sqrt(rms2));
1124 void *TMapFile::GetBreakval()
const
1126 if (!fMmallocDesc)
return 0;
1127 return (
void *)((
struct mdesc *)fMmallocDesc)->breakval;
1142 TMapFile *TMapFile::Create(
const char *name, Option_t *option, Int_t size,
1145 TMapFile *newMapFile;
1146 new TMapFile(name, title, option, size, newMapFile);
1179 void TMapFile::SetMapAddress(Long_t addr)
1181 fgMapAddress = addr;
1201 void *TMapFile::MapToAddress()
1204 if (TStorage::HasCustomNewDelete())
1205 return (
void *)fgMapAddress;
1217 void TMapFile::operator
delete(
void *ptr)
1219 mmalloc_detach(fgMmallocDesc);
1222 TObject::operator
delete(ptr);
1227 TMapFile *TMapFile::WhichMapFile(
void *addr)
1229 if (!gROOT || !gROOT->GetListOfMappedFiles())
return 0;
1231 TObjLink *lnk = ((TList *)gROOT->GetListOfMappedFiles())->LastLink();
1233 TMapFile *mf = (TMapFile*)lnk->GetObject();
1235 if ((ULong_t)addr >= mf->fBaseAddr + mf->fOffset &&
1236 (ULong_t)addr < (ULong_t)mf->GetBreakval() + mf->fOffset)