private void WriteToDisk() { var tasksToNotify = new List<Action<Exception>>(); while (true) { if (cts.IsCancellationRequested) { FlushToDisk(tasksToNotify, closing: true); return; } WriteState item; if (hadWrites) { if ((DateTime.UtcNow - lastWrite) > options.MaxTimeToWaitForFlush) { // we have to flush to disk now, because we have writes and nothing else is forthcoming // or we have so many writes, that we need to flush to clear the buffers FlushToDisk(tasksToNotify); continue; } } if (itemsToWrite.TryDequeue(out item) == false) { if (hadWrites) { FlushToDisk(tasksToNotify); } else { if (deleteCount > (eventsCount / 4)) // we have > 25% wasted space { // we waited enough time to be pretty sure we are idle // and can run compaction without too much problems. if (hasItems.Wait(options.IdleTime, cts.Token) == false) { Compact(); continue; } } else { hasItems.Wait(cts.Token); } hasItems.Reset(); } continue; } StreamInformation info; idToPos.TryGetValue(item.Id, out info); var prevPos = info == null ? DoesNotExists : info.LastPosition; var currentPos = file.Position; var persistedEvent = new PersistedEvent { Id = item.Id, Data = item.Data, State = item.State, Previous = prevPos, Metadata = item.Metadata }; WriteItem(persistedEvent, binaryWriter); var action = CreateCompletionAction(tasksToNotify, item, currentPos); tasksToNotify.Add(action); hadWrites = true; } }
private static void WriteItem(PersistedEvent item, BinaryWriter binaryWriter) { binaryWriter.Write(item.Id); binaryWriter.Write(item.Previous); binaryWriter.Write(item.StreamLength); binaryWriter.Write((int)item.State); item.Metadata.WriteTo(new BsonWriter(binaryWriter)); item.Data.WriteTo(new BsonWriter(binaryWriter)); }