private static void CheckState(string baseDir, string syncDbDir, SyncDatabase syncDb) { var localFiles = Directory.GetFiles(baseDir, "*", SearchOption.AllDirectories).ToList(); var dbDirInBase = syncDbDir.StartsWith(baseDir); foreach (var stored in syncDb.Files) { var localFilePath = Path.Combine(baseDir, stored.RelativePath); var localFileIdx = localFiles.IndexOf(localFilePath); if (localFileIdx < 0) { stored.State = SyncFileState.Deleted; } else { var localFile = localFiles[localFileIdx]; localFiles.RemoveAt(localFileIdx); { var hash = NetworkHelperSequential.HashFileAsync(new FileInfo(localFile)).Result; var localFileHash = hash.ToHashString(); if (localFileHash != stored.HashStr) { stored.State = SyncFileState.Modified; stored.HashStr = localFileHash; } } } } var localInfos = localFiles.Select(localFile => { if (dbDirInBase && localFile.StartsWith(syncDbDir)) { return(null); } var localFileRelativePath = localFile.Replace(baseDir, string.Empty); { var hash = NetworkHelperSequential.HashFileAsync(new FileInfo(localFile)).Result; return(new SyncFileInfo { HashStr = hash.ToHashString(), RelativePath = localFileRelativePath.TrimStart(Path.DirectorySeparatorChar), AbsolutePath = localFile, State = SyncFileState.New, }); } }).Where(i => i != null).ToList(); syncDb.Files.AddRange(localInfos); }
private SyncDatabase GetSyncDb(string baseDir, string syncDbDir, out string error) { error = null; var syncDb = SyncDatabase.Get(baseDir, syncDbDir); if (syncDb == null) { syncDb = SyncDatabase.Initialize(baseDir, syncDbDir); if (syncDb != null) { return(syncDb); } error = "Unable to create sync database."; return(null); } CheckState(baseDir, syncDbDir, syncDb); return(syncDb); }
private async Task <bool> ReceiveFiles(Stream networkStream, IEnumerable <SyncFileInfo> dataToDownload, SyncDatabase syncDb) { foreach (var fileInfo in dataToDownload) { var data = new GetFileCommandData { SessionId = _sessionId, RelativeFilePath = fileInfo.RelativePath, }; var dataBytes = Serializer.Serialize(data); await NetworkHelperSequential.WriteCommandHeader(networkStream, Commands.GetFileCmd, dataBytes.Length); await NetworkHelperSequential.WriteBytes(networkStream, dataBytes); var cmdHeader = await NetworkHelperSequential.ReadCommandHeader(networkStream); if (cmdHeader.Command != Commands.GetFileCmd) { return(false); } if (cmdHeader.PayloadLength == 0) { return(false); } var fileLengthBytes = await NetworkHelperSequential.ReadBytes(networkStream, cmdHeader.PayloadLength); var fileLength = BitConverter.ToInt64(fileLengthBytes, 0); var tmpFilePath = Path.Combine(_newDir, fileInfo.RelativePath); var newHash = await NetworkHelperSequential.ReadToFileAndHashAsync(networkStream, tmpFilePath, (int)fileLength); if (!string.Equals(newHash.ToHashString(), fileInfo.HashStr, StringComparison.OrdinalIgnoreCase)) { throw new InvalidOperationException("File copy error: hash mismatch"); } _sessionFileHelper.AddNew(fileInfo.RelativePath); var fi = syncDb.Files.FirstOrDefault(x => x.RelativePath == fileInfo.RelativePath); if (fi == null) { fi = new SyncFileInfo { RelativePath = fileInfo.RelativePath, }; syncDb.Files.Add(fi); } fi.HashStr = newHash.ToHashString(); fi.State = SyncFileState.NotChanged; } return(true); }
private async Task <bool> SendFiles(NetworkStream networkStream, List <SyncFileInfo> dataToUpload, SyncDatabase syncDb) { foreach (var fileInfo in dataToUpload) { var filePath = Path.Combine(_baseDir, fileInfo.RelativePath); var fileLength = new FileInfo(filePath).Length; var data = new SendFileCommandData { FileLength = fileLength, SessionId = _sessionId, RelativeFilePath = fileInfo.RelativePath, HashStr = syncDb.Files.First(x => x.RelativePath == fileInfo.RelativePath).HashStr, }; var dataBytes = Serializer.Serialize(data); await NetworkHelperSequential.WriteCommandHeader(networkStream, Commands.SendFileCmd, dataBytes.Length); await NetworkHelperSequential.WriteBytes(networkStream, dataBytes); await NetworkHelperSequential.WriteFromFileAndHashAsync(networkStream, filePath, (int)fileLength); } return(true); }