private string GetItemContentFilePath(PersistentStorageItemId id)
        {
            var fileName         = id.ToString();
            var subDirectoryName = fileName.Substring(0, 2);

            return(Path.Combine(this.path, subDirectoryName, fileName));
        }
Esempio n. 2
0
            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));
 }