internal LogsIteratorHelper(String logFile) { _stream = new FileStream(logFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); Reader = new LineReader(_stream); Index = new Index(logFile); }
/// <summary> /// Переиндексация /// </summary> /// <param name="validationResult">Результат валидации индекса</param> /// <param name="logFile">Имя лог-файла</param> /// <param name="indexName">Имя индекса</param> private void ReIndex(IndexValidationResult validationResult, String logFile, String indexName) { if (validationResult.State == IndexState.Corrupted && File.Exists(indexName)) // удаляем существующий индекс File.Delete(indexName); using (var source = OpenForReading(logFile)) using (var index = OpenForWriting(indexName)) { var recordId = String.Empty; var recordOffset = 0L; var recordLines = 0; var reader = new LineReader(source); using (var writer = new BinaryWriter(index, Encoding.Default)) { // записываем размер исходного лога writer.Seek(0, SeekOrigin.Begin); writer.Write(source.Length); switch (validationResult.State) { case IndexState.Corrupted: // оставляем место для количества записей в исходном логе writer.Write(validationResult.RecordsCount); break; case IndexState.Obsolete: // подсчет числа записей начнем с последней известной // записи в логе validationResult.RecordsCount--; // перемещаемся к началу последней записи в логе source.Seek(validationResult.LastRecordOffset, SeekOrigin.Begin); // перемещаемся к концу индексного файла минус один элемент индекса // (начинаем переиндексацию с последней известной записи!) writer.Seek(-(Int32)IndexElementSize, SeekOrigin.End); break; } // читаем исходный лог до конца while (!reader.Eof) { // запоминаем текущую позицию в логе var currentOffset = source.Position; // читаем очередную строку лога var rawEntry = EventRecordHelper.GetRawEntry(reader.ReadLine()); // проверяем ее на валидность по числу полей if (!EventRecordHelper.IsValidEntry(rawEntry)) // вероятнее всего, это - недозаписанное событие // в текущем логе, прерываем чтение break; // если сохраненный идентификатор записи не совпадает с // идентификатором считанной строки, эта строка является // первой в записи if (String.Compare(recordId, rawEntry[0]) != 0) { if (!String.IsNullOrEmpty(recordId)) { // сведения о предыдущей записи нужно сохранить // в индексном файле writer.Write(recordOffset); writer.Write(recordLines); // обнуляем счетчик строк в записи recordLines = 0; } // увеличиваем счетчик записей в логе validationResult.RecordsCount++; recordId = rawEntry[0]; recordOffset = currentOffset; } // увеличиваем число строк в записи recordLines++; // последняя запись if (reader.Eof) { // сохраняем сведения о последней записи writer.Write(recordOffset); writer.Write(recordLines); } } // сохраняем итоговое количество записей в индексе writer.Seek(sizeof(Int64), SeekOrigin.Begin); writer.Write(validationResult.RecordsCount); } } }
/// <summary> /// Переиндексация /// </summary> /// <param name="validationResult">Результат валидации индекса</param> /// <param name="logFile">Имя лог-файла</param> /// <param name="indexName">Имя индекса</param> private void ReIndex(IndexValidationResult validationResult, string logFile, string indexName) { if (validationResult.State == IndexState.Corrupted && File.Exists(indexName)) { // удаляем существующий индекс File.Delete(indexName); } using (var source = OpenForReading(logFile)) using (var index = OpenForWriting(indexName)) { var recordId = string.Empty; var recordOffset = 0L; var recordLines = 0; var reader = new LineReader(source); using (var writer = new BinaryWriter(index, Encoding.Default)) { // записываем размер исходного лога writer.Seek(0, SeekOrigin.Begin); writer.Write(source.Length); switch (validationResult.State) { case IndexState.Corrupted: // оставляем место для количества записей в исходном логе writer.Write(validationResult.RecordsCount); break; case IndexState.Obsolete: // подсчет числа записей начнем с последней известной // записи в логе validationResult.RecordsCount--; // перемещаемся к началу последней записи в логе source.Seek(validationResult.LastRecordOffset, SeekOrigin.Begin); // перемещаемся к концу индексного файла минус один элемент индекса // (начинаем переиндексацию с последней известной записи!) writer.Seek(-(int)IndexElementSize, SeekOrigin.End); break; } // читаем исходный лог до конца while (!reader.Eof) { // запоминаем текущую позицию в логе var currentOffset = source.Position; // читаем очередную строку лога var rawEntry = EventRecordHelper.GetRawEntry(reader.ReadLine()); // проверяем ее на валидность по числу полей if (!EventRecordHelper.IsValidEntry(rawEntry)) { // вероятнее всего, это - недозаписанное событие // в текущем логе, прерываем чтение break; } // если сохраненный идентификатор записи не совпадает с // идентификатором считанной строки, эта строка является // первой в записи if (string.Compare(recordId, rawEntry[0]) != 0) { if (!string.IsNullOrEmpty(recordId)) { // сведения о предыдущей записи нужно сохранить // в индексном файле writer.Write(recordOffset); writer.Write(recordLines); // обнуляем счетчик строк в записи recordLines = 0; } // увеличиваем счетчик записей в логе validationResult.RecordsCount++; recordId = rawEntry[0]; recordOffset = currentOffset; } // увеличиваем число строк в записи recordLines++; // последняя запись if (reader.Eof) { // сохраняем сведения о последней записи writer.Write(recordOffset); writer.Write(recordLines); } } // сохраняем итоговое количество записей в индексе writer.Seek(sizeof(Int64), SeekOrigin.Begin); writer.Write(validationResult.RecordsCount); } } }