private void TransferItem(USNJournalSyncLog syncLog, SyncMountpoint syncFrom) { try { syncLog.ActionStartDate = DateTime.Now; syncLog.ActionFinishDate = null; Singleton.Instance.Repository.Update(syncLog); bool successfull = false; if (syncLog.Action.GetType() == typeof (DeleteAction)) { var path = Path.Get(syncFrom.Path, syncLog.Action.RelativePath); logger.Info($"[{syncLog.Id}] [D] " + path); if (path.Exists) { if (syncLog.Action.IsDirectory) { path.Delete(true); } else { path.Delete(true); } } successfull = true; } else if (syncLog.Action.GetType() == typeof (RenameAction)) { var renameAction = syncLog.Action as RenameAction; logger.Info($"[{syncLog.Id}] [R] {renameAction.RenameFrom} to {renameAction.RelativePath}"); if (String.IsNullOrWhiteSpace(renameAction.RenameFrom)) { CopyFile(syncLog, syncFrom); } Path.Get(syncFrom.Path, renameAction.RenameFrom).Move(Path.Get(syncFrom.Path, renameAction.RelativePath).FullPath); successfull = true; } else { successfull = CopyFile(syncLog, syncFrom); } syncLog.ActionFinishDate = DateTime.Now; syncLog.Successfull = successfull; Singleton.Instance.Repository.Update(syncLog); foreach (var error in Singleton.Instance.Repository.Many<Error>(f=>f.SyncLog.Id == syncLog.Id)) { Singleton.Instance.Repository.Delete(error); } } catch (FileNotFoundException ex) { syncLog.RequiresManualIntervention = true; syncLog.ActionFinishDate = DateTime.Now; Singleton.Instance.Repository.Update(syncLog); logger.Error(ex, "Error on item " + syncLog.Id); Error error = new Error(); error.SyncLog = syncLog; error.Exception = ex; error.ItemId = syncLog.Id; error.Message = ex.Message; Singleton.Instance.Repository.Add(error); } catch (Exception e) { syncLog.ActionFinishDate = DateTime.Now; Singleton.Instance.Repository.Update(syncLog); logger.Error(e, "Error on item " + syncLog.Id); Error error = new Error(); error.SyncLog = syncLog; error.Exception = e; error.ItemId = syncLog.Id; error.Message = e.Message; Singleton.Instance.Repository.Add(error); } }
public void Execute(IJobExecutionContext context) { logger.Trace("USNJournalSync Execution"); if (Singleton.Instance.DestinationMountpoints == null || Singleton.Instance.DestinationMountpoints.Count == 0) { logger.Trace("No destination points"); return; } try { using (Repository repo = new Repository()) { foreach (var syncFrom in Singleton.Instance.DestinationMountpoints) { syncFrom.DestinationServer.Fetch(Singleton.Instance.Servers); syncFrom.Mountpoint.Reference = repo.ById<MonitoredMountpoint>(syncFrom.Mountpoint.ReferenceId); if (syncFrom.Mountpoint.Reference.PublicPath == null) { logger.Warn(string.Format("PublicPath for DestinationMountPoint:{0} is null! Aborting copy.", syncFrom.Id)); continue; } List<FileAction> rawEntries; if (String.IsNullOrWhiteSpace(syncFrom.RelativePathStartFilter)) { rawEntries = repo.Many<FileAction>(f => f.Mountpoint == syncFrom.Mountpoint && f.USN > syncFrom.LastUSN, limit: Singleton.Instance.CurrentServer.NormalCopyLimit, AscendingSort: e => e.USN).ToList(); } else { rawEntries = repo.Many<FileAction>(f => f.RelativePath.StartsWith(syncFrom.RelativePathStartFilter) && f.Mountpoint == syncFrom.Mountpoint && f.USN > syncFrom.LastUSN, limit: Singleton.Instance.CurrentServer.NormalCopyLimit, AscendingSort:e=>e.USN).ToList(); } var changedFiles = RollupService.PerformRollup(rawEntries).ToList(); if (rawEntries.Count == 0) { logger.Trace("No changes found"); continue; } logger.Trace($"{changedFiles.Count} changed files for {syncFrom.Id} since USN {syncFrom.LastUSN}"); long lastUsn = rawEntries.Max(f=>f.USN); Parallel.ForEach(changedFiles, new ParallelOptions{MaxDegreeOfParallelism = Singleton.Instance.CurrentServer.MaxThreads}, fileAction => { USNJournalSyncLog log = new USNJournalSyncLog(); log.Enqueued = DateTime.Now; log.DestinationMachine = Singleton.Instance.CurrentServer; log.SourceMachine = syncFrom.Mountpoint.Reference.Server; log.Entry = fileAction.USNEntry; log.Action = fileAction; repo.Add(log); TransferItem(log, syncFrom); }); IQueryable<USNJournalSyncLog> failedSync; if (String.IsNullOrWhiteSpace(syncFrom.RelativePathStartFilter)) { failedSync = repo.Many<USNJournalSyncLog>(f => !f.Successfull && f.Action.Mountpoint == syncFrom.Mountpoint && !f.RequiresManualIntervention, limit: Singleton.Instance.CurrentServer.FailedCopyLimit); } else { failedSync = repo.Many<USNJournalSyncLog>(f => f.Action.RelativePath.StartsWith(syncFrom.RelativePathStartFilter) && !f.Successfull && f.Action.Mountpoint == syncFrom.Mountpoint && !f.RequiresManualIntervention, limit: Singleton.Instance.CurrentServer.FailedCopyLimit); } Parallel.ForEach(failedSync, new ParallelOptions { MaxDegreeOfParallelism = Singleton.Instance.CurrentServer.MaxThreads }, failedItem => { if (failedItem.Retries == null) { failedItem.Retries = new List<DateTime> { failedItem.ActionStartDate ?? DateTime.Now }; } else { if (failedItem.Retries.Count == 20) { failedItem.RequiresManualIntervention = true; Singleton.Instance.Repository.Update(failedItem); return; } failedItem.Retries.Add(DateTime.Now); } TransferItem(failedItem, syncFrom); }); syncFrom.LastUSN = lastUsn; repo.Update(syncFrom); } } } catch (Exception e) { logger.Error(e, "Error during JournalSync"); } }
private static bool CopyFile(USNJournalSyncLog syncLog, SyncMountpoint syncFrom) { logger.Info($"[{syncLog.Id}] [C] {syncLog.Action.RelativePath}"); var copyAction = syncLog.Action as UpdateAction; var publicPath = syncFrom.Mountpoint.Reference.PublicPath; var relativePath = copyAction.RelativePath; if (publicPath == null) { throw new NullReferenceException("publicPath"); } if (relativePath == null) { throw new NullReferenceException("relativePath"); } Path.Get(publicPath, relativePath).Copy(Path.Get(syncFrom.Path, relativePath), Overwrite.Always, true); return true; }