source: box/trunk/bin/bbackupd/BackupDaemon.h @ 3102

Revision 3102, 15.2 KB checked in by chris, 4 weeks ago (diff)

Allow BackupDaemon? user to reset state for testing.

  • Property svn:eol-style set to native
Line 
1// --------------------------------------------------------------------------
2//
3// File
4//              Name:    BackupDaemon.h
5//              Purpose: Backup daemon
6//              Created: 2003/10/08
7//
8// --------------------------------------------------------------------------
9
10#ifndef BACKUPDAEMON__H
11#define BACKUPDAEMON__H
12
13#include <vector>
14#include <string>
15#include <memory>
16
17#include "BackupClientContext.h"
18#include "BackupClientDirectoryRecord.h"
19#include "BoxTime.h"
20#include "Daemon.h"
21#include "Logging.h"
22#include "Socket.h"
23#include "SocketListen.h"
24#include "SocketStream.h"
25#include "TLSContext.h"
26
27#include "autogen_BackupProtocol.h"
28
29#ifdef WIN32
30        #include "WinNamedPipeListener.h"
31        #include "WinNamedPipeStream.h"
32#endif
33
34#ifdef ENABLE_VSS
35#       include <comdef.h>
36#       include <Vss.h>
37#       include <VsWriter.h>
38#       include <VsBackup.h>
39#endif
40
41class BackupClientDirectoryRecord;
42class BackupClientContext;
43class Configuration;
44class BackupClientInodeToIDMap;
45class ExcludeList;
46class IOStreamGetLine;
47class Archive;
48
49// --------------------------------------------------------------------------
50//
51// Class
52//              Name:    BackupDaemon
53//              Purpose: Backup daemon
54//              Created: 2003/10/08
55//
56// --------------------------------------------------------------------------
57class BackupDaemon : public Daemon, ProgressNotifier, LocationResolver,
58RunStatusProvider, SysadminNotifier
59{
60public:
61        BackupDaemon();
62        ~BackupDaemon();
63
64private:
65        // methods below do partial (specialized) serialization of
66        // client state only
67        bool SerializeStoreObjectInfo(box_time_t theLastSyncTime,
68                box_time_t theNextSyncTime) const;
69        bool DeserializeStoreObjectInfo(box_time_t & theLastSyncTime,
70                box_time_t & theNextSyncTime);
71        bool DeleteStoreObjectInfo() const;
72        BackupDaemon(const BackupDaemon &);
73
74public:
75        #ifdef WIN32
76                // add command-line options to handle Windows services
77                std::string GetOptionString();
78                int ProcessOption(signed int option);
79                int Main(const std::string &rConfigFileName);
80
81                // This shouldn't be here, but apparently gcc on
82                // Windows has no idea about inherited methods...
83                virtual int Main(const char *DefaultConfigFile, int argc,
84                        const char *argv[])
85                {
86                        return Daemon::Main(DefaultConfigFile, argc, argv);
87                }
88        #endif
89
90        void Run();
91        virtual const char *DaemonName() const;
92        virtual std::string DaemonBanner() const;
93        virtual void Usage();
94        const ConfigurationVerify *GetConfigVerify() const;
95
96        bool FindLocationPathName(const std::string &rLocationName, std::string &rPathOut) const;
97
98        enum
99        {
100                // Add stuff to this, make sure the textual equivalents in SetState() are changed too.
101                State_Initialising = -1,
102                State_Idle = 0,
103                State_Connected = 1,
104                State_Error = 2,
105                State_StorageLimitExceeded = 3
106        };
107
108        int GetState() {return mState;}
109
110        // Allow other classes to call this too
111        void NotifySysadmin(SysadminNotifier::EventCode Event);
112
113private:
114        void Run2();
115
116public:
117        void InitCrypto();
118        void RunSyncNowWithExceptionHandling();
119        void RunSyncNow();
120        void ResetCachedState();
121        void OnBackupStart();
122        void OnBackupFinish();
123        // TouchFileInWorkingDir is only here for use by Boxi.
124        // This does NOT constitute an API!
125        void TouchFileInWorkingDir(const char *Filename);
126
127private:
128        void DeleteAllLocations();
129        void SetupLocations(BackupClientContext &rClientContext, const Configuration &rLocationsConf);
130
131        void DeleteIDMapVector(std::vector<BackupClientInodeToIDMap *> &rVector);
132        void DeleteAllIDMaps()
133        {
134                DeleteIDMapVector(mCurrentIDMaps);
135                DeleteIDMapVector(mNewIDMaps);
136        }
137        void FillIDMapVector(std::vector<BackupClientInodeToIDMap *> &rVector, bool NewMaps);
138       
139        void SetupIDMapsForSync();
140        void CommitIDMapsAfterSync();
141        void DeleteCorruptBerkelyDbFiles();
142       
143        void MakeMapBaseName(unsigned int MountNumber, std::string &rNameOut) const;
144
145        void SetState(int State);
146       
147        void WaitOnCommandSocket(box_time_t RequiredDelay, bool &DoSyncFlagOut, bool &SyncIsForcedOut);
148        void CloseCommandConnection();
149        void SendSyncStartOrFinish(bool SendStart);
150       
151        void DeleteUnusedRootDirEntries(BackupClientContext &rContext);
152
153#ifdef PLATFORM_CANNOT_FIND_PEER_UID_OF_UNIX_SOCKET
154        // For warning user about potential security hole
155        virtual void SetupInInitialProcess();
156#endif
157
158        int UseScriptToSeeIfSyncAllowed();
159
160public:
161        int ParseSyncAllowScriptOutput(const std::string& script,
162                const std::string& output);
163        typedef std::list<Location *> Locations;
164        Locations GetLocations() { return mLocations; }
165       
166private:
167        int mState;             // what the daemon is currently doing
168
169        Locations mLocations;
170       
171        std::vector<std::string> mIDMapMounts;
172        std::vector<BackupClientInodeToIDMap *> mCurrentIDMaps;
173        std::vector<BackupClientInodeToIDMap *> mNewIDMaps;
174       
175        int mDeleteRedundantLocationsAfter;
176
177        // For the command socket
178        class CommandSocketInfo
179        {
180        public:
181                CommandSocketInfo();
182                ~CommandSocketInfo();
183        private:
184                CommandSocketInfo(const CommandSocketInfo &);   // no copying
185                CommandSocketInfo &operator=(const CommandSocketInfo &);
186        public:
187#ifdef WIN32
188                WinNamedPipeListener<1 /* listen backlog */> mListeningSocket;
189                std::auto_ptr<WinNamedPipeStream> mpConnectedSocket;
190#else
191                SocketListen<SocketStream, 1 /* listen backlog */> mListeningSocket;
192                std::auto_ptr<SocketStream> mpConnectedSocket;
193#endif
194                IOStreamGetLine *mpGetLine;
195        };
196       
197        // Using a socket?
198        std::auto_ptr<CommandSocketInfo> mapCommandSocketInfo;
199       
200        // Stop notifications being repeated.
201        SysadminNotifier::EventCode mLastNotifiedEvent;
202
203        // Unused entries in the root directory wait a while before being deleted
204        box_time_t mDeleteUnusedRootDirEntriesAfter;    // time to delete them
205        std::vector<std::pair<int64_t,std::string> > mUnusedRootDirEntries;
206
207        int64_t mClientStoreMarker;
208        bool mStorageLimitExceeded;
209        bool mReadErrorsOnFilesystemObjects;
210        box_time_t mLastSyncTime, mNextSyncTime;
211        box_time_t mCurrentSyncStartTime, mUpdateStoreInterval;
212        TLSContext mTlsContext;
213        bool mDeleteStoreObjectInfoFile;
214        bool mDoSyncForcedByPreviousSyncError;
215        int64_t mNumFilesUploaded, mNumDirsCreated;
216        int mMaxBandwidthFromSyncAllowScript;
217
218public:
219        int GetMaxBandwidthFromSyncAllowScript() { return mMaxBandwidthFromSyncAllowScript; }
220        bool StopRun() { return this->Daemon::StopRun(); }
221        bool StorageLimitExceeded() { return mStorageLimitExceeded; }
222 
223private:
224        bool mLogAllFileAccess;
225
226public:
227        ProgressNotifier*  GetProgressNotifier()  { return mpProgressNotifier; }
228        LocationResolver*  GetLocationResolver()  { return mpLocationResolver; }
229        RunStatusProvider* GetRunStatusProvider() { return mpRunStatusProvider; }
230        SysadminNotifier*  GetSysadminNotifier()  { return mpSysadminNotifier; }
231        void SetProgressNotifier (ProgressNotifier*  p) { mpProgressNotifier = p; }
232        void SetLocationResolver (LocationResolver*  p) { mpLocationResolver = p; }
233        void SetRunStatusProvider(RunStatusProvider* p) { mpRunStatusProvider = p; }
234        void SetSysadminNotifier (SysadminNotifier*  p) { mpSysadminNotifier = p; }
235               
236private:
237        ProgressNotifier* mpProgressNotifier;
238        LocationResolver* mpLocationResolver;
239        RunStatusProvider* mpRunStatusProvider;
240        SysadminNotifier* mpSysadminNotifier;
241       
242        /* ProgressNotifier implementation */
243public:
244        virtual void NotifyIDMapsSetup(BackupClientContext& rContext) { }
245
246        virtual void NotifyScanDirectory(
247                const BackupClientDirectoryRecord* pDirRecord,
248                const std::string& rLocalPath) 
249        {
250                if (mLogAllFileAccess)
251                {
252                        BOX_INFO("Scanning directory: " << rLocalPath);
253                } 
254        }
255        virtual void NotifyDirStatFailed(
256                const BackupClientDirectoryRecord* pDirRecord,
257                const std::string& rLocalPath, 
258                const std::string& rErrorMsg)
259        {
260                BOX_WARNING("Failed to access directory: " << rLocalPath
261                        << ": " << rErrorMsg);
262        }
263        virtual void NotifyFileStatFailed(
264                const BackupClientDirectoryRecord* pDirRecord,
265                const std::string& rLocalPath,
266                const std::string& rErrorMsg)
267        {
268                BOX_WARNING("Failed to access file: " << rLocalPath
269                        << ": " << rErrorMsg);
270        }
271        virtual void NotifyDirListFailed(
272                const BackupClientDirectoryRecord* pDirRecord,
273                const std::string& rLocalPath,
274                const std::string& rErrorMsg)
275        {
276                BOX_WARNING("Failed to list directory: " << rLocalPath
277                        << ": " << rErrorMsg);
278        }
279        virtual void NotifyMountPointSkipped(
280                const BackupClientDirectoryRecord* pDirRecord,
281                const std::string& rLocalPath)
282        {
283                #ifdef WIN32
284                        BOX_WARNING("Ignored directory: " << rLocalPath << 
285                                ": is an NTFS junction/reparse point; create "
286                                "a new location if you want to back it up");
287                #else
288                        BOX_WARNING("Ignored directory: " << rLocalPath << 
289                                ": is a mount point; create a new location "
290                                "if you want to back it up");
291                #endif
292        }
293        virtual void NotifyFileExcluded(
294                const BackupClientDirectoryRecord* pDirRecord,
295                const std::string& rLocalPath)
296        {
297                if (mLogAllFileAccess)
298                {
299                        BOX_INFO("Skipping excluded file: " << rLocalPath);
300                } 
301        }
302        virtual void NotifyDirExcluded(
303                const BackupClientDirectoryRecord* pDirRecord,
304                const std::string& rLocalPath)
305        {
306                if (mLogAllFileAccess)
307                {
308                        BOX_INFO("Skipping excluded directory: " << rLocalPath);
309                } 
310        }
311        virtual void NotifyUnsupportedFileType(
312                const BackupClientDirectoryRecord* pDirRecord,
313                const std::string& rLocalPath)
314        {
315                BOX_WARNING("Ignoring file of unknown type: " << rLocalPath);
316        }
317        virtual void NotifyFileReadFailed(
318                const BackupClientDirectoryRecord* pDirRecord,
319                const std::string& rLocalPath,
320                const std::string& rErrorMsg)
321        {
322                BOX_WARNING("Error reading file: " << rLocalPath
323                        << ": " << rErrorMsg);
324        }
325        virtual void NotifyFileModifiedInFuture(
326                const BackupClientDirectoryRecord* pDirRecord,
327                const std::string& rLocalPath)
328        {
329                BOX_WARNING("Some files have modification times excessively "
330                        "in the future. Check clock synchronisation. "
331                        "Example file (only one shown): " << rLocalPath);
332        }
333        virtual void NotifyFileSkippedServerFull(
334                const BackupClientDirectoryRecord* pDirRecord,
335                const std::string& rLocalPath) 
336        {
337                BOX_WARNING("Skipped file: server is full: " << rLocalPath);
338        }
339        virtual void NotifyFileUploadException(
340                const BackupClientDirectoryRecord* pDirRecord,
341                const std::string& rLocalPath,
342                const BoxException& rException)
343        {
344                if (rException.GetType() == CommonException::ExceptionType &&
345                        rException.GetSubType() == CommonException::AccessDenied)
346                {
347                        BOX_ERROR("Failed to upload file: " << rLocalPath
348                                << ": Access denied");
349                }
350                else
351                {
352                        BOX_ERROR("Failed to upload file: " << rLocalPath
353                                << ": caught exception: " << rException.what() 
354                                << " (" << rException.GetType()
355                                << "/"  << rException.GetSubType() << ")");
356                }
357        }
358        virtual void NotifyFileUploadServerError(
359                const BackupClientDirectoryRecord* pDirRecord,
360                const std::string& rLocalPath,
361                int type, int subtype)
362        {
363                std::ostringstream msgs;
364                if (type != BackupProtocolError::ErrorType)
365                {
366                        msgs << "unknown error type " << type;
367                }
368                else
369                {
370                        switch(subtype)
371                        {
372                        case BackupProtocolError::Err_WrongVersion:
373                                msgs << "WrongVersion";
374                                break;
375                        case BackupProtocolError::Err_NotInRightProtocolPhase:
376                                msgs << "NotInRightProtocolPhase";
377                                break;
378                        case BackupProtocolError::Err_BadLogin:
379                                msgs << "BadLogin";
380                                break;
381                        case BackupProtocolError::Err_CannotLockStoreForWriting:
382                                msgs << "CannotLockStoreForWriting";
383                                break;
384                        case BackupProtocolError::Err_SessionReadOnly:
385                                msgs << "SessionReadOnly";
386                                break;
387                        case BackupProtocolError::Err_FileDoesNotVerify:
388                                msgs << "FileDoesNotVerify";
389                                break;
390                        case BackupProtocolError::Err_DoesNotExist:
391                                msgs << "DoesNotExist";
392                                break;
393                        case BackupProtocolError::Err_DirectoryAlreadyExists:
394                                msgs << "DirectoryAlreadyExists";
395                                break;
396                        case BackupProtocolError::Err_CannotDeleteRoot:
397                                msgs << "CannotDeleteRoot";
398                                break;
399                        case BackupProtocolError::Err_TargetNameExists:
400                                msgs << "TargetNameExists";
401                                break;
402                        case BackupProtocolError::Err_StorageLimitExceeded:
403                                msgs << "StorageLimitExceeded";
404                                break;
405                        case BackupProtocolError::Err_DiffFromFileDoesNotExist:
406                                msgs << "DiffFromFileDoesNotExist";
407                                break;
408                        case BackupProtocolError::Err_DoesNotExistInDirectory:
409                                msgs << "DoesNotExistInDirectory";
410                                break;
411                        case BackupProtocolError::Err_PatchConsistencyError:
412                                msgs << "PatchConsistencyError";
413                                break;
414                        default:
415                                msgs << "unknown error subtype " << subtype;
416                        }
417                }
418
419                BOX_ERROR("Failed to upload file: " << rLocalPath
420                        << ": server error: " << msgs.str());
421        }
422        virtual void NotifyFileUploading(
423                const BackupClientDirectoryRecord* pDirRecord,
424                const std::string& rLocalPath) 
425        { 
426                if (mLogAllFileAccess)
427                {
428                        BOX_NOTICE("Uploading complete file: " << rLocalPath);
429                } 
430        }
431        virtual void NotifyFileUploadingPatch(
432                const BackupClientDirectoryRecord* pDirRecord,
433                const std::string& rLocalPath) 
434        {
435                if (mLogAllFileAccess)
436                {
437                        BOX_NOTICE("Uploading patch to file: " << rLocalPath);
438                } 
439        }
440        virtual void NotifyFileUploadingAttributes(
441                const BackupClientDirectoryRecord* pDirRecord,
442                const std::string& rLocalPath) 
443        {
444                if (mLogAllFileAccess)
445                {
446                        BOX_NOTICE("Uploading new file attributes: " << 
447                                rLocalPath);
448                } 
449        }
450        virtual void NotifyFileUploaded(
451                const BackupClientDirectoryRecord* pDirRecord,
452                const std::string& rLocalPath,
453                int64_t FileSize, int64_t UploadedSize) 
454        {
455                if (mLogAllFileAccess)
456                {
457                        BOX_NOTICE("Uploaded file: " << rLocalPath << ", "
458                                "total size = " << FileSize << ", "
459                                "uploaded size = " << UploadedSize);
460                }
461                mNumFilesUploaded++;
462        }
463        virtual void NotifyFileSynchronised(
464                const BackupClientDirectoryRecord* pDirRecord,
465                const std::string& rLocalPath,
466                int64_t FileSize) 
467        {
468                if (mLogAllFileAccess)
469                {
470                        BOX_INFO("Synchronised file: " << rLocalPath);
471                } 
472        }
473        virtual void NotifyDirectoryCreated(
474                int64_t ObjectID,
475                const std::string& rLocalPath,
476                const std::string& rRemotePath)
477        {
478                if (mLogAllFileAccess)
479                {
480                        BOX_NOTICE("Created directory: " << rRemotePath << 
481                                " (ID " << BOX_FORMAT_OBJECTID(ObjectID) <<
482                                ")");
483                }
484                mNumDirsCreated++;
485        }
486        virtual void NotifyDirectoryDeleted(
487                int64_t ObjectID,
488                const std::string& rRemotePath)
489        {
490                if (mLogAllFileAccess)
491                {
492                        BOX_NOTICE("Deleted directory: " << rRemotePath << 
493                                " (ID " << BOX_FORMAT_OBJECTID(ObjectID) <<
494                                ")");
495                }
496        }
497        virtual void NotifyFileDeleted(
498                int64_t ObjectID,
499                const std::string& rRemotePath)
500        {
501                if (mLogAllFileAccess)
502                {
503                        BOX_NOTICE("Deleted file: " << rRemotePath << 
504                                " (ID " << BOX_FORMAT_OBJECTID(ObjectID) <<
505                                ")");
506                }
507        }
508        virtual void NotifyReadProgress(int64_t readSize, int64_t offset,
509                int64_t length, box_time_t elapsed, box_time_t finish)
510        {
511                BOX_TRACE("Read " << readSize << " bytes at " << offset << 
512                        ", " << (length - offset) << " remain, eta " <<
513                        BoxTimeToSeconds(finish - elapsed) << "s");
514        }
515        virtual void NotifyReadProgress(int64_t readSize, int64_t offset,
516                int64_t length)
517        {
518                BOX_TRACE("Read " << readSize << " bytes at " << offset << 
519                        ", " << (length - offset) << " remain");
520        }
521        virtual void NotifyReadProgress(int64_t readSize, int64_t offset)
522        {
523                BOX_TRACE("Read " << readSize << " bytes at " << offset << 
524                        ", unknown bytes remaining");
525        }
526
527#ifdef WIN32
528        private:
529        bool mInstallService, mRemoveService, mRunAsService;
530        std::string mServiceName;
531#endif
532
533#ifdef ENABLE_VSS
534        IVssBackupComponents* mpVssBackupComponents;
535        void CreateVssBackupComponents();
536        bool WaitForAsync(IVssAsync *pAsync, const std::string& description);
537        typedef HRESULT (__stdcall IVssBackupComponents::*AsyncMethod)(IVssAsync**);
538        bool CallAndWaitForAsync(AsyncMethod method,
539                const std::string& description);
540        void CleanupVssBackupComponents();
541#endif
542};
543
544#endif // BACKUPDAEMON__H
Note: See TracBrowser for help on using the repository browser.