SNAP Library , Developer Reference  2013-01-07 14:03:36
SNAP, a general purpose, high performance system for analysis and manipulation of large networks
 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 }