public ObjectId ComputeFileHash(string filePath) { var inputVersionKey = new FileVersionKey(filePath); storage.LoadNewValues(); // Perform a lock per file as it can be expensive to compute // them at the same time (for large file) object versionLock; lock (locks) { if (!locks.TryGetValue(inputVersionKey, out versionLock)) { versionLock = new object(); locks.Add(inputVersionKey, versionLock); } } var hash = ObjectId.Empty; lock (versionLock) { if (!storage.TryGetValue(inputVersionKey, out hash)) { // TODO: we might want to allow retries, timeout, etc. since file processed here are files currently being edited by user try { using (var fileStream = File.OpenRead(filePath)) using (var stream = new DigestStream(Stream.Null)) { fileStream.CopyTo(stream); hash = stream.CurrentHash; } } catch (Exception ex) { log.Debug($"Cannot calculate hash for file [{filePath}]", ex); } storage[inputVersionKey] = hash; } } return(hash); }
/// <summary> /// Compacts the specified storage path. /// </summary> /// <param name="storagePath">The storage path.</param> /// <returns><c>true</c> if the storage path was successfully compacted, <c>false</c> otherwise.</returns> public static bool Compact(string storagePath) { FileStream fileStreamExclusive; try { fileStreamExclusive = new FileStream(storagePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None); } catch (Exception) { return(false); } try { using (var localTracker = new FileVersionStorage(fileStreamExclusive) { UseTransaction = true, AutoLoadNewValues = false }) { localTracker.LoadNewValues(); var latestVersion = new Dictionary <string, KeyValuePair <FileVersionKey, ObjectId> >(StringComparer.OrdinalIgnoreCase); foreach (var keyValue in localTracker.GetValues()) { var filePath = keyValue.Key.Path; KeyValuePair <FileVersionKey, ObjectId> previousKeyValue; if (!latestVersion.TryGetValue(filePath, out previousKeyValue) || keyValue.Key.LastModifiedDate > previousKeyValue.Key.LastModifiedDate) { latestVersion[filePath] = keyValue; } } localTracker.Reset(); localTracker.AddValues(latestVersion.Values); localTracker.Save(); } } catch (Exception) { return(false); } return(true); }