Exemplo n.º 1
0
        /// <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);
                }
            }
        }
Exemplo n.º 2
0
        /// <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);
                    }
                }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Валидация индекса
        /// </summary>
        /// <param name="logFile">Имя исходного лог-файла</param>
        /// <param name="indexName">Имя индексного файла</param>
        /// <returns>Результат валидации индекса</returns>
        private IndexValidationResult ValidateIndex(String logFile, String indexName)
        {
            if (!File.Exists(indexName))
                // индекс поврежден, если индексного файла не существует
                return new IndexValidationResult() { State = IndexState.Corrupted };

            // открываем индекс на чтение
            using (var index = OpenForReading(indexName))
            {
                // проверяем его структуру:
                //   размер исходного лога | sizeof(Int64)
                //   число записей | sizeof(Int64)
                //   смещение/количество строк записи 1 | sizeof(Int64) + sizeof(Int32)
                //   смещение/количество строк записи 2
                //   и т.д.
                //
                // т.о. размер индекса должен быть: 
                // sizeof(Int64) * 2 + [число записей] * (sizeof(Int64) + sizeof(Int32))

                // размер индекса не может быть меньше, чем минимально допустимый
                if (index.Length < IndexSize(0))
                    // индекс поврежден
                    return new IndexValidationResult() { State = IndexState.Corrupted };

                // считываем размер исходного лога и число записей
                using (var reader = new BinaryReader(index, Encoding.Default))
                {
                    var sourceLogSize = reader.ReadInt64();
                    var recordsCount = reader.ReadInt64();

                    // проверяем размер индекса по считанному числу записей
                    if (index.Length != IndexSize(recordsCount))
                        // индекс поврежден
                        return new IndexValidationResult() { State = IndexState.Corrupted };

                    // открываем для чтения исходный лог, нужно определить его размер
                    using (var source = OpenForReading(logFile))
                    {
                        if (sourceLogSize != source.Length)
                        {
                            // индекс устарел
                            var validationResult = new IndexValidationResult();
                            validationResult.State = IndexState.Obsolete;
                            validationResult.RecordsCount = recordsCount;
                            // смещение последней записи в логе
                            // с него будет начинаться частичная переиндексация
                            index.Seek(-IndexElementSize, SeekOrigin.End);
                            validationResult.LastRecordOffset = reader.ReadInt64();

                            return validationResult;
                        }
                    }
                }
            }

            // индекс валиден
            return new IndexValidationResult() { State = IndexState.Valid };
        }
Exemplo n.º 4
0
        /// <summary>
        /// Валидация индекса
        /// </summary>
        /// <param name="logFile">Имя исходного лог-файла</param>
        /// <param name="indexName">Имя индексного файла</param>
        /// <returns>Результат валидации индекса</returns>
        private IndexValidationResult ValidateIndex(string logFile, string indexName)
        {
            if (!File.Exists(indexName))
            {
                // индекс поврежден, если индексного файла не существует
                return new IndexValidationResult()
                       {
                           State = IndexState.Corrupted
                       }
            }
            ;

            // открываем индекс на чтение
            using (var index = OpenForReading(indexName))
            {
                // проверяем его структуру:
                //   размер исходного лога | sizeof(Int64)
                //   число записей | sizeof(Int64)
                //   смещение/количество строк записи 1 | sizeof(Int64) + sizeof(Int32)
                //   смещение/количество строк записи 2
                //   и т.д.
                //
                // т.о. размер индекса должен быть:
                // sizeof(Int64) * 2 + [число записей] * (sizeof(Int64) + sizeof(Int32))

                // размер индекса не может быть меньше, чем минимально допустимый
                if (index.Length < IndexSize(0))
                {
                    // индекс поврежден
                    return new IndexValidationResult()
                           {
                               State = IndexState.Corrupted
                           }
                }
                ;

                // считываем размер исходного лога и число записей
                using (var reader = new BinaryReader(index, Encoding.Default))
                {
                    var sourceLogSize = reader.ReadInt64();

                    var recordsCount = reader.ReadInt64();

                    // проверяем размер индекса по считанному числу записей
                    if (index.Length != IndexSize(recordsCount))
                    {
                        // индекс поврежден
                        return new IndexValidationResult()
                               {
                                   State = IndexState.Corrupted
                               }
                    }
                    ;

                    // открываем для чтения исходный лог, нужно определить его размер
                    using (var source = OpenForReading(logFile))
                    {
                        if (sourceLogSize != source.Length)
                        {
                            // индекс устарел
                            var validationResult = new IndexValidationResult();
                            validationResult.State        = IndexState.Obsolete;
                            validationResult.RecordsCount = recordsCount;
                            // смещение последней записи в логе
                            // с него будет начинаться частичная переиндексация
                            index.Seek(-IndexElementSize, SeekOrigin.End);
                            validationResult.LastRecordOffset = reader.ReadInt64();

                            return(validationResult);
                        }
                    }
                }
            }

            // индекс валиден
            return(new IndexValidationResult()
            {
                State = IndexState.Valid
            });
        }