void AddToCaches(string key, byte[] buffer, long commit)
        {
            var record = new DataWithKey(key, buffer, commit, _all.Length);

            _all = ImmutableAdd(_all, new DataWithKey(key, buffer, commit, _all.Length));
            _items.AddOrUpdate(key, s => new[] { record }, (s, records) => ImmutableAdd(records, record));
        }
        void AddToCaches(string key, byte[] buffer, long commit)
        {
            var record = new DataWithKey(key, buffer, commit, _all.Count());

            _all = AddToNewArray(_all, new DataWithKey(key, buffer, commit, _all.Count() + 1));
            _items.AddOrUpdate(key, s => new[] { record }, (s, records) => AddToNewArray(records, record));
        }
Esempio n. 3
0
        public void LoadHistory(IEnumerable <StorageFrameDecoded> sfd)
        {
            _thread.EnterWriteLock();
            try
            {
                if (StoreVersion != 0)
                {
                    throw new InvalidOperationException("Must clear cache before loading history");
                }

                _cacheFull = new DataWithKey[0];

                // [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 List <DataWithKey>();
                var streamPointerBuilder = new Dictionary <string, List <DataWithKey> >();

                long newStoreVersion = 0;
                foreach (var record in sfd)
                {
                    List <DataWithKey> list;
                    if (!streamPointerBuilder.TryGetValue(record.Name, out list))
                    {
                        streamPointerBuilder.Add(record.Name, list = new List <DataWithKey>());
                    }

                    newStoreVersion += 1;
                    var newStreamVersion = list.Count + 1;

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

                _cacheFull = cacheFullBuilder.ToArray();
                var pairs = streamPointerBuilder.Select(p => new KeyValuePair <string, DataWithKey[]>(p.Key, p.Value.ToArray()));
                _cacheByKey  = new ConcurrentDictionary <string, DataWithKey[]>(pairs);
                StoreVersion = newStoreVersion;
            }
            finally
            {
                _thread.ExitWriteLock();
            }
        }
Esempio n. 4
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();
            }
        }