Exemplo n.º 1
0
        public async Task ProcessDelta(Func <List <DriveItem>, Task> action,
                                       string folderPath,
                                       CryptoDriveContext context,
                                       CancellationToken cancellationToken)
        {
            var pageCounter = 0;

            while (true)
            {
                using (this.Logger.BeginScope(new Dictionary <string, object>
                {
                    [$"DeltaPage ({this.Name})"] = pageCounter
                }))
                {
                    (var deltaPage, var isLast) = await this.GetDeltaPageAsync();

                    await action?.Invoke(deltaPage);

                    pageCounter++;

                    // exit while loop
                    if (isLast)
                    {
                        break;
                    }
                }
            }
        }
Exemplo n.º 2
0
        private Task <(List <DriveItem> DeltaPage, bool IsLast)> GetDeltaPageAsync(string folderPath,
                                                                                   CryptoDriveContext context,
                                                                                   CancellationToken cancellationToken)
        {
            var pageSize  = 10;
            var deltaPage = new List <DriveItem>();

            if (_fileEnumerator is null)
            {
                _fileEnumerator = this.SafelyEnumerateDriveItems(folderPath, context)
                                  .Where(current => this.CheckPathAllowed(current.GetItemPath()))
                                  .GetEnumerator();
            }

            while (!cancellationToken.IsCancellationRequested && _fileEnumerator.MoveNext())
            {
                deltaPage.Add(_fileEnumerator.Current);

                if (deltaPage.Count == pageSize)
                {
                    return(Task.FromResult((deltaPage, false)));
                }
            }

            _fileEnumerator = null;

            return(Task.FromResult((deltaPage, true)));
        }
Exemplo n.º 3
0
        public CryptoDriveSyncEngine(IDriveProxy remoteDrive,
                                     IDriveProxy localDrive,
                                     SyncMode syncMode,
                                     ILogger logger)
        {
            _remoteDrive = remoteDrive;
            _localDrive  = localDrive;
            _syncMode    = syncMode;
            _logger      = logger;

            _context = new CryptoDriveContext();
            _syncId  = 0;

            _regex_conflict = new Regex(@".*\s\(Conflicted Copy [0-9]{4}-[0-9]{2}-[0-9]{2}\s[0-9]{6}\)");
            _regex_replace  = new Regex(@"\s\(Conflicted Copy [0-9]{4}-[0-9]{2}-[0-9]{2}\s[0-9]{6}\)");

            // changes
            _cts          = new CancellationTokenSource();
            _manualReset  = new ManualResetEventSlim();
            _changesQueue = new ConcurrentQueue <string>();

            // handler
            _handler = (sender, e) =>
            {
                _changesQueue.Enqueue(e);
                _manualReset.Set();
            };
        }
Exemplo n.º 4
0
        private IEnumerable <DriveItem> SafelyEnumerateDriveItems(string folderPath, CryptoDriveContext context, [CallerMemberName] string callerName = "")
        {
            var forceNew           = callerName == nameof(this.SafelyEnumerateDriveItems);
            var driveItems         = Enumerable.Empty <DriveItem>();
            var absoluteFolderPath = folderPath.ToAbsolutePath(this.BasePath);

            try
            {
                // get all folders in current folder
                driveItems = driveItems.Concat(Directory.EnumerateDirectories(absoluteFolderPath, "*", SearchOption.TopDirectoryOnly)
                                               .SelectMany(current =>
                {
                    RemoteState oldRemoteState = null;
                    var driveInfo   = new DirectoryInfo(current).ToDriveItem(this.BasePath);
                    var folderPath2 = current.Substring(this.BasePath.Length).NormalizeSlashes();

                    if (!forceNew)
                    {
                        oldRemoteState = context.RemoteStates.FirstOrDefault(remoteState => remoteState.GetItemPath() == folderPath2 &&
                                                                             remoteState.Type == DriveItemType.Folder);
                    }

                    // When we know that the parent folder is not in the database (oldRemoteState == null),
                    // the children aren't there neither (forceNew = true).
                    if (forceNew || oldRemoteState == null)
                    {
                        return(this.SafelyEnumerateDriveItems(folderPath2, context)
                               .Concat(new DriveItem[] { driveInfo }));
                    }
                    else
                    {
                        return new List <DriveItem> {
                            driveInfo
                        }
                    };
                }));

                // get all files in current folder
                driveItems = driveItems.Concat(Directory.EnumerateFiles(absoluteFolderPath)
                                               .SelectMany(current =>
                {
                    var driveInfo = new FileInfo(current).ToDriveItem(this.BasePath);
                    return(new List <DriveItem> {
                        driveInfo
                    });
                }).ToList());

                // get all deleted items
                var remoteStates = context.RemoteStates.Where(current => current.Path == folderPath);

                var deletedItems = remoteStates.Where(current =>
                {
                    switch (current.Type)
                    {
                    case DriveItemType.Folder:
                        return(!Directory.Exists(current.GetItemPath().ToAbsolutePath(this.BasePath)));

                    case DriveItemType.File:
                        return(!File.Exists(current.GetItemPath().ToAbsolutePath(this.BasePath)));

                    case DriveItemType.RemoteItem:
                    default:
                        throw new NotSupportedException();
                    }
                }).Select(current => current.ToDriveItem(deleted: true));

                driveItems = driveItems.Concat(deletedItems);

                return(driveItems);
            }
            catch (UnauthorizedAccessException)
            {
                return(driveItems);
            }
        }