コード例 #1
0
        public async Task <Maybe <TEntity> > GetAsync(TKey key)
        {
            try
            {
                var name = this.GetName(key);
                StorageProfiler.CountReadRequest(name);

                if (!File.Exists(name))
                {
                    return(Maybe <TEntity> .Empty);
                }

                using (var fs = new FileStream(name, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.Asynchronous))
                {
                    if (fs.Length == 0)
                    {
                        return(Maybe <TEntity> .Empty);
                    }

                    var bytes     = new byte[fs.Length];
                    var readBytes = await fs.ReadAsync(bytes, 0, bytes.Length).ConfigureAwait(false);

                    if (readBytes != bytes.Length)
                    {
                        throw new IOException("Not all bytes were read async. Need to implement better async reader.");
                    }

                    using (var ms = new MemoryStream(bytes))
                        return(this._strategy.Deserialize <TEntity>(ms));
                }
            }
            catch (FileNotFoundException)
            {
                // if file happened to be deleted between the moment of check and actual read.
                return(Maybe <TEntity> .Empty);
            }
            catch (DirectoryNotFoundException)
            {
                return(Maybe <TEntity> .Empty);
            }
        }
コード例 #2
0
        public async Task SaveAsync(TKey key, TEntity entity)
        {
            var name = this.GetName(key);

            try
            {
                // This is fast and allows to have git-style subfolders in atomic strategy
                // to avoid NTFS performance degradation (when there are more than
                // 10000 files per folder). Kudos to Gabriel Schenker for pointing this out
                var subfolder = Path.GetDirectoryName(name);
                if (subfolder != null && !Directory.Exists(subfolder))
                {
                    Directory.CreateDirectory(subfolder);
                }

                // we are locking this file.
                using (var file = File.Open(name, FileMode.Create, FileAccess.ReadWrite, FileShare.None))
                    // some serializers have nasty habbit of closing the
                    // underling stream
                    using (var mem = new MemoryStream())
                    {
                        this._strategy.Serialize(entity, mem);
                        var data = mem.ToArray();

                        StorageProfiler.CountWriteRequest(name);
                        // upload only if we changed
                        await file.WriteAsync(data, 0, data.Length);

                        // truncate this file
                        file.SetLength(data.Length);
                    }
            }
            catch (DirectoryNotFoundException)
            {
                var s = string.Format(
                    "Container '{0}' does not exist.",
                    this._folder);
                throw new InvalidOperationException(s);
            }
        }
コード例 #3
0
        public bool TryGet(TKey key, out TEntity view)
        {
            view = default(TEntity);
            try
            {
                var name = this.GetName(key);
                StorageProfiler.CountReadRequest(name);

                if (!File.Exists(name))
                {
                    return(false);
                }

                using (var stream = RetryPolicies.GetPolicy.Get(() => File.Open(name, FileMode.Open, FileAccess.Read, FileShare.Read)))
                {
                    if (stream.Length == 0)
                    {
                        return(false);
                    }
                    view = this._strategy.Deserialize <TEntity>(stream);
                    return(true);
                }
            }
            catch (FileNotFoundException)
            {
                // if file happened to be deleted between the moment of check and actual read.
                return(false);
            }
            catch (DirectoryNotFoundException)
            {
                return(false);
            }
            catch (IOException)
            {
                return(false);
            }
        }
コード例 #4
0
        public async Task <TEntity> AddOrUpdateAsync(TKey key, Func <TEntity> addFactory, Func <TEntity, TEntity> update, AddOrUpdateHint hint = AddOrUpdateHint.ProbablyExists)
        {
            var name = this.GetName(key);

            try
            {
                // This is fast and allows to have git-style subfolders in atomic strategy
                // to avoid NTFS performance degradation (when there are more than
                // 10000 files per folder). Kudos to Gabriel Schenker for pointing this out
                var subfolder = Path.GetDirectoryName(name);
                if (subfolder != null && !Directory.Exists(subfolder))
                {
                    Directory.CreateDirectory(subfolder);
                }

                // we are locking this file.
                using (var file = File.Open(name, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None))
                {
                    var     initial = new byte[0];
                    TEntity result;
                    if (file.Length == 0)
                    {
                        result = addFactory();
                    }
                    else
                    {
                        using (var mem = new MemoryStream())
                        {
                            StorageProfiler.CountReadRequest(name);
                            await file.CopyToAsync(mem);

                            mem.Seek(0, SeekOrigin.Begin);
                            var entity = this._strategy.Deserialize <TEntity>(mem);
                            initial = mem.ToArray();
                            result  = update(entity);
                        }
                    }

                    // some serializers have nasty habbit of closing the
                    // underling stream
                    using (var mem = new MemoryStream())
                    {
                        this._strategy.Serialize(result, mem);
                        var data = mem.ToArray();

                        if (!data.SequenceEqual(initial))
                        {
                            StorageProfiler.CountWriteRequest(name);

                            // upload only if we changed
                            file.Seek(0, SeekOrigin.Begin);
                            await file.WriteAsync(data, 0, data.Length);

                            // truncate this file
                            file.SetLength(data.Length);
                        }
                    }

                    return(result);
                }
            }
            catch (DirectoryNotFoundException)
            {
                var s = string.Format(
                    "Container '{0}' does not exist.",
                    this._folder);
                throw new InvalidOperationException(s);
            }
        }