private string GetItemContentFilePath(PersistentStorageItemId id) { var fileName = id.ToString(); var subDirectoryName = fileName.Substring(0, 2); return(Path.Combine(this.path, subDirectoryName, fileName)); }
public Item(FileSystemBasedPersistentStorage storage, PersistentStorageItemId id) { Debug.Assert(storage != null); this.storage = storage; this.id = id; }
public Item(PersistentStorageItemId id, byte[] content) { Debug.Assert(content != null); this.content = content; this.id = id; }
/// <inheritdoc/> /// <exception cref="FileSystemBasedPersistentStorageException"> /// The item with the specified ID does not exist in this storage. /// </exception> public Task <IPersistentStorageItem> GetItemAsync(PersistentStorageItemId id) { if (this.HasItem(id)) { return(Task.FromResult <IPersistentStorageItem>(new Item(this, id))); } else { throw new FileSystemBasedPersistentStorageException($"Item `{id}` does not exist."); } }
/// <inheritdoc/> /// <exception cref="InMemoryPersistentStorageException"> /// The item with the specified ID does not exist in this storage. /// </exception> public Task <IPersistentStorageItem> GetItemAsync(PersistentStorageItemId id) { if (this.items.TryGetValue(id, out var item)) { return(Task.FromResult <IPersistentStorageItem>(item)); } else { throw new InMemoryPersistentStorageException($"Item `{id}` does not exist."); } }
/// <inheritdoc/> /// <exception cref="ArgumentNullException"> /// <paramref name="writeContentAsync"/> is <see langword="null"/>. /// </exception> /// <exception cref="InMemoryPersistentStorageException"> /// The item could not be created, or the item's ID could not be computed from the specified content. /// </exception> public async Task <IPersistentStorageItem> CreateOrGetItemAsync(Func <Stream, Task> writeContentAsync) { if (writeContentAsync == null) { throw new ArgumentNullException(nameof(writeContentAsync)); } PersistentStorageItemId id; using (var sha = SHA1.Create()) using (var buffer = new MemoryStream()) using (var cryptoStream = new CryptoStream(buffer, sha, CryptoStreamMode.Write)) { try { await writeContentAsync(cryptoStream); await cryptoStream.FlushAsync(); if (!cryptoStream.HasFlushedFinalBlock) { cryptoStream.FlushFinalBlock(); } } catch (Exception ex) { throw new InMemoryPersistentStorageException("Could not write item content.", ex); } try { id = new PersistentStorageItemId(sha.Hash); } catch (Exception ex) { throw new InMemoryPersistentStorageException("Could not compute identity from item content.", ex); } if (this.items.TryGetValue(id, out var item) == false) { if (buffer.TryGetBuffer(out var contentBytes) == false) { throw new InMemoryPersistentStorageException("Could not compute identity from item content."); } var content = new byte[contentBytes.Count]; Array.Copy(contentBytes.Array, contentBytes.Offset, content, 0, contentBytes.Count); item = new Item(id, content); this.items[id] = item; } return(item); } }
/// <inheritdoc/> /// <exception cref="ArgumentNullException"> /// <paramref name="writeContentAsync"/> is <see langword="null"/>. /// </exception> /// <exception cref="FileSystemBasedPersistentStorageException"> /// The item could not be created, or the item's ID could not be computed from the specified content. /// </exception> public async Task <IPersistentStorageItem> CreateOrGetItemAsync(Func <Stream, Task> writeContentAsync) { if (writeContentAsync == null) { throw new ArgumentNullException(nameof(writeContentAsync)); } var temporaryFilePath = Path.GetTempFileName(); try { PersistentStorageItemId id; using (var sha = SHA1.Create()) using (var temporaryFile = File.Open(temporaryFilePath, FileMode.Create, FileAccess.Write, FileShare.None)) using (var cryptoStream = new CryptoStream(temporaryFile, sha, CryptoStreamMode.Write)) { try { await writeContentAsync(cryptoStream); await cryptoStream.FlushAsync(); if (!cryptoStream.HasFlushedFinalBlock) { cryptoStream.FlushFinalBlock(); } } catch (Exception ex) { throw new FileSystemBasedPersistentStorageException("Could not write item content.", ex); } try { id = new PersistentStorageItemId(sha.Hash); } catch (Exception ex) { throw new FileSystemBasedPersistentStorageException("Could not compute identity from item content.", ex); } } var contentFilePath = this.GetItemContentFilePath(id); if (!File.Exists(contentFilePath)) { var contentDirectoryPath = Path.GetDirectoryName(contentFilePath); if (!Directory.Exists(contentDirectoryPath)) { try { Directory.CreateDirectory(contentDirectoryPath); } catch (Exception ex) { throw new FileSystemBasedPersistentStorageException($"Could not create subdirectory for new item `{id}`.", ex); } } try { File.Move(temporaryFilePath, contentFilePath); } catch (Exception ex) { throw new FileSystemBasedPersistentStorageException($"Could not create file for new item `{id}`.", ex); } } return(new Item(this, id)); } finally { File.Delete(temporaryFilePath); } }
/// <inheritdoc/> public bool HasItem(PersistentStorageItemId id) { return(File.Exists(this.GetItemContentFilePath(id))); }
/// <inheritdoc/> public bool HasItem(PersistentStorageItemId id) { return(this.items.ContainsKey(id)); }