Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Parallel.Cli/Commands/PullCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ private async Task PullPathAsync(LocalVaultConfig vault, string path, DateTime t
if (!File.Exists(file.LocalPath) || FileScanner.HasChanged(file, new SystemFile(file.LocalPath)) || force) pullFiles.Add(file);
});

Log.Debug($"Pulling {pullFiles.Count} files...");
CommandLine.WriteLine(syncManager.RemoteVault, $"Pulling {pullFiles.Count:N0} files...", ConsoleColor.DarkGray);
int pulledFiles = await syncManager.PullFilesAsync(pullFiles.ToArray(), new ProgressReport(vault, files.Count()));
CommandLine.WriteLine(vault, $"Successfully pulled {pulledFiles:N0} files from '{vault.Credentials.RootDirectory}'.", ConsoleColor.Green);
await syncManager.DisconnectAsync();
Expand All @@ -95,7 +95,7 @@ private async Task PullFileAsync(ISyncManager syncManager, string fullPath, bool
return;
}

Log.Debug($"Pulling '{fullPath}'");
CommandLine.WriteLine(syncManager.RemoteVault, $"Pulling 1 file...", ConsoleColor.DarkGray);
int pulledFiles = await syncManager.PullFilesAsync([remoteFile], new ProgressReport(syncManager.RemoteVault, 1));
CommandLine.WriteLine(syncManager.RemoteVault, $"Successfully pulled {pulledFiles:N0} file from '{syncManager.RemoteVault.Credentials.RootDirectory}'.", ConsoleColor.Green);
await syncManager.DisconnectAsync();
Expand Down
4 changes: 2 additions & 2 deletions Parallel.Cli/Commands/PushCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ private async Task PushPathInternalAsync(ISyncManager syncManager, string path,
return;
}

