SNAP Library, Developer Reference  2012-10-15 15:06:59
SNAP, a general purpose network analysis and graph mining library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
blobbs.cpp
Go to the documentation of this file.
00001 
00002 // Blob-Pointer
00003 const int TBlobPt::Flags=24;
00004 
00005 void TBlobPt::PutFlag(const int& FlagN, const bool& Val){
00006   EAssert((0<=FlagN)&&(FlagN<Flags));
00007   switch (FlagN/8){
00008     case 0: FSet1.SetBit(7-FlagN%8, Val); break;
00009     case 1: FSet2.SetBit(7-FlagN%8, Val); break;
00010     case 2: FSet3.SetBit(7-FlagN%8, Val); break;
00011     default: Fail;
00012   }
00013 }
00014 
00015 bool TBlobPt::IsFlag(const int& FlagN) const {
00016   EAssert((0<=FlagN)&&(FlagN<Flags));
00017   switch (FlagN/8){
00018     case 0: return FSet1.GetBit(7-FlagN%8);
00019     case 1: return FSet2.GetBit(7-FlagN%8);
00020     case 2: return FSet3.GetBit(7-FlagN%8);
00021     default: Fail; return false;
00022   }
00023 }
00024 
00025 void TBlobPt::PutFSet(const int& FSetN, const TB8Set& FSet){
00026   switch (FSetN){
00027     case 1: FSet1=FSet; break;
00028     case 2: FSet2=FSet; break;
00029     case 3: FSet3=FSet; break;
00030     default: Fail;
00031   }
00032 }
00033 
00034 TB8Set TBlobPt::GetFSet(const int& FSetN){
00035   switch (FSetN){
00036     case 1: return FSet1;
00037     case 2: return FSet2;
00038     case 3: return FSet3;
00039     default: Fail; return TB8Set();
00040   }
00041 }
00042 
00043 TStr TBlobPt::GetStr() const {
00044   TChA ChA;
00045   ChA+='[';
00046   if (Empty()){
00047     ChA+="Null";
00048   } else {
00049     ChA+=TUInt::GetStr(uint(Seg)); ChA+=':'; ChA+=TUInt::GetStr(Addr);
00050     for (int FlagN=0; FlagN<Flags; FlagN++){
00051       if (IsFlag(FlagN)){
00052         ChA+='{'; ChA+=TInt::GetStr(FlagN); ChA+='}';}
00053     }
00054   }
00055   ChA+=']';
00056   return ChA;
00057 }
00058 
00060 // Blob-Base
00061 const int TBlobBs::MnBlobBfL=16;
00062 const int TBlobBs::MxBlobFLen=1000000000;
00063 
00064 void TBlobBs::PutVersionStr(const PFRnd& FBlobBs){
00065   FBlobBs->PutStr(GetVersionStr());
00066 }
00067 
00068 void TBlobBs::AssertVersionStr(const PFRnd& FBlobBs){
00069   TStr CorrVersionStr=GetVersionStr();
00070   bool IsOk=false;
00071   TStr TestVersionStr=FBlobBs->GetStr(CorrVersionStr.Len(), IsOk);
00072   EAssert(IsOk && (CorrVersionStr==TestVersionStr));
00073 }
00074 
00075 TStr TBlobBs::GetBlobBsStateStr(const TBlobBsState& BlobBsState){
00076   TStr StateStr;
00077   switch (BlobBsState){
00078     case bbsOpened: StateStr="Opened"; break;
00079     case bbsClosed: StateStr="Closed"; break;
00080     default: Fail; return TStr();
00081   }
00082   EAssert(StateStr.Len()==GetStateStrLen());
00083   return StateStr;
00084 }
00085 
00086 void TBlobBs::PutBlobBsStateStr(const PFRnd& FBlobBs, const TBlobBsState& State){
00087   FBlobBs->PutStr(GetBlobBsStateStr(State));
00088 }
00089 
00090 void TBlobBs::AssertBlobBsStateStr(
00091  const PFRnd& FBlobBs, const TBlobBsState& State){
00092   TStr CorrStateStr=GetBlobBsStateStr(State);
00093   bool IsOk;
00094   TStr TestStateStr=FBlobBs->GetStr(GetStateStrLen(), IsOk);
00095   if (!(IsOk && (CorrStateStr==TestStateStr))) {
00096         TExcept::ThrowFull("Error in AssertBlobBsStateStr!", TStr(__FILE__)+" line "+TInt::GetStr(__LINE__));
00097   }
00098 }
00099 
00100 const TStr TBlobBs::MxSegLenVNm="MxSegLen";
00101 
00102 void TBlobBs::PutMxSegLen(const PFRnd& FBlobBs, const int& MxSegLen){
00103   FBlobBs->PutStr(MxSegLenVNm);
00104   FBlobBs->PutInt(MxSegLen);
00105 }
00106 
00107 int TBlobBs::GetMxSegLen(const PFRnd& FBlobBs){
00108   EAssert(FBlobBs->GetStr(MxSegLenVNm.Len())==MxSegLenVNm);
00109   return FBlobBs->GetInt();
00110 }
00111 
00112 const TStr TBlobBs::BlockLenVNm="BlockLenV";
00113 
00114 void TBlobBs::GenBlockLenV(TIntV& BlockLenV){
00115   BlockLenV.Clr();
00116   for (int P2Exp=0; P2Exp<TB4Def::MxP2Exp; P2Exp++){
00117     BlockLenV.Add(TInt(TB4Def::GetP2(P2Exp)));}
00118   EAssert(int(BlockLenV.Last())<2000000000);
00119 
00120   {for (int Len=10; Len<100; Len+=10){BlockLenV.Add(Len);}}
00121   {for (int Len=100; Len<10000; Len+=100){BlockLenV.Add(Len);}}
00122   {for (int Len=10000; Len<100000; Len+=1000){BlockLenV.Add(Len);}}
00123   {for (int Len=100000; Len<1000000; Len+=25000){BlockLenV.Add(Len);}}
00124   {for (int Len=1000000; Len<10000000; Len+=1000000){BlockLenV.Add(Len);}}
00125   {for (int Len=10000000; Len<100000000; Len+=10000000){BlockLenV.Add(Len);}}
00126 
00127   BlockLenV.Sort();
00128 }
00129 
00130 void TBlobBs::PutBlockLenV(const PFRnd& FBlobBs, const TIntV& BlockLenV){
00131   FBlobBs->PutStr(BlockLenVNm);
00132   FBlobBs->PutInt(BlockLenV.Len());
00133   for (int BlockLenN=0; BlockLenN<BlockLenV.Len(); BlockLenN++){
00134     FBlobBs->PutInt(BlockLenV[BlockLenN]);}
00135   FBlobBs->PutInt(-1);
00136 }
00137 
00138 void TBlobBs::GetBlockLenV(const PFRnd& FBlobBs, TIntV& BlockLenV){
00139   EAssert(FBlobBs->GetStr(BlockLenVNm.Len())==BlockLenVNm);
00140   BlockLenV.Gen(FBlobBs->GetInt());
00141   for (int BlockLenN=0; BlockLenN<BlockLenV.Len(); BlockLenN++){
00142     BlockLenV[BlockLenN]=FBlobBs->GetInt();}
00143   EAssert(FBlobBs->GetInt()==-1);
00144 }
00145 
00146 const TStr TBlobBs::FFreeBlobPtVNm="FFreeBlobPtV";
00147 
00148 void TBlobBs::GenFFreeBlobPtV(const TIntV& BlockLenV, TBlobPtV& FFreeBlobPtV){
00149   FFreeBlobPtV.Gen(BlockLenV.Len()+1);
00150 }
00151 
00152 void TBlobBs::PutFFreeBlobPtV(const PFRnd& FBlobBs, const TBlobPtV& FFreeBlobPtV){
00153   FBlobBs->PutStr(FFreeBlobPtVNm);
00154   FBlobBs->PutInt(FFreeBlobPtV.Len());
00155   for (int BlockLenN=0; BlockLenN<FFreeBlobPtV.Len(); BlockLenN++){
00156     FFreeBlobPtV[BlockLenN].Save(FBlobBs);}
00157   FBlobBs->PutInt(-1);
00158 }
00159 
00160 void TBlobBs::GetFFreeBlobPtV(const PFRnd& FBlobBs, TBlobPtV& FFreeBlobPtV){
00161   EAssert(FBlobBs->GetStr(FFreeBlobPtVNm.Len())==FFreeBlobPtVNm);
00162   FFreeBlobPtV.Gen(FBlobBs->GetInt());
00163   for (int FFreeBlobPtN=0; FFreeBlobPtN<FFreeBlobPtV.Len(); FFreeBlobPtN++){
00164     FFreeBlobPtV[FFreeBlobPtN]=TBlobPt::Load(FBlobBs);}
00165   EAssert(FBlobBs->GetInt()==-1);
00166 }
00167 
00168 void TBlobBs::GetAllocInfo(
00169  const int& BfL, const TIntV& BlockLenV, int& MxBfL, int& FFreeBlobPtN){
00170   int BlockLenN=0;
00171   while ((BlockLenN<BlockLenV.Len())&&(BfL>BlockLenV[BlockLenN])){
00172     BlockLenN++;}
00173   EAssert(BlockLenN<BlockLenV.Len());
00174   MxBfL=BlockLenV[BlockLenN]; FFreeBlobPtN=BlockLenN;
00175 }
00176 
00177 void TBlobBs::PutBlobTag(const PFRnd& FBlobBs, const TBlobTag& BlobTag){
00178   switch (BlobTag){
00179     case btBegin: FBlobBs->PutUInt(GetBeginBlobTag()); break;
00180     case btEnd: FBlobBs->PutUInt(GetEndBlobTag()); break;
00181     default: Fail;
00182   }
00183 }
00184 
00185 void TBlobBs::AssertBlobTag(const PFRnd& FBlobBs, const TBlobTag& BlobTag){
00186   switch (BlobTag){
00187     case btBegin: EAssert(FBlobBs->GetUInt()==GetBeginBlobTag()); break;
00188     case btEnd: EAssert(FBlobBs->GetUInt()==GetEndBlobTag()); break;
00189         default: TExcept::Throw("Error asserting BlobTag");
00190   }
00191 }
00192 
00193 void TBlobBs::PutBlobState(const PFRnd& FBlobBs, const TBlobState& State){
00194   FBlobBs->PutCh(char(State));
00195 }
00196 
00197 TBlobState TBlobBs::GetBlobState(const PFRnd& FBlobBs){
00198   return TBlobState(int(FBlobBs->GetCh()));
00199 }
00200 
00201 void TBlobBs::AssertBlobState(const PFRnd& FBlobBs, const TBlobState& State){
00202   EAssert(TBlobState(FBlobBs->GetCh())==State);
00203 }
00204 
00205 void TBlobBs::AssertBfCsEqFlCs(const TCs& BfCs, const TCs& FCs){
00206   if (BfCs!=FCs){
00207     printf("[%d:%d]\n", BfCs.Get(), FCs.Get());}
00208   //EAssert(BfCs==FCs);
00209 }
00210 
00212 // General-Blob-Base
00213 TStr TGBlobBs::GetNrBlobBsFNm(const TStr& BlobBsFNm){
00214   TStr NrBlobBsFNm=BlobBsFNm;
00215   if (NrBlobBsFNm.GetFExt().Empty()){
00216     NrBlobBsFNm=NrBlobBsFNm+".gbb";}
00217   return NrBlobBsFNm;
00218 }
00219 
00220 TGBlobBs::TGBlobBs(
00221  const TStr& BlobBsFNm, const TFAccess& _Access, const int& _MxSegLen):
00222   TBlobBs(), FBlobBs(), Access(_Access), MxSegLen(_MxSegLen),
00223   BlockLenV(), FFreeBlobPtV(TB4Def::B4Bits), FirstBlobPt(){
00224   if (MxSegLen==-1){MxSegLen=MxBlobFLen;}
00225   TStr NrBlobBsFNm=GetNrBlobBsFNm(BlobBsFNm);
00226   switch (Access){
00227     case faCreate:
00228       FBlobBs=TFRnd::New(NrBlobBsFNm, faCreate, true); break;
00229     case faUpdate:
00230     case faRdOnly:
00231     case faRestore:
00232       FBlobBs=TFRnd::New(NrBlobBsFNm, faUpdate, true); break;
00233     default: Fail;
00234   }
00235   if (FBlobBs->Empty()){
00236     FBlobBs->SetFPos(0);
00237     PutVersionStr(FBlobBs);
00238     PutBlobBsStateStr(FBlobBs, bbsOpened);
00239     PutMxSegLen(FBlobBs, MxSegLen);
00240     GenBlockLenV(BlockLenV);
00241     PutBlockLenV(FBlobBs, BlockLenV);
00242     GenFFreeBlobPtV(BlockLenV, FFreeBlobPtV);
00243     PutFFreeBlobPtV(FBlobBs, FFreeBlobPtV);
00244   } else {
00245     FBlobBs->SetFPos(0);
00246     AssertVersionStr(FBlobBs);
00247     int FPos=FBlobBs->GetFPos();
00248     if (Access!=faRestore){
00249       AssertBlobBsStateStr(FBlobBs, bbsClosed);}
00250     if (Access!=faRdOnly){
00251       FBlobBs->SetFPos(FPos);
00252       PutBlobBsStateStr(FBlobBs, bbsOpened);
00253     }
00254     MxSegLen=GetMxSegLen(FBlobBs);
00255     GetBlockLenV(FBlobBs, BlockLenV);
00256     GetFFreeBlobPtV(FBlobBs, FFreeBlobPtV);
00257   }
00258   FirstBlobPt=TBlobPt(FBlobBs->GetFPos());
00259   FBlobBs->Flush();
00260 }
00261 
00262 TGBlobBs::~TGBlobBs(){
00263   if (Access!=faRdOnly){
00264     FBlobBs->SetFPos(0);
00265     PutVersionStr(FBlobBs);
00266     PutBlobBsStateStr(FBlobBs, bbsClosed);
00267     PutMxSegLen(FBlobBs, MxSegLen);
00268     PutBlockLenV(FBlobBs, BlockLenV);
00269     PutFFreeBlobPtV(FBlobBs, FFreeBlobPtV);
00270   }
00271   FBlobBs->Flush();
00272   FBlobBs=NULL;
00273 }
00274 
00275 TBlobPt TGBlobBs::PutBlob(const PSIn& SIn){
00276   EAssert((Access==faCreate)||(Access==faUpdate)||(Access==faRestore));
00277   int BfL=SIn->Len();
00278   int MxBfL; int FFreeBlobPtN;
00279   GetAllocInfo(BfL, BlockLenV, MxBfL, FFreeBlobPtN);
00280   TBlobPt BlobPt; TCs Cs;
00281   if (FFreeBlobPtV[FFreeBlobPtN].Empty()){
00282     int FLen=FBlobBs->GetFLen();
00283     if (FLen<=MxSegLen){
00284       EAssert(FLen<=MxBlobFLen);
00285       BlobPt=TBlobPt(FLen);
00286       FBlobBs->SetFPos(BlobPt.GetAddr());
00287       PutBlobTag(FBlobBs, btBegin);
00288       FBlobBs->PutInt(MxBfL);
00289       PutBlobState(FBlobBs, bsActive);
00290       FBlobBs->PutInt(BfL);
00291       FBlobBs->PutSIn(SIn, Cs);
00292       FBlobBs->PutCh(TCh::NullCh, MxBfL-BfL);
00293       FBlobBs->PutCs(Cs);
00294       PutBlobTag(FBlobBs, btEnd);
00295     }
00296   } else {
00297     BlobPt=FFreeBlobPtV[FFreeBlobPtN];
00298     FBlobBs->SetFPos(BlobPt.GetAddr());
00299     AssertBlobTag(FBlobBs, btBegin);
00300     int MxBfL=FBlobBs->GetInt();
00301     int FPos=FBlobBs->GetFPos();
00302     AssertBlobState(FBlobBs, bsFree);
00303     FFreeBlobPtV[FFreeBlobPtN]=TBlobPt::LoadAddr(FBlobBs);
00304     FBlobBs->SetFPos(FPos);
00305     PutBlobState(FBlobBs, bsActive);
00306     FBlobBs->PutInt(BfL);
00307     FBlobBs->PutSIn(SIn, Cs);
00308     FBlobBs->PutCh(TCh::NullCh, MxBfL-BfL);
00309     FBlobBs->PutCs(Cs);
00310     AssertBlobTag(FBlobBs, btEnd);
00311   }
00312   FBlobBs->Flush();
00313   return BlobPt;
00314 }
00315 
00316 TBlobPt TGBlobBs::PutBlob(const TBlobPt& BlobPt, const PSIn& SIn){
00317   EAssert((Access==faCreate)||(Access==faUpdate)||(Access==faRestore));
00318   int BfL=SIn->Len();
00319 
00320   FBlobBs->SetFPos(BlobPt.GetAddr());
00321   AssertBlobTag(FBlobBs, btBegin);
00322   int MxBfL=FBlobBs->GetInt();
00323   AssertBlobState(FBlobBs, bsActive);
00324   if (BfL>MxBfL){
00325     DelBlob(BlobPt);
00326     return PutBlob(SIn);
00327   } else {
00328     TCs Cs;
00329     FBlobBs->PutInt(BfL);
00330     FBlobBs->PutSIn(SIn, Cs);
00331     FBlobBs->PutCh(TCh::NullCh, MxBfL-BfL);
00332     FBlobBs->PutCs(Cs);
00333     PutBlobTag(FBlobBs, btEnd);
00334     FBlobBs->Flush();
00335     return BlobPt;
00336   }
00337 }
00338 
00339 PSIn TGBlobBs::GetBlob(const TBlobPt& BlobPt){
00340   FBlobBs->SetFPos(BlobPt.GetAddr());
00341   AssertBlobTag(FBlobBs, btBegin);
00342   int MxBfL=FBlobBs->GetInt();
00343   AssertBlobState(FBlobBs, bsActive);
00344   int BfL=FBlobBs->GetInt();
00345   TCs BfCs; PSIn SIn=FBlobBs->GetSIn(BfL, BfCs);
00346   FBlobBs->MoveFPos(MxBfL-BfL);
00347   TCs FCs=FBlobBs->GetCs();
00348   AssertBlobTag(FBlobBs, btEnd);
00349   AssertBfCsEqFlCs(BfCs, FCs);
00350   return SIn;
00351 }
00352 
00353 void TGBlobBs::DelBlob(const TBlobPt& BlobPt){
00354   EAssert((Access==faCreate)||(Access==faUpdate)||(Access==faRestore));
00355   FBlobBs->SetFPos(BlobPt.GetAddr());
00356   AssertBlobTag(FBlobBs, btBegin);
00357   int MxBfL=FBlobBs->GetInt();
00358   int FPos=FBlobBs->GetFPos();
00359   AssertBlobState(FBlobBs, bsActive);
00360   /*int BfL=*/FBlobBs->GetInt();
00361   FBlobBs->SetFPos(FPos);
00362   PutBlobState(FBlobBs, bsFree);
00363   int _MxBfL; int FFreeBlobPtN;
00364   GetAllocInfo(MxBfL, BlockLenV, _MxBfL, FFreeBlobPtN);
00365   EAssert(MxBfL==_MxBfL);
00366   FFreeBlobPtV[FFreeBlobPtN].SaveAddr(FBlobBs);
00367   FFreeBlobPtV[FFreeBlobPtN]=BlobPt;
00368   FBlobBs->PutCh(TCh::NullCh, MxBfL+sizeof(TCs));
00369   AssertBlobTag(FBlobBs, btEnd);
00370   FBlobBs->Flush();
00371 }
00372 
00373 TBlobPt TGBlobBs::FFirstBlobPt(){
00374   return FirstBlobPt;
00375 }
00376 
00377 bool TGBlobBs::FNextBlobPt(TBlobPt& TrvBlobPt, TBlobPt& BlobPt, PSIn& BlobSIn){
00378   forever {
00379     uint TrvBlobAddr=TrvBlobPt.GetAddr();
00380     if (TrvBlobAddr>=uint(FBlobBs->GetFLen())){
00381       TrvBlobPt.Clr(); BlobPt.Clr(); BlobSIn=NULL;
00382       return false;
00383     } else {
00384       FBlobBs->SetFPos(TrvBlobAddr);
00385       AssertBlobTag(FBlobBs, btBegin);
00386       int MxBfL=FBlobBs->GetInt();
00387       TBlobState BlobState=GetBlobState(FBlobBs);
00388       switch (BlobState){
00389         case bsActive:{
00390           int BfL=FBlobBs->GetInt();
00391           TCs BfCs; BlobSIn=FBlobBs->GetSIn(BfL, BfCs);
00392           FBlobBs->MoveFPos(MxBfL-BfL);
00393           TCs FCs=FBlobBs->GetCs();
00394           AssertBlobTag(FBlobBs, btEnd);
00395           AssertBfCsEqFlCs(BfCs, FCs);
00396           BlobPt=TrvBlobPt;
00397           TrvBlobPt=TBlobPt(FBlobBs->GetFPos());
00398           return true;}
00399         case bsFree:
00400           FBlobBs->MoveFPos(sizeof(uint)+MxBfL+sizeof(TCs));
00401           AssertBlobTag(FBlobBs, btEnd);
00402           TrvBlobPt=TBlobPt(FBlobBs->GetFPos());
00403           break;
00404         default: Fail; return false;
00405       }
00406     }
00407   }
00408 }
00409 
00410 bool TGBlobBs::Exists(const TStr& BlobBsFNm){
00411   TStr NrBlobBsFNm=GetNrBlobBsFNm(BlobBsFNm);
00412   return TFile::Exists(NrBlobBsFNm);
00413 }
00414 
00416 // Multiple-File-Blob-Base
00417 void TMBlobBs::GetNrFPathFMid(
00418  const TStr& BlobBsFNm, TStr& NrFPath, TStr& NrFMid){
00419   NrFPath=TStr::GetNrFPath(BlobBsFNm.GetFPath());
00420   NrFMid=TStr::GetNrFMid(BlobBsFNm.GetFMid());
00421 }
00422 
00423 TStr TMBlobBs::GetMainFNm(
00424  const TStr& NrFPath, const TStr& NrFMid){
00425   return NrFPath+NrFMid+".mbb";
00426 }
00427 
00428 TStr TMBlobBs::GetSegFNm(
00429  const TStr& NrFPath, const TStr& NrFMid, const int& SegN){
00430   return NrFPath+NrFMid+".mbb"+""+TStr::GetNrNumFExt(SegN);
00431 }
00432 
00433 void TMBlobBs::LoadMain(int& Segs){
00434   PSIn SIn=TFIn::New(GetMainFNm(NrFPath, NrFMid));
00435   TILx Lx(SIn, TFSet()|oloFrcEoln|oloSigNum|oloCsSens);
00436   EAssert(Lx.GetVarStr("Version")==GetVersionStr());
00437   MxSegLen=Lx.GetVarInt("MxSegLen");
00438   Segs=Lx.GetVarInt("Segments");
00439 }
00440 
00441 void TMBlobBs::SaveMain() const {
00442   PSOut SOut=TFOut::New(GetMainFNm(NrFPath, NrFMid));
00443   TOLx Lx(SOut, TFSet()|oloFrcEoln|oloSigNum|oloCsSens);
00444   Lx.PutVarStr("Version", GetVersionStr());
00445   Lx.PutVarInt("MxSegLen", MxSegLen);
00446   Lx.PutVarInt("Segments", SegV.Len());
00447 }
00448 
00449 TMBlobBs::TMBlobBs(
00450  const TStr& BlobBsFNm, const TFAccess& _Access, const int& _MxSegLen):
00451   TBlobBs(), Access(_Access), MxSegLen(_MxSegLen),
00452   NrFPath(), NrFMid(), SegV(), CurSegN(0){
00453   if (MxSegLen==-1){MxSegLen=MxBlobFLen;}
00454   GetNrFPathFMid(BlobBsFNm, NrFPath, NrFMid);
00455   switch (Access){
00456     case faCreate:{
00457       TFile::DelWc(BlobBsFNm+".*");
00458       TStr SegFNm=GetSegFNm(NrFPath, NrFMid, 0);
00459       PBlobBs Seg=TGBlobBs::New(SegFNm, faCreate, MxSegLen);
00460       SegV.Add(Seg);
00461       SaveMain(); break;}
00462     case faUpdate:
00463     case faRdOnly:{
00464       int Segs; LoadMain(Segs);
00465       for (int SegN=0; SegN<Segs; SegN++){
00466         TStr SegFNm=GetSegFNm(NrFPath, NrFMid, SegN);
00467         SegV.Add(TGBlobBs::New(SegFNm, Access, MxSegLen));
00468       }
00469       break;}
00470     case faRestore:{
00471       // assume no segments
00472       int Segs=-1;
00473       // if main-file exists
00474       if (TFile::Exists(GetMainFNm(NrFPath, NrFMid))){
00475         // load main file
00476         int _Segs; LoadMain(_Segs);
00477         // load segment-files which exist
00478         Segs=0;
00479         forever {
00480           // get segment file-name
00481           TStr SegFNm=GetSegFNm(NrFPath, NrFMid, Segs);
00482           // if segment-file exists then add segment else break check-loop
00483           if (TFile::Exists(SegFNm)){
00484             SegV.Add(TGBlobBs::New(SegFNm, Access, MxSegLen));
00485             Segs++;
00486           } else {
00487             break;
00488           }
00489         }
00490       }
00491       // if no segments exist then create blob-base from scratch
00492       if (Segs==-1){
00493         TStr SegFNm=GetSegFNm(NrFPath, NrFMid, 0);
00494         PBlobBs Seg=TGBlobBs::New(SegFNm, faCreate, MxSegLen);
00495         SegV.Add(Seg);
00496         SaveMain();
00497       }
00498       break;}
00499     default: Fail;
00500   }
00501 }
00502 
00503 TMBlobBs::~TMBlobBs(){
00504   if (Access!=faRdOnly){
00505     SaveMain();
00506   }
00507 }
00508 
00509 TBlobPt TMBlobBs::PutBlob(const PSIn& SIn){
00510   EAssert((Access==faCreate)||(Access==faUpdate)||(Access==faRestore));
00511   TBlobPt BlobPt=SegV[CurSegN]->PutBlob(SIn);
00512   if (BlobPt.Empty()){
00513     for (uchar SegN=0; SegN<SegV.Len(); SegN++){
00514       BlobPt=SegV[CurSegN=SegN]->PutBlob(SIn);
00515       if (!BlobPt.Empty()){break;}
00516     }
00517     if (BlobPt.Empty()){
00518       TStr SegFNm=GetSegFNm(NrFPath, NrFMid, SegV.Len());
00519       PBlobBs Seg=TGBlobBs::New(SegFNm, faCreate, MxSegLen);
00520       CurSegN=SegV.Add(Seg); EAssert(CurSegN<=255);
00521       BlobPt=SegV[CurSegN]->PutBlob(SIn);
00522     }
00523   }
00524   if (!BlobPt.Empty()){
00525     BlobPt.PutSeg(uchar(CurSegN));}
00526   return BlobPt;
00527 }
00528 
00529 TBlobPt TMBlobBs::PutBlob(const TBlobPt& BlobPt, const PSIn& SIn){
00530   EAssert((Access==faCreate)||(Access==faUpdate)||(Access==faRestore));
00531   int SegN=BlobPt.GetSeg();
00532   TBlobPt NewBlobPt=SegV[SegN]->PutBlob(BlobPt, SIn);
00533   if (NewBlobPt.Empty()){
00534     NewBlobPt=PutBlob(SIn);
00535   } else {
00536     NewBlobPt.PutSeg(BlobPt.GetSeg());
00537   }
00538   return NewBlobPt;
00539 }
00540 
00541 PSIn TMBlobBs::GetBlob(const TBlobPt& BlobPt){
00542   int SegN=BlobPt.GetSeg();
00543   return SegV[SegN]->GetBlob(BlobPt);
00544 }
00545 
00546 void TMBlobBs::DelBlob(const TBlobPt& BlobPt){
00547   int SegN=BlobPt.GetSeg();
00548   SegV[SegN]->DelBlob(BlobPt);
00549 }
00550 
00551 TBlobPt TMBlobBs::GetFirstBlobPt(){
00552   return SegV[0]->GetFirstBlobPt();
00553 }
00554 
00555 TBlobPt TMBlobBs::FFirstBlobPt(){
00556   return SegV[0]->FFirstBlobPt();
00557 }
00558 
00559 bool TMBlobBs::FNextBlobPt(TBlobPt& TrvBlobPt, TBlobPt& BlobPt, PSIn& BlobSIn){
00560   uchar SegN=TrvBlobPt.GetSeg();
00561   if (SegV[SegN]->FNextBlobPt(TrvBlobPt, BlobPt, BlobSIn)){
00562     TrvBlobPt.PutSeg(SegN);
00563     BlobPt.PutSeg(SegN);
00564     return true;
00565   } else
00566   if (SegN==SegV.Len()-1){
00567     return false;
00568   } else {
00569     SegN++;
00570     TrvBlobPt=SegV[SegN]->FFirstBlobPt();
00571     TrvBlobPt.PutSeg(SegN);
00572     return FNextBlobPt(TrvBlobPt, BlobPt, BlobSIn);
00573   }
00574 }
00575 
00576 bool TMBlobBs::Exists(const TStr& BlobBsFNm){
00577   TStr NrFPath; TStr NrFMid; GetNrFPathFMid(BlobBsFNm, NrFPath, NrFMid);
00578   TStr MainFNm=GetMainFNm(NrFPath, NrFMid);
00579   return TFile::Exists(MainFNm);
00580 }