private void UpdateStatus(S3StausChangedEventHandler eventHandler, Dictionary <string, ProcessItem> files, Dictionary <string, S3Object> list)
        {
            if (eventHandler == null)
            {
                return;
            }
            var uploading            = 0;
            var uploadingTotal       = 0;
            var uploadingException   = 0;
            var downloading          = 0;
            var downloadingTotal     = 0;
            var downloadingException = 0;
            var matchingFiles        = 0;
            var notProcessedFiles    = 0;

            foreach (var file in files)
            {
                switch (file.Value.Action)
                {
                case ProcessAction.Match:
                    matchingFiles++;
                    break;

                case ProcessAction.Upload:
                    uploadingTotal++;
                    break;

                case ProcessAction.Download:
                    downloadingTotal++;
                    break;

                case ProcessAction.UploadingDone:
                    uploadingTotal++;
                    uploading++;
                    break;

                case ProcessAction.UploadingException:
                    uploading++;
                    uploadingTotal++;
                    uploadingException++;
                    break;

                case ProcessAction.DownloadingDone:
                    downloadingTotal++;
                    downloading++;
                    break;

                case ProcessAction.DownloadingException:
                    downloading++;
                    downloadingTotal++;
                    downloadingException++;
                    break;

                case ProcessAction.Empty:
                    notProcessedFiles++;
                    break;

                default:
                    break;
                }
            }
            var status = new S3Status {
                BucketName    = _bucketName, CloudTotal = list.Count + uploading - uploadingException, LocalTotal = files.Count + downloading - downloadingException,
                Uploading     = uploading, UploadingTotal = uploadingTotal, UploadingException = uploadingException,
                Downloading   = downloading, DownloadingTotal = downloadingTotal, DownloadingException = downloadingException,
                MatchingFiles = matchingFiles, NotProcessedFiles = notProcessedFiles
            };

            eventHandler(status);
        }
        private void SyncAction(CancellationToken token, S3StausChangedEventHandler eventHandler)
        {
            var files       = GetFiles();
            var listRequest = new ListObjectsRequest().WithBucketName(_bucketName).WithPrefix(KnownFolders.RootFolderName.ToLowerInvariant());
            var list        = new Dictionary <string, S3Object>();

            UpdateStatus(eventHandler, files, list);
            bool isTruncated  = false;
            bool hadException = false;

            using (var client = CreateAmazonS3Client()) {
                do
                {
                    try {
                        var listResponse = client.ListObjects(listRequest);
                        isTruncated = listResponse.IsTruncated;
                        var currentList = listResponse.S3Objects.Where(obj => obj.Size != 0).ToList();
                        foreach (var item in currentList)
                        {
                            if (token.IsCancellationRequested)
                            {
                                return;
                            }
                            list.Add(item.Key, item);
                            if (files.ContainsKey(item.Key))
                            {
                                var file = files[item.Key];
                                if (file.LocalSize != item.Size)
                                {
                                    file.S3Path = item.Key;
                                    file.S3Size = item.Size;
                                    file.Action = (file.LocalSize > file.S3Size) ? ProcessAction.Upload : ProcessAction.Download;
                                }
                                else
                                {
                                    file.Action = ProcessAction.Match;
                                }
                            }
                            else
                            {
                                var file = new ProcessItem {
                                    S3Path = item.Key, S3Size = item.Size, Action = ProcessAction.Download
                                };
                                files.Add(item.Key, file);
                            }
                        }
                        UpdateStatus(eventHandler, files, list);
                        listRequest.Marker = listResponse.NextMarker;
                    } catch (Exception) {
                        hadException = true;
                    }
                } while (isTruncated);
            }
            if (hadException)
            {
                return;
            }
            foreach (var file in files)
            {
                if (token.IsCancellationRequested)
                {
                    return;
                }
                if (!list.ContainsKey(file.Key))
                {
                    file.Value.S3Path = file.Key;
                    file.Value.Action = ProcessAction.Upload;
                }
            }
            UpdateStatus(eventHandler, files, list);
            Task.Factory.StartNew(() => {
                foreach (var file in files)
                {
                    if (file.Value.Action == ProcessAction.Upload)
                    {
                        Upload(file.Value);
                        UpdateStatus(eventHandler, files, list);
                    }
                    if (token.IsCancellationRequested)
                    {
                        return;
                    }
                }
            });
            Task.Factory.StartNew(() => {
                foreach (var file in files)
                {
                    if (file.Value.Action == ProcessAction.Download)
                    {
                        Download(file.Value);
                        UpdateStatus(eventHandler, files, list);
                    }
                    if (token.IsCancellationRequested)
                    {
                        return;
                    }
                }
            });
        }
 public void Sync(S3StausChangedEventHandler eventHandler)
 {
     _tokenSource = new CancellationTokenSource();
     _task        = Task.Factory.StartNew(() => SyncAction(_tokenSource.Token, eventHandler), TaskCreationOptions.LongRunning);
 }
        public void Sync(string localRootFolder, string remoteFolder, S3StausChangedEventHandler eventHandler)
        {
            var files = GetFiles(localRootFolder, remoteFolder);
            var listRequest = new ListObjectsRequest().WithBucketName(_bucketName).WithPrefix(remoteFolder);
            var list = new Dictionary<string, S3Object>();
            UpdateStatus(eventHandler, files, list);
            bool isTruncated = false;
            bool hadException = false;
            using (var client = CreateAmazonS3Client()) {
                do {
                    try {
                        var listResponse = client.ListObjects(listRequest);
                        isTruncated = listResponse.IsTruncated;
                        var currentList = listResponse.S3Objects.Where(obj => obj.Size != 0).ToList();
                        foreach (var item in currentList) {

                            list.Add(item.Key, item);
                            if (files.ContainsKey(item.Key)) {
                                var file = files[item.Key];
                                if (file.LocalSize != item.Size) {
                                    file.S3Path = item.Key;
                                    file.S3Size = item.Size;
                                    file.Action = (file.LocalSize > file.S3Size) ? ProcessAction.Upload : ProcessAction.Download;
                                } else file.Action = ProcessAction.Match;
                            } else {
                                var file = new ProcessItem {S3Path = item.Key, S3Size = item.Size, Action = ProcessAction.Download};
                                files.Add(item.Key, file);
                            }
                        }
                        UpdateStatus(eventHandler, files, list);
                        listRequest.Marker = listResponse.NextMarker;
                    } catch (Exception) {
                        hadException = true;
                    }
                } while (isTruncated);
            }
            if (hadException) return;
            foreach (var file in files) {
                if (!list.ContainsKey(file.Key)) {
                    file.Value.S3Path = file.Key;
                    file.Value.Action = ProcessAction.Upload;
                }
            }
            UpdateStatus(eventHandler, files, list);
            //Task.Factory.StartNew(() => {
                foreach (var file in files) {
                    if (file.Value.Action == ProcessAction.Upload) {
                        Upload(file.Value);
                        UpdateStatus(eventHandler, files, list);
                    }
                }
            //});
            //Task.Factory.StartNew(() => {
                foreach (var file in files) {
                    if (file.Value.Action == ProcessAction.Download) {
                        Download(localRootFolder, file.Value);
                        UpdateStatus(eventHandler, files, list);
                    }
                }
            //});
        }
        private void UpdateStatus(S3StausChangedEventHandler eventHandler, Dictionary<string, ProcessItem> files, Dictionary<string, S3Object> list)
        {
            if (eventHandler == null) return;
            var uploading = 0;
            var uploadingTotal = 0;
            var uploadingException = 0;
            var downloading = 0;
            var downloadingTotal = 0;
            var downloadingException = 0;
            var matchingFiles = 0;
            var notProcessedFiles = 0;

            foreach (var file in files) {
                switch (file.Value.Action) {
                    case ProcessAction.Match:
                        matchingFiles++;
                        break;
                    case ProcessAction.Upload:
                        uploadingTotal++;
                        break;
                    case ProcessAction.Download:
                        downloadingTotal++;
                        break;
                    case ProcessAction.UploadingDone:
                        uploadingTotal++;
                        uploading++;
                        break;
                    case ProcessAction.UploadingException:
                        uploading++;
                        uploadingTotal++;
                        uploadingException++;
                        break;
                    case ProcessAction.DownloadingDone:
                        downloadingTotal++;
                        downloading++;
                        break;
                    case ProcessAction.DownloadingException:
                        downloading++;
                        downloadingTotal++;
                        downloadingException++;
                        break;
                    case ProcessAction.Empty:
                        notProcessedFiles++;
                        break;
                }
            }
            var status = new S3Status {
                BucketName = _bucketName, CloudTotal = list.Count + uploading - uploadingException, LocalTotal = files.Count + downloading - downloadingException, 
                Uploading = uploading, UploadingTotal = uploadingTotal, UploadingException = uploadingException, 
                Downloading = downloading, DownloadingTotal = downloadingTotal, DownloadingException = downloadingException, 
                MatchingFiles = matchingFiles, NotProcessedFiles = notProcessedFiles};
            eventHandler(status);
        }
 public void Sync(S3StausChangedEventHandler eventHandler)
 {
     _tokenSource = new CancellationTokenSource();
     _task = Task.Factory.StartNew(() => SyncAction(_tokenSource.Token, eventHandler), TaskCreationOptions.LongRunning);
 }