protected override void PerformWork(IList <ArraySegment <Message> > items, out int totalCount, out object state) { totalCount = 0; lock (_cursors) { // perf sensitive: re-use cursors array to minimize allocations if ((_cursorsState == null) || (_cursorsState.Length != _cursors.Count)) { _cursorsState = new ulong[_cursors.Count]; } for (int i = 0; i < _cursors.Count; i++) { MessageStoreResult <Message> storeResult = _cursorTopics[i].Store.GetMessages(_cursors[i].Id, MaxMessages); _cursorsState[i] = storeResult.FirstMessageId + (ulong)storeResult.Messages.Count; if (storeResult.Messages.Count > 0) { items.Add(storeResult.Messages); totalCount += storeResult.Messages.Count; } } // Return the state as a list of cursors state = _cursorsState; } }
private ulong ExtractMessages(int streamIndex, ScaleoutMapping mapping, IList <ArraySegment <Message> > items, ref int totalCount) { // For each of the event keys we care about, extract all of the messages // from the payload lock (EventKeys) { for (var i = 0; i < EventKeys.Count; ++i) { string eventKey = EventKeys[i]; for (int j = 0; j < mapping.LocalKeyInfo.Count; j++) { LocalEventKeyInfo info = mapping.LocalKeyInfo[j]; // Capture info.MessageStore because it could be GC'd while we're working with it. var messageStore = info.MessageStore; if (messageStore != null && info.Key.Equals(eventKey, StringComparison.OrdinalIgnoreCase)) { MessageStoreResult <Message> storeResult = messageStore.GetMessages(info.Id, 1); if (storeResult.Messages.Count > 0) { // TODO: Figure out what to do when we have multiple event keys per mapping Message message = storeResult.Messages.Array[storeResult.Messages.Offset]; // Only add the message to the list if the stream index matches if (message.StreamIndex == streamIndex) { items.Add(storeResult.Messages); totalCount += storeResult.Messages.Count; _trace.TraceVerbose("Adding {0} message(s) for mapping id: {1}, event key: '{2}', event id: {3}, streamIndex: {4}", storeResult.Messages.Count, mapping.Id, info.Key, info.Id, streamIndex); // We got a mapping id bigger than what we expected which // means we missed messages. Use the new mappingId. if (message.MappingId > mapping.Id) { _trace.TraceEvent(TraceEventType.Verbose, 0, $"Extracted additional messages, updating cursor to new Mapping ID: {message.MappingId}"); return(message.MappingId); } } else { // REVIEW: When the stream indexes don't match should we leave the mapping id as is? // If we do nothing then we'll end up querying old cursor ids until // we eventually find a message id that matches this stream index. _trace.TraceInformation( "Stream index mismatch. Mapping id: {0}, event key: '{1}', event id: {2}, message.StreamIndex: {3}, streamIndex: {4}", mapping.Id, info.Key, info.Id, message.StreamIndex, streamIndex); } } } } } } return(mapping.Id); }
public bool MoveNext() { _offset++; if (_offset < _length) { return(true); } if (!_result.HasMoreData) { return(false); } // If the store falls out of scope var store = (ScaleoutStore)_storeReference.Target; if (store == null) { return(false); } // Get the next result MessageStoreResult <ScaleoutMapping> result = store.GetMessages(_nextId); Initialize(result); _offset++; return(_offset < _length); }
private void Initialize(MessageStoreResult <ScaleoutMapping> result) { _result = result; _offset = _result.Messages.Offset - 1; _length = _result.Messages.Offset + _result.Messages.Count; _nextId = _result.FirstMessageId + (ulong)_result.Messages.Count; }
public ScaleoutStoreEnumerator(ScaleoutStore store, MessageStoreResult <ScaleoutMapping> result) : this() { _storeReference = new WeakReference(store); Initialize(result); }
public IEnumerator <ScaleoutMapping> GetEnumerator(ulong id) { MessageStoreResult <ScaleoutMapping> result = _store.GetMessagesByMappingId(id); return(new ScaleoutStoreEnumerator(_store, result)); }