34 #define TMemFile_TRACE
35 #ifndef TMemFile_TRACE
37 Debug("TMemFile", "%s", x);
52 TMemFile::TMemBlock::TMemBlock(Long64_t size, TMemBlock *previous) : fPrevious(previous)
56 fBuffer =
new UChar_t[size];
64 TMemFile::TMemBlock::TMemBlock(UChar_t *data, Long64_t size) : fBuffer(data), fSize(size)
71 TMemFile::TMemBlock::~TMemBlock()
79 void TMemFile::TMemBlock::CreateNext(Long64_t size)
81 R__ASSERT(fNext ==
nullptr);
82 fNext =
new TMemBlock(size,
this);
87 TMemFile::EMode TMemFile::ParseOption(Option_t *option)
91 if (fOption ==
"NEW") fOption =
"CREATE";
93 EMode mode = EMode::kRead;
94 if (fOption ==
"CREATE")
95 mode = EMode::kCreate;
96 else if (fOption ==
"RECREATE")
97 mode = EMode::kRecreate;
98 else if (fOption ==
"UPDATE")
99 mode = EMode::kUpdate;
110 TMemFile::TMemFile(
const char *path,
const ZeroCopyView_t &datarange)
111 : TFile(path,
"WEB",
"read-only TMemFile", 0 ),
112 fBlockList(reinterpret_cast<UChar_t *>(const_cast<char *>(datarange.fStart)), datarange.fSize),
113 fSize(datarange.fSize), fBlockSeek(&(fBlockList))
120 if (!fBlockList.fBuffer) {
132 TMemFile::TMemFile(
const char *path, ExternalDataPtr_t data)
133 : TMemFile(path, ZeroCopyView_t(data->data(), data->size()))
135 fExternalData = data;
141 TMemFile::TMemFile(
const char *name, std::unique_ptr<TBufferFile> buffer)
142 : TMemFile(name, ZeroCopyView_t(buffer->Buffer(), (size_t)buffer->BufferSize()))
144 assert(!fD && !fWritable);
146 fIsOwnedByROOT =
true;
161 TMemFile::TMemFile(
const char *path, Option_t *option,
const char *ftitle, Int_t compress, Long64_t defBlockSize)
162 : TMemFile(path, nullptr, -1, option, ftitle, compress, defBlockSize)
169 TMemFile::TMemFile(
const char *path,
char *buffer, Long64_t size, Option_t *option,
const char *ftitle, Int_t compress,
170 Long64_t defBlockSize)
171 : TFile(path,
"WEB", ftitle, compress), fBlockList(size), fIsOwnedByROOT(kTRUE), fSize(size),
172 fBlockSeek(&(fBlockList))
174 fDefaultBlockSize = defBlockSize == 0LL ? fgDefaultBlockSize : defBlockSize;
176 EMode optmode = ParseOption(option);
178 if (NeedsToWrite(optmode)) {
179 Int_t mode = O_RDWR | O_CREAT;
180 if (optmode == EMode::kRecreate) mode |= O_TRUNC;
182 fD = TMemFile::SysOpen(path, O_RDWR | O_CREAT, 0644);
184 SysError(
"TMemFile",
"file %s can not be opened", path);
190 fD = TMemFile::SysOpen(path, O_RDONLY, 0644);
192 SysError(
"TMemFile",
"file %s can not be opened for reading", path);
199 SysWriteImpl(fD,buffer,size);
201 Init(!NeedsExistingFile(optmode));
213 TMemFile::TMemFile(
const TMemFile &orig)
214 : TFile(orig.GetEndpointUrl()->GetUrl(),
"WEB", orig.GetTitle(), orig.GetCompressionSettings()),
215 fBlockList(orig.GetEND()), fExternalData(orig.fExternalData), fIsOwnedByROOT(orig.fIsOwnedByROOT),
216 fSize(orig.GetEND()), fBlockSeek(&(fBlockList))
218 EMode optmode = ParseOption(orig.fOption);
221 fWritable = orig.fWritable;
223 if (!IsExternalData()) {
225 orig.CopyTo(fBlockList.fBuffer,fSize);
228 Init(!NeedsExistingFile(optmode));
235 TMemFile::~TMemFile()
240 if (IsExternalData()) {
242 fBlockList.fBuffer =
nullptr;
244 R__ASSERT(!fBlockList.fNext &&
"External block is not the only one!");
254 Long64_t TMemFile::CopyTo(
void *to, Long64_t maxsize)
const
256 Long64_t len = GetSize();
260 Long64_t storedSysOffset = fSysOffset;
261 Long64_t storedBlockOffset = fBlockOffset;
262 TMemBlock *storedBlockSeek = fBlockSeek;
264 const_cast<TMemFile*
>(
this)->SysSeek(fD, 0, SEEK_SET);
265 len =
const_cast<TMemFile*
>(
this)->SysReadImpl(fD, to, len);
267 const_cast<TMemFile*
>(
this)->fBlockSeek = storedBlockSeek;
268 const_cast<TMemFile*
>(
this)->fBlockOffset = storedBlockOffset;
269 const_cast<TMemFile*
>(
this)->fSysOffset = storedSysOffset;
277 void TMemFile::CopyTo(TBuffer &tobuf)
const
279 const TMemBlock *current = &fBlockList;
281 tobuf.WriteFastArray(current->fBuffer,current->fSize);
282 current = current->fNext;
289 Long64_t TMemFile::GetSize()
const
297 void TMemFile::Print(Option_t *option )
const
299 Printf(
"TMemFile: name=%s, title=%s, option=%s", GetName(), GetTitle(), GetOption());
300 if (strcmp(option,
"blocks")==0) {
301 const TMemBlock *current = &fBlockList;
304 Printf(
"TMemBlock: %d size=%lld addr=%p curr=%p prev=%p next=%p",
305 counter,current->fSize,current->fBuffer,
306 current,current->fPrevious,current->fNext);
307 current = current->fNext;
311 GetList()->R__FOR_EACH(TObject,Print)(option);
319 void TMemFile::ResetAfterMerge(TFileMergeInfo *info)
321 ResetObjects(
this,info);
341 fClassIndex =
nullptr;
345 fProcessIDs =
nullptr;
358 fBlockSeek = &fBlockList;
361 R__LOCKGUARD(gROOTMutex);
362 gROOT->GetListOfFiles()->Remove(
this);
366 TDirectory::TContext ctxt(
this);
371 TIter next(this->GetList());
373 while ((idcur = next())) {
374 if (idcur->IsA() == TDirectoryFile::Class()) {
375 ((TDirectoryFile*)idcur)->ResetAfterMerge(info);
386 void TMemFile::ResetObjects(TDirectoryFile *directory, TFileMergeInfo *info)
const
388 if (directory->GetListOfKeys()) {
389 TIter next(directory->GetListOfKeys());
391 while( (key = (TKey*)next()) ) {
392 if (
nullptr == directory->GetList()->FindObject(key->GetName())) {
393 Warning(
"ResetObjects",
"Key/Object %s is not attached to the directory %s and can not be ResetAfterMerge correctly",
394 key->GetName(),directory->GetName());
397 directory->GetListOfKeys()->Delete(
"slow");
401 listHargs.Form(
"(TFileMergeInfo*)0x%lx",(ULong_t)info);
403 TIter next(directory->GetList());
405 while ((idcur = next())) {
406 TClass *objcl = idcur->IsA();
407 if (objcl == TDirectoryFile::Class()) {
408 ResetObjects((TDirectoryFile*)idcur,info);
409 }
else if (objcl->GetResetAfterMerge()) {
410 (objcl->GetResetAfterMerge())(idcur,info);
411 }
else if (idcur->IsA()->GetMethodWithPrototype(
"ResetAfterMerge",
"TFileMergeInfo*") ) {
413 idcur->Execute(
"ResetAfterMerge", listHargs.Data(), &error);
415 Error(
"ResetObjects",
"calling ResetAfterMerge() on '%s' failed.",
429 Int_t TMemFile::SysReadImpl(Int_t,
void *buf, Long64_t len)
433 if (fBlockSeek ==
nullptr || fBlockSeek->fBuffer ==
nullptr) {
435 gSystem->SetErrorStr(
"The memory file is not open.");
439 if (fSysOffset + len > fSize) {
440 len = fSize - fSysOffset;
443 if (fBlockOffset+len <= fBlockSeek->fSize) {
446 memcpy(buf,fBlockSeek->fBuffer+fBlockOffset,len);
453 Int_t sublen = fBlockSeek->fSize - fBlockOffset;
454 memcpy(buf,fBlockSeek->fBuffer+fBlockOffset,sublen);
457 buf = (
char*)buf + sublen;
458 Int_t len_left = len - sublen;
459 fBlockSeek = fBlockSeek->fNext;
462 while (len_left > fBlockSeek->fSize) {
463 R__ASSERT(fBlockSeek);
465 memcpy(buf, fBlockSeek->fBuffer, fBlockSeek->fSize);
466 buf = (
char*)buf + fBlockSeek->fSize;
467 len_left -= fBlockSeek->fSize;
468 fBlockSeek = fBlockSeek->fNext;
472 R__ASSERT(fBlockSeek);
473 memcpy(buf,fBlockSeek->fBuffer, len_left);
474 fBlockOffset = len_left;
487 Int_t TMemFile::SysRead(Int_t fd,
void *buf, Int_t len)
489 return SysReadImpl(fd, buf, len);
496 Long64_t TMemFile::SysSeek(Int_t, Long64_t offset, Int_t whence)
499 if (whence == SEEK_SET) {
501 fBlockSeek = &fBlockList;
502 Long64_t counter = 0;
503 while(fBlockSeek->fNext && (counter+fBlockSeek->fSize) < fSysOffset)
505 counter += fBlockSeek->fSize;
506 fBlockSeek = fBlockSeek->fNext;
508 fBlockOffset = fSysOffset - counter;
509 }
else if (whence == SEEK_CUR) {
513 }
else if (offset > 0) {
515 if ( (fBlockOffset+offset) < fBlockSeek->fSize) {
516 fSysOffset += offset;
517 fBlockOffset += offset;
519 Long64_t counter = fSysOffset;
520 fSysOffset += offset;
521 while(fBlockSeek->fNext && counter < fSysOffset)
523 counter += fBlockSeek->fSize;
524 fBlockSeek = fBlockSeek->fNext;
526 fBlockOffset = fSysOffset - counter;
530 Long64_t counter = fSysOffset;
531 fSysOffset += offset;
532 if (fSysOffset < 0) {
533 SysError(
"TMemFile",
"Unable to seek past the beginning of file");
535 fBlockSeek = &fBlockList;
539 if (offset+fBlockOffset >= 0) {
541 fBlockOffset += offset;
543 while(fBlockSeek->fPrevious && counter > fSysOffset)
545 counter -= fBlockSeek->fSize;
546 fBlockSeek = fBlockSeek->fPrevious;
548 fBlockOffset = fSysOffset - counter;
552 }
else if (whence == SEEK_END) {
554 SysError(
"TMemFile",
"Unable to seek past end of file");
558 SysError(
"TMemFile",
"Unable to seek to end of file");
563 SysError(
"TMemFile",
"Unknown whence!");
572 Int_t TMemFile::SysOpen(
const char * , Int_t , UInt_t )
574 if (!fBlockList.fBuffer) {
575 fBlockList.fBuffer =
new UChar_t[fDefaultBlockSize];
576 fBlockList.fSize = fDefaultBlockSize;
577 fSize = fDefaultBlockSize;
579 if (fBlockList.fBuffer) {
589 Int_t TMemFile::SysClose(Int_t )
597 Int_t TMemFile::SysWriteImpl(Int_t ,
const void *buf, Long64_t len)
601 if (IsExternalData()) {
602 gSystem->SetErrorStr(
"A memory file with shared data is read-only.");
606 if (fBlockList.fBuffer == 0) {
608 gSystem->SetErrorStr(
"The memory file is not open.");
611 if (fBlockOffset+len <= fBlockSeek->fSize) {
614 memcpy(fBlockSeek->fBuffer+fBlockOffset,buf,len);
621 Int_t sublen = fBlockSeek->fSize - fBlockOffset;
622 memcpy(fBlockSeek->fBuffer+fBlockOffset,buf,sublen);
625 buf = (
char*)buf + sublen;
626 Int_t len_left = len - sublen;
627 if (!fBlockSeek->fNext) {
628 fBlockSeek->CreateNext(fDefaultBlockSize);
629 fSize += fDefaultBlockSize;
631 fBlockSeek = fBlockSeek->fNext;
634 while (len_left > fBlockSeek->fSize) {
635 R__ASSERT(fBlockSeek);
637 memcpy(fBlockSeek->fBuffer, buf, fBlockSeek->fSize);
638 buf = (
char*)buf + fBlockSeek->fSize;
639 len_left -= fBlockSeek->fSize;
640 if (!fBlockSeek->fNext) {
641 fBlockSeek->CreateNext(fDefaultBlockSize);
642 fSize += fDefaultBlockSize;
644 fBlockSeek = fBlockSeek->fNext;
648 R__ASSERT(fBlockSeek);
649 memcpy(fBlockSeek->fBuffer, buf, len_left);
650 fBlockOffset = len_left;
661 Int_t TMemFile::SysWrite(Int_t fd,
const void *buf, Int_t len)
663 return SysWriteImpl(fd,buf,len);
669 Int_t TMemFile::SysStat(Int_t, Long_t* , Long64_t* , Long_t* , Long_t* )
671 MayNotUse(
"SysStat");
679 Int_t TMemFile::SysSync(Int_t)
687 void TMemFile::ResetErrno()
const
689 TSystem::ResetErrno();