Exemplo n.º 1
0
        public void ConcurrentAppend(string streamName, byte[] data, OnCommit commit, long expectedStreamVersion = -1)
        {
            _thread.EnterWriteLock();

            try
            {
                var list = _cacheByKey.GetOrAdd(streamName, s => new DataWithKey[0]);
                var actualStreamVersion = list.Length;

                if (expectedStreamVersion >= 0)
                {
                    if (actualStreamVersion != expectedStreamVersion)
                    {
                        throw new AppendOnlyStoreConcurrencyException(expectedStreamVersion, actualStreamVersion, streamName);
                    }
                }
                long newStreamVersion = actualStreamVersion + 1;
                long newStoreVersion  = StoreVersion + 1;

                commit(newStreamVersion, newStoreVersion);

                // update in-memory cache only after real commit completed


                var dataWithKey = new DataWithKey(streamName, data, newStreamVersion, newStoreVersion);
                _cacheFull = ImmutableAdd(_cacheFull, dataWithKey);
                _cacheByKey.AddOrUpdate(streamName, s => new[] { dataWithKey }, (s, records) => ImmutableAdd(records, dataWithKey));
                StoreVersion = newStoreVersion;
            }
            finally
            {
                _thread.ExitWriteLock();
            }
        }
Exemplo n.º 2
0
        public void LoadHistory(IEnumerable <StorageFrameDecoded> sfd)
        {
            this._thread.EnterWriteLock();
            try
            {
                if (this.StoreVersion != 0)
                {
                    throw new InvalidOperationException("Must clear cache before loading history");
                }

                this._cacheFull = new Dictionary <long, DataWithKey>();

                // [abdullin]: known performance problem identified by Nicolas Mehlei
                // creating new immutable array on each line will kill performance
                // We need to at least do some batching here

                var cacheFullBuilder     = new Dictionary <long, DataWithKey>();
                var streamPointerBuilder = new Dictionary <string, List <DataWithKey> >();

                long newStoreVersion = 0;
                foreach (var record in sfd)
                {
                    newStoreVersion += 1;

                    if (record.Name == "audit" || record.Name == "func")
                    {
                        continue;
                    }

                    List <DataWithKey> list;
                    if (!streamPointerBuilder.TryGetValue(record.Name, out list))
                    {
                        streamPointerBuilder.Add(record.Name, list = new List <DataWithKey>());
                    }

                    var newStreamVersion = list.Count + 1;

                    var data = new DataWithKey(record.Name, record.Bytes, newStreamVersion, newStoreVersion);
                    list.Add(data);
                    cacheFullBuilder.Add(data.StoreVersion, data);
                }

                this._cacheFull   = cacheFullBuilder;
                this._cacheByKey  = new ConcurrentDictionary <string, List <DataWithKey> >(streamPointerBuilder.Select(p => new KeyValuePair <string, List <DataWithKey> >(p.Key, p.Value)));
                this.StoreVersion = newStoreVersion;
            }
            finally
            {
                this._thread.ExitWriteLock();
            }
        }
Exemplo n.º 3
0
        public void ConcurrentAppend(string streamName, byte[] data, OnCommit commit, long expectedStreamVersion = -1)
        {
            this._thread.EnterWriteLock();

            try
            {
                var list = this._cacheByKey.GetOrAdd(streamName, s => new List <DataWithKey>());
                var actualStreamVersion = list.Count;

                if (expectedStreamVersion >= 0)
                {
                    if (actualStreamVersion != expectedStreamVersion)
                    {
                        throw new AppendOnlyStoreConcurrencyException(expectedStreamVersion, actualStreamVersion, streamName);
                    }
                }
                long newStreamVersion = actualStreamVersion + 1;
                var  newStoreVersion  = this.StoreVersion + 1;

                commit(newStreamVersion, newStoreVersion);

                // update in-memory cache only after real commit completed
                if (streamName != "audit" && streamName != "func")
                {
                    var dataWithKey = new DataWithKey(streamName, data, newStreamVersion, newStoreVersion);
                    this._cacheFull.Add(newStoreVersion, dataWithKey);
                    this._cacheByKey.GetOrAdd(streamName, s => new List <DataWithKey> {
                        dataWithKey
                    }).Add(dataWithKey);
                }
                this.StoreVersion = newStoreVersion;
            }
            finally
            {
                this._thread.ExitWriteLock();
            }
        }