private async Task AppendInternalAsync(PendingWrite mine) { using (await _asyncLock.LockAsync()) { var completed = new List<PendingWrite>(); try { if (mine.Done()) return; await MakeRoomForWrite(mine.Stream.Length, mine.Etag); var seq = _options.Status.NextSeqeunce(); var room = _currentBufferSize - _memTable.MemTable.ApproximateMemoryUsage; PendingWrite write; while (_pending.TryDequeue(out write)) { var memoryHandle = _memTable.MemTable.Write(write.Stream); await _memTable.Log.Write7BitEncodedIntAsync(memoryHandle.Size); using (var stream = _memTable.MemTable.Read(memoryHandle)) { await _memTable.Log.CopyFromAsync(stream); } _memTable.MemTable.Add(seq, ItemType.Value, EtagToSlice(write.Etag), memoryHandle); room -= memoryHandle.Size; completed.Add(write); PendingWrite next; if (_pending.TryPeek(out next) == false) break; if (next.Stream.Length > room) // don't use more than the current mem table allows break; } foreach (var pendingWrite in completed) { pendingWrite.Result.SetResult(null); } } catch (Exception e) { foreach (var pendingWrite in completed) { pendingWrite.Result.SetException(e); } throw; } finally { _writeCompletedEvent.Pulse(); } } }
public async Task AppendAsync(RavenJObject data) { if (disposed) throw new ObjectDisposedException("EventStream"); var nextEtag = _options.Status.NextEtag(); data["@etag"] = nextEtag.ToString(); data["@date"] = DateTime.UtcNow.ToString("o"); using (var stream = new BufferPoolMemoryStream(_options.BufferPool)) { var bsonWriter = new BsonWriter(stream); data.WriteTo(bsonWriter); bsonWriter.Flush(); stream.Position = 0; var mine = new PendingWrite(stream, nextEtag); _pending.Enqueue(mine); while (mine.Done() == false && _pending.Peek() != mine) { await _writeCompletedEvent.WaitAsync(); } if (mine.Done()) return; await AppendInternalAsync(mine); } }