SynchronizeController.cpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. //---------------------------------------------------------------------------
  2. #include <WinPCH.h>
  3. #pragma hdrstop
  4. #include <RemoteFiles.h>
  5. #include <Terminal.h>
  6. #include <DiscMon.hpp>
  7. #include "SynchronizeController.h"
  8. //---------------------------------------------------------------------------
  9. __fastcall TSynchronizeController::TSynchronizeController(
  10. TSynchronizeEvent AOnSynchronize, TSynchronizeInvalidEvent AOnSynchronizeInvalid,
  11. TSynchronizeTooManyDirectories AOnTooManyDirectories)
  12. {
  13. FOnSynchronize = AOnSynchronize;
  14. FOnSynchronizeInvalid = AOnSynchronizeInvalid;
  15. FOnTooManyDirectories = AOnTooManyDirectories;
  16. FSynchronizeMonitor = NULL;
  17. FSynchronizeAbort = NULL;
  18. FSynchronizeLog = NULL;
  19. FOptions = NULL;
  20. }
  21. //---------------------------------------------------------------------------
  22. __fastcall TSynchronizeController::~TSynchronizeController()
  23. {
  24. DebugAssert(FSynchronizeMonitor == NULL);
  25. }
  26. //---------------------------------------------------------------------------
  27. void __fastcall TSynchronizeController::StartStop(TObject * Sender,
  28. bool Start, const TSynchronizeParamType & Params, const TCopyParamType & CopyParam,
  29. TSynchronizeOptions * Options,
  30. TSynchronizeAbortEvent OnAbort, TSynchronizeThreadsEvent OnSynchronizeThreads,
  31. TSynchronizeLog OnSynchronizeLog)
  32. {
  33. if (Start)
  34. {
  35. Configuration->Usage->Inc(L"KeepUpToDates");
  36. try
  37. {
  38. DebugAssert(OnSynchronizeLog != NULL);
  39. FSynchronizeLog = OnSynchronizeLog;
  40. FOptions = Options;
  41. if (FLAGSET(Params.Options, soSynchronize) &&
  42. (FOnSynchronize != NULL))
  43. {
  44. FOnSynchronize(this, Params.LocalDirectory,
  45. Params.RemoteDirectory, CopyParam,
  46. Params, NULL, FOptions, true);
  47. }
  48. FCopyParam = CopyParam;
  49. FCopyParam.IncludeFileMask.SetRoots(Params.LocalDirectory, Params.RemoteDirectory);
  50. FSynchronizeParams = Params;
  51. DebugAssert(OnAbort);
  52. FSynchronizeAbort = OnAbort;
  53. if (FLAGSET(FSynchronizeParams.Options, soRecurse))
  54. {
  55. SynchronizeLog(slScan,
  56. FMTLOAD(SYNCHRONIZE_SCAN, (FSynchronizeParams.LocalDirectory)));
  57. }
  58. FSynchronizeMonitor = new TDiscMonitor(dynamic_cast<TComponent*>(Sender));
  59. FSynchronizeMonitor->SubTree = false;
  60. TMonitorFilters Filters;
  61. Filters << moFilename << moLastWrite;
  62. if (FLAGSET(FSynchronizeParams.Options, soRecurse))
  63. {
  64. Filters << moDirName;
  65. }
  66. FSynchronizeMonitor->Filters = Filters;
  67. FSynchronizeMonitor->MaxDirectories = 0;
  68. FSynchronizeMonitor->ChangeDelay = GUIConfiguration->KeepUpToDateChangeDelay;
  69. FSynchronizeMonitor->OnTooManyDirectories = SynchronizeTooManyDirectories;
  70. FSynchronizeMonitor->OnDirectoriesChange = SynchronizeDirectoriesChange;
  71. FSynchronizeMonitor->OnFilter = SynchronizeFilter;
  72. FSynchronizeMonitor->AddDirectory(FSynchronizeParams.LocalDirectory,
  73. FLAGSET(FSynchronizeParams.Options, soRecurse));
  74. FSynchronizeMonitor->OnChange = SynchronizeChange;
  75. FSynchronizeMonitor->OnInvalid = SynchronizeInvalid;
  76. FSynchronizeMonitor->OnSynchronize = OnSynchronizeThreads;
  77. // get count before open to avoid thread issues
  78. int Directories = FSynchronizeMonitor->Directories->Count;
  79. FSynchronizeMonitor->Open();
  80. SynchronizeLog(slStart, FMTLOAD(SYNCHRONIZE_START, (Directories)));
  81. }
  82. catch(...)
  83. {
  84. SAFE_DESTROY(FSynchronizeMonitor);
  85. throw;
  86. }
  87. }
  88. else
  89. {
  90. FOptions = NULL;
  91. SAFE_DESTROY(FSynchronizeMonitor);
  92. }
  93. }
  94. //---------------------------------------------------------------------------
  95. void __fastcall TSynchronizeController::SynchronizeChange(
  96. TObject * /*Sender*/, const UnicodeString Directory, bool & SubdirsChanged)
  97. {
  98. try
  99. {
  100. UnicodeString RemoteDirectory;
  101. UnicodeString RootLocalDirectory;
  102. RootLocalDirectory = IncludeTrailingBackslash(FSynchronizeParams.LocalDirectory);
  103. RemoteDirectory = UnixIncludeTrailingBackslash(FSynchronizeParams.RemoteDirectory);
  104. UnicodeString LocalDirectory = IncludeTrailingBackslash(Directory);
  105. DebugAssert(LocalDirectory.SubString(1, RootLocalDirectory.Length()) ==
  106. RootLocalDirectory);
  107. RemoteDirectory = RemoteDirectory +
  108. ToUnixPath(LocalDirectory.SubString(RootLocalDirectory.Length() + 1,
  109. LocalDirectory.Length() - RootLocalDirectory.Length()));
  110. SynchronizeLog(slChange, FMTLOAD(SYNCHRONIZE_CHANGE,
  111. (ExcludeTrailingBackslash(LocalDirectory))));
  112. if (FOnSynchronize != NULL)
  113. {
  114. TSynchronizeOptions DefaultOptions; // Just as a container for the Files field
  115. // this is completely wrong as the options structure
  116. // can contain non-root specific options in future
  117. TSynchronizeOptions * Options =
  118. ((LocalDirectory == RootLocalDirectory) ? FOptions : &DefaultOptions);
  119. TSynchronizeChecklist * Checklist = NULL;
  120. FOnSynchronize(this, LocalDirectory, RemoteDirectory, FCopyParam,
  121. FSynchronizeParams, &Checklist, Options, false);
  122. if (Checklist != NULL)
  123. {
  124. try
  125. {
  126. if (FLAGSET(FSynchronizeParams.Options, soRecurse))
  127. {
  128. SubdirsChanged = false;
  129. DebugAssert(Checklist != NULL);
  130. for (int Index = 0; Index < Checklist->Count; Index++)
  131. {
  132. const TSynchronizeChecklist::TItem * Item = Checklist->Item[Index];
  133. // note that there may be action saDeleteRemote even if nothing has changed
  134. // so this is sub-optimal
  135. if (Item->IsDirectory)
  136. {
  137. if ((Item->Action == TSynchronizeChecklist::saUploadNew) ||
  138. (Item->Action == TSynchronizeChecklist::saDeleteRemote))
  139. {
  140. SubdirsChanged = true;
  141. break;
  142. }
  143. else
  144. {
  145. DebugFail();
  146. }
  147. }
  148. }
  149. }
  150. else
  151. {
  152. SubdirsChanged = false;
  153. }
  154. }
  155. __finally
  156. {
  157. delete Checklist;
  158. }
  159. }
  160. }
  161. }
  162. catch(Exception & E)
  163. {
  164. SynchronizeAbort(dynamic_cast<EFatal*>(&E) != NULL);
  165. }
  166. }
  167. //---------------------------------------------------------------------------
  168. void __fastcall TSynchronizeController::SynchronizeAbort(bool Close)
  169. {
  170. if (FSynchronizeMonitor != NULL)
  171. {
  172. FSynchronizeMonitor->Close();
  173. }
  174. DebugAssert(FSynchronizeAbort);
  175. FSynchronizeAbort(NULL, Close);
  176. }
  177. //---------------------------------------------------------------------------
  178. void __fastcall TSynchronizeController::LogOperation(TSynchronizeOperation Operation,
  179. const UnicodeString FileName)
  180. {
  181. TSynchronizeLogEntry Entry;
  182. UnicodeString Message;
  183. switch (Operation)
  184. {
  185. case soDelete:
  186. Entry = slDelete;
  187. Message = FMTLOAD(SYNCHRONIZE_DELETED, (FileName));
  188. break;
  189. default:
  190. DebugFail();
  191. // fallthru
  192. case soUpload:
  193. Entry = slUpload;
  194. Message = FMTLOAD(SYNCHRONIZE_UPLOADED, (FileName));
  195. break;
  196. }
  197. SynchronizeLog(Entry, Message);
  198. }
  199. //---------------------------------------------------------------------------
  200. void __fastcall TSynchronizeController::SynchronizeLog(TSynchronizeLogEntry Entry,
  201. const UnicodeString Message)
  202. {
  203. if (FSynchronizeLog != NULL)
  204. {
  205. FSynchronizeLog(this, Entry, Message);
  206. }
  207. }
  208. //---------------------------------------------------------------------------
  209. void __fastcall TSynchronizeController::SynchronizeFilter(TObject * /*Sender*/,
  210. const UnicodeString DirectoryName, bool & Add)
  211. {
  212. if ((FOptions != NULL) && (FOptions->Filter != NULL))
  213. {
  214. if (IncludeTrailingBackslash(ExtractFilePath(DirectoryName)) ==
  215. IncludeTrailingBackslash(FSynchronizeParams.LocalDirectory))
  216. {
  217. int FoundIndex;
  218. Add = FOptions->Filter->Find(ExtractFileName(DirectoryName), FoundIndex);
  219. }
  220. }
  221. if (Add && !FCopyParam.AllowAnyTransfer()) // optimization
  222. {
  223. TFileMasks::TParams MaskParams; // size/time does not matter for directories
  224. bool Hidden = FLAGSET(FileGetAttrFix(DirectoryName), faHidden);
  225. // Missing call to GetBaseFileName
  226. Add = FCopyParam.AllowTransfer(DirectoryName, osLocal, true, MaskParams, Hidden);
  227. }
  228. }
  229. //---------------------------------------------------------------------------
  230. void __fastcall TSynchronizeController::SynchronizeInvalid(
  231. TObject * /*Sender*/, const UnicodeString Directory, const UnicodeString ErrorStr)
  232. {
  233. if (FOnSynchronizeInvalid != NULL)
  234. {
  235. FOnSynchronizeInvalid(this, Directory, ErrorStr);
  236. }
  237. SynchronizeAbort(false);
  238. }
  239. //---------------------------------------------------------------------------
  240. void __fastcall TSynchronizeController::SynchronizeTooManyDirectories(
  241. TObject * /*Sender*/, int & MaxDirectories)
  242. {
  243. if (FOnTooManyDirectories != NULL)
  244. {
  245. FOnTooManyDirectories(this, MaxDirectories);
  246. }
  247. }
  248. //---------------------------------------------------------------------------
  249. void __fastcall TSynchronizeController::SynchronizeDirectoriesChange(
  250. TObject * /*Sender*/, int Directories)
  251. {
  252. SynchronizeLog(slDirChange, FMTLOAD(SYNCHRONIZE_START, (Directories)));
  253. }
  254. //---------------------------------------------------------------------------
  255. void __fastcall LogSynchronizeEvent(TTerminal * Terminal, const UnicodeString & Message)
  256. {
  257. if (Terminal != NULL)
  258. {
  259. Terminal->LogEvent(FORMAT("Keep up to date: %s", (Message)));
  260. }
  261. }