| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 | //---------------------------------------------------------------------------#include <vcl.h>#pragma hdrstop#include <Common.h>#include <RemoteFiles.h>#include <Terminal.h>#include <DiscMon.hpp>#include <Exceptions.h>#include "GUIConfiguration.h"#include "CoreMain.h"#include "TextsCore.h"#include "SynchronizeController.h"//---------------------------------------------------------------------------#pragma package(smart_init)//---------------------------------------------------------------------------__fastcall TSynchronizeController::TSynchronizeController(  TSynchronizeEvent AOnSynchronize, TSynchronizeInvalidEvent AOnSynchronizeInvalid,  TSynchronizeTooManyDirectories AOnTooManyDirectories){  FOnSynchronize = AOnSynchronize;  FOnSynchronizeInvalid = AOnSynchronizeInvalid;  FOnTooManyDirectories = AOnTooManyDirectories;  FSynchronizeMonitor = NULL;  FSynchronizeAbort = NULL;  FSynchronizeLog = NULL;  FOptions = NULL;}//---------------------------------------------------------------------------__fastcall TSynchronizeController::~TSynchronizeController(){  DebugAssert(FSynchronizeMonitor == NULL);}//---------------------------------------------------------------------------void __fastcall TSynchronizeController::StartStop(TObject * Sender,  bool Start, const TSynchronizeParamType & Params, const TCopyParamType & CopyParam,  TSynchronizeOptions * Options,  TSynchronizeAbortEvent OnAbort, TSynchronizeThreadsEvent OnSynchronizeThreads,  TSynchronizeLog OnSynchronizeLog){  if (Start)  {    Configuration->Usage->Inc(L"KeepUpToDates");    try    {      DebugAssert(OnSynchronizeLog != NULL);      FSynchronizeLog = OnSynchronizeLog;      FOptions = Options;      if (FLAGSET(Params.Options, soSynchronize) &&          (FOnSynchronize != NULL))      {        FOnSynchronize(this, Params.LocalDirectory,          Params.RemoteDirectory, CopyParam,          Params, NULL, FOptions, true);      }      FCopyParam = CopyParam;      FCopyParam.IncludeFileMask.SetRoots(Params.LocalDirectory, Params.RemoteDirectory);      FSynchronizeParams = Params;      DebugAssert(OnAbort);      FSynchronizeAbort = OnAbort;      if (FLAGSET(FSynchronizeParams.Options, soRecurse))      {        SynchronizeLog(slScan,          FMTLOAD(SYNCHRONIZE_SCAN, (FSynchronizeParams.LocalDirectory)));      }      FSynchronizeMonitor = new TDiscMonitor(dynamic_cast<TComponent*>(Sender));      FSynchronizeMonitor->SubTree = false;      TMonitorFilters Filters;      Filters << moFilename << moLastWrite;      if (FLAGSET(FSynchronizeParams.Options, soRecurse))      {        Filters << moDirName;      }      FSynchronizeMonitor->Filters = Filters;      FSynchronizeMonitor->MaxDirectories = 0;      FSynchronizeMonitor->ChangeDelay = GUIConfiguration->KeepUpToDateChangeDelay;      FSynchronizeMonitor->OnTooManyDirectories = SynchronizeTooManyDirectories;      FSynchronizeMonitor->OnDirectoriesChange = SynchronizeDirectoriesChange;      FSynchronizeMonitor->OnFilter = SynchronizeFilter;      FSynchronizeMonitor->AddDirectory(FSynchronizeParams.LocalDirectory,        FLAGSET(FSynchronizeParams.Options, soRecurse));      FSynchronizeMonitor->OnChange = SynchronizeChange;      FSynchronizeMonitor->OnInvalid = SynchronizeInvalid;      FSynchronizeMonitor->OnSynchronize = OnSynchronizeThreads;      // get count before open to avoid thread issues      int Directories = FSynchronizeMonitor->Directories->Count;      FSynchronizeMonitor->Open();      SynchronizeLog(slStart, FMTLOAD(SYNCHRONIZE_START, (Directories)));    }    catch(...)    {      SAFE_DESTROY(FSynchronizeMonitor);      throw;    }  }  else  {    FOptions = NULL;    SAFE_DESTROY(FSynchronizeMonitor);  }}//---------------------------------------------------------------------------void __fastcall TSynchronizeController::SynchronizeChange(  TObject * /*Sender*/, const UnicodeString Directory, bool & SubdirsChanged){  try  {    UnicodeString RemoteDirectory;    UnicodeString RootLocalDirectory;    RootLocalDirectory = IncludeTrailingBackslash(FSynchronizeParams.LocalDirectory);    RemoteDirectory = UnixIncludeTrailingBackslash(FSynchronizeParams.RemoteDirectory);    UnicodeString LocalDirectory = IncludeTrailingBackslash(Directory);    DebugAssert(LocalDirectory.SubString(1, RootLocalDirectory.Length()) ==      RootLocalDirectory);    RemoteDirectory = RemoteDirectory +      ToUnixPath(LocalDirectory.SubString(RootLocalDirectory.Length() + 1,        LocalDirectory.Length() - RootLocalDirectory.Length()));    SynchronizeLog(slChange, FMTLOAD(SYNCHRONIZE_CHANGE,      (ExcludeTrailingBackslash(LocalDirectory))));    if (FOnSynchronize != NULL)    {      TSynchronizeOptions DefaultOptions; // Just as a container for the Files field      // this is completely wrong as the options structure      // can contain non-root specific options in future      TSynchronizeOptions * Options =        ((LocalDirectory == RootLocalDirectory) ? FOptions : &DefaultOptions);      TSynchronizeChecklist * Checklist = NULL;      FOnSynchronize(this, LocalDirectory, RemoteDirectory, FCopyParam,        FSynchronizeParams, &Checklist, Options, false);      if (Checklist != NULL)      {        try        {          if (FLAGSET(FSynchronizeParams.Options, soRecurse))          {            SubdirsChanged = false;            DebugAssert(Checklist != NULL);            for (int Index = 0; Index < Checklist->Count; Index++)            {              const TSynchronizeChecklist::TItem * Item = Checklist->Item[Index];              // note that there may be action saDeleteRemote even if nothing has changed              // so this is sub-optimal              if (Item->IsDirectory)              {                if ((Item->Action == TSynchronizeChecklist::saUploadNew) ||                    (Item->Action == TSynchronizeChecklist::saDeleteRemote))                {                  SubdirsChanged = true;                  break;                }                else                {                  DebugFail();                }              }            }          }          else          {            SubdirsChanged = false;          }        }        __finally        {          delete Checklist;        }      }    }  }  catch(Exception & E)  {    SynchronizeAbort(dynamic_cast<EFatal*>(&E) != NULL);  }}//---------------------------------------------------------------------------void __fastcall TSynchronizeController::SynchronizeAbort(bool Close){  if (FSynchronizeMonitor != NULL)  {    FSynchronizeMonitor->Close();  }  DebugAssert(FSynchronizeAbort);  FSynchronizeAbort(NULL, Close);}//---------------------------------------------------------------------------void __fastcall TSynchronizeController::LogOperation(TSynchronizeOperation Operation,  const UnicodeString FileName){  TSynchronizeLogEntry Entry;  UnicodeString Message;  switch (Operation)  {    case soDelete:      Entry = slDelete;      Message = FMTLOAD(SYNCHRONIZE_DELETED, (FileName));      break;    default:      DebugFail();      // fallthru    case soUpload:      Entry = slUpload;      Message = FMTLOAD(SYNCHRONIZE_UPLOADED, (FileName));      break;  }  SynchronizeLog(Entry, Message);}//---------------------------------------------------------------------------void __fastcall TSynchronizeController::SynchronizeLog(TSynchronizeLogEntry Entry,  const UnicodeString Message){  if (FSynchronizeLog != NULL)  {    FSynchronizeLog(this, Entry, Message);  }}//---------------------------------------------------------------------------void __fastcall TSynchronizeController::SynchronizeFilter(TObject * /*Sender*/,  const UnicodeString DirectoryName, bool & Add){  if ((FOptions != NULL) && (FOptions->Filter != NULL))  {    if (IncludeTrailingBackslash(ExtractFilePath(DirectoryName)) ==          IncludeTrailingBackslash(FSynchronizeParams.LocalDirectory))    {      int FoundIndex;      Add = FOptions->Filter->Find(ExtractFileName(DirectoryName), FoundIndex);    }  }  if (Add && !FCopyParam.AllowAnyTransfer()) // optimization  {    TFileMasks::TParams MaskParams; // size/time does not matter for directories    bool Hidden = FLAGSET(FileGetAttrFix(DirectoryName), faHidden);    // Missing call to GetBaseFileName    Add = FCopyParam.AllowTransfer(DirectoryName, osLocal, true, MaskParams, Hidden);  }}//---------------------------------------------------------------------------void __fastcall TSynchronizeController::SynchronizeInvalid(  TObject * /*Sender*/, const UnicodeString Directory, const UnicodeString ErrorStr){  if (FOnSynchronizeInvalid != NULL)  {    FOnSynchronizeInvalid(this, Directory, ErrorStr);  }  SynchronizeAbort(false);}//---------------------------------------------------------------------------void __fastcall TSynchronizeController::SynchronizeTooManyDirectories(  TObject * /*Sender*/, int & MaxDirectories){  if (FOnTooManyDirectories != NULL)  {    FOnTooManyDirectories(this, MaxDirectories);  }}//---------------------------------------------------------------------------void __fastcall TSynchronizeController::SynchronizeDirectoriesChange(  TObject * /*Sender*/, int Directories){  SynchronizeLog(slDirChange, FMTLOAD(SYNCHRONIZE_START, (Directories)));}//---------------------------------------------------------------------------void __fastcall LogSynchronizeEvent(TTerminal * Terminal, const UnicodeString & Message){  if (Terminal != NULL)  {    Terminal->LogEvent(FORMAT("Keep up to date: %s", (Message)));  }}
 |