示例#1
0
        public TEntity AddOrUpdate(TKey key, Func <TEntity> addFactory, Func <TEntity, TEntity> update, AddOrUpdateHint hint = AddOrUpdateHint.ProbablyExists)
        {
            var result = default(TEntity);

            // Adds a key/value pair to the ConcurrentDictionary<TKey, TEnitity> if the key does not exist,
            // or updates a key/value pair in the ConcurrentDictionary<TKey, TEntity> if the key already exists.
            _store.AddOrUpdate(GetName(key), s =>
            {
                result = addFactory();
                using (var memory = new MemoryStream())
                {
                    _strategy.Serialize(result, memory);
                    return(memory.ToArray());
                }
            }, (s, bytes) =>
            {
                TEntity entity;
                using (var memory = new MemoryStream(bytes))
                {
                    entity = _strategy.Deserialize <TEntity>(memory);
                }
                result = update(entity);
                using (var memory = new MemoryStream())
                {
                    _strategy.Serialize(result, memory);
                    return(memory.ToArray());
                }
            });
            return(result);
        }
        public TEntity AddOrUpdate(TKey key, Func <TEntity> addFactory, Func <TEntity, TEntity> update, AddOrUpdateHint hint)
        {
            var result = default(TEntity);

            _store.AddOrUpdate(GetName(key), s =>
            {
                result = addFactory();
                using (var memory = new MemoryStream())
                {
                    _strategy.Serialize(result, memory);
                    return(memory.ToArray());
                }
            }, (s2, bytes) =>
            {
                TEntity entity;
                using (var memory = new MemoryStream(bytes))
                {
                    entity = _strategy.Deserialize <TEntity>(memory);
                }
                result = update(entity);
                using (var memory = new MemoryStream())
                {
                    _strategy.Serialize(result, memory);
                    return(memory.ToArray());
                }
            });
            return(result);
        }
示例#3
0
        public TEntity AddOrUpdate(TKey key, Func <TEntity> addViewFactory, Func <TEntity, TEntity> updateViewFactory,
                                   AddOrUpdateHint hint)
        {
            string  etag = null;
            var     blob = GetBlobReference(key);
            TEntity view;

            try
            {
                // atomic entities should be small, so we can use the simple method
                var bytes = blob.DownloadByteArray();
                using (var stream = new MemoryStream(bytes))
                {
                    view = _strategy.Deserialize <TEntity>(stream);
                }

                view = updateViewFactory(view);
                etag = blob.Attributes.Properties.ETag;
            }
            catch (StorageClientException ex)
            {
                switch (ex.ErrorCode)
                {
                case StorageErrorCode.ContainerNotFound:
                    var s = string.Format(
                        "Container '{0}' does not exist. You need to initialize this atomic storage and ensure that '{1}' is known to '{2}'.",
                        blob.Container.Name, typeof(TEntity).Name, _strategy.GetType().Name);
                    throw new InvalidOperationException(s, ex);

                case StorageErrorCode.BlobNotFound:
                case StorageErrorCode.ResourceNotFound:
                    view = addViewFactory();
                    break;

                default:
                    throw;
                }
            }
            // atomic entities should be small, so we can use the simple method
            // http://toolheaven.net/post/Azure-and-blob-write-performance.aspx
            using (var memory = new MemoryStream())
            {
                _strategy.Serialize(view, memory);
                // note that upload from stream does weird things
                var bro = etag != null
                    ? new BlobRequestOptions {
                    AccessCondition = AccessCondition.IfMatch(etag)
                }
                    : new BlobRequestOptions {
                    AccessCondition = AccessCondition.IfNoneMatch("*")
                };


                // make sure that upload is not rejected due to cashed content MD5
                // http://social.msdn.microsoft.com/Forums/hu-HU/windowsazuredata/thread/4764e38f-b200-4efe-ada2-7de442dc4452
                blob.Properties.ContentMD5 = null;
                blob.UploadByteArray(memory.ToArray(), bro);
            }
            return(view);
        }
        public TEntity AddOrUpdate(TKey key, Func <TEntity> addFactory, Func <TEntity, TEntity> update,
                                   AddOrUpdateHint hint)
        {
            var name = 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))
                {
                    TEntity result;
                    if (file.Length == 0)
                    {
                        result = addFactory();
                    }
                    else
                    {
                        using (var mem = new MemoryStream())
                        {
                            file.CopyTo(mem);
                            mem.Seek(0, SeekOrigin.Begin);
                            var entity = _strategy.Deserialize <TEntity>(mem);
                            result = update(entity);
                        }
                    }

                    // some serializers have nasty habbit of closing the
                    // underling stream
                    using (var mem = new MemoryStream())
                    {
                        _strategy.Serialize(result, mem);
                        var data = mem.ToArray();
                        file.Seek(0, SeekOrigin.Begin);
                        file.Write(data, 0, data.Length);
                        // truncate this file
                        file.SetLength(data.Length);
                    }

                    return(result);
                }
            }
            catch (DirectoryNotFoundException)
            {
                var s = string.Format(
                    "Container '{0}' does not exist.",
                    _folder);
                throw new InvalidOperationException(s);
            }
        }
        public TEntity AddOrUpdate(TKey key, Func <TEntity> addFactory, Func <TEntity, TEntity> update, AddOrUpdateHint hint)
        {
            var name = GetName(key);

            try
            {
                var subfolder = Path.GetDirectoryName(name);
                if (subfolder != null && !Directory.Exists(subfolder))
                {
                    Directory.CreateDirectory(subfolder);
                }

                // we are locking the file.
                using (var file = File.Open(name, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None))
                {
                    byte[]  initial = new byte[0];
                    TEntity result;
                    if (file.Length == 0)
                    {
                        result = addFactory();
                    }
                    else
                    {
                        using (var mem = new MemoryStream())
                        {
                            file.CopyTo(mem);
                            mem.Seek(0, SeekOrigin.Begin);
                            var entity = _strategy.Deserialize <TEntity>(mem);
                            initial = mem.ToArray();
                            result  = update(entity);
                        }
                    }


                    using (var mem = new MemoryStream())
                    {
                        _strategy.Serialize(result, mem);
                        var data = mem.ToArray();

                        if (!data.SequenceEqual(initial))
                        {
                            // upload only if we changed
                            file.Seek(0, SeekOrigin.Begin);
                            file.Write(data, 0, data.Length);
                            // truncate this file
                            file.SetLength(data.Length);
                        }
                    }

                    return(result);
                }
            }
            catch (FileNotFoundException)
            {
                var s = string.Format("File '{0}' does not exist.", name);
                throw new InvalidOperationException(s);
            }
            catch (DirectoryNotFoundException)
            {
                var s = string.Format("Container '{0}' does not exist.", _folder);
                throw new InvalidOperationException(s);
            }
            catch (IOException) // fix for fast read / slow write concurency
            {
                _log.WriteLine("File write failed for {0} - {1} with key {2}. Will retry.", _folder, name, key);
                Thread.Sleep(120);
                return(AddOrUpdate(key, addFactory, update, hint));
            }
        }