Changeset 2534


Ignore:
Timestamp:
27/06/2009 12:38:52 (3 years ago)
Author:
chris
Message:

Add code for BackupStoreRefCountDatabase?.

Create a refcount database when creating a new account.

Add an easier way to get the account root directory.

Location:
box/trunk/lib/backupstore
Files:
2 edited
2 copied

Legend:

Unmodified
Added
Removed
  • box/trunk/lib/backupstore/BackupStoreAccounts.cpp

    r881 r2534  
    1515#include "BackupStoreAccounts.h" 
    1616#include "BackupStoreAccountDatabase.h" 
     17#include "BackupStoreRefCountDatabase.h" 
    1718#include "RaidFileWrite.h" 
    1819#include "BackupStoreInfo.h" 
     
    6263void BackupStoreAccounts::Create(int32_t ID, int DiscSet, int64_t SizeSoftLimit, int64_t SizeHardLimit, const std::string &rAsUsername) 
    6364{ 
     65        // Create the entry in the database 
     66        BackupStoreAccountDatabase::Entry Entry(mrDatabase.AddEntry(ID, 
     67                DiscSet)); 
     68         
    6469        { 
    6570                // Become the user specified in the config file? 
     
    101106                // Save it back 
    102107                info->Save(); 
     108 
     109                // Create the refcount database 
     110                BackupStoreRefCountDatabase::CreateNew(Entry); 
     111                std::auto_ptr<BackupStoreRefCountDatabase> refcount( 
     112                        BackupStoreRefCountDatabase::Load(Entry, false)); 
     113                refcount->AddReference(BACKUPSTORE_ROOT_DIRECTORY_ID); 
    103114        } 
    104115 
    105116        // As the original user... 
    106  
    107         // Create the entry in the database 
    108         mrDatabase.AddEntry(ID, DiscSet); 
    109          
    110117        // Write the database back 
    111         mrDatabase.Write();      
     118        mrDatabase.Write(); 
    112119} 
    113120 
     
    139146// 
    140147// -------------------------------------------------------------------------- 
    141 std::string BackupStoreAccounts::MakeAccountRootDir(int32_t ID, int DiscSet) const 
     148std::string BackupStoreAccounts::MakeAccountRootDir(int32_t ID, int DiscSet) 
    142149{ 
    143150        char accid[64]; // big enough! 
  • box/trunk/lib/backupstore/BackupStoreAccounts.h

    r217 r2534  
    1313#include <string> 
    1414 
    15 class BackupStoreAccountDatabase; 
     15#include "BackupStoreAccountDatabase.h" 
    1616 
    1717// -------------------------------------------------------------------------- 
     
    3636        bool AccountExists(int32_t ID); 
    3737        void GetAccountRoot(int32_t ID, std::string &rRootDirOut, int &rDiscSetOut) const; 
     38        static std::string GetAccountRoot(const 
     39                BackupStoreAccountDatabase::Entry &rEntry) 
     40        { 
     41                return MakeAccountRootDir(rEntry.GetID(), rEntry.GetDiscSet()); 
     42        } 
    3843 
    3944private: 
    40         std::string MakeAccountRootDir(int32_t ID, int DiscSet) const; 
     45        static std::string MakeAccountRootDir(int32_t ID, int DiscSet); 
    4146 
    4247private: 
  • box/trunk/lib/backupstore/BackupStoreRefCountDatabase.cpp

    r2415 r2534  
    22// 
    33// File 
    4 //              Name:    BackupStoreInfo.cpp 
    5 //              Purpose: Main backup store information storage 
    6 //              Created: 2003/08/28 
     4//              Name:    BackupStoreRefCountDatabase.cpp 
     5//              Purpose: Backup store object reference count database storage 
     6//              Created: 2009/06/01 
    77// 
    88// -------------------------------------------------------------------------- 
     
    1212#include <algorithm> 
    1313 
    14 #include "BackupStoreInfo.h" 
     14#include "BackupStoreRefCountDatabase.h" 
    1515#include "BackupStoreException.h" 
    16 #include "RaidFileWrite.h" 
    17 #include "RaidFileRead.h" 
     16#include "BackupStoreAccountDatabase.h" 
     17#include "BackupStoreAccounts.h" 
     18#include "RaidFileController.h" 
     19#include "RaidFileUtil.h" 
     20#include "RaidFileException.h" 
    1821 
    1922#include "MemLeakFindOn.h" 
    2023 
    21 // set packing to one byte 
    22 #ifdef STRUCTURE_PACKING_FOR_WIRE_USE_HEADERS 
    23 #include "BeginStructPackForWire.h" 
    24 #else 
    25 BEGIN_STRUCTURE_PACKING_FOR_WIRE 
    26 #endif 
    27  
    28 // ****************** 
    29 // make sure the defaults in CreateNew are modified! 
    30 // ****************** 
    31 typedef struct 
    32 { 
    33         int32_t mMagicValue;    // also the version number 
    34         int32_t mAccountID; 
    35         int64_t mClientStoreMarker; 
    36         int64_t mLastObjectIDUsed; 
    37         int64_t mBlocksUsed; 
    38         int64_t mBlocksInOldFiles; 
    39         int64_t mBlocksInDeletedFiles; 
    40         int64_t mBlocksInDirectories; 
    41         int64_t mBlocksSoftLimit; 
    42         int64_t mBlocksHardLimit; 
    43         uint32_t mCurrentMarkNumber; 
    44         uint32_t mOptionsPresent;               // bit mask of optional elements present 
    45         int64_t mNumberDeletedDirectories; 
    46         // Then loads of int64_t IDs for the deleted directories 
    47 } info_StreamFormat; 
    48  
    49 #define INFO_MAGIC_VALUE        0x34832476 
    50  
    51 // Use default packing 
    52 #ifdef STRUCTURE_PACKING_FOR_WIRE_USE_HEADERS 
    53 #include "EndStructPackForWire.h" 
    54 #else 
    55 END_STRUCTURE_PACKING_FOR_WIRE 
    56 #endif 
    57  
    58 #ifdef BOX_RELEASE_BUILD 
    59         #define         NUM_DELETED_DIRS_BLOCK  256 
    60 #else 
    61         #define         NUM_DELETED_DIRS_BLOCK  2 
    62 #endif 
    63  
    64 #define INFO_FILENAME   "info" 
    65  
    66 // -------------------------------------------------------------------------- 
    67 // 
    68 // Function 
    69 //              Name:    BackupStoreInfo::BackupStoreInfo() 
     24#define REFCOUNT_MAGIC_VALUE    0x52656643 // RefC 
     25#define REFCOUNT_FILENAME       "refcount" 
     26 
     27// -------------------------------------------------------------------------- 
     28// 
     29// Function 
     30//              Name:    BackupStoreRefCountDatabase::BackupStoreRefCountDatabase() 
    7031//              Purpose: Default constructor 
    7132//              Created: 2003/08/28 
    7233// 
    7334// -------------------------------------------------------------------------- 
    74 BackupStoreInfo::BackupStoreInfo() 
    75         : mAccountID(-1), 
    76           mDiscSet(-1), 
    77           mReadOnly(true), 
    78           mIsModified(false), 
    79           mClientStoreMarker(0), 
    80           mLastObjectIDUsed(-1), 
    81           mBlocksUsed(0), 
    82           mBlocksInOldFiles(0), 
    83           mBlocksInDeletedFiles(0) 
    84 { 
    85 } 
    86  
    87 // -------------------------------------------------------------------------- 
    88 // 
    89 // Function 
    90 //              Name:    BackupStoreInfo::~BackupStoreInfo 
     35BackupStoreRefCountDatabase::BackupStoreRefCountDatabase(const 
     36        BackupStoreAccountDatabase::Entry& rAccount) 
     37: mAccount(rAccount), 
     38  mFilename(GetFilename(rAccount)), 
     39  mReadOnly(true), 
     40  mIsModified(false) 
     41{ 
     42} 
     43 
     44// -------------------------------------------------------------------------- 
     45// 
     46// Function 
     47//              Name:    BackupStoreRefCountDatabase::~BackupStoreRefCountDatabase 
    9148//              Purpose: Destructor 
    9249//              Created: 2003/08/28 
    9350// 
    9451// -------------------------------------------------------------------------- 
    95 BackupStoreInfo::~BackupStoreInfo() 
    96 { 
    97 } 
    98  
    99 // -------------------------------------------------------------------------- 
    100 // 
    101 // Function 
    102 //              Name:    BackupStoreInfo::CreateNew(int32_t, const std::string &, int) 
    103 //              Purpose: Create a new info file on disc 
    104 //              Created: 2003/08/28 
    105 // 
    106 // -------------------------------------------------------------------------- 
    107 void BackupStoreInfo::CreateNew(int32_t AccountID, const std::string &rRootDir, int DiscSet, int64_t BlockSoftLimit, int64_t BlockHardLimit) 
    108 { 
    109         // Initial header (is entire file) 
    110         info_StreamFormat hdr = { 
    111                 htonl(INFO_MAGIC_VALUE), // mMagicValue 
    112                 htonl(AccountID), // mAccountID 
    113                 0, // mClientStoreMarker 
    114                 box_hton64(1), // mLastObjectIDUsed (which is the root directory) 
    115                 0, // mBlocksUsed 
    116                 0, // mBlocksInOldFiles 
    117                 0, // mBlocksInDeletedFiles 
    118                 0, // mBlocksInDirectories 
    119                 box_hton64(BlockSoftLimit), // mBlocksSoftLimit 
    120                 box_hton64(BlockHardLimit), // mBlocksHardLimit 
    121                 0, // mCurrentMarkNumber 
    122                 0, // mOptionsPresent 
    123                 0 // mNumberDeletedDirectories 
    124         }; 
     52BackupStoreRefCountDatabase::~BackupStoreRefCountDatabase() 
     53{ 
     54} 
     55 
     56std::string BackupStoreRefCountDatabase::GetFilename(const 
     57        BackupStoreAccountDatabase::Entry& rAccount) 
     58{ 
     59        std::string RootDir = BackupStoreAccounts::GetAccountRoot(rAccount); 
     60        ASSERT(RootDir[RootDir.size() - 1] == '/' || 
     61                RootDir[RootDir.size() - 1] == DIRECTORY_SEPARATOR_ASCHAR); 
     62 
     63        std::string fn(RootDir + "refcount.db"); 
     64        RaidFileController &rcontroller(RaidFileController::GetController()); 
     65        RaidFileDiscSet rdiscSet(rcontroller.GetDiscSet(rAccount.GetDiscSet())); 
     66        return RaidFileUtil::MakeWriteFileName(rdiscSet, fn); 
     67} 
     68 
     69// -------------------------------------------------------------------------- 
     70// 
     71// Function 
     72//              Name:    BackupStoreRefCountDatabase::Create(int32_t, 
     73//                       const std::string &, int, bool) 
     74//              Purpose: Create a new database, overwriting an existing 
     75//                       one only if AllowOverwrite is true. 
     76//              Created: 2003/08/28 
     77// 
     78// -------------------------------------------------------------------------- 
     79void BackupStoreRefCountDatabase::Create(const 
     80        BackupStoreAccountDatabase::Entry& rAccount, bool AllowOverwrite) 
     81{ 
     82        // Initial header 
     83        refcount_StreamFormat hdr; 
     84        hdr.mMagicValue = htonl(REFCOUNT_MAGIC_VALUE); 
     85        hdr.mAccountID = htonl(rAccount.GetID()); 
    12586         
    12687        // Generate the filename 
    127         ASSERT(rRootDir[rRootDir.size() - 1] == '/' || 
    128                 rRootDir[rRootDir.size() - 1] == DIRECTORY_SEPARATOR_ASCHAR); 
    129         std::string fn(rRootDir + INFO_FILENAME); 
    130          
     88        std::string Filename = GetFilename(rAccount); 
     89 
    13190        // Open the file for writing 
    132         RaidFileWrite rf(DiscSet, fn); 
    133         rf.Open(false);         // no overwriting, as this is a new file 
     91        if (FileExists(Filename) && !AllowOverwrite) 
     92        { 
     93                BOX_ERROR("Attempted to overwrite refcount database file: " << 
     94                        Filename); 
     95                THROW_EXCEPTION(RaidFileException, CannotOverwriteExistingFile); 
     96        } 
     97 
     98        int flags = O_CREAT | O_BINARY | O_RDWR; 
     99        if (!AllowOverwrite) 
     100        { 
     101                flags |= O_EXCL; 
     102        } 
     103 
     104        std::auto_ptr<FileStream> DatabaseFile(new FileStream(Filename, flags)); 
    134105         
    135106        // Write header 
    136         rf.Write(&hdr, sizeof(hdr)); 
    137          
    138         // Commit it to disc, converting it to RAID now 
    139         rf.Commit(true); 
    140          
    141         // Done. 
    142 } 
    143  
    144 // -------------------------------------------------------------------------- 
    145 // 
    146 // Function 
    147 //              Name:    BackupStoreInfo::Load(int32_t, const std::string &, int, bool) 
    148 //              Purpose: Loads the info from disc, given the root information. Can be marked as read only. 
    149 //              Created: 2003/08/28 
    150 // 
    151 // -------------------------------------------------------------------------- 
    152 std::auto_ptr<BackupStoreInfo> BackupStoreInfo::Load(int32_t AccountID, const std::string &rRootDir, int DiscSet, bool ReadOnly, int64_t *pRevisionID) 
     107        DatabaseFile->Write(&hdr, sizeof(hdr)); 
     108} 
     109 
     110// -------------------------------------------------------------------------- 
     111// 
     112// Function 
     113//              Name:    BackupStoreRefCountDatabase::Load(int32_t AccountID, 
     114//                       BackupStoreAccountDatabase& rAccountDatabase, 
     115//                       bool ReadOnly); 
     116//              Purpose: Loads the info from disc, given the root 
     117//                       information. Can be marked as read only. 
     118//              Created: 2003/08/28 
     119// 
     120// -------------------------------------------------------------------------- 
     121std::auto_ptr<BackupStoreRefCountDatabase> BackupStoreRefCountDatabase::Load( 
     122        const BackupStoreAccountDatabase::Entry& rAccount, bool ReadOnly) 
    153123{ 
    154124        // Generate the filename 
    155         std::string fn(rRootDir + DIRECTORY_SEPARATOR INFO_FILENAME); 
    156          
    157         // Open the file for reading (passing on optional request for revision ID) 
    158         std::auto_ptr<RaidFileRead> rf(RaidFileRead::Open(DiscSet, fn, pRevisionID)); 
     125        std::string filename = GetFilename(rAccount); 
     126        int flags = ReadOnly ? O_RDONLY : O_RDWR; 
     127 
     128        // Open the file for read/write 
     129        std::auto_ptr<FileStream> dbfile(new FileStream(filename, 
     130                flags | O_BINARY)); 
    159131         
    160132        // Read in a header 
    161         info_StreamFormat hdr; 
    162         if(!rf->ReadFullBuffer(&hdr, sizeof(hdr), 0 /* not interested in bytes read if this fails */)) 
     133        refcount_StreamFormat hdr; 
     134        if(!dbfile->ReadFullBuffer(&hdr, sizeof(hdr), 0 /* not interested in bytes read if this fails */)) 
    163135        { 
    164136                THROW_EXCEPTION(BackupStoreException, CouldNotLoadStoreInfo) 
     
    166138         
    167139        // Check it 
    168         if(ntohl(hdr.mMagicValue) != INFO_MAGIC_VALUE || (int32_t)ntohl(hdr.mAccountID) != AccountID) 
     140        if(ntohl(hdr.mMagicValue) != REFCOUNT_MAGIC_VALUE || 
     141                (int32_t)ntohl(hdr.mAccountID) != rAccount.GetID()) 
    169142        { 
    170143                THROW_EXCEPTION(BackupStoreException, BadStoreInfoOnLoad) 
     
    172145         
    173146        // Make new object 
    174         std::auto_ptr<BackupStoreInfo> info(new BackupStoreInfo); 
     147        std::auto_ptr<BackupStoreRefCountDatabase> refcount(new BackupStoreRefCountDatabase(rAccount)); 
    175148         
    176149        // Put in basic location info 
    177         info->mAccountID = AccountID; 
    178         info->mDiscSet = DiscSet; 
    179         info->mFilename = fn; 
    180         info->mReadOnly = ReadOnly; 
    181          
    182         // Insert info from file 
    183         info->mClientStoreMarker        = box_ntoh64(hdr.mClientStoreMarker); 
    184         info->mLastObjectIDUsed         = box_ntoh64(hdr.mLastObjectIDUsed); 
    185         info->mBlocksUsed               = box_ntoh64(hdr.mBlocksUsed); 
    186         info->mBlocksInOldFiles         = box_ntoh64(hdr.mBlocksInOldFiles); 
    187         info->mBlocksInDeletedFiles     = box_ntoh64(hdr.mBlocksInDeletedFiles); 
    188         info->mBlocksInDirectories      = box_ntoh64(hdr.mBlocksInDirectories); 
    189         info->mBlocksSoftLimit          = box_ntoh64(hdr.mBlocksSoftLimit); 
    190         info->mBlocksHardLimit          = box_ntoh64(hdr.mBlocksHardLimit); 
    191          
    192         // Load up array of deleted objects 
    193         int64_t numDelObj = box_ntoh64(hdr.mNumberDeletedDirectories); 
    194          
    195         // Then load them in 
    196         if(numDelObj > 0) 
    197         { 
    198                 int64_t objs[NUM_DELETED_DIRS_BLOCK]; 
    199                  
    200                 int64_t toload = numDelObj; 
    201                 while(toload > 0) 
    202                 { 
    203                         // How many in this one? 
    204                         int b = (toload > NUM_DELETED_DIRS_BLOCK)?NUM_DELETED_DIRS_BLOCK:((int)(toload)); 
    205                          
    206                         if(!rf->ReadFullBuffer(objs, b * sizeof(int64_t), 0 /* not interested in bytes read if this fails */)) 
    207                         { 
    208                                 THROW_EXCEPTION(BackupStoreException, CouldNotLoadStoreInfo) 
    209                         } 
    210                          
    211                         // Add them 
    212                         for(int t = 0; t < b; ++t) 
    213                         { 
    214                                 info->mDeletedDirectories.push_back(box_ntoh64(objs[t])); 
    215                         } 
    216                          
    217                         // Number loaded 
    218                         toload -= b; 
    219                 } 
    220         } 
    221  
    222         // Final check 
    223         if(static_cast<int64_t>(info->mDeletedDirectories.size()) != numDelObj) 
    224         { 
    225                 THROW_EXCEPTION(BackupStoreException, BadStoreInfoOnLoad) 
    226         } 
     150        refcount->mReadOnly = ReadOnly; 
     151        refcount->mapDatabaseFile = dbfile; 
    227152         
    228153        // return it to caller 
    229         return info; 
    230 } 
    231  
    232  
    233 // -------------------------------------------------------------------------- 
    234 // 
    235 // Function 
    236 //              Name:    BackupStoreInfo::CreateForRegeneration(...) 
    237 //              Purpose: Return an object which can be used to save for regeneration. 
    238 //              Created: 23/4/04 
    239 // 
    240 // -------------------------------------------------------------------------- 
    241 std::auto_ptr<BackupStoreInfo> BackupStoreInfo::CreateForRegeneration(int32_t AccountID, const std::string &rRootDir, 
    242         int DiscSet, int64_t LastObjectID, int64_t BlocksUsed, int64_t BlocksInOldFiles, 
    243         int64_t BlocksInDeletedFiles, int64_t BlocksInDirectories, int64_t BlockSoftLimit, int64_t BlockHardLimit) 
    244 { 
    245         // Generate the filename 
    246         std::string fn(rRootDir + DIRECTORY_SEPARATOR INFO_FILENAME); 
    247          
    248         // Make new object 
    249         std::auto_ptr<BackupStoreInfo> info(new BackupStoreInfo); 
    250          
    251         // Put in basic info 
    252         info->mAccountID = AccountID; 
    253         info->mDiscSet = DiscSet; 
    254         info->mFilename = fn; 
    255         info->mReadOnly = false; 
    256          
    257         // Insert info starting info 
    258         info->mClientStoreMarker        = 0; 
    259         info->mLastObjectIDUsed         = LastObjectID; 
    260         info->mBlocksUsed                       = BlocksUsed; 
    261         info->mBlocksInOldFiles         = BlocksInOldFiles; 
    262         info->mBlocksInDeletedFiles     = BlocksInDeletedFiles; 
    263         info->mBlocksInDirectories      = BlocksInDirectories; 
    264         info->mBlocksSoftLimit          = BlockSoftLimit; 
    265         info->mBlocksHardLimit          = BlockHardLimit; 
    266          
    267         // return it to caller 
    268         return info; 
    269 } 
    270  
    271  
    272 // -------------------------------------------------------------------------- 
    273 // 
    274 // Function 
    275 //              Name:    BackupStoreInfo::Save() 
     154        return refcount; 
     155} 
     156 
     157// -------------------------------------------------------------------------- 
     158// 
     159// Function 
     160//              Name:    BackupStoreRefCountDatabase::Save() 
    276161//              Purpose: Save modified info back to disc 
    277162//              Created: 2003/08/28 
    278163// 
    279164// -------------------------------------------------------------------------- 
    280 void BackupStoreInfo::Save() 
     165/* 
     166void BackupStoreRefCountDatabase::Save() 
    281167{ 
    282168        // Make sure we're initialised (although should never come to this) 
    283         if(mFilename.empty() || mAccountID == -1 || mDiscSet == -1) 
     169        if(mFilename.empty() || mAccount.GetID() == 0) 
    284170        { 
    285171                THROW_EXCEPTION(BackupStoreException, Internal) 
     
    293179         
    294180        // Then... open a write file 
    295         RaidFileWrite rf(mDiscSet, mFilename); 
     181        RaidFileWrite rf(mAccount.GetDiscSet(), mFilename); 
    296182        rf.Open(true);          // allow overwriting 
    297183         
    298184        // Make header 
    299185        info_StreamFormat hdr; 
    300         hdr.mMagicValue                                 = htonl(INFO_MAGIC_VALUE); 
    301         hdr.mAccountID                                  = htonl(mAccountID); 
     186        hdr.mMagicValue                         = htonl(INFO_MAGIC_VALUE); 
     187        hdr.mAccountID                          = htonl(mAccountID); 
    302188        hdr.mClientStoreMarker                  = box_hton64(mClientStoreMarker); 
    303189        hdr.mLastObjectIDUsed                   = box_hton64(mLastObjectIDUsed); 
     
    349235        mIsModified = false; 
    350236} 
    351  
    352  
    353  
    354 // -------------------------------------------------------------------------- 
    355 // 
    356 // Function 
    357 //              Name:    BackupStoreInfo::ChangeBlocksUsed(int32_t) 
    358 //              Purpose: Change number of blocks used, by a delta amount 
    359 //              Created: 2003/08/28 
    360 // 
    361 // -------------------------------------------------------------------------- 
    362 void BackupStoreInfo::ChangeBlocksUsed(int64_t Delta) 
    363 { 
    364         if(mReadOnly) 
    365         { 
    366                 THROW_EXCEPTION(BackupStoreException, StoreInfoIsReadOnly) 
    367         } 
    368         if((mBlocksUsed + Delta) < 0) 
    369         { 
    370                 THROW_EXCEPTION(BackupStoreException, StoreInfoBlockDeltaMakesValueNegative) 
    371         } 
    372          
    373         mBlocksUsed += Delta; 
    374          
    375         mIsModified = true; 
    376 } 
    377  
    378 // -------------------------------------------------------------------------- 
    379 // 
    380 // Function 
    381 //              Name:    BackupStoreInfo::ChangeBlocksInOldFiles(int32_t) 
    382 //              Purpose: Change number of blocks in old files, by a delta amount 
    383 //              Created: 2003/08/28 
    384 // 
    385 // -------------------------------------------------------------------------- 
    386 void BackupStoreInfo::ChangeBlocksInOldFiles(int64_t Delta) 
    387 { 
    388         if(mReadOnly) 
    389         { 
    390                 THROW_EXCEPTION(BackupStoreException, StoreInfoIsReadOnly) 
    391         } 
    392         if((mBlocksInOldFiles + Delta) < 0) 
    393         { 
    394                 THROW_EXCEPTION(BackupStoreException, StoreInfoBlockDeltaMakesValueNegative) 
    395         } 
    396          
    397         mBlocksInOldFiles += Delta; 
    398          
    399         mIsModified = true; 
    400 } 
    401  
    402 // -------------------------------------------------------------------------- 
    403 // 
    404 // Function 
    405 //              Name:    BackupStoreInfo::ChangeBlocksInDeletedFiles(int32_t) 
    406 //              Purpose: Change number of blocks in deleted files, by a delta amount 
    407 //              Created: 2003/08/28 
    408 // 
    409 // -------------------------------------------------------------------------- 
    410 void BackupStoreInfo::ChangeBlocksInDeletedFiles(int64_t Delta) 
    411 { 
    412         if(mReadOnly) 
    413         { 
    414                 THROW_EXCEPTION(BackupStoreException, StoreInfoIsReadOnly) 
    415         } 
    416         if((mBlocksInDeletedFiles + Delta) < 0) 
    417         { 
    418                 THROW_EXCEPTION(BackupStoreException, StoreInfoBlockDeltaMakesValueNegative) 
    419         } 
    420          
    421         mBlocksInDeletedFiles += Delta; 
    422          
    423         mIsModified = true; 
    424 } 
    425  
    426 // -------------------------------------------------------------------------- 
    427 // 
    428 // Function 
    429 //              Name:    BackupStoreInfo::ChangeBlocksInDirectories(int32_t) 
    430 //              Purpose: Change number of blocks in directories, by a delta amount 
    431 //              Created: 2003/08/28 
    432 // 
    433 // -------------------------------------------------------------------------- 
    434 void BackupStoreInfo::ChangeBlocksInDirectories(int64_t Delta) 
    435 { 
    436         if(mReadOnly) 
    437         { 
    438                 THROW_EXCEPTION(BackupStoreException, StoreInfoIsReadOnly) 
    439         } 
    440         if((mBlocksInDirectories + Delta) < 0) 
    441         { 
    442                 THROW_EXCEPTION(BackupStoreException, StoreInfoBlockDeltaMakesValueNegative) 
    443         } 
    444          
    445         mBlocksInDirectories += Delta; 
    446          
    447         mIsModified = true; 
    448 } 
    449  
    450  
    451 // -------------------------------------------------------------------------- 
    452 // 
    453 // Function 
    454 //              Name:    BackupStoreInfo::CorrectAllUsedValues(int64_t, int64_t, int64_t, int64_t) 
    455 //              Purpose: Set all the usage counts to specific values -- use for correcting in housekeeping 
    456 //                               if something when wrong during the backup connection, and the store info wasn't 
    457 //                               saved back to disc. 
    458 //              Created: 15/12/03 
    459 // 
    460 // -------------------------------------------------------------------------- 
    461 void BackupStoreInfo::CorrectAllUsedValues(int64_t Used, int64_t InOldFiles, int64_t InDeletedFiles, int64_t InDirectories) 
    462 { 
    463         if(mReadOnly) 
    464         { 
    465                 THROW_EXCEPTION(BackupStoreException, StoreInfoIsReadOnly) 
    466         } 
    467          
    468         // Set the values 
    469         mBlocksUsed = Used; 
    470         mBlocksInOldFiles = InOldFiles; 
    471         mBlocksInDeletedFiles = InDeletedFiles; 
    472         mBlocksInDirectories = InDirectories; 
    473          
    474         mIsModified = true; 
    475 } 
    476  
    477  
    478 // -------------------------------------------------------------------------- 
    479 // 
    480 // Function 
    481 //              Name:    BackupStoreInfo::AddDeletedDirectory(int64_t) 
    482 //              Purpose: Add a directory ID to the deleted list 
    483 //              Created: 2003/08/28 
    484 // 
    485 // -------------------------------------------------------------------------- 
    486 void BackupStoreInfo::AddDeletedDirectory(int64_t DirID) 
    487 { 
    488         if(mReadOnly) 
    489         { 
    490                 THROW_EXCEPTION(BackupStoreException, StoreInfoIsReadOnly) 
    491         } 
    492          
    493         mDeletedDirectories.push_back(DirID); 
    494          
    495         mIsModified = true; 
    496 } 
    497  
    498 // -------------------------------------------------------------------------- 
    499 // 
    500 // Function 
    501 //              Name:    BackupStoreInfo::RemovedDeletedDirectory(int64_t) 
    502 //              Purpose: Remove a directory from the deleted list 
    503 //              Created: 2003/08/28 
    504 // 
    505 // -------------------------------------------------------------------------- 
    506 void BackupStoreInfo::RemovedDeletedDirectory(int64_t DirID) 
    507 { 
    508         if(mReadOnly) 
    509         { 
    510                 THROW_EXCEPTION(BackupStoreException, StoreInfoIsReadOnly) 
    511         } 
    512          
    513         std::vector<int64_t>::iterator i(std::find(mDeletedDirectories.begin(), mDeletedDirectories.end(), DirID)); 
    514         if(i == mDeletedDirectories.end()) 
    515         { 
    516                 THROW_EXCEPTION(BackupStoreException, StoreInfoDirNotInList) 
    517         } 
    518         mDeletedDirectories.erase(i); 
    519          
    520         mIsModified = true; 
    521 } 
    522  
    523 // -------------------------------------------------------------------------- 
    524 // 
    525 // Function 
    526 //              Name:    BackupStoreInfo::ChangeLimits(int64_t, int64_t) 
    527 //              Purpose: Change the soft and hard limits 
    528 //              Created: 15/12/03 
    529 // 
    530 // -------------------------------------------------------------------------- 
    531 void BackupStoreInfo::ChangeLimits(int64_t BlockSoftLimit, int64_t BlockHardLimit) 
    532 { 
    533         if(mReadOnly) 
    534         { 
    535                 THROW_EXCEPTION(BackupStoreException, StoreInfoIsReadOnly) 
    536         } 
    537  
    538         mBlocksSoftLimit = BlockSoftLimit; 
    539         mBlocksHardLimit = BlockHardLimit; 
    540          
    541         mIsModified = true; 
    542 } 
    543  
    544  
    545 // -------------------------------------------------------------------------- 
    546 // 
    547 // Function 
    548 //              Name:    BackupStoreInfo::AllocateObjectID() 
    549 //              Purpose: Allocate an ID for a new object in the store. 
    550 //              Created: 2003/09/03 
    551 // 
    552 // -------------------------------------------------------------------------- 
    553 int64_t BackupStoreInfo::AllocateObjectID() 
    554 { 
    555         if(mReadOnly) 
    556         { 
    557                 THROW_EXCEPTION(BackupStoreException, StoreInfoIsReadOnly) 
    558         } 
    559         if(mLastObjectIDUsed < 0) 
    560         { 
    561                 THROW_EXCEPTION(BackupStoreException, StoreInfoNotInitialised) 
    562         } 
    563          
    564         // Return the next object ID 
    565         return ++mLastObjectIDUsed; 
    566          
    567         mIsModified = true; 
    568 } 
    569  
    570  
    571  
    572 // -------------------------------------------------------------------------- 
    573 // 
    574 // Function 
    575 //              Name:    BackupStoreInfo::SetClientStoreMarker(int64_t) 
    576 //              Purpose: Sets the client store marker 
    577 //              Created: 2003/10/29 
    578 // 
    579 // -------------------------------------------------------------------------- 
    580 void BackupStoreInfo::SetClientStoreMarker(int64_t ClientStoreMarker) 
    581 { 
    582         if(mReadOnly) 
    583         { 
    584                 THROW_EXCEPTION(BackupStoreException, StoreInfoIsReadOnly) 
    585         } 
    586          
    587         mClientStoreMarker = ClientStoreMarker; 
    588          
    589         mIsModified = true; 
    590 } 
    591  
    592  
    593  
     237*/ 
     238 
     239 
     240// -------------------------------------------------------------------------- 
     241// 
     242// Function 
     243//              Name:    BackupStoreRefCountDatabase::GetRefCount(int64_t 
     244//                       ObjectID) 
     245//              Purpose: Get the number of references to the specified object 
     246//                       out of the database 
     247//              Created: 2009/06/01 
     248// 
     249// -------------------------------------------------------------------------- 
     250int32_t BackupStoreRefCountDatabase::GetRefCount(int64_t ObjectID) const 
     251{ 
     252        IOStream::pos_type offset = GetOffset(ObjectID); 
     253 
     254        if (GetSize() < offset + GetEntrySize()) 
     255        { 
     256                BOX_ERROR("attempted read of unknown refcount for object " << 
     257                        BOX_FORMAT_OBJECTID(ObjectID)); 
     258                THROW_EXCEPTION(BackupStoreException, 
     259                        UnknownObjectRefCountRequested); 
     260        } 
     261 
     262        mapDatabaseFile->Seek(offset, SEEK_SET); 
     263 
     264        refcount_t refcount; 
     265        if (mapDatabaseFile->Read(&refcount, sizeof(refcount)) != 
     266                sizeof(refcount)) 
     267        { 
     268                BOX_LOG_SYS_ERROR("short read on refcount database: " << 
     269                        mFilename); 
     270                THROW_EXCEPTION(BackupStoreException, CouldNotLoadStoreInfo); 
     271        } 
     272 
     273        return ntohl(refcount); 
     274} 
     275 
     276int64_t BackupStoreRefCountDatabase::GetLastObjectIDUsed() const 
     277{ 
     278        return (GetSize() - sizeof(refcount_StreamFormat)) / 
     279                sizeof(refcount_t); 
     280} 
     281 
     282void BackupStoreRefCountDatabase::AddReference(int64_t ObjectID) 
     283{ 
     284        refcount_t refcount; 
     285 
     286        if (ObjectID > GetLastObjectIDUsed()) 
     287        { 
     288                // new object, assume no previous references 
     289                refcount = 0; 
     290        } 
     291        else 
     292        { 
     293                // read previous value from database 
     294                refcount = GetRefCount(ObjectID); 
     295        } 
     296 
     297        refcount++; 
     298 
     299        SetRefCount(ObjectID, refcount); 
     300} 
     301 
     302void BackupStoreRefCountDatabase::SetRefCount(int64_t ObjectID, 
     303        refcount_t NewRefCount) 
     304{ 
     305        IOStream::pos_type offset = GetOffset(ObjectID); 
     306        mapDatabaseFile->Seek(offset, SEEK_SET); 
     307        refcount_t RefCountNetOrder = htonl(NewRefCount); 
     308        mapDatabaseFile->Write(&RefCountNetOrder, sizeof(RefCountNetOrder)); 
     309} 
     310 
     311bool BackupStoreRefCountDatabase::RemoveReference(int64_t ObjectID) 
     312{ 
     313        refcount_t refcount = GetRefCount(ObjectID); // must exist in database 
     314        ASSERT(refcount > 0); 
     315        refcount--; 
     316        SetRefCount(ObjectID, refcount); 
     317        return (refcount > 0); 
     318} 
     319 
  • box/trunk/lib/backupstore/BackupStoreRefCountDatabase.h

    r1868 r2534  
    22// 
    33// File 
    4 //              Name:    BackupStoreInfo.h 
     4//              Name:    BackupStoreRefCountDatabase.h 
    55//              Purpose: Main backup store information storage 
    66//              Created: 2003/08/28 
     
    88// -------------------------------------------------------------------------- 
    99 
    10 #ifndef BACKUPSTOREINFO__H 
    11 #define BACKUPSTOREINFO__H 
     10#ifndef BACKUPSTOREREFCOUNTDATABASE__H 
     11#define BACKUPSTOREREFCOUNTDATABASE__H 
    1212 
    1313#include <memory> 
     
    1515#include <vector> 
    1616 
     17#include "BackupStoreAccountDatabase.h" 
     18#include "FileStream.h" 
     19 
    1720class BackupStoreCheck; 
     21class BackupStoreContext; 
     22 
     23// set packing to one byte 
     24#ifdef STRUCTURE_PACKING_FOR_WIRE_USE_HEADERS 
     25#include "BeginStructPackForWire.h" 
     26#else 
     27BEGIN_STRUCTURE_PACKING_FOR_WIRE 
     28#endif 
     29 
     30typedef struct 
     31{ 
     32        uint32_t mMagicValue;   // also the version number 
     33        uint32_t mAccountID; 
     34} refcount_StreamFormat; 
     35 
     36// Use default packing 
     37#ifdef STRUCTURE_PACKING_FOR_WIRE_USE_HEADERS 
     38#include "EndStructPackForWire.h" 
     39#else 
     40END_STRUCTURE_PACKING_FOR_WIRE 
     41#endif 
    1842 
    1943// -------------------------------------------------------------------------- 
    2044// 
    2145// Class 
    22 //              Name:    BackupStoreInfo 
    23 //              Purpose: Main backup store information storage 
    24 //              Created: 2003/08/28 
     46//              Name:    BackupStoreRefCountDatabase 
     47//              Purpose: Backup store reference count database storage 
     48//              Created: 2009/06/01 
    2549// 
    2650// -------------------------------------------------------------------------- 
    27 class BackupStoreInfo 
     51class BackupStoreRefCountDatabase 
    2852{ 
    2953        friend class BackupStoreCheck; 
     54        friend class BackupStoreContext; 
    3055public: 
    31         ~BackupStoreInfo(); 
     56        ~BackupStoreRefCountDatabase(); 
    3257private: 
    3358        // Creation through static functions only 
    34         BackupStoreInfo(); 
     59        BackupStoreRefCountDatabase(const BackupStoreAccountDatabase::Entry& 
     60                rAccount); 
    3561        // No copying allowed 
    36         BackupStoreInfo(const BackupStoreInfo &); 
     62        BackupStoreRefCountDatabase(const BackupStoreRefCountDatabase &); 
    3763         
    3864public: 
    39         // Create a New account, saving a blank info object to the disc 
    40         static void CreateNew(int32_t AccountID, const std::string &rRootDir, int DiscSet, int64_t BlockSoftLimit, int64_t BlockHardLimit); 
     65        // Create a new database for a new account. This method will refuse 
     66        // to overwrite any existing file. 
     67        static void CreateNew(const BackupStoreAccountDatabase::Entry& rAccount) 
     68        { 
     69                Create(rAccount, false); 
     70        } 
    4171         
    4272        // Load it from the store 
    43         static std::auto_ptr<BackupStoreInfo> Load(int32_t AccountID, const std::string &rRootDir, int DiscSet, bool ReadOnly, int64_t *pRevisionID = 0); 
    44          
    45         // Has info been modified? 
    46         bool IsModified() const {return mIsModified;} 
    47          
    48         // Save modified infomation back to store 
    49         void Save(); 
     73        static std::auto_ptr<BackupStoreRefCountDatabase> Load(const 
     74                BackupStoreAccountDatabase::Entry& rAccount, bool ReadOnly); 
    5075         
    5176        // Data access functions 
    52         int32_t GetAccountID() const {return mAccountID;} 
    53         int64_t GetLastObjectIDUsed() const {return mLastObjectIDUsed;} 
    54         int64_t GetBlocksUsed() const {return mBlocksUsed;} 
    55         int64_t GetBlocksInOldFiles() const {return mBlocksInOldFiles;} 
    56         int64_t GetBlocksInDeletedFiles() const {return mBlocksInDeletedFiles;} 
    57         int64_t GetBlocksInDirectories() const {return mBlocksInDirectories;} 
    58         const std::vector<int64_t> &GetDeletedDirectories() const {return mDeletedDirectories;} 
    59         int64_t GetBlocksSoftLimit() const {return mBlocksSoftLimit;} 
    60         int64_t GetBlocksHardLimit() const {return mBlocksHardLimit;} 
    61         bool IsReadOnly() const {return mReadOnly;} 
    62         int GetDiscSetNumber() const {return mDiscSet;} 
     77        int32_t GetRefCount(int64_t ObjectID) const; 
     78        int64_t GetLastObjectIDUsed() const; 
    6379         
    6480        // Data modification functions 
    65         void ChangeBlocksUsed(int64_t Delta); 
    66         void ChangeBlocksInOldFiles(int64_t Delta); 
    67         void ChangeBlocksInDeletedFiles(int64_t Delta); 
    68         void ChangeBlocksInDirectories(int64_t Delta); 
    69         void CorrectAllUsedValues(int64_t Used, int64_t InOldFiles, int64_t InDeletedFiles, int64_t InDirectories); 
    70         void AddDeletedDirectory(int64_t DirID); 
    71         void RemovedDeletedDirectory(int64_t DirID); 
    72         void ChangeLimits(int64_t BlockSoftLimit, int64_t BlockHardLimit); 
    73          
    74         // Object IDs 
    75         int64_t AllocateObjectID(); 
    76                  
    77         // Client marker set and get 
    78         int64_t GetClientStoreMarker() {return mClientStoreMarker;} 
    79         void SetClientStoreMarker(int64_t ClientStoreMarker); 
     81        void AddReference(int64_t ObjectID); 
     82        bool RemoveReference(int64_t ObjectID); 
    8083 
    8184private: 
    82         static std::auto_ptr<BackupStoreInfo> CreateForRegeneration(int32_t AccountID, const std::string &rRootDir, 
    83                 int DiscSet, int64_t LastObjectID, int64_t BlocksUsed, int64_t BlocksInOldFiles, 
    84                 int64_t BlocksInDeletedFiles, int64_t BlocksInDirectories, int64_t BlockSoftLimit, int64_t BlockHardLimit); 
     85        // Create a new database for an existing account. Used during 
     86        // account checking if opening the old database throws an exception. 
     87        // This method will overwrite any existing file. 
     88        static void CreateForRegeneration(const 
     89                BackupStoreAccountDatabase::Entry& rAccount) 
     90        { 
     91                Create(rAccount, true); 
     92        } 
    8593 
    86 private: 
     94        static void Create(const BackupStoreAccountDatabase::Entry& rAccount, 
     95                bool AllowOverwrite); 
     96 
     97        typedef int32_t refcount_t; 
     98 
     99        static std::string GetFilename(const BackupStoreAccountDatabase::Entry& 
     100                rAccount); 
     101        IOStream::pos_type GetSize() const 
     102        { 
     103                return mapDatabaseFile->GetPosition() + 
     104                        mapDatabaseFile->BytesLeftToRead(); 
     105        } 
     106        IOStream::pos_type GetEntrySize() const 
     107        { 
     108                return sizeof(refcount_t); 
     109        } 
     110        IOStream::pos_type GetOffset(int64_t ObjectID) const 
     111        { 
     112                return ((ObjectID - 1) * GetEntrySize()) + 
     113                        sizeof(refcount_StreamFormat); 
     114        } 
     115        void SetRefCount(int64_t ObjectID, refcount_t NewRefCount); 
     116         
    87117        // Location information 
    88         int32_t mAccountID; 
    89         int mDiscSet; 
     118        BackupStoreAccountDatabase::Entry mAccount; 
    90119        std::string mFilename; 
    91120        bool mReadOnly; 
    92121        bool mIsModified; 
    93          
    94         // Client infomation 
    95         int64_t mClientStoreMarker; 
    96          
    97         // Account information 
    98         int64_t mLastObjectIDUsed; 
    99         int64_t mBlocksUsed; 
    100         int64_t mBlocksInOldFiles; 
    101         int64_t mBlocksInDeletedFiles; 
    102         int64_t mBlocksInDirectories; 
    103         int64_t mBlocksSoftLimit; 
    104         int64_t mBlocksHardLimit; 
    105         std::vector<int64_t> mDeletedDirectories; 
     122        std::auto_ptr<FileStream> mapDatabaseFile; 
    106123}; 
    107124 
    108  
    109 #endif // BACKUPSTOREINFO__H 
    110  
    111  
     125#endif // BACKUPSTOREREFCOUNTDATABASE__H 
Note: See TracChangeset for help on using the changeset viewer.