/// <summary> /// Выполняет буферизованное чтение событий из логов /// </summary> /// <param name="iteratorParams">Параметры итератора</param> /// <returns>Итератор для буферизованного чтения событий</returns> internal IEnumerable <EventRecord[]> GetBufferedEvents( EventIteratorParams iteratorParams) { // проверяем параметры итератора // фильтр по типу событий пустой, возвращать нечего if (iteratorParams.EventTypeFilter == null || iteratorParams.EventTypeFilter.Count() == 0) { yield break; } // фильтр по источникам событий пустой, возвращать нечего if (iteratorParams.SourceFilter == null || iteratorParams.SourceFilter.Count() == 0) { yield break; } var buffer = new List <EventRecord>(iteratorParams.MaxEventsPerIteration); foreach (var eventRecord in GetEventsRundown(iteratorParams)) { buffer.Add(eventRecord); if (buffer.Count == iteratorParams.MaxEventsPerIteration) { yield return(buffer.ToArray()); buffer.Clear(); } } // возвращаем остаток событий if (buffer.Count > 0) { yield return(buffer.ToArray()); } }
/// <summary> /// Перебирает события в логах /// </summary> /// <param name="iteratorParams">Параметры итератора</param> /// <returns>Итератор для перебора событий</returns> private IEnumerable<EventRecord> GetEventsRundown(EventIteratorParams iteratorParams) { var logsIterator = new LogsIterator(_storageNamePredicate); var totalRead = 0; // перебираем логи в порядке убывания даты foreach (var helper in logsIterator.StreamedLogsRundown( iteratorParams.FromDate, iteratorParams.ToDate)) { // читаем лог с конца, для позиционирования в логе используем индекс // чтение выполняем блоками по _reverseBlockSize событий // определяем количество итераций по текущему логу var iterationsCount = helper.Index.RecordCount / _reverseBlockSize; if (helper.Index.RecordCount % _reverseBlockSize > 0) iterationsCount++; if (iterationsCount == 0) // пустой лог continue; for (var i = 0L; i < iterationsCount; i++) { // флаг принудительной остановки чтения лога, если он не дописан var stopReadThisLog = false; // определяем индекс первой записи в блоке (начинается с нуля) var firstRecordOfBlock = helper.Index.RecordCount - (i + 1) * _reverseBlockSize; // и число событий, которые нужно считать var eventsToRead = _reverseBlockSize; if (firstRecordOfBlock < 0) { // если попали сюда, это означает, что число записей в логе // не кратно _reverseBlockSize и нужно уточнить eventsToRead: eventsToRead = _reverseBlockSize + firstRecordOfBlock; // номер первой записи в этом случае равен нулю: firstRecordOfBlock = 0; } // переходим к нужному куску индексированных данных helper.Index.Seek(firstRecordOfBlock); // читаем очередной блок записей var bufferedEvents = new EventRecord[eventsToRead]; try { // флаг принудительного поиска по логу var seekInLog = true; for (var j = 0L; j < eventsToRead; j++) { // определяем индексированные данные очередной записи var currentIndex = helper.Index.GetNext(); if (seekInLog) { // устанавливаем смещение в логе на начало очередной записи helper.Reader.Seek(currentIndex.Offset, SeekOrigin.Begin); seekInLog = false; } // читаем очередное сообщение for (var k = 0; k < currentIndex.LinesCount; k++) { var storageEntry = EventRecordHelper.GetRawEntry( helper.Reader.ReadLine()); if (!iteratorParams.SourceFilter.Contains(storageEntry[3].TrimEnd()) || !iteratorParams.EventTypeFilter.Contains(storageEntry[4].TrimEnd())) { // прерываем чтение этого сообщения и взводим флаг принудительного // поиска по логу seekInLog = true; break; } if (bufferedEvents[j] == null) bufferedEvents[j] = EventRecordHelper.CreateFromStorageEntry( storageEntry); else bufferedEvents[j].Text.Add(storageEntry[5]); } } } catch (IndexOutOfRangeException) { // попали в недописанный кусок лога stopReadThisLog = true; } // разворачиваем блок записей Array.Reverse(bufferedEvents); // возвращаем записи как результат работы итератора foreach (var eventRecord in bufferedEvents) { if (eventRecord == null) // пропускаем события, не попавшие под фильтр continue; // возвращаем событие yield return eventRecord; // увеличиваем счетчик событий totalRead++; // достигли максимального количества событий if (totalRead == iteratorParams.MaxEvents) yield break; } if (stopReadThisLog) break; } } }
/// <summary> /// Перебирает события в логах /// </summary> /// <param name="iteratorParams">Параметры итератора</param> /// <returns>Итератор для перебора событий</returns> private IEnumerable <EventRecord> GetEventsRundown(EventIteratorParams iteratorParams) { var logsIterator = new LogsIterator(_storageNamePredicate); var totalRead = 0; // перебираем логи в порядке убывания даты foreach (var helper in logsIterator.StreamedLogsRundown( iteratorParams.FromDate, iteratorParams.ToDate)) { // читаем лог с конца, для позиционирования в логе используем индекс // чтение выполняем блоками по _reverseBlockSize событий // определяем количество итераций по текущему логу var iterationsCount = helper.Index.RecordCount / _reverseBlockSize; if (helper.Index.RecordCount % _reverseBlockSize > 0) { iterationsCount++; } if (iterationsCount == 0) { // пустой лог continue; } for (var i = 0L; i < iterationsCount; i++) { // флаг принудительной остановки чтения лога, если он не дописан var stopReadThisLog = false; // определяем индекс первой записи в блоке (начинается с нуля) var firstRecordOfBlock = helper.Index.RecordCount - (i + 1) * _reverseBlockSize; // и число событий, которые нужно считать var eventsToRead = _reverseBlockSize; if (firstRecordOfBlock < 0) { // если попали сюда, это означает, что число записей в логе // не кратно _reverseBlockSize и нужно уточнить eventsToRead: eventsToRead = _reverseBlockSize + firstRecordOfBlock; // номер первой записи в этом случае равен нулю: firstRecordOfBlock = 0; } // переходим к нужному куску индексированных данных helper.Index.Seek(firstRecordOfBlock); // читаем очередной блок записей var bufferedEvents = new EventRecord[eventsToRead]; try { // флаг принудительного поиска по логу var seekInLog = true; for (var j = 0L; j < eventsToRead; j++) { // определяем индексированные данные очередной записи var currentIndex = helper.Index.GetNext(); if (seekInLog) { // устанавливаем смещение в логе на начало очередной записи helper.Reader.Seek(currentIndex.Offset, SeekOrigin.Begin); seekInLog = false; } // читаем очередное сообщение for (var k = 0; k < currentIndex.LinesCount; k++) { var storageEntry = EventRecordHelper.GetRawEntry( helper.Reader.ReadLine()); if (!iteratorParams.SourceFilter.Contains(storageEntry[3].TrimEnd()) || !iteratorParams.EventTypeFilter.Contains(storageEntry[4].TrimEnd())) { // прерываем чтение этого сообщения и взводим флаг принудительного // поиска по логу seekInLog = true; break; } if (bufferedEvents[j] == null) { bufferedEvents[j] = EventRecordHelper.CreateFromStorageEntry( storageEntry); } else { bufferedEvents[j].Text.Add(storageEntry[5]); } } } } catch (IndexOutOfRangeException) { // попали в недописанный кусок лога stopReadThisLog = true; } // разворачиваем блок записей Array.Reverse(bufferedEvents); // возвращаем записи как результат работы итератора foreach (var eventRecord in bufferedEvents) { if (eventRecord == null) { // пропускаем события, не попавшие под фильтр continue; } // возвращаем событие yield return(eventRecord); // увеличиваем счетчик событий totalRead++; // достигли максимального количества событий if (totalRead == iteratorParams.MaxEvents) { yield break; } } if (stopReadThisLog) { break; } } } }
/// <summary> /// Выполняет буферизованное чтение событий из логов /// </summary> /// <param name="iteratorParams">Параметры итератора</param> /// <returns>Итератор для буферизованного чтения событий</returns> internal IEnumerable<EventRecord[]> GetBufferedEvents( EventIteratorParams iteratorParams) { // проверяем параметры итератора // фильтр по типу событий пустой, возвращать нечего if (iteratorParams.EventTypeFilter == null || iteratorParams.EventTypeFilter.Count() == 0) yield break; // фильтр по источникам событий пустой, возвращать нечего if (iteratorParams.SourceFilter == null || iteratorParams.SourceFilter.Count() == 0) yield break; var buffer = new List<EventRecord>(iteratorParams.MaxEventsPerIteration); foreach (var eventRecord in GetEventsRundown(iteratorParams)) { buffer.Add(eventRecord); if (buffer.Count == iteratorParams.MaxEventsPerIteration) { yield return buffer.ToArray(); buffer.Clear(); } } // возвращаем остаток событий if (buffer.Count > 0) yield return buffer.ToArray(); }