CommandLine.WriteLine(syncManager.RemoteVault, $"Backing up {files.Length:N0} files...", ConsoleColor.DarkGray);
int pushedFiles = await syncManager.PushFilesAsync(files, new ProgressReport(syncManager.RemoteVault, successFiles));
CommandLine.WriteLine(syncManager.RemoteVault, $"Pushing {files.Length:N0} files...", ConsoleColor.DarkGray);
int pushedFiles = await syncManager.PushFilesAsync(files, new ProgressReport(syncManager.RemoteVault, successFiles), force);
CommandLine.WriteLine(syncManager.RemoteVault, $"Successfully pushed {pushedFiles:N0} files in {_sw.Elapsed}.", ConsoleColor.Green);
}
}
Expand Down
47 changes: 14 additions & 33 deletions Parallel.Core/IO/Scanning/FileScanner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,7 @@ public async Task<SystemFile[]> GetFileChangesAsync(string path, string[] ignore
ConcurrentBag<string> scannedFiles = new();
ConcurrentBag<SystemFile> changedFiles = new();

Log.Debug("Getting system files...");
HashSet<string> localFiles = FileScanner.GetFiles(path, ignoreFolders, ".").ToHashSet();

Log.Debug("Getting database files...");
IEnumerable<SystemFile> remoteFiles = _db is null ? [] : await _db.GetLatestFilesAsync(path, false);
System.Threading.Tasks.Parallel.ForEach(remoteFiles, ParallelConfig.Options, (remoteFile, ct) =>
{
Expand Down Expand Up @@ -94,16 +91,16 @@ public async Task<SystemFile[]> GetFileChangesAsync(string path, string[] ignore
/// <summary>
/// Gets if a file has changed.
/// </summary>
/// <param name="sourcePath">The source file to compare.</param>
/// <param name="targetPath">The target file to compare to.</param>
/// <param name="source">The source file to compare.</param>
/// <param name="target">The target file to compare to.</param>
/// <returns>True is success, otherwise false.</returns>
public static bool HasChanged(SystemFile sourcePath, SystemFile? targetPath)
public static bool HasChanged(SystemFile source, SystemFile? target)
{
if (string.IsNullOrEmpty(sourcePath.CheckSum)) sourcePath.TryGenerateCheckSum();
return targetPath == null || (sourcePath.LastWrite.TotalMilliseconds > targetPath.LastWrite.TotalMilliseconds && Convert.ToBoolean(!sourcePath.CheckSum?.Equals(targetPath.CheckSum)));
if (target is null || !source.TryGenerateCheckSum()) return false;
if (source.LastWrite.TotalMilliseconds <= target.LastWrite.TotalMilliseconds) return false;
return source.CheckSum != target.CheckSum;
}


/// <summary>
/// Gets the total size, in bytes, of a directory.
/// </summary>
Expand Down Expand Up @@ -222,22 +219,22 @@ public static IEnumerable<string> GetFiles(string root, string[] exempt, string
IEnumerable<string> files;
try
{
Log.Debug($"Scanning -> {current}");
files = Directory.EnumerateFiles(current, searchPattern);
}
catch
{
Log.Debug($"No file access -> {current}");
Log.Warning($"No file access -> {current}");
continue;
}

foreach (string file in files)
{
if (IsIgnored(file, exempt))
{
Log.Debug($"Ignored -> {file}");
continue;
}
// This is a better system. However, if a user adds something to ignore, with this code it will never mark it for deletion.
// if (IsIgnored(file, exempt))
// {
// Log.Debug($"Ignored -> {file}");
// continue;
// }

yield return file;
}
Expand All @@ -250,7 +247,7 @@ public static IEnumerable<string> GetFiles(string root, string[] exempt, string
}
catch
{
Log.Debug($"No directory access -> {current}");
Log.Warning($"No directory access -> {current}");
continue;
}

Expand All @@ -273,8 +270,6 @@ public static Dictionary<string, SystemFile[]> GetDuplicateFiles(string path)
SystemFile entry = new(file);
dict.AddOrUpdate(entry.Name, _ => [entry], (k, v) =>
{
Log.Debug($"Checking: {entry.LocalPath}");

lock (v)
{
SystemFile? key = v.FirstOrDefault();
Expand All @@ -287,20 +282,6 @@ public static Dictionary<string, SystemFile[]> GetDuplicateFiles(string path)

return v;
});

/*if (dict.TryGetValue(entry.Name, out List<SystemFile>? value))
{
SystemFile? key = value.FirstOrDefault();
if (!HasChanged(entry, key))
{
Log.Debug($"HasChanged: {entry.LocalPath}");
value.Add(entry);
}
}
else
{
dict[entry.Name] = new List<SystemFile> { entry };
}*/
});

return dict.Where(kv => kv.Value.Count > 1).OrderByDescending(kv => kv.Value.Count).ToDictionary(k => k.Key, v => v.Value.OrderBy(l => l.LastWrite.TotalMilliseconds).ToArray());
Expand Down
2 changes: 1 addition & 1 deletion Parallel.Core/IO/Syncing/BaseSyncManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ public async Task DisconnectAsync()
}

/// <inheritdoc />
public abstract Task<int> PushFilesAsync(SystemFile[] files, IProgressReporter progress);
public abstract Task<int> PushFilesAsync(SystemFile[] files, IProgressReporter progress, bool overwrite);

/// <inheritdoc />
public abstract Task<int> PullFilesAsync(SystemFile[] files, IProgressReporter progress);
Expand Down
32 changes: 0 additions & 32 deletions Parallel.Core/IO/Syncing/DeltaSyncManager.cs

This file was deleted.

10 changes: 6 additions & 4 deletions Parallel.Core/IO/Syncing/FileSyncManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class FileSyncManager : BaseSyncManager
public FileSyncManager(LocalVaultConfig localVault) : base(localVault) { }

/// <inheritdoc/>
public override async Task<int> PushFilesAsync(SystemFile[] files, IProgressReporter progress)
public override async Task<int> PushFilesAsync(SystemFile[] files, IProgressReporter progress, bool overwrite)
{
if (files.Length == 0) return 0;
int queued = 0, completed = 0, total = 0;
Expand All @@ -37,15 +37,16 @@ public override async Task<int> PushFilesAsync(SystemFile[] files, IProgressRepo
Task worker = System.Threading.Tasks.Parallel.ForEachAsync(uploadFiles, ParallelConfig.Options, async (file, ct) =>
{
Interlocked.Increment(ref queued);
if (string.IsNullOrEmpty(file.CheckSum) && !file.TryGenerateCheckSum()) return;
if (!file.TryGenerateCheckSum()) return;

SemaphoreSlim lockedThread = threadPool.GetOrAdd(file.CheckSum!, _ => new SemaphoreSlim(1, 1));
await lockedThread.WaitAsync(ct);

try
{
Log.Debug($"Pushing -> {file.LocalPath}");
file.RemotePath = PathBuilder.GetObjectPath(RemoteVault, file.CheckSum!);
long result = await StorageProvider.UploadFileAsync(file, false, ct);
long result = await StorageProvider.UploadFileAsync(file, overwrite, ct);
if (result <= 0)
{
progress.Failed(new InvalidOperationException(), file);
Expand Down Expand Up @@ -103,7 +104,8 @@ public override async Task<int> PullFilesAsync(SystemFile[] files, IProgressRepo
Task worker = System.Threading.Tasks.Parallel.ForEachAsync(files, ParallelConfig.Options, async (file, ct) =>
{
Interlocked.Increment(ref queued);
if (string.IsNullOrEmpty(file.CheckSum) && !file.TryGenerateCheckSum()) return;
if (!file.TryGenerateCheckSum()) return;

SemaphoreSlim lockedThread = threadPool.GetOrAdd(file.CheckSum!, _ => new SemaphoreSlim(1, 1));
await lockedThread.WaitAsync(ct);

Expand Down
4 changes: 2 additions & 2 deletions Parallel.Core/IO/Syncing/ISyncManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ public interface ISyncManager
/// Pushes an array of files to a vault.
/// </summary>
/// <param name="files"></param>
/// <param name="force"></param>
/// <param name="progress"></param>
Task<int> PushFilesAsync(SystemFile[] files, IProgressReporter progress);
/// <param name="overwrite"></param>
Task<int> PushFilesAsync(SystemFile[] files, IProgressReporter progress, bool overwrite);

/// <summary>
/// Pulls an array of files from a vault.
Expand Down
4 changes: 1 addition & 3 deletions Parallel.Core/Models/SystemFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,17 +174,15 @@ public bool TryGenerateCheckSum()

try
{
Log.Debug($"Generating checksum -> {LocalPath}");
if (!File.Exists(LocalPath)) return false;

using SHA256 sha256 = SHA256.Create();
using FileStream fs = File.OpenRead(LocalPath);
CheckSum = Convert.ToHexStringLower(sha256.ComputeHash(fs));
return !string.IsNullOrEmpty(CheckSum);
}
catch (Exception ex)
{
Log.Error(ex, $"Checksum generation failed -> {LocalPath}");
Log.Error(ex.GetBaseException().ToString());
return false;
}
}
Expand Down