public IReadOnlyList <FileDiff> compare(IReadOnlyList <FreezeFile> local, IReadOnlyList <FreezeFile> provider) { List <FileDiff> files = new List <FileDiff>(); maxTasks = IOUtils.DefaultTasks(maxTasks); var dels = from pf in provider where local.Where((x) => string.Compare(x.path, pf.path, true) == 0).Any() == false select new FileDiff { local = null, remote = pf, type = DiffType.deleted }; files.AddRange(dels); var creates = from lf in local where provider.Where((x) => string.Compare(x.path, lf.path, true) == 0).Any() == false select new FileDiff { local = lf, remote = null, type = DiffType.created }; files.AddRange(creates); IEnumerable <FileDiff> updates = null; if (usehash) { var lst = from lf in local join pf in provider on lf.path equals pf.path select new FileDiff { local = lf, remote = pf }; byte[] keyfile; { var kt = new MemoryStream(); var fs = new FileStream(privateKey, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); var len = BUCommon.IOUtils.WriteStream(fs, kt).Result; fs.Close(); fs.Dispose(); fs = null; keyfile = kt.ToArray(); } var tasks = Parallel.ForEach(lst , new ParallelOptions { MaxDegreeOfParallelism = maxTasks } , () => { var sr = new StreamReader(new MemoryStream(keyfile, 0, keyfile.Length, false, false)); var rsa = KeyLoader.LoadRSAKey(sr); var fe1 = new FileEncrypt(rsa); sr = null; return(new DiffProcessor.TLocalData { fe = fe1, auth = null }); } , (x, pls, tl) => { if (string.IsNullOrWhiteSpace(x.remote.enchash)) { x.type = x.local.modified > x.remote.uploaded ? DiffType.updated : DiffType.same; } else { x.type = DiffType.same; var fstream = x.local.readStream(pathRoot); var hash = tl.fe.hashContents("SHA1", fstream); var bytes = Convert.FromBase64String(x.remote.enchash); var rhash = tl.fe.decBytes(bytes); for (int i = 0; i < hash.raw.Length; ++i) { if (hash.raw[i] != rhash[i]) { x.type = DiffType.updated; break; } } } return(tl); } , (tl) => { tl.fe = null; } ); } else { updates = from lf in local join pf in provider on lf.path equals pf.path where lf.modified > pf.uploaded select new FileDiff { local = lf, remote = pf, type = DiffType.updated }; } files.AddRange(updates); return(files); }
public void run() { byte[] keyfile; { var kt = new MemoryStream(); var fs = new FileStream(encKey, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); var len = BUCommon.IOUtils.WriteStream(fs, kt).Result; fs.Close(); fs.Dispose(); fs = null; keyfile = kt.ToArray(); } if (maxTasks <= 0 || maxTasks > 100) { maxTasks = 0; } if (noAction) { maxTasks = 1; runType = RunType.none; } var service = account.service; var cache = service.fileCache; var tasks = Parallel.ForEach(_diffs , new ParallelOptions { MaxDegreeOfParallelism = maxTasks } , () => { var sr = new StreamReader(new MemoryStream(keyfile, 0, keyfile.Length, false, false)); var rsa = KeyLoader.LoadRSAKey(sr); var fe1 = new FileEncrypt(rsa); sr = null; object td = null; if (!noAction) { td = service.threadStart(); } return(new TLocalData { fe = fe1, auth = td }); } , (x, pls, tl) => { progressHandler?.Invoke(x); string path = string.Empty; FileStream filestrm = null; try { switch (runType) { case RunType.upload: { path = x.local.path.Replace('/', Path.DirectorySeparatorChar); path = Path.Combine(root, path); switch (x.type) { case DiffType.deleted: { service.delete(x.remote); lock (cache) { cache.delete(x.remote); } break; } case DiffType.created: case DiffType.updated: { filestrm = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete); var hash = tl.fe.hashContents(filestrm); /* since we're reading anyways, populate the file hash. */ x.local.localHash = hash; var memstrm = tl.fe.encrypt(filestrm); memstrm.Seek(0, System.IO.SeekOrigin.Begin); x.local.localHash = tl.fe.hashContents("SHA1", memstrm); memstrm.Seek(0, System.IO.SeekOrigin.Begin); byte[] buf = tl.fe.encBytes(x.local.localHash.raw); var b64 = Convert.ToBase64String(buf); var ff = service.uploadFile(tl.auth, container, x.local, memstrm, b64); memstrm.Dispose(); memstrm = null; if (ff == null) { errorHandler?.Invoke(x, new Exception("Failed to proces!")); } else { ff.localHash = x.local.localHash; lock (cache) { cache.add(x.local); cache.add(ff); } } break; } } break; } case RunType.download: { if (x.type == DiffType.created || x.type == DiffType.updated) { /* this really needs to check to see if we need to download it. * that will make it resumeable. */ path = Path.Combine(root, x.remote.path.Replace('/', Path.DirectorySeparatorChar)); { /* need to make sure the download directory parts exist before we download and save the file. */ var pathfname = Path.GetFileName(path); var pathpart = path.Substring(0, path.Length - pathfname.Length); System.IO.Directory.CreateDirectory(pathpart); } var strm = service.downloadFile(tl.auth, x.remote); filestrm = new FileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite | FileShare.Delete); tl.fe.decrypt(strm, filestrm); strm.Dispose(); strm = null; var hash = tl.fe.hashContents(filestrm); x.remote.localHash = hash; lock (cache) { cache.add(x.remote); } filestrm.Close(); filestrm.Dispose(); filestrm = null; } break; } case RunType.none: { break; } } } catch (Exception e) { errorHandler?.Invoke(x, e); pls.Stop(); throw new ArgumentException(string.Format("Error processing file diff item. {0} - {1}", x.type , (x.local != null ? x.local.path : x.remote.path)) , e); } return(tl); } , x => { if (!noAction) { service.threadStop(x.auth); } } ); _diffs.Clear(); }