private void CleanUpload(UploadInfo upload) { if (upload.SourcePath == null) { var sourcepath = Path.Combine(cachePath, upload.Id); try { File.Delete(sourcepath); } catch (Exception) { Log.Warn("CleanUpload did not find the file, probably successfully moved"); } } try { var infopath = Path.Combine(cachePath, upload.Id + ".info"); File.Delete(infopath); var tempPath = Path.Combine(cachePath, upload.Id + ".temp"); File.Delete(tempPath); } catch (Exception) { Log.Warn("CleanUpload did not find the info file, probably successfully moved"); } upload.Dispose(); }
private async Task Upload(UploadInfo item) { var path = Path.Combine(cachePath, item.Id); try { try { if (item.Length == 0) { Log.Trace("Zero Length file: " + item.Path); await OnUploadFailed(item, FailReason.ZeroLength, null); CleanUpload(path); item.Dispose(); return; } Log.Trace("Started upload: " + item.Path); FSItem.Builder node; if (!item.Overwrite) { var checkparent = await cloud.Nodes.GetNode(item.ParentId); if (checkparent == null || !checkparent.IsDir) { Log.Error("Folder does not exist to upload file: " + item.Path); await OnUploadFailed(item, FailReason.NoFolderNode, "Parent folder is missing"); CleanUpload(path); item.Dispose(); return; } var checknode = await cloud.Nodes.GetChild(item.ParentId, Path.GetFileName(item.Path)); if (checknode != null) { Log.Warn("File with such name already exists and Upload is New: " + item.Path); await OnUploadFailed(item, FailReason.Conflict, "File already exists"); CleanUpload(path); item.Dispose(); return; } node = await cloud.Files.UploadNew( item.ParentId, Path.GetFileName(item.Path), () => new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true), (p) => UploadProgress(item, p)); } else { var checknode = await cloud.Nodes.GetNode(item.Id); if (checknode == null) { Log.Error("File does not exist to be overwritten: " + item.Path); File.Delete(path + ".info"); await OnUploadFailed(item, FailReason.NoOverwriteNode, "No file to overwrite"); CleanUpload(path); item.Dispose(); return; } node = await cloud.Files.Overwrite( item.Id, () => new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true), (p) => UploadProgress(item, p)); } if (node == null) { throw new NullReferenceException("File node is null: " + item.Path); } CleanUpload(path); node.ParentPath = Path.GetDirectoryName(item.Path); Log.Trace("Finished upload: " + item.Path + " id:" + node.Id); await OnUploadFinished(item, node); item.Dispose(); return; } catch (FileNotFoundException ex) { Log.Error($"Upload error upload file not found: {item.Path}\r\n{ex}"); await OnUploadFailed(item, FailReason.FileNotFound, "Cached upload file is not found"); CleanUpload(path); item.Dispose(); return; } catch (OperationCanceledException) { if (item.Cancellation.IsCancellationRequested) { Log.Info("Upload canceled"); await OnUploadFailed(item, FailReason.Cancelled, "Upload cancelled"); CleanUpload(path); item.Dispose(); } return; } catch (CloudException ex) { if (ex.Error == System.Net.HttpStatusCode.Conflict) { var node = await cloud.Nodes.GetChild(item.ParentId, Path.GetFileName(item.Path)); if (node != null) { Log.Warn($"Upload finished with conflict and file does exist: {item.Path}\r\n{ex}"); await OnUploadFinished(item, node); CleanUpload(path); item.Dispose(); return; } Log.Error($"Upload conflict but no file: {item.Path}\r\n{ex}"); await OnUploadFailed(item, FailReason.Unexpected, "Upload conflict but there is no file in the same place"); } else if (ex.Error == System.Net.HttpStatusCode.NotFound) { Log.Error($"Upload error Folder Not Found: {item.Path}\r\n{ex}"); await OnUploadFailed(item, FailReason.NoFolderNode, "Folder node for new file is not found"); CleanUpload(path); item.Dispose(); return; } else if (ex.Error == System.Net.HttpStatusCode.GatewayTimeout) { Log.Warn($"Gateway timeout happened: {item.Path}\r\nWait 30 seconds to check if file was really uploaded"); await Task.Delay(30000); var node = await cloud.Nodes.GetChild(item.ParentId, Path.GetFileName(item.Path)); if (node != null) { Log.Warn($"Gateway timeout happened: {item.Path}\r\nBut after 30 seconds file did appear"); File.Delete(path + ".info"); node.ParentPath = Path.GetDirectoryName(item.Path); Log.Trace($"Finished upload: {item.Path} id:{node.Id}"); await OnUploadFinished(item, node); item.Dispose(); return; } Log.Error($"Gateway timeout happened: {item.Path}\r\nBut after 30 seconds file still did not appear."); await OnUploadFailed(item, FailReason.Unexpected, $"Gateway timeout happened but after 30 seconds file still did not appear"); } else { Log.Error($"Cloud exception: {item.Path}"); await OnUploadFailed(item, FailReason.Unexpected, $"Unexpected Error. Upload will retry.\r\n{ex.Message}"); } } } catch (Exception ex) { Log.Error($"Upload failed: {item.Path}\r\n{ex}"); await OnUploadFailed(item, FailReason.Unexpected, $"Unexpected Error. Upload will retry.\r\n{ex.Message}"); } finally { uploadLimitSemaphore.Release(); UploadInfo outItem; allUploads.TryRemove(item.Id, out outItem); } await Task.Delay(ReuploadDelay); Log.Warn($"Repeat upload: {item.Path}"); allUploads.TryAdd(item.Id, item); leftUploads.Add(item); }
private async Task Upload(UploadInfo item) { var sourcepath = item.SourcePath ?? Path.Combine(cachePath, item.Id); var infopath = Path.Combine(cachePath, item.Id + ".info"); try { var itemName = Path.GetFileName(item.Path); var parentId = item.ParentId; try { Log.Trace("Started upload: " + item.Path); FSItem.Builder node; if (CheckFileHash && item.ContentId == null) { await SetState(item, UploadState.ContentId); item.ContentId = await CalcContentId(sourcepath); } if (!item.Overwrite) { var checkparent = await cloud.Nodes.GetNode(parentId); if (checkparent == null || !checkparent.IsDir) { Log.ErrorTrace("Folder does not exist to upload file: " + item.Path); await OnUploadFailed(item, FailReason.NoFolderNode, "Parent folder is missing"); CleanUpload(item); return; } var checknode = await cloud.Nodes.GetChild(parentId, itemName); if (checknode != null) { Log.Warn("File with such name already exists and Upload is New: " + item.Path); await OnUploadFailed(item, FailReason.Conflict, "File already exists"); CleanUpload(item); return; } var lastPresenceCheck = DateTime.UtcNow; await SetState(item, UploadState.Uploading); node = await cloud.Files.UploadNew( parentId, itemName, () => new FileStream(sourcepath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true), async p => { lastPresenceCheck = await CheckDuplicate(item, itemName, lastPresenceCheck); await UploadProgress(item, p); }); } else { var checknode = await cloud.Nodes.GetNode(item.Id); if (checknode == null) { Log.ErrorTrace("File does not exist to be overwritten: " + item.Path); await OnUploadFailed(item, FailReason.NoOverwriteNode, "No file to overwrite"); CleanUpload(item); return; } if (item.ContentId != null && item.ContentId == checknode.ContentId) { Log.Warn($"File content is the same. Skip overwrite: {item.Path}"); node = checknode; } else { await SetState(item, UploadState.Uploading); node = await cloud.Files.Overwrite( item.Id, () => new FileStream(sourcepath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true), async p => await UploadProgress(item, p)); } } if (node == null) { throw new NullReferenceException("File node is null: " + item.Path); } if (node.Length != item.Length) { item.Overwrite = true; throw new Exception($"Uploaded file size not correct: {item.Path} Correct Size: {item.Length} Got: {node.Length}"); } if (item.ContentId != null && item.ContentId != node.ContentId) { Log.ErrorTrace($"Upload finished with content id mismatch: {item.Path} local:{item.ContentId} remote:{node.ContentId}"); await OnUploadFailed( item, FailReason.ContentIdMismatch, "Uploaded item content id does not match local file content id. Consider to check uploaded file and reupload."); CleanUpload(item); return; } node.ParentPath = Path.GetDirectoryName(item.Path); Log.Trace("Finished upload: " + item.Path + " id:" + node.Id); await OnUploadFinished(item, node); CleanUpload(item); return; } catch (FileNotFoundException ex) { Log.Error($"Upload error upload file not found: {item.Path}", ex); await OnUploadFailed(item, FailReason.FileNotFound, "Cached upload file is not found"); CleanUpload(item); return; } catch (OperationCanceledException) { if (item.Cancellation.IsCancellationRequested) { Log.Info("Upload canceled"); await OnUploadFailed(item, FailReason.Cancelled, "Upload cancelled"); CleanUpload(item); } return; } catch (CloudException ex) { if (ex.Error == System.Net.HttpStatusCode.Conflict) { var node = await cloud.Nodes.GetChild(parentId, itemName); if (node != null) { Log.Warn($"Upload finished with conflict and file does exist: {item.Path}\r\n{ex}"); await OnUploadFinished(item, node); CleanUpload(item); return; } Log.Error($"Upload conflict but no file: {item.Path}", ex); await OnUploadFailed(item, FailReason.Unexpected, "Upload conflict but there is no file in the same place"); } else if (ex.Error == System.Net.HttpStatusCode.NotFound) { Log.Error($"Upload error Folder Not Found: {item.Path}", ex); await OnUploadFailed(item, FailReason.NoFolderNode, "Folder node for new file is not found"); CleanUpload(item); return; } else if (ex.Error == System.Net.HttpStatusCode.GatewayTimeout) { Log.Warn($"Gateway timeout happened: {item.Path}\r\nWait 30 seconds to check if file was really uploaded"); await Task.Delay(30000); var node = await cloud.Nodes.GetChild(parentId, itemName); if (node != null) { Log.Warn($"Gateway timeout happened: {item.Path}\r\nBut after 30 seconds file did appear"); File.Delete(infopath); node.ParentPath = Path.GetDirectoryName(item.Path); Log.Trace($"Finished upload: {item.Path} id:{node.Id}"); await OnUploadFinished(item, node); item.Dispose(); return; } Log.ErrorTrace($"Gateway timeout happened: {item.Path}\r\nBut after 30 seconds file still did not appear."); await OnUploadFailed(item, FailReason.Unexpected, "Gateway timeout happened but after 30 seconds file still did not appear"); } else { Log.ErrorTrace($"Upload cloud exception: {item.Path} - {ex.Message}"); await OnUploadFailed(item, FailReason.Unexpected, $"Unexpected Error. Upload will retry.\r\n{ex.Message}"); } } } catch (Exception ex) { Log.Error($"Upload failed: {item.Path}", ex); await OnUploadFailed(item, FailReason.Unexpected, $"Unexpected Error. Upload will retry.\r\n{ex.Message}"); } finally { uploadLimitSemaphore.Release(); allUploads.TryRemove(item.Id, out _); } await Task.Delay(ReuploadDelay); Log.Warn($"Repeat upload: {item.Path}"); allUploads.TryAdd(item.Id, item); leftUploads.Add(item); }