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)); }
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(); } }
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(); } }