#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "TClass.h"
#if ROOT_VERSION_CODE >= ROOT_VERSION(5,15,0)
#include <TBufferFile.h>
#define MyBuffer TBufferFile
#else
#include <TBuffer.h>
#define MyBuffer TBuffer
#endif
#ifdef R__BYTESWAP
#include "Bswapcpy.h"
#endif
#include "TFAsroFile.h"
#define MAX_UNIQUE_NAMES 0xffffffffu
extern "C" void R__zip (Int_t cxlevel, Int_t *nin, char *bufin, Int_t *lout, char *bufout, Int_t *nout);
extern "C" void R__unzip(Int_t *nin, UChar_t *bufin, Int_t *lout, char *bufout, Int_t *nout);
const Int_t MAX_CUT_LENGTH = 0xffffff;
static Bool_t Compress(int compLevel, char * in, int inLength, char * out,
UInt_t * outLength);
static Bool_t Uncompress(UChar_t * in, char * out, UInt_t outLength);
ClassImp(TFAsroKey)
ClassImp(TFAsroValue)
ClassImp(TFAsroFile)
TFAsroKey::TFAsroKey(const TFAsroKey & key)
{
fElName = key.fElName;
fSubName = key.fSubName;
fCycle = key.fCycle;
}
TFAsroKey & TFAsroKey::operator = (const TFAsroKey & key)
{
if (this != &key)
{
fElName = key.fElName;
fSubName = key.fSubName;
fCycle = key.fCycle;
}
return *this;
}
bool TFAsroKey::operator < (const TFAsroKey & key) const
{
if (fElName != key.fElName)
return fElName < key.fElName;
if (fCycle != key.fCycle)
return fCycle < key.fCycle;
return fSubName < key.fSubName;
}
TFAsroValue::TFAsroValue()
{
fPos = 0;
fFileLength = 0;
fDataLength = 0;
fClassName = 0;
}
TFAsroValue::TFAsroValue(const TFAsroValue & value)
{
fPos = value.fPos;
fFileLength = value.fFileLength;
fDataLength = value.fDataLength;
fClassName = value.fClassName;
}
TFAsroValue & TFAsroValue::operator = (const TFAsroValue & value)
{
if (this != &value)
{
fPos = value.fPos;
fFileLength = value.fFileLength;
fDataLength = value.fDataLength;
fClassName = value.fClassName;
}
return *this;
}
Bool_t TFAsroColIter::Next()
{
if (mi_entry == mi_end)
return kFALSE;
m_colName = mi_entry->first.GetSubName();
m_classNameIndex = mi_entry->second.GetClassName();
mi_entry++;
return kTRUE;
}
Bool_t TFAsroElementIter::Next()
{
fKey.IncreseCycle();
std::map<TFAsroKey, TFAsroValue>::iterator i_entry;
i_entry = fEntries->lower_bound(fKey);
if (i_entry == fEntries->end())
return kFALSE;
fKey = i_entry->first;
return kTRUE;
}
TFAsroFile::TFAsroFile()
{
fDes[0] = fDes[1] = fDes[2] = 0;
fFreeReserve = 0;
fFree = NULL;
fFile = -1;
}
TFAsroFile::TFAsroFile(const char * fileName, Bool_t * readOnly)
{
bool ok = true;
fFree = NULL;
fFile = open(fileName, O_RDWR | O_CREAT,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (fFile < 0)
{
if (*readOnly)
{
fFile = open(fileName, O_RDONLY);
if (fFile < 0)
return;
}
else
return;
}
else
*readOnly = kFALSE;
struct stat buf;
fstat(fFile, &buf);
if (buf.st_size > 0)
{
char id[8] = "";
ok &= read(fFile, id, 8) == 8;
if (!ok || strncmp(id, "ASRO0001", 8) != 0)
{
close(fFile);
fFile = -2;
return;
}
#ifdef R__BYTESWAP
UInt_t des[4];
ok &= read(fFile, des, 4 * sizeof(UInt_t)) == 4 * sizeof(UInt_t);
bswapcpy32(fDes, des, 4);
#else
ok &= read(fFile, fDes, 4 * sizeof(UInt_t)) == 4 * sizeof(UInt_t);
#endif
lseek(fFile, fDes[0], SEEK_SET);
if (fDes[1] > 0)
{
MyBuffer buffer(TBuffer::kRead, fDes[1]);
ok &= read(fFile, buffer.Buffer(), fDes[1]) == fDes[1];
Streamer(buffer);
}
fFreeReserve = fDes[2];
fFree = new UInt_t[fFreeReserve / sizeof(UInt_t)];
#ifdef R__BYTESWAP
UInt_t * freeSwap = new UInt_t[fFreeReserve / sizeof(UInt_t)];
ok &= read(fFile, freeSwap, fDes[2]) == fDes[2];
bswapcpy32(fFree, freeSwap, fFreeReserve / sizeof(UInt_t));
delete freeSwap;
#else
ok &= read(fFile, fFree, fDes[2]) == fDes[2];
#endif
}
else
{
ok &= write(fFile, "ASRO0001", 8) == 8;
fDes[0] = 8 + 4 * sizeof(UInt_t);
fDes[1] = 0;
fDes[2] = 2 * sizeof(UInt_t);
fDes[3] = 0;
fFreeReserve = fDes[2];
fFree = new UInt_t[fFreeReserve / sizeof(UInt_t)];
fFree[0] = 8 + 6 * sizeof(UInt_t);
fFree[1] = 0xFFFFFFFFU - (8 + 6 * sizeof(UInt_t));
#ifdef R__BYTESWAP
UInt_t desSwap[4];
UInt_t freeSwap[2];
bswapcpy32(desSwap, fDes, 4);
bswapcpy32(freeSwap, fFree, 2);
ok &= write(fFile, desSwap, 4 * sizeof(UInt_t)) == 4 * sizeof(UInt_t);
ok &= write(fFile, freeSwap, fDes[2]) == fDes[2];
#else
ok &= write(fFile, fDes, 4 * sizeof(UInt_t)) == 4 * sizeof(UInt_t);
ok &= write(fFile, fFree, fDes[2]) == fDes[2];
#endif
}
if (ok)
fFileName = fileName;
else
{
close(fFile);
fFile = -3;
}
}
TFAsroFile::~TFAsroFile()
{
if (fFile >= 0)
close(fFile);
delete [] fFree;
}
TObject * TFAsroFile::Read(const char * name, const char * subName, Int_t cycle)
{
if (fFile < 0)
return NULL;
UInt_t nameIndex;
int numNames = fNames.size();
if (numNames == 0)
return NULL;
for (nameIndex = 0; nameIndex < numNames; nameIndex++)
if (fNames[nameIndex] == name)
break;
if (nameIndex == numNames)
return NULL;
return Read( TFAsroKey(nameIndex, subName, cycle) );
}
TObject * TFAsroFile::Read(const TFAsroKey & key)
{
if (fFile < 0)
return NULL;
std::map<TFAsroKey, TFAsroValue>::iterator i_entry;
i_entry = fEntries.find(key);
if (i_entry == fEntries.end())
return NULL;
bool ok;
lseek(fFile, i_entry->second.GetPos(), SEEK_SET);
MyBuffer buffer(TBuffer::kRead, i_entry->second.GetDataLength());
if (i_entry->second.GetDataLength() == i_entry->second.GetFileLength())
ok = read(fFile, buffer.Buffer(), i_entry->second.GetDataLength()) ==
i_entry->second.GetDataLength();
else
{
UChar_t * fileBuffer = new UChar_t[i_entry->second.GetFileLength()];
ok = read(fFile, fileBuffer, i_entry->second.GetFileLength()) ==
i_entry->second.GetFileLength();
Uncompress(fileBuffer, buffer.Buffer(), i_entry->second.GetDataLength());
delete [] fileBuffer;
}
if (!ok)
return NULL;
TClass cl(fClassNames[i_entry->second.GetClassName()].Data());
TObject * obj = (TObject*)cl.New();
if (obj)
obj->Streamer(buffer);
return obj;
}
bool TFAsroFile::InitWrite()
{
if (fFile < 0) return false;
MakeFree(fDes[0], fDes[1] + fDes[2] + fDes[3]);
lseek(fFile, 8, SEEK_SET);
UInt_t zero = 0;
return write(fFile, &zero, sizeof(UInt_t)) == sizeof(UInt_t);
}
bool TFAsroFile::Write(TObject * obj, int compLevel,
const char * name, const char * subName, Int_t cycle)
{
if (fFile < 0) return false;
UInt_t nameIndex;
int numNames = fNames.size();
for (nameIndex = 0; nameIndex < numNames; nameIndex++)
if (fNames[nameIndex] == name)
break;
if (nameIndex == numNames)
fNames.push_back(TString(name));
TFAsroKey key(nameIndex, subName, cycle);
TFAsroValue & asroValue = fEntries[key];
if (asroValue.GetPos() > 0)
MakeFree(asroValue.GetPos(), asroValue.GetFileLength());
MyBuffer buffer(TBuffer::kWrite);
obj->Streamer(buffer);
asroValue.SetDataLength(buffer.Length());
char * dataBuffer;
if (compLevel <= 0 || buffer.Length() < 256)
{
dataBuffer = buffer.Buffer();
asroValue.SetFileLength(buffer.Length());
}
else
{
UInt_t fileLength;
dataBuffer = new char[buffer.Length()];
if (Compress(compLevel, buffer.Buffer(), buffer.Length(),
dataBuffer, &fileLength))
asroValue.SetFileLength(fileLength);
else
{
delete [] dataBuffer;
dataBuffer = buffer.Buffer();
asroValue.SetFileLength(buffer.Length());
}
}
fDes[3] = 2 * sizeof(UInt_t);
UInt_t classNameIndex;
int numClassNames = fClassNames.size();
const char * className = obj->IsA()->GetName();
for (classNameIndex = 0; classNameIndex < numClassNames; classNameIndex++)
if (fClassNames[classNameIndex] == className)
break;
if (classNameIndex == numClassNames)
fClassNames.push_back(TString(className));
asroValue.SetPos(GetFree(asroValue.GetFileLength()));
asroValue.SetClassName(classNameIndex);
lseek(fFile, asroValue.GetPos(), SEEK_SET);
bool ok = write(fFile, dataBuffer, asroValue.GetFileLength()) ==
asroValue.GetFileLength();
if (dataBuffer != buffer.Buffer())
delete [] dataBuffer;
return ok;
}
bool TFAsroFile::FinishWrite()
{
if (fFile < 0) return false;
bool ok = true;
MyBuffer desBuffer(TBuffer::kWrite);
Streamer(desBuffer);
fDes[1] = desBuffer.Length();
fDes[3] = 2 * sizeof(UInt_t);
fDes[0] = GetFree(fDes[1] + fDes[2] + fDes[3]);
lseek(fFile, fDes[0], SEEK_SET);
ok &= write(fFile, desBuffer.Buffer(), fDes[1]) == fDes[1];
#ifdef R__BYTESWAP
UInt_t * freeSwap = new UInt_t[fDes[2] / sizeof(UInt_t)];
bswapcpy32(freeSwap, fFree, fDes[2] / sizeof(UInt_t));
ok &= write(fFile, freeSwap, fDes[2]) == fDes[2];
delete [] freeSwap;
UInt_t desSwap[4];
bswapcpy32(desSwap, fDes, 4);
lseek(fFile, 8, SEEK_SET);
ok &= write(fFile, desSwap, 4 * sizeof(UInt_t)) == 4 * sizeof(UInt_t);
#else
ok &= write(fFile, fFree, fDes[2]) == fDes[2];
lseek(fFile, 8, SEEK_SET);
ok &= write(fFile, fDes, 4 * sizeof(UInt_t)) == 4 * sizeof(UInt_t);
#endif
return ok;
}
bool TFAsroFile::Delete(const char * name, const char * subName, Int_t cycle)
{
if (fFile < 0)
return false;
UInt_t nameIndex;
int numNames = fNames.size();
if (numNames == 0)
return false;
for (nameIndex = 0; nameIndex < numNames; nameIndex++)
if (fNames[nameIndex] == name)
break;
if (nameIndex == numNames)
return false;
TFAsroKey key(nameIndex, subName, cycle);
std::map<TFAsroKey, TFAsroValue>::iterator i_entry;
i_entry = fEntries.find(key);
if (i_entry == fEntries.end())
return false;
MakeFree(fDes[0], fDes[1] + fDes[2] + fDes[3]);
MakeFree(i_entry->second.GetPos(), i_entry->second.GetFileLength());
fEntries.erase(i_entry);
if (subName[0] == 0)
{
std::map<TFAsroKey, TFAsroValue>::iterator i_begin =
fEntries.upper_bound(TFAsroKey(nameIndex, "", cycle));
std::map<TFAsroKey, TFAsroValue>::iterator i_end =
fEntries.lower_bound(TFAsroKey(nameIndex, "", cycle + 1));
std::map<TFAsroKey, TFAsroValue>::iterator i_col = i_begin;
while (i_col != i_end)
{
MakeFree(i_col->second.GetPos(), i_col->second.GetFileLength());
i_col++;
}
fEntries.erase(i_begin, i_end);
}
bool ok = true;
MyBuffer buffer(TBuffer::kWrite);
Streamer(buffer);
fDes[1] = buffer.Length();
fDes[3] = 2 * 2 * sizeof(UInt_t);
fDes[0] = GetFree(fDes[1] + fDes[2] + fDes[3]);
lseek(fFile, fDes[0], SEEK_SET);
ok &= write(fFile, buffer.Buffer(), fDes[1]) == fDes[1];
#ifdef R__BYTESWAP
UInt_t * freeSwap = new UInt_t[fDes[2] / sizeof(UInt_t)];
bswapcpy32(freeSwap, fFree, fDes[2] / sizeof(UInt_t));
ok &= write(fFile, freeSwap, fDes[2]) == fDes[2];
delete [] freeSwap;
UInt_t desSwap[4];
bswapcpy32(desSwap, fDes, 4);
lseek(fFile, 8, SEEK_SET);
ok &= write(fFile, desSwap, 4 * sizeof(UInt_t)) == 4 * sizeof(UInt_t);
#else
ok &= write(fFile, fFree, fDes[2]) == fDes[2];
lseek(fFile, 8, SEEK_SET);
ok &= write(fFile, fDes, 4 * sizeof(UInt_t)) == 4 * sizeof(UInt_t);
#endif
return ok;
}
UInt_t TFAsroFile::GetFree(UInt_t size)
{
UInt_t bestFit = 0;
UInt_t bestSize = 0xFFFFFFFFU;
for (UInt_t index = 0; index < fDes[2] / (2 * sizeof(UInt_t)); index++)
if (size <= fFree[index * 2 + 1] && bestSize > fFree[index * 2 + 1])
{
bestFit = index;
bestSize = fFree[index * 2 + 1];
}
UInt_t pos = fFree[bestFit * 2];
if (size == fFree[bestFit * 2 + 1])
{
memmove(fFree + 2 * bestFit, fFree + 2 * (bestFit + 1),
fDes[2] - (bestFit + 1) * 2 * sizeof(UInt_t));
fDes[2] -= 2 * sizeof(UInt_t);
fDes[3] += 2 * sizeof(UInt_t);
}
else
{
fFree[bestFit * 2] += size;
fFree[bestFit * 2 + 1] -= size;
}
return pos;
}
void TFAsroFile::MakeFree(UInt_t pos, UInt_t size)
{
UInt_t index = 0;
while (index < fDes[2] / (2 * sizeof(UInt_t)) &&
pos > fFree[index * 2])
index++;
if (index == 0)
{
if (pos + size == fFree[0])
{
fFree[0] = pos;
fFree[1] += size;
}
else
{
if (fDes[2] == fFreeReserve)
{
fFreeReserve += 100 * sizeof(UInt_t);
UInt_t * tmp = new UInt_t[fFreeReserve / sizeof(UInt_t)];
memcpy(tmp + 2, fFree, fDes[2]);
delete [] fFree;
fFree = tmp;
}
else
{
memmove(fFree + 2, fFree, fDes[2]);
}
fDes[2] += 2 * sizeof(UInt_t);
fDes[3] -= 2 * sizeof(UInt_t);
fFree[0] = pos;
fFree[1] = size;
}
return;
}
bool before = fFree[(index - 1) * 2] + fFree[(index - 1) * 2 + 1] == pos;
bool after = pos + size == fFree[index * 2] ;
if (before && !after )
fFree[(index - 1) * 2 + 1] += size;
else if (!before && after)
{
fFree[index * 2] -= size;
fFree[index * 2 + 1] += size;
}
else if (before && after )
{
fFree[(index - 1) * 2 + 1] += size + fFree[index * 2 + 1];
memmove(fFree + 2 * index, fFree + 2 * (index + 1),
fDes[2] - (index + 1) * 2 * sizeof(UInt_t));
fDes[2] -= 2 * sizeof(UInt_t);
fDes[3] += 2 * sizeof(UInt_t);
}
else if (!before && !after)
{
if (fDes[2] == fFreeReserve)
{
fFreeReserve += 100 * sizeof(UInt_t);
UInt_t * tmp = new UInt_t[fFreeReserve / sizeof(UInt_t)];
memcpy(tmp, fFree, index * 2 * sizeof(UInt_t));
memcpy(tmp + (index + 1) * 2, fFree + index * 2,
fDes[2] - index * 2 * sizeof(UInt_t) );
delete [] fFree;
fFree = tmp;
}
else
{
memmove(fFree + 2 * (index + 1), fFree + 2 * index ,
fDes[2] - index * 2 * sizeof(UInt_t));
}
fDes[2] += 2 * sizeof(UInt_t);
fDes[3] -= 2 * sizeof(UInt_t);
fFree[index * 2] = pos;
fFree[index * 2 + 1] = size;
}
}
UInt_t TFAsroFile::GetFreeCycle(const char * name)
{
UInt_t nameIndex;
int numNames = fNames.size();
for (nameIndex = 0; nameIndex < numNames; nameIndex++)
if (fNames[nameIndex] == name)
break;
if (nameIndex == numNames)
fNames.push_back(TString(name));
std::map<TFAsroKey, TFAsroValue>::iterator i_entry;
i_entry = fEntries.upper_bound(TFAsroKey(nameIndex, "", 0));
UInt_t prevCycle = 0;
while (i_entry != fEntries.end() &&
nameIndex == i_entry->first.GetElName() )
{
if (i_entry->first.GetCycle() - prevCycle > 1)
return prevCycle + 1;
prevCycle = i_entry->first.GetCycle();
i_entry++;
}
return prevCycle < MAX_UNIQUE_NAMES ? prevCycle + 1 : 0;
}
UInt_t TFAsroFile::GetNumSubs(const char * name, Int_t cycle)
{
UInt_t nameIndex;
int numNames = fNames.size();
if (numNames == 0)
return 0;
for (nameIndex = 0; nameIndex < numNames; nameIndex++)
if (fNames[nameIndex] == name)
break;
if (nameIndex == numNames)
return 0;
std::map<TFAsroKey, TFAsroValue>::iterator i_entry;
i_entry = fEntries.upper_bound(TFAsroKey(nameIndex, "", cycle));
UInt_t numSub = 0;
while (i_entry != fEntries.end() &&
i_entry->first.GetCycle() == cycle &&
nameIndex == i_entry->first.GetElName() )
{
numSub++;
i_entry++;
}
return numSub;
}
UInt_t TFAsroFile::GetNextCycle(const char * name, Int_t cycle)
{
UInt_t nameIndex;
int numNames = fNames.size();
if (numNames == 0)
return 1;
for (nameIndex = 0; nameIndex < numNames; nameIndex++)
if (fNames[nameIndex] == name)
break;
if (nameIndex == numNames)
return 1;
std::map<TFAsroKey, TFAsroValue>::iterator i_entry;
i_entry = fEntries.lower_bound(TFAsroKey(nameIndex, "", cycle + 1));
if (i_entry == fEntries.end() ||
nameIndex != i_entry->first.GetElName() )
return 0;
return i_entry->first.GetCycle();
}
TFAsroColIter * TFAsroFile::MakeColIter(const char * name, Int_t cycle)
{
UInt_t nameIndex;
int numNames = fNames.size();
for (nameIndex = 0; nameIndex < numNames; nameIndex++)
if (fNames[nameIndex] == name)
break;
std::map<TFAsroKey, TFAsroValue>::iterator i_entry, i_end;
i_entry = fEntries.upper_bound(TFAsroKey(nameIndex, "", cycle));
i_end = fEntries.lower_bound(TFAsroKey(nameIndex, "", cycle + 1));
return new TFAsroColIter(i_entry, i_end, &fClassNames);
}
static Bool_t Compress(int compLevel, char * in, int inLength, char * out,
UInt_t * outLength)
{
*outLength = 0;
while (inLength > 0)
{
int length;
if (inLength <= MAX_CUT_LENGTH)
length = inLength;
else if (inLength < MAX_CUT_LENGTH * 2)
length = inLength / 2;
else
length = MAX_CUT_LENGTH;
inLength -= length;
int nout;
R__zip(compLevel, &length, in, &length, out, &nout);
if (nout == 0)
return kFALSE;
in += length;
out += nout;
*outLength += nout;
}
return kTRUE;
}
static Bool_t Uncompress(UChar_t * in, char * out, UInt_t outLength)
{
Int_t readTotal = 0;
while (1)
{
Int_t nin = 9 + ((Int_t)in[3] | ((Int_t)in[4] << 8) | ((Int_t)in[5] << 16));
Int_t nout = (Int_t)in[6] | ((Int_t)in[7] << 8) | ((Int_t)in[8] << 16);
Int_t read;
R__unzip(&nin, in, &nout, out, &read);
if (read == 0) return kFALSE;
readTotal += read;
if (readTotal >= outLength) return kTRUE;
in += nin;
out += read;
}
}
Last update: Fri Mar 14 13:55:06 2008
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.