Changeset 2181

Show
Ignore:
Timestamp:
28/05/2008 15:24:05 (2 years ago)
Author:
chris
Message:

Track and log file deletions by name.

Split crypto init and file sync process into its own method, to reduce
call depth and facilitate calling in process from tests.

Differentiate between 3 uses of stat in BackupClientDirectoryRecord? by
renaming the structures.

Use stat instead of lstat when checking the filesystem that's holding an
entity, in case it's a symbolic link to a different filesystem.

Location:
box/trunk/bin/bbackupd
Files:
8 modified

Legend:

Unmodified
Added
Removed
  • box/trunk/bin/bbackupd/BackupClientContext.cpp

    r2127 r2181  
    4949        bool ExtendedLogging, 
    5050        bool ExtendedLogToFile, 
    51         std::string ExtendedLogFile 
     51        std::string ExtendedLogFile, 
     52        ProgressNotifier& rProgressNotifier 
    5253) 
    5354        : mrDaemon(rDaemon), 
     
    7071          mpExcludeDirs(0), 
    7172          mKeepAliveTimer(0), 
    72           mbIsManaged(false) 
     73          mbIsManaged(false), 
     74          mrProgressNotifier(rProgressNotifier) 
    7375{ 
    7476} 
  • box/trunk/bin/bbackupd/BackupClientContext.h

    r2127 r2181  
    1313#include "BoxTime.h" 
    1414#include "BackupClientDeleteList.h" 
     15#include "BackupClientDirectoryRecord.h" 
    1516#include "BackupStoreFile.h" 
    1617#include "ExcludeList.h" 
     
    4647                bool ExtendedLogging, 
    4748                bool ExtendedLogToFile, 
    48                 std::string ExtendedLogFile 
     49                std::string ExtendedLogFile, 
     50                ProgressNotifier &rProgressNotifier 
    4951        ); 
    5052        virtual ~BackupClientContext(); 
     
    7173         
    7274        bool StorageLimitExceeded() {return mStorageLimitExceeded;} 
     75        void SetStorageLimitExceeded() {mStorageLimitExceeded = true;} 
    7376 
    7477        // -------------------------------------------------------------------------- 
     
    199202        virtual bool   IsManaged() { return mbIsManaged; } 
    200203         
     204        ProgressNotifier& GetProgressNotifier() const  
     205        {  
     206                return mrProgressNotifier; 
     207        } 
     208 
    201209private: 
    202210        BackupDaemon &mrDaemon; 
     
    222230        int mKeepAliveTime; 
    223231        int mMaximumDiffingTime; 
     232        ProgressNotifier &mrProgressNotifier; 
    224233}; 
    225234 
  • box/trunk/bin/bbackupd/BackupClientDeleteList.cpp

    r217 r2181  
    4343} 
    4444 
    45 // -------------------------------------------------------------------------- 
    46 // 
    47 // Function 
    48 //              Name:    BackupClientDeleteList::AddDirectoryDelete(int64_t) 
     45BackupClientDeleteList::FileToDelete::FileToDelete(int64_t DirectoryID, 
     46        const BackupStoreFilename& rFilename, 
     47        const std::string& rLocalPath) 
     48: mDirectoryID(DirectoryID), 
     49  mFilename(rFilename), 
     50  mLocalPath(rLocalPath) 
     51{ } 
     52 
     53BackupClientDeleteList::DirToDelete::DirToDelete(int64_t ObjectID, 
     54        const std::string& rLocalPath) 
     55: mObjectID(ObjectID), 
     56  mLocalPath(rLocalPath) 
     57{ } 
     58 
     59// -------------------------------------------------------------------------- 
     60// 
     61// Function 
     62//              Name:    BackupClientDeleteList::AddDirectoryDelete(int64_t, 
     63//                       const BackupStoreFilename&) 
    4964//              Purpose: Add a directory to the list of directories to be deleted. 
    5065//              Created: 10/11/03 
    5166// 
    5267// -------------------------------------------------------------------------- 
    53 void BackupClientDeleteList::AddDirectoryDelete(int64_t ObjectID) 
     68void BackupClientDeleteList::AddDirectoryDelete(int64_t ObjectID, 
     69        const std::string& rLocalPath) 
    5470{ 
    5571        // Only add the delete to the list if it's not in the "no delete" set 
    56         if(mDirectoryNoDeleteList.find(ObjectID) == mDirectoryNoDeleteList.end()) 
     72        if(mDirectoryNoDeleteList.find(ObjectID) == 
     73                mDirectoryNoDeleteList.end()) 
    5774        { 
    5875                // Not in the list, so should delete it 
    59                 mDirectoryList.push_back(ObjectID); 
    60         } 
    61 } 
    62  
    63  
    64 // -------------------------------------------------------------------------- 
    65 // 
    66 // Function 
    67 //              Name:    BackupClientDeleteList::AddFileDelete(int64_t, BackupStoreFilenameClear &) 
     76                mDirectoryList.push_back(DirToDelete(ObjectID, rLocalPath)); 
     77        } 
     78} 
     79 
     80 
     81// -------------------------------------------------------------------------- 
     82// 
     83// Function 
     84//              Name:    BackupClientDeleteList::AddFileDelete(int64_t, 
     85//                       const BackupStoreFilename &) 
    6886//              Purpose:  
    6987//              Created: 10/11/03 
    7088// 
    7189// -------------------------------------------------------------------------- 
    72 void BackupClientDeleteList::AddFileDelete(int64_t DirectoryID, const BackupStoreFilename &rFilename) 
     90void BackupClientDeleteList::AddFileDelete(int64_t DirectoryID, 
     91        const BackupStoreFilename &rFilename, const std::string& rLocalPath) 
    7392{ 
    7493        // Try to find it in the no delete list 
    75         std::vector<std::pair<int64_t, BackupStoreFilename> >::iterator delEntry(mFileNoDeleteList.begin()); 
     94        std::vector<std::pair<int64_t, BackupStoreFilename> >::iterator 
     95                delEntry(mFileNoDeleteList.begin()); 
    7696        while(delEntry != mFileNoDeleteList.end()) 
    7797        { 
    78                 if((delEntry)->first == DirectoryID && (delEntry)->second == rFilename) 
     98                if((delEntry)->first == DirectoryID  
     99                        && (delEntry)->second == rFilename) 
    79100                { 
    80101                        // Found! 
     
    87108        if(delEntry == mFileNoDeleteList.end()) 
    88109        { 
    89                 mFileList.push_back(std::pair<int64_t, BackupStoreFilename>(DirectoryID, rFilename)); 
     110                mFileList.push_back(FileToDelete(DirectoryID, rFilename, 
     111                        rLocalPath)); 
    90112        } 
    91113} 
     
    114136         
    115137        // Do the deletes 
    116         for(std::vector<int64_t>::iterator i(mDirectoryList.begin()); i != mDirectoryList.end(); ++i) 
    117         { 
    118                 connection.QueryDeleteDirectory(*i); 
     138        for(std::vector<DirToDelete>::iterator i(mDirectoryList.begin()); 
     139                i != mDirectoryList.end(); ++i) 
     140        { 
     141                connection.QueryDeleteDirectory(i->mObjectID); 
     142                rContext.GetProgressNotifier().NotifyDirectoryDeleted( 
     143                        i->mObjectID, i->mLocalPath); 
    119144        } 
    120145         
     
    123148         
    124149        // Delete the files 
    125         for(std::vector<std::pair<int64_t, BackupStoreFilename> >::iterator i(mFileList.begin()); i != mFileList.end(); ++i) 
    126         { 
    127                 connection.QueryDeleteFile(i->first, i->second); 
     150        for(std::vector<FileToDelete>::iterator i(mFileList.begin()); 
     151                i != mFileList.end(); ++i) 
     152        { 
     153                connection.QueryDeleteFile(i->mDirectoryID, i->mFilename); 
     154                rContext.GetProgressNotifier().NotifyFileDeleted( 
     155                        i->mDirectoryID, i->mLocalPath); 
    128156        } 
    129157} 
     
    141169{ 
    142170        // First of all, is it in the delete vector? 
    143         std::vector<int64_t>::iterator delEntry(std::find(mDirectoryList.begin(), mDirectoryList.end(), ObjectID)); 
     171        std::vector<DirToDelete>::iterator delEntry(mDirectoryList.begin()); 
     172        for(; delEntry != mDirectoryList.end(); delEntry++) 
     173        { 
     174                if(delEntry->mObjectID == ObjectID) 
     175                { 
     176                        // Found! 
     177                        break; 
     178                } 
     179        } 
    144180        if(delEntry != mDirectoryList.end()) 
    145181        { 
     
    149185        else 
    150186        { 
    151                 // Haven't been asked to delete it yet, put it in the no delete list 
     187                // Haven't been asked to delete it yet, put it in the 
     188                // no delete list 
    152189                mDirectoryNoDeleteList.insert(ObjectID); 
    153190        } 
     
    163200// 
    164201// -------------------------------------------------------------------------- 
    165 void BackupClientDeleteList::StopFileDeletion(int64_t DirectoryID, const BackupStoreFilename &rFilename) 
     202void BackupClientDeleteList::StopFileDeletion(int64_t DirectoryID, 
     203        const BackupStoreFilename &rFilename) 
    166204{ 
    167205        // Find this in the delete list 
    168         std::vector<std::pair<int64_t, BackupStoreFilename> >::iterator delEntry(mFileList.begin()); 
     206        std::vector<FileToDelete>::iterator delEntry(mFileList.begin()); 
    169207        while(delEntry != mFileList.end()) 
    170208        { 
    171                 if((delEntry)->first == DirectoryID && (delEntry)->second == rFilename) 
     209                if(delEntry->mDirectoryID == DirectoryID 
     210                        && delEntry->mFilename == rFilename) 
    172211                { 
    173212                        // Found! 
     
    187226                mFileNoDeleteList.push_back(std::pair<int64_t, BackupStoreFilename>(DirectoryID, rFilename)); 
    188227        } 
    189  
    190 } 
    191  
    192  
    193  
    194  
    195  
     228} 
     229 
  • box/trunk/bin/bbackupd/BackupClientDeleteList.h

    r217 r2181  
    2929class BackupClientDeleteList 
    3030{ 
     31private: 
     32        class FileToDelete 
     33        { 
     34                public: 
     35                int64_t mDirectoryID; 
     36                BackupStoreFilename mFilename; 
     37                std::string mLocalPath; 
     38                FileToDelete(int64_t DirectoryID,  
     39                        const BackupStoreFilename& rFilename, 
     40                        const std::string& rLocalPath); 
     41        }; 
     42 
     43        class DirToDelete 
     44        { 
     45                public: 
     46                int64_t mObjectID; 
     47                std::string mLocalPath; 
     48                DirToDelete(int64_t ObjectID, const std::string& rLocalPath); 
     49        }; 
     50 
    3151public: 
    3252        BackupClientDeleteList(); 
    3353        ~BackupClientDeleteList(); 
    3454         
    35         void AddDirectoryDelete(int64_t ObjectID); 
    36         void AddFileDelete(int64_t DirectoryID, const BackupStoreFilename &rFilename); 
     55        void AddDirectoryDelete(int64_t ObjectID, 
     56                const std::string& rLocalPath); 
     57        void AddFileDelete(int64_t DirectoryID, 
     58                const BackupStoreFilename &rFilename, 
     59                const std::string& rLocalPath); 
    3760 
    3861        void StopDirectoryDeletion(int64_t ObjectID); 
    39         void StopFileDeletion(int64_t DirectoryID, const BackupStoreFilename &rFilename); 
     62        void StopFileDeletion(int64_t DirectoryID, 
     63                const BackupStoreFilename &rFilename); 
    4064         
    4165        void PerformDeletions(BackupClientContext &rContext); 
    4266         
    4367private: 
    44         std::vector<int64_t> mDirectoryList; 
     68        std::vector<DirToDelete> mDirectoryList; 
    4569        std::set<int64_t> mDirectoryNoDeleteList;       // note: things only get in this list if they're not present in mDirectoryList when they are 'added' 
    46         std::vector<std::pair<int64_t, BackupStoreFilename> > mFileList; 
     70        std::vector<FileToDelete> mFileList; 
    4771        std::vector<std::pair<int64_t, BackupStoreFilename> > mFileNoDeleteList; 
    4872}; 
  • box/trunk/bin/bbackupd/BackupClientDirectoryRecord.cpp

    r2143 r2181  
    33// File 
    44//              Name:    BackupClientDirectoryRecord.cpp 
    5 //              Purpose: Implementation of record about directory for backup client 
     5//              Purpose: Implementation of record about directory for 
     6//                       backup client 
    67//              Created: 2003/10/08 
    78// 
     
    101102// 
    102103// Function 
    103 //              Name:    BackupClientDirectoryRecord::SyncDirectory(BackupClientDirectoryRecord::SyncParams &, int64_t, const std::string &, bool) 
    104 //              Purpose: Syncronise, recusively, a local directory with the server. 
     104//              Name:    BackupClientDirectoryRecord::SyncDirectory(i 
     105//                       BackupClientDirectoryRecord::SyncParams &, 
     106//                       int64_t, const std::string &, 
     107//                       const std::string &, bool) 
     108//              Purpose: Recursively synchronise a local directory 
     109//                       with the server. 
    105110//              Created: 2003/10/08 
    106111// 
    107112// -------------------------------------------------------------------------- 
    108 void BackupClientDirectoryRecord::SyncDirectory(BackupClientDirectoryRecord::SyncParams &rParams, int64_t ContainingDirectoryID, 
    109         const std::string &rLocalPath, bool ThisDirHasJustBeenCreated) 
     113void BackupClientDirectoryRecord::SyncDirectory( 
     114        BackupClientDirectoryRecord::SyncParams &rParams, 
     115        int64_t ContainingDirectoryID, 
     116        const std::string &rLocalPath, 
     117        const std::string &rRemotePath, 
     118        bool ThisDirHasJustBeenCreated) 
    110119{ 
     120        BackupClientContext& rContext(rParams.mrContext); 
     121        ProgressNotifier& rNotifier(rContext.GetProgressNotifier()); 
     122 
    111123        // Signal received by daemon? 
    112124        if(rParams.mrDaemon.StopRun()) 
     
    119131        // and on the immediate sub directories. 
    120132        mSyncDone = false; 
    121         for(std::map<std::string, BackupClientDirectoryRecord *>::iterator i = mSubDirectories.begin(); 
     133        for(std::map<std::string, BackupClientDirectoryRecord *>::iterator 
     134                i  = mSubDirectories.begin(); 
    122135                i != mSubDirectories.end(); ++i) 
    123136        { 
     
    125138        } 
    126139 
    127         // Work out the time in the future after which the file should be uploaded regardless. 
    128         // This is a simple way to avoid having too many problems with file servers when they have 
    129         // clients with badly out of sync clocks. 
    130         rParams.mUploadAfterThisTimeInTheFuture = GetCurrentBoxTime() + rParams.mMaxFileTimeInFuture; 
    131          
    132         // Build the current state checksum to compare against while getting info from dirs 
    133         // Note checksum is used locally only, so byte order isn't considered. 
     140        // Work out the time in the future after which the file should 
     141        // be uploaded regardless. This is a simple way to avoid having 
     142        // too many problems with file servers when they have clients 
     143        // with badly out of sync clocks. 
     144        rParams.mUploadAfterThisTimeInTheFuture = GetCurrentBoxTime() + 
     145                rParams.mMaxFileTimeInFuture; 
     146         
     147        // Build the current state checksum to compare against while 
     148        // getting info from dirs. Note checksum is used locally only, 
     149        // so byte order isn't considered. 
    134150        MD5Digest currentStateChecksum; 
    135151         
     152        struct stat dest_st; 
    136153        // Stat the directory, to get attribute info 
    137         { 
    138                 struct stat st; 
    139                 if(::stat(rLocalPath.c_str(), &st) != 0) 
    140                 { 
    141                         // The directory has probably been deleted, so just ignore this error. 
    142                         // In a future scan, this deletion will be noticed, deleted from server, and this object deleted. 
    143                         rParams.GetProgressNotifier().NotifyDirStatFailed( 
    144                                 this, rLocalPath, strerror(errno)); 
     154        // If it's a symbolic link, we want the link target here 
     155        // (as we're about to back up the contents of the directory) 
     156        { 
     157                if(::stat(rLocalPath.c_str(), &dest_st) != 0) 
     158                { 
     159                        // The directory has probably been deleted, so 
     160                        // just ignore this error. In a future scan, this 
     161                        // deletion will be noticed, deleted from server, 
     162                        // and this object deleted. 
     163                        rNotifier.NotifyDirStatFailed(this, rLocalPath, 
     164                                strerror(errno)); 
    145165                        return; 
    146166                } 
    147                 // Store inode number in map so directories are tracked in case they're renamed 
    148                 { 
    149                         BackupClientInodeToIDMap &idMap(rParams.mrContext.GetNewIDMap()); 
    150                         idMap.AddToMap(st.st_ino, mObjectID, ContainingDirectoryID); 
     167                // Store inode number in map so directories are tracked 
     168                // in case they're renamed 
     169                { 
     170                        BackupClientInodeToIDMap &idMap( 
     171                                rParams.mrContext.GetNewIDMap()); 
     172                        idMap.AddToMap(dest_st.st_ino, mObjectID, 
     173                                ContainingDirectoryID); 
    151174                } 
    152175                // Add attributes to checksum 
    153                 currentStateChecksum.Add(&st.st_mode, sizeof(st.st_mode)); 
    154                 currentStateChecksum.Add(&st.st_uid, sizeof(st.st_uid)); 
    155                 currentStateChecksum.Add(&st.st_gid, sizeof(st.st_gid)); 
     176                currentStateChecksum.Add(&dest_st.st_mode, 
     177                        sizeof(dest_st.st_mode)); 
     178                currentStateChecksum.Add(&dest_st.st_uid, 
     179                        sizeof(dest_st.st_uid)); 
     180                currentStateChecksum.Add(&dest_st.st_gid, 
     181                        sizeof(dest_st.st_gid)); 
    156182                // Inode to be paranoid about things moving around 
    157                 currentStateChecksum.Add(&st.st_ino, sizeof(st.st_ino)); 
     183                currentStateChecksum.Add(&dest_st.st_ino, 
     184                        sizeof(dest_st.st_ino)); 
    158185#ifdef HAVE_STRUCT_STAT_ST_FLAGS 
    159                 currentStateChecksum.Add(&st.st_flags, sizeof(st.st_flags)); 
     186                currentStateChecksum.Add(&dest_st.st_flags, 
     187                        sizeof(dest_st.st_flags)); 
    160188#endif 
    161189 
    162190                StreamableMemBlock xattr; 
    163                 BackupClientFileAttributes::FillExtendedAttr(xattr, rLocalPath.c_str()); 
     191                BackupClientFileAttributes::FillExtendedAttr(xattr, 
     192                        rLocalPath.c_str()); 
    164193                currentStateChecksum.Add(xattr.GetBuffer(), xattr.GetSize()); 
    165194        } 
     
    171200        bool downloadDirectoryRecordBecauseOfFutureFiles = false; 
    172201 
    173         struct stat dir_st; 
    174         if(::lstat(rLocalPath.c_str(), &dir_st) != 0) 
     202        struct stat link_st; 
     203        if(::lstat(rLocalPath.c_str(), &link_st) != 0) 
    175204        { 
    176205                // Report the error (logs and  
    177206                // eventual email to administrator) 
    178                 rParams.GetProgressNotifier().NotifyFileStatFailed(this,  
    179                         rLocalPath, strerror(errno)); 
     207                rNotifier.NotifyFileStatFailed(this, rLocalPath, 
     208                        strerror(errno)); 
    180209                 
    181210                // FIXME move to NotifyFileStatFailed() 
     
    193222                try 
    194223                { 
    195                         rParams.GetProgressNotifier().NotifyScanDirectory( 
    196                                 this, rLocalPath); 
     224                        rNotifier.NotifyScanDirectory(this, rLocalPath); 
    197225 
    198226                        dirHandle = ::opendir(rLocalPath.c_str()); 
     
    203231                                if (errno == EACCES) 
    204232                                { 
    205                                         rParams.GetProgressNotifier().NotifyDirListFailed( 
    206                                                 this, rLocalPath, "Access denied"); 
     233                                        rNotifier.NotifyDirListFailed(this, 
     234                                                rLocalPath, "Access denied"); 
    207235                                } 
    208236                                else 
    209237                                { 
    210                                         rParams.GetProgressNotifier().NotifyDirListFailed(this,  
     238                                        rNotifier.NotifyDirListFailed(this,  
    211239                                                rLocalPath, strerror(errno)); 
    212240                                } 
    213241                                 
    214                                 // Report the error (logs and eventual email to administrator) 
    215                                 SetErrorWhenReadingFilesystemObject(rParams, rLocalPath.c_str()); 
     242                                // Report the error (logs and eventual email 
     243                                // to administrator) 
     244                                SetErrorWhenReadingFilesystemObject(rParams, 
     245                                        rLocalPath.c_str()); 
    216246                                // Ignore this directory for now. 
    217247                                return; 
     
    229259         
    230260                        struct dirent *en = 0; 
    231                         struct stat st; 
     261                        struct stat file_st; 
    232262                        std::string filename; 
    233263                        while((en = ::readdir(dirHandle)) != 0) 
     
    235265                                rParams.mrContext.DoKeepAlive(); 
    236266                                 
    237                                 // Don't need to use LinuxWorkaround_FinishDirentStruct(en, rLocalPath.c_str()); 
    238                                 // on Linux, as a stat is performed to get all this info 
     267                                // Don't need to use 
     268                                // LinuxWorkaround_FinishDirentStruct(en, 
     269                                // rLocalPath.c_str()); 
     270                                // on Linux, as a stat is performed to 
     271                                // get all this info 
    239272 
    240273                                if(en->d_name[0] == '.' &&  
     
    260293                                int type = en->d_type; 
    261294                                #else 
    262                                 if(::lstat(filename.c_str(), &st) != 0) 
     295                                if(::lstat(filename.c_str(), &file_st) != 0) 
    263296                                { 
    264297                                        // Report the error (logs and  
    265298                                        // eventual email to administrator) 
    266                                         rParams.GetProgressNotifier().NotifyFileStatFailed(this,  
     299                                        rNotifier.NotifyFileStatFailed(this,  
    267300                                                filename, strerror(errno)); 
    268301                                         
     
    275308                                } 
    276309 
    277                                 if(st.st_dev != dir_st.st_dev) 
     310                                if(file_st.st_dev != dest_st.st_dev) 
    278311                                { 
    279312                                        if(!(rParams.mrContext.ExcludeDir( 
    280313                                                filename))) 
    281314                                        { 
    282                                                 rParams.GetProgressNotifier() 
    283                                                         .NotifyMountPointSkipped( 
    284                                                                 this, filename); 
     315                                                rNotifier.NotifyMountPointSkipped( 
     316                                                        this, filename); 
    285317                                        } 
    286318                                        continue; 
    287319                                } 
    288320 
    289                                 int type = st.st_mode & S_IFMT; 
     321                                int type = file_st.st_mode & S_IFMT; 
    290322                                #endif 
    291323 
     
    297329                                        if(rParams.mrContext.ExcludeFile(filename)) 
    298330                                        { 
    299                                                 rParams.GetProgressNotifier() 
    300                                                         .NotifyFileExcluded( 
     331                                                rNotifier.NotifyFileExcluded( 
    301332                                                                this,  
    302333                                                                filename); 
     
    316347                                        if(rParams.mrContext.ExcludeDir(filename)) 
    317348                                        { 
    318                                                 rParams.GetProgressNotifier() 
    319                                                         .NotifyDirExcluded( 
     349                                                rNotifier.NotifyDirExcluded( 
    320350                                                                this,  
    321351                                                                filename); 
     
    332362                                        if(rParams.mrContext.ExcludeFile(filename)) 
    333363                                        { 
    334                                                 rParams.GetProgressNotifier() 
    335                                                         .NotifyFileExcluded( 
     364                                                rNotifier.NotifyFileExcluded( 
    336365                                                                this,  
    337366                                                                filename); 
     
    339368                                        else 
    340369                                        { 
    341                                                 rParams.GetProgressNotifier() 
    342                                                         .NotifyUnsupportedFileType( 
     370                                                rNotifier.NotifyUnsupportedFileType( 
    343371                                                                this, filename); 
    344372                                                SetErrorWhenReadingFilesystemObject( 
     
    355383                                // We didn't stat the file before, 
    356384                                // but now we need the information. 
    357                                 if(::lstat(filename.c_str(), &st) != 0) 
    358                                 { 
    359                                         rParams.GetProgressNotifier() 
    360                                                 .NotifyFileStatFailed(this,  
     385                                if(::lstat(filename.c_str(), &file_st) != 0) 
     386                                { 
     387                                        rNotifier.NotifyFileStatFailed(this,  
    361388                                                        filename,  
    362389                                                        strerror(errno)); 
     
    371398                                } 
    372399 
    373                                 if(st.st_dev != dir_st.st_dev) 
    374                                 { 
    375                                         rParams.GetProgressNotifier() 
    376                                                 .NotifyMountPointSkipped(this,  
     400                                if(file_st.st_dev != link_st.st_dev) 
     401                                { 
     402                                        rNotifier.NotifyMountPointSkipped(this,  
    377403                                                        filename); 
    378404                                        continue; 
     
    380406                                #endif 
    381407 
    382                                 checksum_info.mModificationTime = FileModificationTime(st); 
    383                                 checksum_info.mAttributeModificationTime = FileAttrModificationTime(st); 
    384                                 checksum_info.mSize = st.st_size; 
     408                                checksum_info.mModificationTime = FileModificationTime(file_st); 
     409                                checksum_info.mAttributeModificationTime = FileAttrModificationTime(file_st); 
     410                                checksum_info.mSize = file_st.st_size; 
    385411                                currentStateChecksum.Add(&checksum_info, sizeof(checksum_info)); 
    386412                                currentStateChecksum.Add(en->d_name, strlen(en->d_name)); 
     
    395421                                        if(!rParams.mHaveLoggedWarningAboutFutureFileTimes) 
    396422                                        { 
    397                                                 rParams.GetProgressNotifier().NotifyFileModifiedInFuture( 
     423                                                rNotifier.NotifyFileModifiedInFuture( 
    398424                                                        this, filename); 
    399425                                                rParams.mHaveLoggedWarningAboutFutureFileTimes = true; 
     
    469495                 
    470496                // Do the directory reading 
    471                 bool updateCompleteSuccess = UpdateItems(rParams, rLocalPath, pdirOnStore, entriesLeftOver, files, dirs); 
     497                bool updateCompleteSuccess = UpdateItems(rParams, rLocalPath, 
     498                        rRemotePath, pdirOnStore, entriesLeftOver, files, dirs); 
    472499                 
    473500                // LAST THING! (think exception safety) 
     
    605632// 
    606633// -------------------------------------------------------------------------- 
    607 bool BackupClientDirectoryRecord::UpdateItems(BackupClientDirectoryRecord::SyncParams &rParams, 
    608         const std::string &rLocalPath, BackupStoreDirectory *pDirOnStore, 
     634bool BackupClientDirectoryRecord::UpdateItems( 
     635        BackupClientDirectoryRecord::SyncParams &rParams, 
     636        const std::string &rLocalPath, 
     637        const std::string &rRemotePath, 
     638        BackupStoreDirectory *pDirOnStore, 
    609639        std::vector<BackupStoreDirectory::Entry *> &rEntriesLeftOver, 
    610         std::vector<std::string> &rFiles, const std::vector<std::string> &rDirs) 
     640        std::vector<std::string> &rFiles, 
     641        const std::vector<std::string> &rDirs) 
    611642{ 
     643        BackupClientContext& rContext(rParams.mrContext); 
     644        ProgressNotifier& rNotifier(rContext.GetProgressNotifier()); 
     645 
    612646        bool allUpdatedSuccessfully = true; 
    613647 
     
    635669        { 
    636670                // Send keep-alive message if needed 
    637                 rParams.mrContext.DoKeepAlive(); 
     671                rContext.DoKeepAlive(); 
    638672                 
    639673                // Filename of this file 
     
    652686                        if(::lstat(filename.c_str(), &st) != 0) 
    653687                        { 
    654                                 rParams.GetProgressNotifier().NotifyFileStatFailed(this,  
     688                                rNotifier.NotifyFileStatFailed(this,  
    655689                                        filename, strerror(errno)); 
    656690 
     
    690724                { 
    691725                        // Directory exists in the place of this file -- sort it out 
    692                         RemoveDirectoryInPlaceOfFile(rParams, pDirOnStore, en->GetObjectID(), *f); 
     726                        RemoveDirectoryInPlaceOfFile(rParams, pDirOnStore, 
     727                                en, *f); 
    693728                        en = 0; 
    694729                } 
     
    702737                         
    703738                        // Do we know about the inode number? 
    704                         const BackupClientInodeToIDMap &idMap(rParams.mrContext.GetCurrentIDMap()); 
     739                        const BackupClientInodeToIDMap &idMap(rContext.GetCurrentIDMap()); 
    705740                        int64_t renameObjectID = 0, renameInDirectory = 0; 
    706741                        if(idMap.Lookup(inodeNum, renameObjectID, renameInDirectory)) 
     
    712747                                box_time_t srvModTime = 0, srvAttributesHash = 0; 
    713748                                BackupStoreFilenameClear oldLeafname; 
    714                                 if(rParams.mrContext.FindFilename(renameObjectID, renameInDirectory, localPotentialOldName, isDir, isCurrentVersion, &srvModTime, &srvAttributesHash, &oldLeafname)) 
     749                                if(rContext.FindFilename(renameObjectID, renameInDirectory, localPotentialOldName, isDir, isCurrentVersion, &srvModTime, &srvAttributesHash, &oldLeafname)) 
    715750                                {        
    716751                                        // Only interested if it's a file and the latest version 
     
    725760 
    726761                                                        // Get the connection to the server  
    727                                                         BackupProtocolClient &connection(rParams.mrContext.GetConnection()); 
     762                                                        BackupProtocolClient &connection(rContext.GetConnection()); 
    728763 
    729764                                                        // Only do this step if there is room on the server. 
    730765                                                        // This step will be repeated later when there is space available 
    731                                                         if(!rParams.mrContext.StorageLimitExceeded()) 
     766                                                        if(!rContext.StorageLimitExceeded()) 
    732767                                                        { 
    733768                                                                // Rename the existing files (ie include old versions) on the server 
     
    737772                                                                         
    738773                                                                // Stop the attempt to delete the file in the original location 
    739                                                                 BackupClientDeleteList &rdelList(rParams.mrContext.GetDeleteList()); 
     774                                                                BackupClientDeleteList &rdelList(rContext.GetDeleteList()); 
    740775                                                                rdelList.StopFileDeletion(renameInDirectory, oldLeafname); 
    741776                                                                 
     
    872907                } 
    873908 
     909                bool fileSynced = true; 
     910 
    874911                if (doUpload) 
    875912                { 
     913                        // Upload needed, don't mark sync success until 
     914                        // we've actually done it 
     915                        fileSynced = false; 
     916 
    876917                        // Make sure we're connected -- must connect here so we know whether 
    877918                        // the storage limit has been exceeded, and hence whether or not 
    878919                        // to actually upload the file. 
    879                         rParams.mrContext.GetConnection(); 
     920                        rContext.GetConnection(); 
    880921 
    881922                        // Only do this step if there is room on the server. 
    882923                        // This step will be repeated later when there is space available 
    883                         if(!rParams.mrContext.StorageLimitExceeded()) 
     924                        if(!rContext.StorageLimitExceeded()) 
    884925                        { 
    885926                                // Upload the file to the server, recording the object ID it returns 
     
    891932                                { 
    892933                                        latestObjectID = UploadFile(rParams, filename, storeFilename, fileSize, modTime, attributesHash, noPreviousVersionOnServer); 
    893                                         uploadSuccess = true; 
     934                                        if (latestObjectID == 0) 
     935                                        { 
     936                                                // storage limit exceeded 
     937                                                rParams.mrContext.SetStorageLimitExceeded(); 
     938                                                uploadSuccess = false; 
     939                                                allUpdatedSuccessfully = false; 
     940                                        } 
     941                                        else 
     942                                        { 
     943                                                uploadSuccess = true; 
     944                                        } 
    894945                                } 
    895946                                catch(ConnectionException &e) 
     
    897948                                        // Connection errors should just be passed on to the main handler, retries 
    898949                                        // would probably just cause more problems. 
    899                                         rParams.GetProgressNotifier() 
    900                                                 .NotifyFileUploadException( 
    901                                                         this, filename, e); 
     950                                        // StorageLimitExceeded never gets here. 
     951                                         
     952                                        rParams.mrDaemon.NotifySysadmin(BackupDaemon::NotifyEvent_StoreFull); 
     953                                        rNotifier.NotifyFileUploadException( 
     954                                                this, filename, e); 
    902955                                        throw; 
    903956                                } 
     
    908961                                        // Log it. 
    909962                                        SetErrorWhenReadingFilesystemObject(rParams, filename.c_str()); 
    910                                         rParams.GetProgressNotifier() 
    911                                                 .NotifyFileUploadException( 
    912                                                         this, filename, e); 
     963                                        rNotifier.NotifyFileUploadException( 
     964                                                this, filename, e); 
    913965                                } 
    914966 
     
    916968                                if(uploadSuccess) 
    917969                                { 
     970                                        fileSynced = true; 
     971 
    918972                                        // delete from pending entries 
    919973                                        if(pendingFirstSeenTime != 0 && mpPendingEntries != 0) 
     
    925979                        else 
    926980                        { 
    927                                 rParams.GetProgressNotifier().NotifyFileSkippedServerFull(this, 
     981                                rNotifier.NotifyFileSkippedServerFull(this, 
    928982                                        filename); 
    929983                        } 
     
    932986                { 
    933987                        // Attributes have probably changed, upload them again. 
    934                         // If the attributes have changed enough, the directory hash will have changed too, 
    935                         // and so the dir will have been downloaded, and the entry will be available. 
     988                        // If the attributes have changed enough, the directory 
     989                        // hash will have changed too, and so the dir will have 
     990                        // been downloaded, and the entry will be available. 
    936991 
    937992                        // Get connection 
    938                         BackupProtocolClient &connection(rParams.mrContext.GetConnection()); 
     993                        BackupProtocolClient &connection(rContext.GetConnection()); 
    939994 
    940995                        // Only do this step if there is room on the server. 
    941                         // This step will be repeated later when there is space available 
    942                         if(!rParams.mrContext.StorageLimitExceeded()) 
     996                        // This step will be repeated later when there is 
     997                        // space available 
     998                        if(!rContext.StorageLimitExceeded()) 
    943999                        { 
    9441000                                // Update store 
     
    9471003                                MemBlockStream attrStream(attr); 
    9481004                                connection.QuerySetReplacementFileAttributes(mObjectID, attributesHash, storeFilename, attrStream); 
     1005                                fileSynced = true; 
    9491006                        } 
    9501007                } 
     
    9821039                { 
    9831040                        // Get the map 
    984                         BackupClientInodeToIDMap &idMap(rParams.mrContext.GetNewIDMap()); 
     1041                        BackupClientInodeToIDMap &idMap(rContext.GetNewIDMap()); 
    9851042                 
    9861043                        // Need to get an ID from somewhere... 
     
    9941051                                // Don't know it -- haven't sent anything to the store, and didn't get a listing. 
    9951052                                // Look it up in the current map, and if it's there, use that. 
    996                                 const BackupClientInodeToIDMap &currentIDMap(rParams.mrContext.GetCurrentIDMap()); 
     1053                                const BackupClientInodeToIDMap &currentIDMap(rContext.GetCurrentIDMap()); 
    9971054                                int64_t objid = 0, dirid = 0; 
    9981055                                if(currentIDMap.Lookup(inodeNum, objid, dirid)) 
     
    10031060                                        // or there is a problem somewhere. If this happened on a short test run, look 
    10041061                                        // into it. However, in a long running process this may happen occasionally and 
    1005                                         // not indiciate anything wrong. 
     1062                                        // not indicate anything wrong. 
    10061063                                        // Run the release version for real life use, where this check is not made. 
    10071064                                        idMap.AddToMap(inodeNum, objid, mObjectID /* containing directory */);                           
     
    10101067                } 
    10111068                 
    1012                 rParams.GetProgressNotifier().NotifyFileSynchronised(this,  
    1013                         filename, fileSize); 
     1069                if (fileSynced) 
     1070                { 
     1071                        rNotifier.NotifyFileSynchronised(this, filename, 
     1072                                fileSize); 
     1073                } 
    10141074        } 
    10151075 
     
    10311091        { 
    10321092                // Send keep-alive message if needed 
    1033                 rParams.mrContext.DoKeepAlive(); 
     1093                rContext.DoKeepAlive(); 
    10341094                 
    10351095                // Get the local filename 
     
    10511111                if((en != 0) && ((en->GetFlags() & BackupStoreDirectory::Entry::Flags_Dir) == 0)) 
    10521112                { 
    1053                         // Entry exists, but is not a directory. Bad. Get rid of it. 
    1054                         BackupProtocolClient &connection(rParams.mrContext.GetConnection()); 
     1113                        // Entry exists, but is not a directory. Bad. 
     1114                        // Get rid of it. 
     1115                        BackupProtocolClient &connection(rContext.GetConnection()); 
    10551116                        connection.QueryDeleteFile(mObjectID /* in directory */, storeFilename); 
     1117                        rNotifier.NotifyFileDeleted(en->GetObjectID(), 
     1118                                storeFilename.GetClearFilename()); 
    10561119                         
    10571120                        // Nothing found 
     
    10591122                } 
    10601123 
    1061                 // Flag for having created directory, so can optimise the recusive call not to 
    1062                 // read it again, because we know it's empty. 
     1124                // Flag for having created directory, so can optimise the 
     1125                // recusive call not to read it again, because we know 
     1126                // it's empty. 
    10631127                bool haveJustCreatedDirOnServer = false; 
    10641128 
     
    10871151                                subDirObjectID = en->GetObjectID(); 
    10881152                        } 
    1089                         else if(rParams.mrContext.StorageLimitExceeded())        
     1153                        else if(rContext.StorageLimitExceeded())         
    10901154                        // know we've got a connection if we get this far, 
    10911155                        // as dir will have been modified. 
     
    11131177                                int64_t renameObjectID = 0, renameInDirectory = 0; 
    11141178                                bool renameDir = false; 
    1115                                 const BackupClientInodeToIDMap &idMap(rParams.mrContext.GetCurrentIDMap()); 
     1179                                const BackupClientInodeToIDMap &idMap( 
     1180                                        rContext.GetCurrentIDMap()); 
    11161181                                if(idMap.Lookup(inodeNum, renameObjectID, renameInDirectory)) 
    11171182                                { 
     
    11201185                                        bool isDir = false; 
    11211186                                        bool isCurrentVersion = false; 
    1122                                         if(rParams.mrContext.FindFilename(renameObjectID, renameInDirectory, localPotentialOldName, isDir, isCurrentVersion)) 
     1187                                        if(rContext.FindFilename(renameObjectID, renameInDirectory, localPotentialOldName, isDir, isCurrentVersion)) 
    11231188                                        {        
    11241189                                                // Only interested if it's a directory 
     
    11381203 
    11391204                                // Get connection 
    1140                                 BackupProtocolClient &connection(rParams.mrContext.GetConnection()); 
     1205                                BackupProtocolClient &connection(rContext.GetConnection()); 
    11411206                                 
    11421207                                // Don't do a check for storage limit exceeded here, because if we get to this 
     
    11581223 
    11591224                                        // Stop it being deleted later 
    1160                                         BackupClientDeleteList &rdelList(rParams.mrContext.GetDeleteList()); 
     1225                                        BackupClientDeleteList &rdelList( 
     1226                                                rContext.GetDeleteList()); 
    11611227                                        rdelList.StopDirectoryDeletion(renameObjectID); 
    11621228 
     
    11951261                } 
    11961262                 
    1197                 ASSERT(psubDirRecord != 0 || rParams.mrContext.StorageLimitExceeded()); 
     1263                ASSERT(psubDirRecord != 0 || rContext.StorageLimitExceeded()); 
    11981264                 
    11991265                if(psubDirRecord) 
    12001266                { 
    12011267                        // Sync this sub directory too 
    1202                         psubDirRecord->SyncDirectory(rParams, mObjectID, dirname, haveJustCreatedDirOnServer); 
     1268                        psubDirRecord->SyncDirectory(rParams, mObjectID, 
     1269                                dirname, rRemotePath + "/" + *d, 
     1270                                haveJustCreatedDirOnServer); 
    12031271                } 
    12041272 
     
    12291297                        // If there's an error during the process, it doesn't matter if things 
    12301298                        // aren't actually deleted, as the whole state will be reset anyway. 
    1231                         BackupClientDeleteList &rdel(rParams.mrContext.GetDeleteList()); 
     1299                        BackupClientDeleteList &rdel(rContext.GetDeleteList()); 
     1300 
     1301                        std::string localName = MakeFullPath(rLocalPath, 
     1302                                en->GetName()); 
    12321303                         
    12331304                        // Delete this entry -- file or directory? 
     
    12351306                        { 
    12361307                                // Set a pending deletion for the file 
    1237                                 rdel.AddFileDelete(mObjectID, en->GetName());                            
     1308                                rdel.AddFileDelete(mObjectID, en->GetName(), 
     1309                                        localName); 
    12381310                        } 
    12391311                        else if((en->GetFlags() & BackupStoreDirectory::Entry::Flags_Dir) != 0) 
    12401312                        { 
    12411313                                // Set as a pending deletion for the directory 
    1242                                 rdel.AddDirectoryDelete(en->GetObjectID()); 
     1314                                rdel.AddDirectoryDelete(en->GetObjectID(), 
     1315                                        localName); 
    12431316                                 
    1244                                 // If there's a directory record for it in the sub directory map, delete it now 
     1317                                // If there's a directory record for it in  
     1318                                // the sub directory map, delete it now 
    12451319                                BackupStoreFilenameClear dirname(en->GetName()); 
    12461320                                std::map<std::string, BackupClientDirectoryRecord *>::iterator e(mSubDirectories.find(dirname.GetClearFilename())); 
     
    12771351// 
    12781352// -------------------------------------------------------------------------- 
    1279 void BackupClientDirectoryRecord::RemoveDirectoryInPlaceOfFile(SyncParams &rParams, BackupStoreDirectory *pDirOnStore, int64_t ObjectID, const std::string &rFilename) 
     1353void BackupClientDirectoryRecord::RemoveDirectoryInPlaceOfFile( 
     1354        SyncParams &rParams, 
     1355        BackupStoreDirectory* pDirOnStore, 
     1356        BackupStoreDirectory::Entry* pEntry, 
     1357        const std::string &rFilename) 
    12801358{ 
    12811359        // First, delete the directory 
    12821360        BackupProtocolClient &connection(rParams.mrContext.GetConnection()); 
    1283         connection.QueryDeleteDirectory(ObjectID); 
     1361        connection.QueryDeleteDirectory(pEntry->GetObjectID()); 
     1362 
     1363        BackupStoreFilenameClear clear(pEntry->GetName()); 
     1364        rParams.mrContext.GetProgressNotifier().NotifyDirectoryDeleted( 
     1365                pEntry->GetObjectID(), clear.GetClearFilename()); 
    12841366 
    12851367        // Then, delete any directory record 
    1286         std::map<std::string, BackupClientDirectoryRecord *>::iterator e(mSubDirectories.find(rFilename)); 
     1368        std::map<std::string, BackupClientDirectoryRecord *>::iterator 
     1369                e(mSubDirectories.find(rFilename)); 
     1370 
    12871371        if(e != mSubDirectories.end()) 
    12881372        { 
     
    13011385// 
    13021386// Function 
    1303 //              Name:    BackupClientDirectoryRecord::UploadFile(BackupClientDirectoryRecord::SyncParams &, const std::string &, const BackupStoreFilename &, int64_t, box_time_t, box_time_t, bool) 
    1304 //              Purpose: Private. Upload a file to the server -- may send a patch instead of the whole thing 
     1387//              Name:    BackupClientDirectoryRecord::UploadFile( 
     1388//                       BackupClientDirectoryRecord::SyncParams &, 
     1389//                       const std::string &, 
     1390//                       const BackupStoreFilename &, 
     1391//                       int64_t, box_time_t, box_time_t, bool) 
     1392//              Purpose: Private. Upload a file to the server. May send 
     1393//                       a patch instead of the whole thing 
    13051394//              Created: 20/1/04 
    13061395// 
    13071396// -------------------------------------------------------------------------- 
    1308 int64_t BackupClientDirectoryRecord::UploadFile(BackupClientDirectoryRecord::SyncParams &rParams, const std::string &rFilename, const BackupStoreFilename &rStoreFilename, 
    1309                         int64_t FileSize, box_time_t ModificationTime, box_time_t AttributesHash, bool NoPreviousVersionOnServer) 
     1397int64_t BackupClientDirectoryRecord::UploadFile( 
     1398        BackupClientDirectoryRecord::SyncParams &rParams, 
     1399        const std::string &rFilename, 
     1400        const BackupStoreFilename &rStoreFilename, 
     1401        int64_t FileSize, 
     1402        box_time_t ModificationTime, 
     1403        box_time_t AttributesHash, 
     1404        bool NoPreviousVersionOnServer) 
    13101405{ 
     1406        BackupClientContext& rContext(rParams.mrContext); 
     1407        ProgressNotifier& rNotifier(rContext.GetProgressNotifier()); 
     1408 
    13111409        // Get the connection 
    1312         BackupProtocolClient &connection(rParams.mrContext.GetConnection()); 
     1410        BackupProtocolClient &connection(rContext.GetConnection()); 
    13131411 
    13141412        // Info 
     
    13191417        try 
    13201418        { 
    1321                 // Might an old version be on the server, and is the file size over the diffing threshold? 
    1322                 if(!NoPreviousVersionOnServer && FileSize >= rParams.mDiffingUploadSizeThreshold) 
     1419                // Might an old version be on the server, and is the file 
     1420                // size over the diffing threshold? 
     1421                if(!NoPreviousVersionOnServer && 
     1422                        FileSize >= rParams.mDiffingUploadSizeThreshold) 
    13231423                { 
    13241424                        // YES -- try to do diff, if possible 
     
    13301430                        { 
    13311431                                // Found an old version 
    1332                                 rParams.GetProgressNotifier().NotifyFileUploadingPatch(this,  
     1432                                rNotifier.NotifyFileUploadingPatch(this,  
    13331433                                        rFilename); 
    13341434 
     
    13401440                                // 
    13411441 
    1342                                 rParams.mrContext.ManageDiffProcess(); 
     1442                                rContext.ManageDiffProcess(); 
    13431443 
    13441444                                bool isCompletelyDifferent = false; 
     
    13491449                                                rStoreFilename, diffFromID, *blockIndexStream, 
    13501450                                                connection.GetTimeout(),  
    1351                                                 &rParams.mrContext, // DiffTimer implementation 
     1451                                                &rContext, // DiffTimer implementation 
    13521452                                                0 /* not interested in the modification time */,  
    13531453                                                &isCompletelyDifferent)); 
    13541454         
    1355                                 rParams.mrContext.UnManageDiffProcess(); 
     1455                                rContext.UnManageDiffProcess(); 
    13561456 
    13571457                                // 
     
    13611461                                                AttributesHash, isCompletelyDifferent?(0):(diffFromID), rStoreFilename, *patchStream)); 
    13621462                                 
     1463                                // Get object ID from the result                 
     1464                                objID = stored->GetObjectID(); 
     1465 
    13631466                                // Don't attempt to upload it again! 
    13641467                                doNormalUpload = false; 
     
    13691472                { 
    13701473                        // below threshold or nothing to diff from, so upload whole 
    1371                         rParams.GetProgressNotifier().NotifyFileUploading(this,  
    1372                                 rFilename); 
     1474                        rNotifier.NotifyFileUploading(this, rFilename); 
    13731475                         
    13741476                        // Prepare to upload, getting a stream which will encode the file as we go along 
     
    13911493        catch(BoxException &e) 
    13921494        { 
    1393                 rParams.mrContext.UnManageDiffProcess(); 
     1495                rContext.UnManageDiffProcess(); 
    13941496 
    13951497                if(e.GetType() == ConnectionException::ExceptionType && e.GetSubType() == ConnectionException::Protocol_UnexpectedReply) 
     
    14051507                                        // The hard limit was exceeded on the server, notify! 
    14061508                                        rParams.mrDaemon.NotifySysadmin(BackupDaemon::NotifyEvent_StoreFull); 
    1407                                 } 
    1408                                 rParams.GetProgressNotifier() 
    1409                                         .NotifyFileUploadServerError( 
    1410                                                 this, rFilename, type, subtype); 
     1509                                        // return an error code instead of 
     1510                                        // throwing an exception that we 
     1511                                        // can't debug. 
     1512                                        return 0; 
     1513                                } 
     1514                                rNotifier.NotifyFileUploadServerError(this, 
     1515                                        rFilename, type, subtype); 
    14111516                        } 
    14121517                } 
     
    14161521        } 
    14171522 
    1418         rParams.GetProgressNotifier().NotifyFileUploaded(this, rFilename, FileSize); 
     1523        rNotifier.NotifyFileUploaded(this, rFilename, FileSize); 
    14191524 
    14201525        // Return the new object ID of this file 
     
    14581563// -------------------------------------------------------------------------- 
    14591564BackupClientDirectoryRecord::SyncParams::SyncParams(BackupDaemon &rDaemon,  
    1460         ProgressNotifier &rProgressNotifier, BackupClientContext &rContext) 
    1461         : mrProgressNotifier(rProgressNotifier), 
    1462           mSyncPeriodStart(0), 
     1565        BackupClientContext &rContext) 
     1566        : mSyncPeriodStart(0), 
    14631567          mSyncPeriodEnd(0), 
    14641568          mMaxUploadWait(0), 
  • box/trunk/bin/bbackupd/BackupClientDirectoryRecord.h

    r1801 r2181  
    9797                const std::string& rLocalPath, 
    9898                int64_t FileSize) = 0; 
     99        virtual void NotifyDirectoryDeleted( 
     100                int64_t ObjectID, 
     101                const std::string& rRemotePath) = 0; 
     102        virtual void NotifyFileDeleted( 
     103                int64_t ObjectID, 
     104                const std::string& rRemotePath) = 0; 
    99105}; 
    100106 
     
    138144                SyncParams( 
    139145                        BackupDaemon &rDaemon, 
    140                         ProgressNotifier &rProgressNotifier, 
    141146                        BackupClientContext &rContext); 
    142147                ~SyncParams(); 
     
    145150                SyncParams(const SyncParams&); 
    146151                SyncParams &operator=(const SyncParams&); 
    147                 ProgressNotifier &mrProgressNotifier; 
    148152                 
    149153        public: 
     
    162166                box_time_t mUploadAfterThisTimeInTheFuture; 
    163167                bool mHaveLoggedWarningAboutFutureFileTimes; 
    164          
    165                 ProgressNotifier& GetProgressNotifier() const  
    166                 {  
    167                         return mrProgressNotifier; 
    168                 } 
    169168        }; 
    170169 
    171         void SyncDirectory(SyncParams &rParams, int64_t ContainingDirectoryID, const std::string &rLocalPath, 
     170        void SyncDirectory(SyncParams &rParams, 
     171                int64_t ContainingDirectoryID, 
     172                const std::string &rLocalPath, 
     173                const std::string &rRemotePath, 
    172174                bool ThisDirHasJustBeenCreated = false); 
    173175 
     
    175177        void DeleteSubDirectories(); 
    176178        BackupStoreDirectory *FetchDirectoryListing(SyncParams &rParams); 
    177         void UpdateAttributes(SyncParams &rParams, BackupStoreDirectory *pDirOnStore, const std::string &rLocalPath); 
    178         bool UpdateItems(SyncParams &rParams, const std::string &rLocalPath, BackupStoreDirectory *pDirOnStore, 
     179        void UpdateAttributes(SyncParams &rParams, 
     180                BackupStoreDirectory *pDirOnStore, 
     181                const std::string &rLocalPath); 
     182        bool UpdateItems(SyncParams &rParams, const std::string &rLocalPath, 
     183                const std::string &rRemotePath, 
     184                BackupStoreDirectory *pDirOnStore, 
    179185                std::vector<BackupStoreDirectory::Entry *> &rEntriesLeftOver, 
    180                 std::vector<std::string> &rFiles, const std::vector<std::string> &rDirs); 
    181         int64_t UploadFile(SyncParams &rParams, const std::string &rFilename, const BackupStoreFilename &rStoreFilename, 
    182                 int64_t FileSize, box_time_t ModificationTime, box_time_t AttributesHash, bool NoPreviousVersionOnServer); 
    183         void SetErrorWhenReadingFilesystemObject(SyncParams &rParams, const char *Filename); 
    184         void RemoveDirectoryInPlaceOfFile(SyncParams &rParams, BackupStoreDirectory *pDirOnStore, int64_t ObjectID, const std::string &rFilename); 
     186                std::vector<std::string> &rFiles, 
     187                const std::vector<std::string> &rDirs); 
     188        int64_t UploadFile(SyncParams &rParams, 
     189                const std::string &rFilename, 
     190                const BackupStoreFilename &rStoreFilename, 
     191                int64_t FileSize, box_time_t ModificationTime, 
     192                box_time_t AttributesHash, bool NoPreviousVersionOnServer); 
     193        void SetErrorWhenReadingFilesystemObject(SyncParams &rParams, 
     194                const char *Filename); 
     195        void RemoveDirectoryInPlaceOfFile(SyncParams &rParams, 
     196                BackupStoreDirectory* pDirOnStore, 
     197                BackupStoreDirectory::Entry* pEntry, 
     198                const std::string &rFilename); 
    185199 
    186200private: 
    187         int64_t                 mObjectID; 
     201        int64_t         mObjectID; 
    188202        std::string     mSubDirName; 
    189         bool                    mInitialSyncDone; 
    190         bool                    mSyncDone; 
     203        bool            mInitialSyncDone; 
     204        bool            mSyncDone; 
    191205 
    192206        // Checksum of directory contents and attributes, used to detect changes 
    193207        uint8_t mStateChecksum[MD5Digest::DigestLength]; 
    194208 
    195         std::map<std::string, box_time_t>                                               *mpPendingEntries; 
    196         std::map<std::string, BackupClientDirectoryRecord *>    mSubDirectories; 
     209        std::map<std::string, box_time_t> *mpPendingEntries; 
     210        std::map<std::string, BackupClientDirectoryRecord *> mSubDirectories; 
    197211        // mpPendingEntries is a pointer rather than simple a member 
    198         // variables, because most of the time it'll be empty. This would waste a lot 
    199         // of memory because of STL allocation policies. 
     212        // variable, because most of the time it'll be empty. This would 
     213        // waste a lot of memory because of STL allocation policies. 
    200214}; 
    201215 
  • box/trunk/bin/bbackupd/BackupDaemon.cpp

    r2148 r2181  
    4848 
    4949#include "SSLLib.h" 
    50 #include "TLSContext.h" 
    5150 
    5251#include "BackupDaemon.h" 
     
    125124          mpCommandSocketInfo(0), 
    126125          mDeleteUnusedRootDirEntriesAfter(0), 
     126          mClientStoreMarker(BackupClientContext::ClientStoreMarker_NotKnown), 
     127          mStorageLimitExceeded(false), 
     128          mReadErrorsOnFilesystemObjects(false), 
     129          mLastSyncTime(0), 
    127130          mLogAllFileAccess(false) 
    128131        #ifdef WIN32 
     
    295298        mLocations.clear(); 
    296299         
    297         // And delete everything from the assoicated mount vector 
     300        // And delete everything from the associated mount vector 
    298301        mIDMapMounts.clear(); 
    299302} 
     
    686689} 
    687690 
    688 // -------------------------------------------------------------------------- 
    689 // 
    690 // Function 
    691 //              Name:    BackupDaemon::Run2() 
    692 //              Purpose: Run function for daemon (second stage) 
    693 //              Created: 2003/10/08 
    694 // 
    695 // -------------------------------------------------------------------------- 
    696 void BackupDaemon::Run2() 
     691void BackupDaemon::InitCrypto() 
    697692{ 
    698693        // Read in the certificates creating a TLS context 
    699         TLSContext tlsContext; 
    700694        const Configuration &conf(GetConfiguration()); 
    701695        std::string certFile(conf.GetKeyValue("CertificateFile")); 
    702696        std::string keyFile(conf.GetKeyValue("PrivateKeyFile")); 
    703697        std::string caFile(conf.GetKeyValue("TrustedCAsFile")); 
    704         tlsContext.Initialise(false /* as client */, certFile.c_str(), keyFile.c_str(), caFile.c_str()); 
     698        mTlsContext.Initialise(false /* as client */, certFile.c_str(), 
     699                keyFile.c_str(), caFile.c_str()); 
    705700         
    706701        // Set up the keys for various things 
    707702        BackupClientCryptoKeys_Setup(conf.GetKeyValue("KeysFile").c_str()); 
    708  
    709         // Setup various timings 
    710         int maximumDiffingTime = 600; 
    711         int keepAliveTime = 60; 
    712  
    713         // max diffing time, keep-alive time 
    714         if(conf.KeyExists("MaximumDiffingTime")) 
    715         { 
    716                 maximumDiffingTime = conf.GetKeyValueInt("MaximumDiffingTime"); 
    717         } 
    718         if(conf.KeyExists("KeepAliveTime")) 
    719         { 
    720                 keepAliveTime = conf.GetKeyValueInt("KeepAliveTime"); 
    721         } 
     703} 
     704 
     705// -------------------------------------------------------------------------- 
     706// 
     707// Function 
     708//              Name:    BackupDaemon::Run2() 
     709//              Purpose: Run function for daemon (second stage) 
     710//              Created: 2003/10/08 
     711// 
     712// -------------------------------------------------------------------------- 
     713void BackupDaemon::Run2() 
     714{ 
     715        InitCrypto(); 
     716 
     717        const Configuration &conf(GetConfiguration()); 
    722718 
    723719        // How often to connect to the store (approximate) 
    724         box_time_t updateStoreInterval = SecondsToBoxTime(conf.GetKeyValueInt("UpdateStoreInterval")); 
     720        box_time_t updateStoreInterval = SecondsToBoxTime( 
     721                conf.GetKeyValueInt("UpdateStoreInterval")); 
    725722 
    726723        // But are we connecting automatically? 
    727724        bool automaticBackup = conf.GetKeyValueBool("AutomaticBackup"); 
    728725         
    729         // The minimum age a file needs to be before it will be considered for uploading 
    730         box_time_t minimumFileAge = SecondsToBoxTime(conf.GetKeyValueInt("MinimumFileAge")); 
    731  
    732         // The maximum time we'll wait to upload a file, regardless of how often it's modified 
    733         box_time_t maxUploadWait = SecondsToBoxTime(conf.GetKeyValueInt("MaxUploadWait")); 
    734         // Adjust by subtracting the minimum file age, so is relative to sync period end in comparisons 
    735         maxUploadWait = (maxUploadWait > minimumFileAge)?(maxUploadWait - minimumFileAge):(0); 
    736  
    737726        // When the next sync should take place -- which is ASAP 
    738727        box_time_t nextSyncTime = 0; 
    739728 
    740729        // When the last sync started (only updated if the store was not full when the sync ended) 
    741         box_time_t lastSyncTime = 0; 
     730        mLastSyncTime = 0; 
    742731 
    743732        // -------------------------------------------------------------------------------------------- 
    744733  
    745         // And what's the current client store marker? 
    746         int64_t clientStoreMarker =  
    747                 BackupClientContext::ClientStoreMarker_NotKnown; 
    748         // haven't contacted the store yet 
    749  
    750734        bool deleteStoreObjectInfoFile = DeserializeStoreObjectInfo( 
    751                 clientStoreMarker, lastSyncTime, nextSyncTime); 
     735                mLastSyncTime, nextSyncTime); 
    752736  
    753737        // -------------------------------------------------------------------------------------------- 
     
    756740        // Set state 
    757741        SetState(State_Idle); 
     742 
     743        bool doSyncForcedByPreviousSyncError = false; 
    758744 
    759745        // Loop around doing backups 
     
    766752 
    767753                // Is a delay necessary? 
    768                 { 
    769                         box_time_t currentTime; 
    770                         do 
    771                         { 
    772                                 // Check whether we should be stopping, 
    773                                 // and don't run a sync if so. 
    774                                 if(StopRun()) break; 
    775                                  
    776                                 currentTime = GetCurrentBoxTime(); 
    777          
    778                                 // Pause a while, but no more than  
    779                                 // MAX_SLEEP_TIME seconds (use the conditional 
    780                                 // because times are unsigned) 
    781                                 box_time_t requiredDelay =  
    782                                         (nextSyncTime < currentTime) 
    783                                         ? (0) 
    784                                         : (nextSyncTime - currentTime); 
    785  
    786                                 // If there isn't automatic backup happening,  
    787                                 // set a long delay. And limit delays at the  
    788                                 // same time. 
    789                                 if(!automaticBackup || requiredDelay >  
    790                                         SecondsToBoxTime(MAX_SLEEP_TIME)) 
    791                                 { 
    792                                         requiredDelay = SecondsToBoxTime( 
    793                                                 MAX_SLEEP_TIME); 
    794                                 } 
    795  
    796                                 // Only delay if necessary 
    797                                 if(requiredDelay > 0) 
    798                                 { 
    799                                         // Sleep somehow. There are choices  
    800                                         // on how this should be done, 
    801                                         // depending on the state of the  
    802                                         // control connection 
    803                                         if(mpCommandSocketInfo != 0) 
    804                                         { 
    805                                                 // A command socket exists,  
    806                                                 // so sleep by waiting on it 
    807                                                 WaitOnCommandSocket( 
    808                                                         requiredDelay, doSync,  
    809                                                         doSyncForcedByCommand); 
    810                                         } 
    811                                         else 
    812                                         { 
    813                                                 // No command socket or  
    814                                                 // connection, just do a  
    815                                                 // normal sleep 
    816                                                 time_t sleepSeconds =  
    817                                                         BoxTimeToSeconds( 
    818                                                         requiredDelay); 
    819                                                 ::sleep((sleepSeconds <= 0) 
    820                                                         ? 1 
    821                                                         : sleepSeconds); 
    822                                         } 
    823                                 } 
    824                                  
    825                         } while((!automaticBackup || (currentTime < nextSyncTime)) && !doSync && !StopRun()); 
    826                 } 
     754                box_time_t currentTime; 
     755 
     756                do 
     757                { 
     758                        // Check whether we should be stopping, 
     759                        // and don't run a sync if so. 
     760                        if(StopRun()) break; 
     761                         
     762                        currentTime = GetCurrentBoxTime(); 
     763 
     764                        // Pause a while, but no more than  
     765                        // MAX_SLEEP_TIME seconds (use the conditional 
     766                        // because times are unsigned) 
     767                        box_time_t requiredDelay =  
     768                                (nextSyncTime < currentTime) 
     769                                ? (0) 
     770                                : (nextSyncTime - currentTime); 
     771 
     772                        // If there isn't automatic backup happening,  
     773                        // set a long delay. And limit delays at the  
     774                        // same time. 
     775                        if(!automaticBackup && !doSyncForcedByPreviousSyncError) 
     776                        { 
     777                                requiredDelay = SecondsToBoxTime(MAX_SLEEP_TIME); 
     778                        } 
     779                        else if(requiredDelay > SecondsToBoxTime(MAX_SLEEP_TIME)) 
     780                        { 
     781                                requiredDelay = SecondsToBoxTime(MAX_SLEEP_TIME); 
     782                        } 
     783 
     784                        // Only delay if necessary 
     785                        if(requiredDelay > 0) 
     786                        { 
     787                                // Sleep somehow. There are choices  
     788                                // on how this should be done, 
     789                                // depending on the state of the  
     790                                // control connection 
     791                                if(mpCommandSocketInfo != 0) 
     792                                { 
     793                                        // A command socket exists,  
     794                                        // so sleep by waiting on it 
     795                                        WaitOnCommandSocket(requiredDelay, 
     796                                                doSync, doSyncForcedByCommand); 
     797                                } 
     798                                else 
     799                                { 
     800                                        // No command socket or  
     801                                        // connection, just do a  
     802                                        // normal sleep 
     803                                        time_t sleepSeconds =  
     804                                                BoxTimeToSeconds(requiredDelay); 
     805                                        ::sleep((sleepSeconds <= 0) 
     806                                                ? 1 : sleepSeconds); 
     807                                } 
     808                        } 
     809                         
     810                        if ((automaticBackup || doSyncForcedByPreviousSyncError) 
     811                                && currentTime >= nextSyncTime) 
     812                        { 
     813                                doSync = true; 
     814                        } 
     815                } 
     816                while(!doSync && !StopRun()); 
    827817 
    828818                // Time of sync start, and if it's time for another sync  
    829819                // (and we're doing automatic syncs), set the flag 
    830820                box_time_t currentSyncStartTime = GetCurrentBoxTime(); 
    831                 if(automaticBackup && currentSyncStartTime >= nextSyncTime) 
     821                if((automaticBackup || doSyncForcedByPreviousSyncError) && 
     822                        currentSyncStartTime >= nextSyncTime) 
    832823                { 
    833824                        doSync = true; 
     
    860851                        BackupStoreFile::ResetStats(); 
    861852                         
    862                         // Calculate the sync period of files to examine 
    863                         box_time_t syncPeriodStart = lastSyncTime; 
    864                         box_time_t syncPeriodEnd = currentSyncStartTime -  
    865                                 minimumFileAge; 
    866  
    867                         if(syncPeriodStart >= syncPeriodEnd && 
    868                                 syncPeriodStart - syncPeriodEnd < minimumFileAge) 
    869                         { 
    870                                 // This can happen if we receive a force-sync 
    871                                 // command less than minimumFileAge after 
    872                                 // the last sync. Deal with it by moving back 
    873                                 // syncPeriodStart, which should not do any 
    874                                 // damage. 
    875                                 syncPeriodStart = syncPeriodEnd - 
    876                                         SecondsToBoxTime(1); 
    877                         } 
    878  
    879                         if(syncPeriodStart >= syncPeriodEnd) 
    880                         { 
    881                                 BOX_ERROR("Invalid (negative) sync period: " 
    882                                         "perhaps your clock is going " 
    883                                         "backwards (" << syncPeriodStart << 
    884                                         " to " << syncPeriodEnd << ")"); 
    885                                 THROW_EXCEPTION(ClientException, 
    886                                         ClockWentBackwards); 
    887                         } 
    888  
    889                         // Check logic 
    890                         ASSERT(syncPeriodEnd > syncPeriodStart); 
    891                         // Paranoid check on sync times 
    892                         if(syncPeriodStart >= syncPeriodEnd) continue; 
    893                          
    894                         // Adjust syncPeriodEnd to emulate snapshot  
    895                         // behaviour properly 
    896                         box_time_t syncPeriodEndExtended = syncPeriodEnd; 
    897                         // Using zero min file age? 
    898                         if(minimumFileAge == 0) 
    899                         { 
    900                                 // Add a year on to the end of the end time, 
    901                                 // to make sure we sync files which are  
    902                                 // modified after the scan run started. 
    903                                 // Of course, they may be eligible to be  
    904                                 // synced again the next time round, 
    905                                 // but this should be OK, because the changes  
    906                                 // only upload should upload no data. 
    907                                 syncPeriodEndExtended += SecondsToBoxTime( 
    908                                         (time_t)(356*24*3600)); 
    909                         } 
    910  
    911853                        // Delete the serialised store object file, 
    912854                        // so that we don't try to reload it after a 
     
    934876                        try 
    935877                        { 
    936                                 // Set state and log start 
    937                                 SetState(State_Connected); 
    938                                 BOX_NOTICE("Beginning scan of local files"); 
    939  
    940                                 std::string extendedLogFile; 
    941                                 if (conf.KeyExists("ExtendedLogFile")) 
    942                                 { 
    943                                         extendedLogFile = conf.GetKeyValue( 
    944                                                 "ExtendedLogFile"); 
    945                                 } 
    946                                  
    947                                 if (conf.KeyExists("LogAllFileAccess")) 
    948                                 { 
    949                                         mLogAllFileAccess =  
    950                                                 conf.GetKeyValueBool( 
    951                                                         "LogAllFileAccess"); 
    952                                 } 
    953                                  
    954                                 // Then create a client context object (don't  
    955                                 // just connect, as this may be unnecessary) 
    956                                 BackupClientContext clientContext 
    957                                 ( 
    958                                         *this,  
    959                                         tlsContext,  
    960                                         conf.GetKeyValue("StoreHostname"), 
    961                                         conf.GetKeyValueInt("StorePort"), 
    962                                         conf.GetKeyValueInt("AccountNumber"),  
    963                                         conf.GetKeyValueBool("ExtendedLogging"), 
    964                                         conf.KeyExists("ExtendedLogFile"), 
    965                                         extendedLogFile 
    966                                 ); 
    967                                          
    968                                 // Set up the sync parameters 
    969                                 BackupClientDirectoryRecord::SyncParams params( 
    970                                         *this, *this, clientContext); 
    971                                 params.mSyncPeriodStart = syncPeriodStart; 
    972                                 params.mSyncPeriodEnd = syncPeriodEndExtended; 
    973                                 // use potentially extended end time 
    974                                 params.mMaxUploadWait = maxUploadWait; 
    975                                 params.mFileTrackingSizeThreshold =  
    976                                         conf.GetKeyValueInt( 
    977                                         "FileTrackingSizeThreshold"); 
    978                                 params.mDiffingUploadSizeThreshold =  
    979                                         conf.GetKeyValueInt( 
    980                                         "DiffingUploadSizeThreshold"); 
    981                                 params.mMaxFileTimeInFuture =  
    982                                         SecondsToBoxTime( 
    983                                                 conf.GetKeyValueInt( 
    984                                                         "MaxFileTimeInFuture")); 
    985                                 mDeleteRedundantLocationsAfter = 
    986                                         conf.GetKeyValueInt( 
    987                                                 "DeleteRedundantLocationsAfter"); 
    988  
    989                                 clientContext.SetMaximumDiffingTime(maximumDiffingTime); 
    990                                 clientContext.SetKeepAliveTime(keepAliveTime); 
    991                                  
    992                                 // Set store marker 
    993                                 clientContext.SetClientStoreMarker(clientStoreMarker); 
    994                                  
    995                                 // Set up the locations, if necessary --  
    996                                 // need to do it here so we have a  
    997                                 // (potential) connection to use 
    998                                 if(mLocations.empty()) 
    999                                 { 
    1000                                         const Configuration &locations( 
    1001                                                 conf.GetSubConfiguration( 
    1002                                                         "BackupLocations")); 
    1003                                          
    1004                                         // Make sure all the directory records 
    1005                                         // are set up 
    1006                                         SetupLocations(clientContext, locations); 
    1007                                 } 
    1008                                  
    1009                                 // Get some ID maps going 
    1010                                 SetupIDMapsForSync(); 
    1011  
    1012                                 // Delete any unused directories? 
    1013                                 DeleteUnusedRootDirEntries(clientContext); 
    1014                                                                  
    1015878                                // Notify administrator 
    1016879                                NotifySysadmin(NotifyEvent_BackupStart); 
    1017880 
    1018                                 // Go through the records, syncing them 
    1019                                 for(std::vector<Location *>::const_iterator  
    1020                                         i(mLocations.begin());  
    1021                                         i != mLocations.end(); ++i) 
    1022                                 { 
    1023                                         // Set current and new ID map pointers 
    1024                                         // in the context 
    1025                                         clientContext.SetIDMaps(mCurrentIDMaps[(*i)->mIDMapIndex], mNewIDMaps[(*i)->mIDMapIndex]); 
    1026                                  
    1027                                         // Set exclude lists (context doesn't 
    1028                                         // take ownership) 
    1029                                         clientContext.SetExcludeLists( 
    1030                                                 (*i)->mpExcludeFiles, 
    1031                                                 (*i)->mpExcludeDirs); 
    1032  
    1033                                         // Sync the directory 
    1034                                         (*i)->mpDirectoryRecord->SyncDirectory( 
    1035                                                 params, 
    1036                                                 BackupProtocolClientListDirectory::RootDirectory, 
    1037                                                 (*i)->mPath); 
    1038  
    1039                                         // Unset exclude lists (just in case) 
    1040                                         clientContext.SetExcludeLists(0, 0); 
    1041                                 } 
    1042                                  
     881                                RunSyncNow(); 
     882 
    1043883                                // Errors reading any files? 
    1044                                 if(params.mReadErrorsOnFilesystemObjects) 
     884                                if(mReadErrorsOnFilesystemObjects) 
    1045885                                { 
    1046886                                        // Notify administrator 
     
    1054894                                } 
    1055895                                 
    1056                                 // Perform any deletions required -- these are 
    1057                                 // delayed until the end to allow renaming to  
    1058                                 // happen neatly. 
    1059                                 clientContext.PerformDeletions(); 
    1060  
    1061                                 // Close any open connection 
    1062                                 clientContext.CloseAnyOpenConnection(); 
    1063                                  
    1064                                 // Get the new store marker 
    1065                                 clientStoreMarker = clientContext.GetClientStoreMarker(); 
    1066                                  
    1067896                                // Check the storage limit 
    1068                                 if(clientContext.StorageLimitExceeded()) 
     897                                if(mStorageLimitExceeded) 
    1069898                                { 
    1070899                                        // Tell the sysadmin about this 
     
    1073902                                else 
    1074903                                { 
    1075                                         // The start time of the next run is 
    1076                                         // the end time of this run. 
    1077                                         // This is only done if the storage 
    1078                                         // limit wasn't exceeded (as things 
    1079                                         // won't have been done properly if 
    1080                                         // it was) 
    1081                                         lastSyncTime = syncPeriodEnd; 
    1082  
    1083904                                        // unflag the storage full notify flag 
    1084905                                        // so that next time the store is full, 
     
    1093914                                        SYNC_PERIOD_RANDOM_EXTRA_TIME_SHIFT_BY); 
    1094915                         
    1095                                 // Commit the ID Maps 
    1096                                 CommitIDMapsAfterSync(); 
    1097  
    1098                                 // Log 
    1099                                 BOX_NOTICE("Finished scan of local files"); 
    1100  
    1101916                                // Notify administrator 
    1102917                                NotifySysadmin(NotifyEvent_BackupFinish); 
     
    1109924 
    1110925                                deleteStoreObjectInfoFile =  
    1111                                         SerializeStoreObjectInfo( 
    1112                                                 clientStoreMarker,  
    1113                                                 lastSyncTime, nextSyncTime); 
     926                                        SerializeStoreObjectInfo(mLastSyncTime, 
     927                                                nextSyncTime); 
    1114928 
    1115929                                // -------------------------------------------------------------------------------------------- 
     930 
     931                                // If we were retrying after an error, 
     932                                // now would be a good time to stop :-) 
     933                                doSyncForcedByPreviousSyncError = false; 
    1116934                        } 
    1117935                        catch(BoxException &e) 
     
    1154972 
    1155973                                // Clear state data 
    1156                                 syncPeriodStart = 0; 
    1157                                 // go back to beginning of time 
    1158                                 clientStoreMarker = BackupClientContext::ClientStoreMarker_NotKnown;    // no store marker, so download everything 
     974                                // Go back to beginning of time 
     975                                mLastSyncTime = 0; 
     976                                mClientStoreMarker = BackupClientContext::ClientStoreMarker_NotKnown;   // no store marker, so download everything 
    1159977                                DeleteAllLocations(); 
    1160978                                DeleteAllIDMaps(); 
     
    1169987                                } 
    1170988 
    1171                                 // If the Berkely db files get corrupted, delete them and try again immediately 
     989                                // If the Berkely db files get corrupted, 
     990                                // delete them and try again immediately. 
    1172991                                if(isBerkelyDbFailure) 
    1173992                                { 
     
    11891008                                        ::sleep(10); 
    11901009                                        nextSyncTime = currentSyncStartTime +  
    1191                                                 SecondsToBoxTime(90) + 
     1010                                                SecondsToBoxTime(100) + 
    11921011                                                Random::RandomInt( 
    11931012                                                        updateStoreInterval >>  
    11941013                                                        SYNC_PERIOD_RANDOM_EXTRA_TIME_SHIFT_BY); 
     1014                                        doSyncForcedByPreviousSyncError = true; 
    11951015                                } 
    11961016                        } 
     
    12221042} 
    12231043 
     1044void BackupDaemon::RunSyncNow() 
     1045{ 
     1046        // Set state and log start 
     1047        SetState(State_Connected); 
     1048        BOX_NOTICE("Beginning scan of local files"); 
     1049 
     1050        const Configuration &conf(GetConfiguration()); 
     1051 
     1052        std::string extendedLogFile; 
     1053        if (conf.KeyExists("ExtendedLogFile")) 
     1054        { 
     1055                extendedLogFile = conf.GetKeyValue("ExtendedLogFile"); 
     1056        } 
     1057         
     1058        if (conf.KeyExists("LogAllFileAccess")) 
     1059        { 
     1060                mLogAllFileAccess = conf.GetKeyValueBool("LogAllFileAccess"); 
     1061        } 
     1062         
     1063        // Then create a client context object (don't  
     1064        // just connect, as this may be unnecessary) 
     1065        BackupClientContext clientContext 
     1066        ( 
     1067                *this,  
     1068                mTlsContext,  
     1069                conf.GetKeyValue("StoreHostname"), 
     1070                conf.GetKeyValueInt("StorePort"), 
     1071                conf.GetKeyValueInt("AccountNumber"),  
     1072                conf.GetKeyValueBool("ExtendedLogging"), 
     1073                conf.KeyExists("ExtendedLogFile"), 
     1074                extendedLogFile, *this 
     1075        ); 
     1076                 
     1077        // The minimum age a file needs to be before it will be 
     1078        // considered for uploading 
     1079        box_time_t minimumFileAge = SecondsToBoxTime( 
     1080                conf.GetKeyValueInt("MinimumFileAge")); 
     1081 
     1082        // The maximum time we'll wait to upload a file, regardless 
     1083        // of how often it's modified 
     1084        box_time_t maxUploadWait = SecondsToBoxTime( 
     1085                conf.GetKeyValueInt("MaxUploadWait")); 
     1086        // Adjust by subtracting the minimum file age, so is relative 
     1087        // to sync period end in comparisons 
     1088        if (maxUploadWait > minimumFileAge) 
     1089        { 
     1090                maxUploadWait -= minimumFileAge; 
     1091        } 
     1092        else 
     1093        { 
     1094                maxUploadWait = 0; 
     1095        } 
     1096 
     1097        // Calculate the sync period of files to examine 
     1098        box_time_t syncPeriodStart = mLastSyncTime; 
     1099        box_time_t syncPeriodEnd = GetCurrentBoxTime() - minimumFileAge; 
     1100 
     1101        if(syncPeriodStart >= syncPeriodEnd && 
     1102                syncPeriodStart - syncPeriodEnd < minimumFileAge) 
     1103        { 
     1104                // This can happen if we receive a force-sync 
     1105                // command less than minimumFileAge after 
     1106                // the last sync. Deal with it by moving back 
     1107                // syncPeriodStart, which should not do any 
     1108                // damage. 
     1109                syncPeriodStart = syncPeriodEnd - 
     1110                        SecondsToBoxTime(1); 
     1111        } 
     1112 
     1113        if(syncPeriodStart >= syncPeriodEnd) 
     1114        { 
     1115                BOX_ERROR("Invalid (negative) sync period: " 
     1116                        "perhaps your clock is going " 
     1117                        "backwards (" << syncPeriodStart << 
     1118                        " to " << syncPeriodEnd << ")"); 
     1119                THROW_EXCEPTION(ClientException, 
     1120                        ClockWentBackwards); 
     1121        } 
     1122 
     1123        // Check logic 
     1124        ASSERT(syncPeriodEnd > syncPeriodStart); 
     1125        // Paranoid check on sync times 
     1126        if(syncPeriodStart >= syncPeriodEnd) return; 
     1127         
     1128        // Adjust syncPeriodEnd to emulate snapshot  
     1129        // behaviour properly 
     1130        box_time_t syncPeriodEndExtended = syncPeriodEnd; 
     1131 
     1132        // Using zero min file age? 
     1133        if(minimumFileAge == 0) 
     1134        { 
     1135                // Add a year on to the end of the end time, 
     1136                // to make sure we sync files which are  
     1137                // modified after the scan run started. 
     1138                // Of course, they may be eligible to be  
     1139                // synced again the next time round, 
     1140                // but this should be OK, because the changes  
     1141                // only upload should upload no data. 
     1142                syncPeriodEndExtended += SecondsToBoxTime( 
     1143                        (time_t)(356*24*3600)); 
     1144        } 
     1145 
     1146        // Set up the sync parameters 
     1147        BackupClientDirectoryRecord::SyncParams params( 
     1148                *this, clientContext); 
     1149        params.mSyncPeriodStart = syncPeriodStart; 
     1150        params.mSyncPeriodEnd = syncPeriodEndExtended; 
     1151        // use potentially extended end time 
     1152        params.mMaxUploadWait = maxUploadWait; 
     1153        params.mFileTrackingSizeThreshold =  
     1154                conf.GetKeyValueInt( 
     1155                "FileTrackingSizeThreshold"); 
     1156        params.mDiffingUploadSizeThreshold =  
     1157                conf.GetKeyValueInt( 
     1158                "DiffingUploadSizeThreshold"); 
     1159        params.mMaxFileTimeInFuture =  
     1160                SecondsToBoxTime( 
     1161                        conf.GetKeyValueInt( 
     1162                                "MaxFileTimeInFuture")); 
     1163        mDeleteRedundantLocationsAfter = 
     1164                conf.GetKeyValueInt( 
     1165                        "DeleteRedundantLocationsAfter"); 
     1166        mStorageLimitExceeded = false; 
     1167        mReadErrorsOnFilesystemObjects = false; 
     1168 
     1169        // Setup various timings 
     1170        int maximumDiffingTime = 600; 
     1171        int keepAliveTime = 60; 
     1172 
     1173        // max diffing time, keep-alive time 
     1174        if(conf.KeyExists("MaximumDiffingTime")) 
     1175        { 
     1176                maximumDiffingTime = conf.GetKeyValueInt("MaximumDiffingTime"); 
     1177        } 
     1178        if(conf.KeyExists("KeepAliveTime")) 
     1179        { 
     1180                keepAliveTime = conf.GetKeyValueInt("KeepAliveTime"); 
     1181        } 
     1182 
     1183        clientContext.SetMaximumDiffingTime(maximumDiffingTime); 
     1184        clientContext.SetKeepAliveTime(keepAliveTime); 
     1185         
     1186        // Set store marker 
     1187        clientContext.SetClientStoreMarker(mClientStoreMarker); 
     1188         
     1189        // Set up the locations, if necessary --  
     1190        // need to do it here so we have a  
     1191        // (potential) connection to use 
     1192        if(mLocations.empty()) 
     1193        { 
     1194                const Configuration &locations( 
     1195                        conf.GetSubConfiguration( 
     1196                                "BackupLocations")); 
     1197                 
     1198                // Make sure all the directory records 
     1199                // are set up 
     1200                SetupLocations(clientContext, locations); 
     1201        } 
     1202         
     1203        // Get some ID maps going 
     1204        SetupIDMapsForSync(); 
     1205 
     1206        // Delete any unused directories? 
     1207        DeleteUnusedRootDirEntries(clientContext); 
     1208                                         
     1209        // Go through the records, syncing them 
     1210        for(std::vector<Location *>::const_iterator  
     1211                i(mLocations.begin());  
     1212                i != mLocations.end(); ++i) 
     1213        { 
     1214                // Set current and new ID map pointers 
     1215                // in the context 
     1216                clientContext.SetIDMaps(mCurrentIDMaps[(*i)->mIDMapIndex], 
     1217                        mNewIDMaps[(*i)->mIDMapIndex]); 
     1218         
     1219                // Set exclude lists (context doesn't 
     1220                // take ownership) 
     1221                clientContext.SetExcludeLists( 
     1222                        (*i)->mpExcludeFiles, 
     1223                        (*i)->mpExcludeDirs); 
     1224 
     1225                // Sync the directory 
     1226                (*i)->mpDirectoryRecord->SyncDirectory( 
     1227                        params, 
     1228                        BackupProtocolClientListDirectory::RootDirectory, 
     1229                        (*i)->mPath, std::string("/") + (*i)->mName); 
     1230 
     1231                // Unset exclude lists (just in case) 
     1232                clientContext.SetExcludeLists(0, 0); 
     1233        } 
     1234         
     1235        // Errors reading any files? 
     1236        if(params.mReadErrorsOnFilesystemObjects) 
     1237        { 
     1238                // Notify administrator 
     1239                NotifySysadmin(NotifyEvent_ReadError); 
     1240        } 
     1241        else 
     1242        { 
     1243                // Unset the read error flag, so the                                            // error is reported again if it 
     1244                // happens again 
     1245                mNotificationsSent[NotifyEvent_ReadError] = false; 
     1246        } 
     1247         
     1248        // Perform any deletions required -- these are 
     1249        // delayed until the end to allow renaming to  
     1250        // happen neatly. 
     1251        clientContext.PerformDeletions(); 
     1252 
     1253        // Close any open connection 
     1254        clientContext.CloseAnyOpenConnection(); 
     1255         
     1256        // Get the new store marker 
     1257        mClientStoreMarker = clientContext.GetClientStoreMarker(); 
     1258        mStorageLimitExceeded = clientContext.StorageLimitExceeded(); 
     1259        mReadErrorsOnFilesystemObjects = 
     1260                params.mReadErrorsOnFilesystemObjects; 
     1261 
     1262        if(!mStorageLimitExceeded) 
     1263        { 
     1264                // The start time of the next run is the end time of this 
     1265                // run. This is only done if the storage limit wasn't 
     1266                // exceeded (as things won't have been done properly if 
     1267                // it was) 
     1268                mLastSyncTime = syncPeriodEnd; 
     1269        } 
     1270 
     1271        // Commit the ID Maps 
     1272        CommitIDMapsAfterSync(); 
     1273 
     1274        // Log 
     1275        BOX_NOTICE("Finished scan of local files"); 
     1276} 
    12241277 
    12251278// -------------------------------------------------------------------------- 
     
    24612514        BOX_NOTICE("Deleting unused locations from store root..."); 
    24622515        BackupProtocolClient &connection(rContext.GetConnection()); 
    2463         for(std::vector<std::pair<int64_t,std::string> >::iterator i(mUnusedRootDirEntries.begin()); i != mUnusedRootDirEntries.end(); ++i) 
     2516        for(std::vector<std::pair<int64_t,std::string> >::iterator 
     2517                i(mUnusedRootDirEntries.begin()); 
     2518                i != mUnusedRootDirEntries.end(); ++i) 
    24642519        { 
    24652520                connection.QueryDeleteDirectory(i->first); 
    2466                  
    2467                 // Log this 
    2468                 BOX_NOTICE("Deleted " << i->second << " (ID " << i->first 
    2469                         << ") from store root"); 
     2521                rContext.GetProgressNotifier().NotifyFileDeleted( 
     2522                        i->first, i->second); 
    24702523        } 
    24712524 
     
    27382791// 
    27392792// Function 
    2740 //              Name:    BackupDaemon::SerializeStoreObjectInfo(int64_t aClientStoreMarker, box_time_t theLastSyncTime, box_time_t theNextSyncTime) 
    2741 //              Purpose: Serializes remote directory and file information into a stream of bytes, using an Archive abstraction. 
    2742 // 
     2793//              Name:    BackupDaemon::SerializeStoreObjectInfo( 
     2794//                       box_time_t theLastSyncTime, 
     2795//                       box_time_t theNextSyncTime) 
     2796//              Purpose: Serializes remote directory and file information 
     2797//                       into a stream of bytes, using an Archive 
     2798//                       abstraction. 
    27432799//              Created: 2005/04/11 
    27442800// 
     
    27492805static const int STOREOBJECTINFO_VERSION = 2; 
    27502806 
    2751 bool BackupDaemon::SerializeStoreObjectInfo(int64_t aClientStoreMarker, box_time_t theLastSyncTime, box_time_t theNextSyncTime) const 
     2807bool BackupDaemon::SerializeStoreObjectInfo(box_time_t theLastSyncTime, 
     2808        box_time_t theNextSyncTime) const 
    27522809{ 
    27532810        if(!GetConfiguration().KeyExists("StoreObjectInfoFile")) 
     
    27782835                anArchive.Write(STOREOBJECTINFO_VERSION); 
    27792836                anArchive.Write(GetLoadedConfigModifiedTime()); 
    2780                 anArchive.Write(aClientStoreMarker); 
     2837                anArchive.Write(mClientStoreMarker); 
    27812838                anArchive.Write(theLastSyncTime); 
    27822839                anArchive.Write(theNextSyncTime); 
     
    28302887        catch(std::exception &e) 
    28312888        { 
    2832                 BOX_ERROR("Internal error writing store object " 
    2833                         "info file (" << StoreObjectInfoFile << "): " 
    2834                         << e.what()); 
     2889                BOX_ERROR("Failed to write StoreObjectInfoFile: " << 
     2890                        StoreObjectInfoFile << ": " << e.what()); 
    28352891        } 
    28362892        catch(...) 
    28372893        { 
    2838                 BOX_ERROR("Internal error writing store object " 
    2839                         "info file (" << StoreObjectInfoFile << "): " 
    2840                         "unknown error"); 
     2894                BOX_ERROR("Failed to write StoreObjectInfoFile: " << 
     2895                        StoreObjectInfoFile << ": unknown error"); 
    28412896        } 
    28422897 
     
    28472902// 
    28482903// Function 
    2849 //              Name:    BackupDaemon::DeserializeStoreObjectInfo(int64_t & aClientStoreMarker, box_time_t & theLastSyncTime, box_time_t & theNextSyncTime) 
    2850 //              Purpose: Deserializes remote directory and file information from a stream of bytes, using an Archive abstraction. 
    2851 // 
     2904//              Name:    BackupDaemon::DeserializeStoreObjectInfo( 
     2905//                       box_time_t & theLastSyncTime, 
     2906//                       box_time_t & theNextSyncTime) 
     2907//              Purpose: Deserializes remote directory and file information 
     2908//                       from a stream of bytes, using an Archive 
     2909//                       abstraction. 
    28522910//              Created: 2005/04/11 
    28532911// 
    28542912// -------------------------------------------------------------------------- 
    2855 bool BackupDaemon::DeserializeStoreObjectInfo(int64_t & aClientStoreMarker, box_time_t & theLastSyncTime, box_time_t & theNextSyncTime) 
     2913bool BackupDaemon::DeserializeStoreObjectInfo(box_time_t & theLastSyncTime, 
     2914        box_time_t & theNextSyncTime) 
    28562915{ 
    28572916        // 
     
    29453004                // this is it, go at it 
    29463005                // 
    2947                 anArchive.Read(aClientStoreMarker); 
     3006                anArchive.Read(mClientStoreMarker); 
    29483007                anArchive.Read(theLastSyncTime); 
    29493008                anArchive.Read(theNextSyncTime); 
     
    30233082        DeleteAllLocations(); 
    30243083 
    3025         aClientStoreMarker = BackupClientContext::ClientStoreMarker_NotKnown; 
     3084        mClientStoreMarker = BackupClientContext::ClientStoreMarker_NotKnown; 
    30263085        theLastSyncTime = 0; 
    30273086        theNextSyncTime = 0; 
  • box/trunk/bin/bbackupd/BackupDaemon.h

    r2099 r2181  
    1515#include <memory> 
    1616 
     17#include "BackupClientDirectoryRecord.h" 
    1718#include "BoxTime.h" 
    1819#include "Daemon.h" 
    19 #include "BackupClientDirectoryRecord.h" 
     20#include "Logging.h" 
    2021#include "Socket.h" 
    2122#include "SocketListen.h" 
    2223#include "SocketStream.h" 
    23 #include "Logging.h" 
     24#include "TLSContext.h" 
     25 
    2426#include "autogen_BackupProtocolClient.h" 
    2527 
     
    5355        // methods below do partial (specialized) serialization of  
    5456        // client state only 
    55         bool SerializeStoreObjectInfo(int64_t aClientStoreMarker,  
    56                 box_time_t theLastSyncTime, box_time_t theNextSyncTime) const; 
    57         bool DeserializeStoreObjectInfo(int64_t & aClientStoreMarker,  
    58                 box_time_t & theLastSyncTime, box_time_t & theNextSyncTime); 
     57        bool SerializeStoreObjectInfo(box_time_t theLastSyncTime, 
     58                box_time_t theNextSyncTime) const; 
     59        bool DeserializeStoreObjectInfo(box_time_t & theLastSyncTime, 
     60                box_time_t & theNextSyncTime); 
    5961        bool DeleteStoreObjectInfo() const; 
    6062        BackupDaemon(const BackupDaemon &); 
     
    112114        void Run2(); 
    113115 
     116public: 
     117        void InitCrypto(); 
     118        void RunSyncNow(); 
     119 
     120private: 
    114121        void DeleteAllLocations(); 
    115122        void SetupLocations(BackupClientContext &rClientContext, const Configuration &rLocationsConf); 
     
    206213        std::vector<std::pair<int64_t,std::string> > mUnusedRootDirEntries; 
    207214 
     215        int64_t mClientStoreMarker; 
     216        bool mStorageLimitExceeded; 
     217        bool mReadErrorsOnFilesystemObjects; 
     218        box_time_t mLastSyncTime; 
     219        TLSContext mTlsContext; 
     220 
    208221public: 
    209222        bool StopRun() { return this->Daemon::StopRun(); } 
     223        bool StorageLimitExceeded() { return mStorageLimitExceeded; } 
    210224  
    211225private: 
     
    428442                }  
    429443        } 
     444        virtual void NotifyDirectoryDeleted( 
     445                int64_t ObjectID, 
     446                const std::string& rRemotePath) 
     447        { 
     448                if (mLogAllFileAccess) 
     449                { 
     450                        BOX_NOTICE("Deleted directory: " << rRemotePath <<  
     451                                " (ID " << BOX_FORMAT_OBJECTID(ObjectID) << 
     452                                ")"); 
     453                } 
     454        } 
     455        virtual void NotifyFileDeleted( 
     456                int64_t ObjectID, 
     457                const std::string& rRemotePath) 
     458        { 
     459                if (mLogAllFileAccess) 
     460                { 
     461                        BOX_NOTICE("Deleted file: " << rRemotePath <<  
     462                                " (ID " << BOX_FORMAT_OBJECTID(ObjectID) << 
     463                                ")"); 
     464                } 
     465        } 
    430466 
    431467#ifdef WIN32