public void CorrectEquals() { var left = new DataRecordIndexPointer(1, 0, 0, 256); var right = new DataRecordIndexPointer(2, 0, 0, 256); Assert.AreNotEqual(left, right); }
public void CorrectlyAddMultiPageIndex() { var dataRecordIndexPointer1 = new DataRecordIndexPointer(1, 1, 0, 512); var dataRecordIndexPointer2 = new DataRecordIndexPointer(1, 2, 0, 512); var dataRecordIndexPointer3 = new DataRecordIndexPointer(1, 3, 0, 256); var multipageIndex = new DataRecordIndexPointer( dataRecordIndexPointer1.DataRecordId, dataRecordIndexPointer1.DataPageNumber, dataRecordIndexPointer1.Offset, dataRecordIndexPointer1.Length, dataRecordIndexPointer2, dataRecordIndexPointer3 ); _dataRecordIndexStorage.AddToIndex(multipageIndex); var isFound = _dataRecordIndexStorage.TryGetIndex(multipageIndex.DataRecordId, out var pointer); Assert.Multiple(() => { Assert.IsTrue(isFound, "Данные по индексу должны найтись."); Assert.AreEqual(multipageIndex, pointer, "То что положили, то и должны вернуть."); Assert.AreEqual(multipageIndex.AdditionalDataRecordIndexPointers.Length, pointer.AdditionalDataRecordIndexPointers.Length, "То что положили, то и должны вернуть."); }); }
public async Task CorrectlyAddSinglePageIndex() { var path = Path.Combine(MockFilesDirectory, "singlepage-write"); var fileInfo = new FileInfo(Path.Combine(path, "data-record-index-pointers.index")); if (fileInfo.Exists) { fileInfo.Delete(); await Task.Delay(100); } var dataRecordIndexPointer = new DataRecordIndexPointer(1, 10, 0, 132); DataRecordIndexPointer foundPointer; bool isFound; using (var dataRecordIndexStore = new Core.DataRecordIndexStorage(path, new DataRecordIndexStoreConfig(TimeSpan.FromMilliseconds(200)))) { dataRecordIndexStore.AddToIndex(dataRecordIndexPointer); isFound = dataRecordIndexStore.TryGetIndex(dataRecordIndexPointer.DataRecordId, out foundPointer); } Assert.Multiple(() => { Assert.IsTrue(isFound, "Данные по индексу должны найтись."); Assert.AreEqual(dataRecordIndexPointer, foundPointer, "То что положили, то и должны вернуть."); Assert.AreEqual(File.ReadAllBytes(Path.Combine(path, "expected.index")), File.ReadAllBytes(fileInfo.FullName)); }); }
public void CorrectlyReadMultiPageIndex() { var path = Path.Combine(MockFilesDirectory, "multipage-read"); DataRecordIndexPointer multipageIndex; DataRecordIndexPointer foundPointer; bool isFound; using (var dataRecordIndexStore = new Core.DataRecordIndexStorage(path, new DataRecordIndexStoreConfig(TimeSpan.FromMilliseconds(200)))) { var dataRecordIndexPointer1 = new DataRecordIndexPointer(1, 1, 0, 512); var dataRecordIndexPointer2 = new DataRecordIndexPointer(1, 2, 0, 512); var dataRecordIndexPointer3 = new DataRecordIndexPointer(1, 3, 0, 256); multipageIndex = new DataRecordIndexPointer( dataRecordIndexPointer1.DataRecordId, dataRecordIndexPointer1.DataPageNumber, dataRecordIndexPointer1.Offset, dataRecordIndexPointer1.Length, dataRecordIndexPointer2, dataRecordIndexPointer3 ); isFound = dataRecordIndexStore.TryGetIndex(multipageIndex.DataRecordId, out foundPointer); } Assert.Multiple(() => { Assert.IsTrue(isFound, "Данные по индексу должны найтись."); Assert.AreEqual(multipageIndex, foundPointer, "То что положили, то и должны вернуть."); Assert.AreEqual(multipageIndex.AdditionalDataRecordIndexPointers.Length, foundPointer.AdditionalDataRecordIndexPointers.Length, "То что положили, то и должны вернуть."); }); }
/// <summary> /// Попытаться найти из индекса. /// </summary> /// <param name="recordId">Идентификатор записи.</param> /// <param name="recordIndexPointer">Указатель на данные.</param> /// <returns>True, если удалось найти данные.</returns> public bool TryGetIndex(long recordId, out DataRecordIndexPointer recordIndexPointer) { var node = _tree.Find(recordId); recordIndexPointer = node.IsValid ? node.Value : default; return(node.IsValid); }
public void SinglePageIndexReconstitute() { var pointer = new DataRecordIndexPointer(1, 1, 0, 256); var bytes = pointer.GetBytes(); var point = new DataRecordIndexPointer(bytes); Assert.Multiple(() => { EqualityAssert(pointer, point); }); }
public void EmptyBytesReconstitute() { var pointer = new DataRecordIndexPointer(); var bytes = pointer.GetBytes(); var point = new DataRecordIndexPointer(bytes); Assert.Multiple(() => { EqualityAssert(pointer, point); }); }
/// <summary> /// Ассерты на идентичность. /// </summary> /// <param name="left"></param> /// <param name="right"></param> private static void EqualityAssert(DataRecordIndexPointer left, DataRecordIndexPointer right) { Assert.AreEqual(left, right, "Equality"); Assert.IsTrue(left.Equals(right), "left.Equals(right)"); Assert.IsTrue(right.Equals(left), "right.Equals(left)"); Assert.IsTrue(left.Equals((object)right), "left.Equals((object)right)"); Assert.IsTrue(right.Equals((object)left), "right.Equals((object)left)"); Assert.IsTrue(Equals(left, right), "Equals(left, right)"); Assert.AreEqual(left.GetHashCode(), right.GetHashCode(), "HashCodes"); Assert.IsFalse(right.Equals(null), "right.Equals(null)"); }
public void CorrectlyAddToIndex() { var dataRecordIndexPointer = new DataRecordIndexPointer(1, 10, 0, 132); _dataRecordIndexStorage.AddToIndex(dataRecordIndexPointer); var isFound = _dataRecordIndexStorage.TryGetIndex(dataRecordIndexPointer.DataRecordId, out var pointer); Assert.Multiple(() => { Assert.IsTrue(isFound, "Данные по индексу должны найтись."); Assert.AreEqual(dataRecordIndexPointer, pointer, "То что положили, то и должны вернуть."); }); }
public async Task CorrectlyAddMultiPageIndex() { var path = Path.Combine(MockFilesDirectory, "multipage-write"); var fileInfo = new FileInfo(Path.Combine(path, "data-record-index-pointers.index")); if (fileInfo.Exists) { fileInfo.Delete(); await Task.Delay(100); } DataRecordIndexPointer multipageIndex; DataRecordIndexPointer foundPointer; bool isFound; using (var dataRecordIndexStore = new Core.DataRecordIndexStorage(path, new DataRecordIndexStoreConfig(TimeSpan.FromMilliseconds(200)))) { var dataRecordIndexPointer1 = new DataRecordIndexPointer(1, 1, 0, 512); var dataRecordIndexPointer2 = new DataRecordIndexPointer(1, 2, 0, 512); var dataRecordIndexPointer3 = new DataRecordIndexPointer(1, 3, 0, 256); multipageIndex = new DataRecordIndexPointer( dataRecordIndexPointer1.DataRecordId, dataRecordIndexPointer1.DataPageNumber, dataRecordIndexPointer1.Offset, dataRecordIndexPointer1.Length, dataRecordIndexPointer2, dataRecordIndexPointer3 ); dataRecordIndexStore.AddToIndex(multipageIndex); isFound = dataRecordIndexStore.TryGetIndex(multipageIndex.DataRecordId, out foundPointer); } Assert.Multiple(() => { Assert.IsTrue(isFound, "Данные по индексу должны найтись."); Assert.AreEqual(multipageIndex, foundPointer, "То что положили, то и должны вернуть."); Assert.AreEqual(multipageIndex.AdditionalDataRecordIndexPointers.Length, foundPointer.AdditionalDataRecordIndexPointers.Length, "То что положили, то и должны вернуть."); Assert.AreEqual(File.ReadAllBytes(Path.Combine(path, "expected.index")), File.ReadAllBytes(fileInfo.FullName)); }); }
public void CorrectlyReadSinglePageIndex() { var path = Path.Combine(MockFilesDirectory, "singlepage-read"); DataRecordIndexPointer dataRecordIndexPointer; DataRecordIndexPointer foundIndexPointer; bool isFound; using (var dataRecordIndexStore = new Core.DataRecordIndexStorage(path, new DataRecordIndexStoreConfig(TimeSpan.FromMilliseconds(200)))) { dataRecordIndexPointer = new DataRecordIndexPointer(1, 10, 0, 132); isFound = dataRecordIndexStore.TryGetIndex(dataRecordIndexPointer.DataRecordId, out foundIndexPointer); } Assert.Multiple(() => { Assert.IsTrue(isFound, "Данные по индексу должны найтись."); Assert.AreEqual(dataRecordIndexPointer, foundIndexPointer, "То что положили, то и должны вернуть."); }); }
public void CorrectlyReadFromIndex() { var dataRecordIndexPointer1 = new DataRecordIndexPointer(1, 10, 0, 132); var dataRecordIndexPointer12 = new DataRecordIndexPointer(12, 10, 0, 132); var dataRecordIndexPointer2 = new DataRecordIndexPointer(2, 10, 0, 132); _dataRecordIndexStorage.AddToIndex(dataRecordIndexPointer1); _dataRecordIndexStorage.AddToIndex(dataRecordIndexPointer12); _dataRecordIndexStorage.AddToIndex(dataRecordIndexPointer2); var isFound = _dataRecordIndexStorage.TryGetIndex(dataRecordIndexPointer12.DataRecordId, out var pointer); var notFound13 = _dataRecordIndexStorage.TryGetIndex(13, out var defaultPointer); Assert.Multiple(() => { Assert.IsTrue(isFound, "Данные по индексу должны найтись."); Assert.AreEqual(dataRecordIndexPointer12, pointer, "То что положили, то и должны вернуть."); Assert.IsFalse(notFound13); Assert.AreEqual(default(DataRecordIndexPointer), defaultPointer); }); }
/// <summary> /// Добавить указатель в индекс. /// </summary> /// <param name="recordIndexPointer">Указатель для добавления в индекс.</param> public void AddToIndex(DataRecordIndexPointer recordIndexPointer) { // формируем общий список указателей. var pointers = new List <DataRecordIndexPointer>(recordIndexPointer.AdditionalDataRecordIndexPointers.Length + 1) { recordIndexPointer }; pointers.AddRange(recordIndexPointer.AdditionalDataRecordIndexPointers); lock (_syncWriteLock) { // добавляем в индекс. _tree.Add(recordIndexPointer.DataRecordId, recordIndexPointer); // сортируем по номерам страниц и последовательно пишем в файл. foreach (var pointer in pointers.OrderBy(p => p.DataPageNumber)) { _bufferedFileWriter.Write(pointer.GetBytes(), 0, DataRecordIndexPointer.Size); } } }
/// <summary> /// Прочитать индекс из файла. /// </summary> private void ReconstituteIndexFromFile() { lock (_syncWriteLock) { _tree.Clear(); using (var fileStream = new FileStream( _fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, _config.BufferSize, FileOptions.SequentialScan )) { using (var reader = new BinaryReader(fileStream)) { var sameDataRecordIdPointers = new List <DataRecordIndexPointer>(); // список для агрегации. var bytes = reader.ReadBytes(DataRecordIndexPointer.Size); if (bytes.Length != DataRecordIndexPointer.Size) { return; } // прочитали первый указатель. var currentDataRecordIndexPointer = new DataRecordIndexPointer(bytes); // если он всего один, то добавляем и выходим. if (reader.BaseStream.Position == reader.BaseStream.Length) { _tree.Add(currentDataRecordIndexPointer.DataRecordId, currentDataRecordIndexPointer); return; } // читаем весь файл. while (reader.BaseStream.Position != reader.BaseStream.Length) { // прочитали следующий указатель. var data = reader.ReadBytes(DataRecordIndexPointer.Size); var dataRecordIndexPointer = data.Length == DataRecordIndexPointer.Size ? new DataRecordIndexPointer(data) : new DataRecordIndexPointer(); // если он оказался таким же, какой и ранее, добавляем в список текущих. if (dataRecordIndexPointer.DataRecordId == currentDataRecordIndexPointer.DataRecordId) { sameDataRecordIdPointers.Add(dataRecordIndexPointer); // если это последний элемент, то нам не нужно переходить к следующему циклу. if (reader.BaseStream.Position != reader.BaseStream.Length) { continue; } } if (sameDataRecordIdPointers.Any()) { // создаем агрегированный указатель на основе текущего var aggregated = new DataRecordIndexPointer( currentDataRecordIndexPointer.DataRecordId, currentDataRecordIndexPointer.DataPageNumber, currentDataRecordIndexPointer.Offset, currentDataRecordIndexPointer.Length, sameDataRecordIdPointers.ToArray() ); _tree.Add(aggregated.DataRecordId, aggregated); sameDataRecordIdPointers.Clear(); } else { _tree.Add(currentDataRecordIndexPointer.DataRecordId, currentDataRecordIndexPointer); } // заменяем текущий. currentDataRecordIndexPointer = dataRecordIndexPointer; } } } } }