// -------------------------------------------------------------------------- // // File // Name: BackupStoreCheckData.cpp // Purpose: Data handling for store checking // Created: 21/4/04 // // -------------------------------------------------------------------------- #include "Box.h" #include #include #include "BackupStoreCheck.h" #include "autogen_BackupStoreException.h" #include "MemLeakFindOn.h" // -------------------------------------------------------------------------- // // Function // Name: BackupStoreCheck::FreeInfo() // Purpose: Free all the data stored // Created: 21/4/04 // // -------------------------------------------------------------------------- void BackupStoreCheck::FreeInfo() { // Free all the blocks for(Info_t::iterator i(mInfo.begin()); i != mInfo.end(); ++i) { ::free(i->second); } // Clear the contents of the map mInfo.clear(); // Reset the last ID, just in case mpInfoLastBlock = 0; mInfoLastBlockEntries = 0; mLastIDInInfo = 0; } // -------------------------------------------------------------------------- // // Function // Name: BackupStoreCheck::AddID(BackupStoreCheck_ID_t, BackupStoreCheck_ID_t, bool) // Purpose: Add an ID to the list // Created: 21/4/04 // // -------------------------------------------------------------------------- void BackupStoreCheck::AddID(BackupStoreCheck_ID_t ID, BackupStoreCheck_ID_t Container, BackupStoreCheck_Size_t ObjectSize, bool IsFile) { // Check ID is OK. if(ID <= mLastIDInInfo) { THROW_EXCEPTION(BackupStoreException, InternalAlgorithmErrorCheckIDNotMonotonicallyIncreasing) } // Can this go in the current block? if(mpInfoLastBlock == 0 || mInfoLastBlockEntries >= BACKUPSTORECHECK_BLOCK_SIZE) { // No. Allocate a new one IDBlock *pblk = (IDBlock*)calloc(1, sizeof(IDBlock)); if(pblk == 0) { throw std::bad_alloc(); } // Store in map mInfo[ID] = pblk; // Allocated and stored OK, setup for use mpInfoLastBlock = pblk; mInfoLastBlockEntries = 0; } ASSERT(mpInfoLastBlock != 0 && mInfoLastBlockEntries < BACKUPSTORECHECK_BLOCK_SIZE); // Add to block mpInfoLastBlock->mID[mInfoLastBlockEntries] = ID; mpInfoLastBlock->mContainer[mInfoLastBlockEntries] = Container; mpInfoLastBlock->mObjectSizeInBlocks[mInfoLastBlockEntries] = ObjectSize; SetFlags(mpInfoLastBlock, mInfoLastBlockEntries, IsFile?(0):(Flags_IsDir)); // Increment size ++mInfoLastBlockEntries; // Store last ID mLastIDInInfo = ID; } // -------------------------------------------------------------------------- // // Function // Name: BackupStoreCheck::LookupID(BackupStoreCheck_ID_t, int32_t // Purpose: Look up an ID. Return the block it's in, or zero if not found, and the // index within that block if the thing is found. // Created: 21/4/04 // // -------------------------------------------------------------------------- BackupStoreCheck::IDBlock *BackupStoreCheck::LookupID(BackupStoreCheck_ID_t ID, int32_t &rIndexOut) { IDBlock *pblock = 0; // Find the lower matching block who's first entry is not less than ID Info_t::const_iterator ib(mInfo.lower_bound(ID)); // Was there a block if(ib == mInfo.end()) { // Block wasn't found... could be in last block pblock = mpInfoLastBlock; } else { // Found it as first entry? if(ib->first == ID) { rIndexOut = 0; return ib->second; } // Go back one block as it's not the first entry in this one if(ib == mInfo.begin()) { // Was first block, can't go back return 0; } // Go back... --ib; // So, the ID will be in this block, if it's in anything pblock = ib->second; } if(pblock == 0) return 0; ASSERT(pblock != 0); // How many entries are there in the block int32_t bentries = (pblock == mpInfoLastBlock)?mInfoLastBlockEntries:BACKUPSTORECHECK_BLOCK_SIZE; // Do binary search within block int high = bentries; int low = -1; while(high - low > 1) { int i = (high + low) / 2; if(ID <= pblock->mID[i]) { high = i; } else { low = i; } } if(ID == pblock->mID[high]) { // Found rIndexOut = high; return pblock; } // Not found return 0; } #ifndef BOX_RELEASE_BUILD // -------------------------------------------------------------------------- // // Function // Name: BackupStoreCheck::DumpObjectInfo() // Purpose: Debug only. Trace out all object info. // Created: 22/4/04 // // -------------------------------------------------------------------------- void BackupStoreCheck::DumpObjectInfo() { for(Info_t::const_iterator i(mInfo.begin()); i != mInfo.end(); ++i) { IDBlock *pblock = i->second; int32_t bentries = (pblock == mpInfoLastBlock)?mInfoLastBlockEntries:BACKUPSTORECHECK_BLOCK_SIZE; BOX_TRACE("BLOCK @ " << BOX_FORMAT_HEX32(pblock) << ", " << bentries << " entries"); for(int e = 0; e < bentries; ++e) { uint8_t flags = GetFlags(pblock, e); BOX_TRACE(std::hex << "id " << pblock->mID[e] << ", c " << pblock->mContainer[e] << ", " << ((flags & Flags_IsDir)?"dir":"file") << ", " << ((flags & Flags_IsContained) ? "contained":"unattached")); } } } #endif