public void ReadBareMinParams([Values] TestUtils.DeviceType deviceType) { string filename = path + "ReadBareMinParams" + deviceType.ToString() + ".log"; log = TestUtils.CreateTestDevice(deviceType, filename); fht = new FasterKV <KeyStruct, ValueStruct> (128, new LogSettings { LogDevice = log, MemorySizeBits = 22, SegmentSizeBits = 22, PageSizeBits = 10 }); session = fht.For(new Functions()).NewSession <Functions>(); var key1 = new KeyStruct { kfield1 = 13, kfield2 = 14 }; var value = new ValueStruct { vfield1 = 23, vfield2 = 24 }; session.Upsert(ref key1, ref value, Empty.Default, 0); var(status, output) = session.Read(key1); AssertCompleted(Status.OK, status); Assert.AreEqual(value.vfield1, output.value.vfield1); Assert.AreEqual(value.vfield2, output.value.vfield2); Assert.AreEqual(key1.kfield1, 13); Assert.AreEqual(key1.kfield2, 14); }
public void UpsertNoRefNoDefaultsTest() { // Just checking more parameter values so one device is enough deviceType = TestUtils.DeviceType.MLSD; string filename = path + "UpsertNoRefNoDefaultsTest" + deviceType.ToString() + ".log"; log = TestUtils.CreateTestDevice(deviceType, filename); fht = new FasterKV <KeyStruct, ValueStruct> (128, new LogSettings { LogDevice = log, MemorySizeBits = 29 }); session = fht.For(new Functions()).NewSession <Functions>(); InputStruct input = default; OutputStruct output = default; var key1 = new KeyStruct { kfield1 = 13, kfield2 = 14 }; var value = new ValueStruct { vfield1 = 23, vfield2 = 24 }; session.Upsert(key1, value, Empty.Default, 0); var status = session.Read(ref key1, ref input, ref output, Empty.Default, 0); AssertCompleted(Status.OK, status); Assert.AreEqual(value.vfield1, output.value.vfield1); Assert.AreEqual(value.vfield2, output.value.vfield2); }
public void NativeInMemWriteRead() { InputStruct input = default; OutputStruct output = default; var key1 = new KeyStruct { kfield1 = 13, kfield2 = 14 }; var value = new ValueStruct { vfield1 = 23, vfield2 = 24 }; session.Upsert(ref key1, ref value, Empty.Default, 0); var status = session.Read(ref key1, ref input, ref output, Empty.Default, 0); if (status == Status.PENDING) { session.CompletePending(true); } else { Assert.IsTrue(status == Status.OK); } Assert.IsTrue(output.value.vfield1 == value.vfield1); Assert.IsTrue(output.value.vfield2 == value.vfield2); }
public void UpsertDefaultsTest([Values] TestUtils.DeviceType deviceType) { string filename = path + "UpsertDefaultsTest" + deviceType.ToString() + ".log"; log = TestUtils.CreateTestDevice(deviceType, filename); fht = new FasterKV <KeyStruct, ValueStruct> (128, new LogSettings { LogDevice = log, MemorySizeBits = 22, SegmentSizeBits = 22, PageSizeBits = 10 }); session = fht.For(new Functions()).NewSession <Functions>(); InputStruct input = default; OutputStruct output = default; var key1 = new KeyStruct { kfield1 = 13, kfield2 = 14 }; var value = new ValueStruct { vfield1 = 23, vfield2 = 24 }; Assert.AreEqual(0, fht.EntryCount); session.Upsert(ref key1, ref value); var status = session.Read(ref key1, ref input, ref output, Empty.Default, 0); AssertCompleted(Status.OK, status); Assert.AreEqual(1, fht.EntryCount); Assert.AreEqual(value.vfield1, output.value.vfield1); Assert.AreEqual(value.vfield2, output.value.vfield2); }
public void ReadAtAddressReadFlagsNone() { // Just functional test of ReadFlag so one device is enough deviceType = TestUtils.DeviceType.MLSD; string filename = path + "ReadAtAddressReadFlagsNone" + deviceType.ToString() + ".log"; log = TestUtils.CreateTestDevice(deviceType, filename); fht = new FasterKV <KeyStruct, ValueStruct> (128, new LogSettings { LogDevice = log, MemorySizeBits = 29 }); session = fht.For(new Functions()).NewSession <Functions>(); InputStruct input = default; OutputStruct output = default; var key1 = new KeyStruct { kfield1 = 13, kfield2 = 14 }; var value = new ValueStruct { vfield1 = 23, vfield2 = 24 }; var readAtAddress = fht.Log.BeginAddress; session.Upsert(ref key1, ref value, Empty.Default, 0); var status = session.ReadAtAddress(readAtAddress, ref input, ref output, ReadFlags.None, Empty.Default, 0); AssertCompleted(Status.OK, status); Assert.AreEqual(value.vfield1, output.value.vfield1); Assert.AreEqual(value.vfield2, output.value.vfield2); Assert.AreEqual(key1.kfield1, 13); Assert.AreEqual(key1.kfield2, 14); }
public unsafe void TestShiftHeadAddress() { InputStruct input = default(InputStruct); Random r = new Random(10); for (int c = 0; c < 1000; c++) { var i = r.Next(10000); var key1 = new KeyStruct { kfield1 = i, kfield2 = i + 1 }; var value = new ValueStruct { vfield1 = i, vfield2 = i + 1 }; fht.Upsert(ref key1, ref value, Empty.Default, 0); } r = new Random(10); for (int c = 0; c < 1000; c++) { var i = r.Next(10000); OutputStruct output = default(OutputStruct); var key1 = new KeyStruct { kfield1 = i, kfield2 = i + 1 }; var value = new ValueStruct { vfield1 = i, vfield2 = i + 1 }; if (fht.Read(ref key1, ref input, ref output, Empty.Default, 0) == Status.PENDING) { fht.CompletePending(true); } Assert.IsTrue(output.value.vfield1 == value.vfield1); Assert.IsTrue(output.value.vfield2 == value.vfield2); } // Shift head and retry - should not find in main memory now fht.ShiftHeadAddress(fht.LogTailAddress, true); r = new Random(10); for (int c = 0; c < 1000; c++) { var i = r.Next(10000); OutputStruct output = default(OutputStruct); var key1 = new KeyStruct { kfield1 = i, kfield2 = i + 1 }; var value = new ValueStruct { vfield1 = i, vfield2 = i + 1 }; Assert.IsTrue(fht.Read(ref key1, ref input, ref output, Empty.Default, 0) == Status.PENDING); fht.CompletePending(true); } }
public void NativeInMemWriteReadDelete2() { // Just set this one since Write Read Delete already does all four devices deviceType = TestUtils.DeviceType.MLSD; const int count = 10; // Setup(128, new LogSettings { MemorySizeBits = 22, SegmentSizeBits = 22, PageSizeBits = 10 }, deviceType); Setup(128, new LogSettings { MemorySizeBits = 29 }, deviceType); InputStruct input = default; OutputStruct output = default; for (int i = 0; i < 10 * count; i++) { var key1 = new KeyStruct { kfield1 = i, kfield2 = 14 }; var value = new ValueStruct { vfield1 = i, vfield2 = 24 }; session.Upsert(ref key1, ref value, Empty.Default, 0); } for (int i = 0; i < 10 * count; i++) { var key1 = new KeyStruct { kfield1 = i, kfield2 = 14 }; session.Delete(ref key1, Empty.Default, 0); } for (int i = 0; i < 10 * count; i++) { var key1 = new KeyStruct { kfield1 = i, kfield2 = 14 }; var value = new ValueStruct { vfield1 = i, vfield2 = 24 }; var status = session.Read(ref key1, ref input, ref output, Empty.Default, 0); AssertCompleted(new(StatusCode.NotFound), status); session.Upsert(ref key1, ref value, Empty.Default, 0); } for (int i = 0; i < 10 * count; i++) { var key1 = new KeyStruct { kfield1 = i, kfield2 = 14 }; var status = session.Read(ref key1, ref input, ref output, Empty.Default, 0); AssertCompleted(new(StatusCode.Found), status); } }
public override bool CopyUpdater(ref KeyStruct key, ref InputStruct input, ref ValueStruct oldValue, ref ValueStruct newValue, ref OutputStruct output, ref RMWInfo rmwInfo) { Assert.IsFalse(rmwInfo.RecordInfo.IsNull()); newValue.vfield1 = oldValue.vfield1 + input.ifield1; newValue.vfield2 = oldValue.vfield2 + input.ifield2; output.value = newValue; return(true); }
// RMW functions public override bool InitialUpdater(ref KeyStruct key, ref InputStruct input, ref ValueStruct value, ref OutputStruct output, ref RMWInfo rmwInfo) { Assert.IsFalse(rmwInfo.RecordInfo.IsNull()); value.vfield1 = input.ifield1; value.vfield2 = input.ifield2; output.value = value; return(true); }
public unsafe void NativeInMemWriteRead2() { InputStruct input = default(InputStruct); Random r = new Random(10); for (int c = 0; c < 1000; c++) { var i = r.Next(10000); var key1 = new KeyStruct { kfield1 = i, kfield2 = i + 1 }; var value = new ValueStruct { vfield1 = i, vfield2 = i + 1 }; fht.Upsert(ref key1, ref value, Empty.Default, 0); } r = new Random(10); for (int c = 0; c < 1000; c++) { var i = r.Next(10000); OutputStruct output = default(OutputStruct); var key1 = new KeyStruct { kfield1 = i, kfield2 = i + 1 }; var value = new ValueStruct { vfield1 = i, vfield2 = i + 1 }; if (fht.Read(ref key1, ref input, ref output, Empty.Default, 0) == Status.PENDING) { fht.CompletePending(true); } Assert.IsTrue(output.value.vfield1 == value.vfield1); Assert.IsTrue(output.value.vfield2 == value.vfield2); } // Clean up and retry - should not find now fht.ShiftBeginAddress(fht.LogTailAddress); r = new Random(10); for (int c = 0; c < 1000; c++) { var i = r.Next(10000); OutputStruct output = default(OutputStruct); var key1 = new KeyStruct { kfield1 = i, kfield2 = i + 1 }; var value = new ValueStruct { vfield1 = i, vfield2 = i + 1 }; Assert.IsTrue(fht.Read(ref key1, ref input, ref output, Empty.Default, 0) == Status.NOTFOUND); } }
public void BlittableLogCompactionTest1([Values] CompactionType compactionType) { using var session = fht.For(new FunctionsCompaction()).NewSession <FunctionsCompaction>(); InputStruct input = default; const int totalRecords = 2000; var start = fht.Log.TailAddress; long compactUntil = 0; for (int i = 0; i < totalRecords; i++) { if (i == 1000) { compactUntil = fht.Log.TailAddress; } var key1 = new KeyStruct { kfield1 = i, kfield2 = i + 1 }; var value = new ValueStruct { vfield1 = i, vfield2 = i + 1 }; session.Upsert(ref key1, ref value, 0, 0); } compactUntil = session.Compact(compactUntil, compactionType); fht.Log.Truncate(); Assert.AreEqual(compactUntil, fht.Log.BeginAddress); // Read 2000 keys - all should be present for (int i = 0; i < totalRecords; i++) { OutputStruct output = default; var key1 = new KeyStruct { kfield1 = i, kfield2 = i + 1 }; var value = new ValueStruct { vfield1 = i, vfield2 = i + 1 }; var status = session.Read(ref key1, ref input, ref output, 0, 0); if (status.IsPending) { session.CompletePending(true); } else { Assert.IsTrue(status.Found); Assert.AreEqual(value.vfield1, output.value.vfield1); Assert.AreEqual(value.vfield2, output.value.vfield2); } } }
public void ShouldCreateNewRecordIfConcurrentWriterReturnsFalse() { var copyOnWrite = new FunctionsCopyOnWrite(); // FunctionsCopyOnWrite var log = default(IDevice); try { log = Devices.CreateLogDevice(TestUtils.MethodTestDir + "/hlog1.log", deleteOnClose: true); using var fht = new FasterKV <KeyStruct, ValueStruct> (128, new LogSettings { LogDevice = log, MemorySizeBits = 29 }); using var session = fht.NewSession(copyOnWrite); var key = default(KeyStruct); var value = default(ValueStruct); key = new KeyStruct() { kfield1 = 1, kfield2 = 2 }; value = new ValueStruct() { vfield1 = 1000, vfield2 = 2000 }; session.Upsert(ref key, ref value, Empty.Default, 0); value = new ValueStruct() { vfield1 = 1001, vfield2 = 2002 }; session.Upsert(ref key, ref value, Empty.Default, 0); var recordCount = 0; using (var iterator = fht.Log.Scan(fht.Log.BeginAddress, fht.Log.TailAddress)) { while (iterator.GetNext(out var info)) { recordCount++; } } Assert.AreEqual(1, copyOnWrite.ConcurrentWriterCallCount, 2); Assert.AreEqual(2, recordCount); } finally { if (log != null) { log.Dispose(); } } }
public void BlittableLogCompactionTest1() { using var session = fht.NewSession(); InputStruct input = default; const int totalRecords = 2000; var start = fht.Log.TailAddress; long compactUntil = 0; for (int i = 0; i < totalRecords; i++) { if (i == 1000) { compactUntil = fht.Log.TailAddress; } var key1 = new KeyStruct { kfield1 = i, kfield2 = i + 1 }; var value = new ValueStruct { vfield1 = i, vfield2 = i + 1 }; session.Upsert(ref key1, ref value, 0, 0); } fht.Log.Compact(compactUntil); Assert.IsTrue(fht.Log.BeginAddress == compactUntil); // Read 2000 keys - all should be present for (int i = 0; i < totalRecords; i++) { OutputStruct output = default; var key1 = new KeyStruct { kfield1 = i, kfield2 = i + 1 }; var value = new ValueStruct { vfield1 = i, vfield2 = i + 1 }; var status = session.Read(ref key1, ref input, ref output, 0, 0); if (status == Status.PENDING) { session.CompletePending(true); } else { Assert.IsTrue(status == Status.OK); Assert.IsTrue(output.value.vfield1 == value.vfield1); Assert.IsTrue(output.value.vfield2 == value.vfield2); } } }
static void VerifyStructs(int key, ref KeyStruct keyStruct, ref InputStruct inputStruct, ref OutputStruct outputStruct, ref ContextStruct contextStruct) { Assert.AreEqual(key, keyStruct.kfield1); Assert.AreEqual(key + numRecords * 10, keyStruct.kfield2); Assert.AreEqual(key + numRecords * 30, inputStruct.ifield1); Assert.AreEqual(key + numRecords * 40, inputStruct.ifield2); Assert.AreEqual(key, outputStruct.value.vfield1); Assert.AreEqual(key + numRecords * 10, outputStruct.value.vfield2); Assert.AreEqual(key + numRecords * 50, contextStruct.cfield1); Assert.AreEqual(key + numRecords * 60, contextStruct.cfield2); }
static void VerifyStructs(int key, ref KeyStruct keyStruct, ref InputStruct inputStruct, ref OutputStruct outputStruct, ref ContextStruct contextStruct, bool useRMW) { Assert.AreEqual(key, keyStruct.kfield1); Assert.AreEqual(key + numRecords * 10, keyStruct.kfield2); Assert.AreEqual(key + numRecords * 30, inputStruct.ifield1); Assert.AreEqual(key + numRecords * 40, inputStruct.ifield2); // RMW causes the InPlaceUpdater to be called, which adds input fields to the value. Assert.AreEqual(key + (useRMW ? inputStruct.ifield1 : 0), outputStruct.value.vfield1); Assert.AreEqual(key + numRecords * 10 + (useRMW ? inputStruct.ifield2 : 0), outputStruct.value.vfield2); Assert.AreEqual(key + numRecords * 50, contextStruct.cfield1); Assert.AreEqual(key + numRecords * 60, contextStruct.cfield2); }
public void BlittableDiskWriteScan() { using var session = fht.NewSession(); var s = fht.Log.Subscribe(new LogObserver()); var start = fht.Log.TailAddress; for (int i = 0; i < totalRecords; i++) { var key1 = new KeyStruct { kfield1 = i, kfield2 = i + 1 }; var value = new ValueStruct { vfield1 = i, vfield2 = i + 1 }; session.Upsert(ref key1, ref value, Empty.Default, 0); } fht.Log.FlushAndEvict(true); var iter = fht.Log.Scan(start, fht.Log.TailAddress, ScanBufferingMode.SinglePageBuffering); int val = 0; while (iter.GetNext(out _, out KeyStruct key, out ValueStruct value)) { Assert.IsTrue(key.kfield1 == val); Assert.IsTrue(key.kfield2 == val + 1); Assert.IsTrue(value.vfield1 == val); Assert.IsTrue(value.vfield2 == val + 1); val++; } Assert.IsTrue(totalRecords == val); iter = fht.Log.Scan(start, fht.Log.TailAddress, ScanBufferingMode.DoublePageBuffering); val = 0; while (iter.GetNext(out RecordInfo recordInfo, out KeyStruct key, out ValueStruct value)) { Assert.IsTrue(key.kfield1 == val); Assert.IsTrue(key.kfield2 == val + 1); Assert.IsTrue(value.vfield1 == val); Assert.IsTrue(value.vfield2 == val + 1); val++; } Assert.IsTrue(totalRecords == val); s.Dispose(); }
public void ReadAtAddressReadFlagsSkipReadCache() { InputStruct input = default; OutputStruct output = default; long invalidAddress = Constants.kInvalidAddress; var key1 = new KeyStruct { kfield1 = 13, kfield2 = 14 }; var value = new ValueStruct { vfield1 = 23, vfield2 = 24 }; var readAtAddress = fht.Log.BeginAddress; session.Upsert(ref key1, ref value, Empty.Default, 0); //**** When Bug Fixed ... use the invalidAddress line // Bug #136259 // Ah—slight bug here.I took a quick look to verify that the logicalAddress passed to SingleReader was kInvalidAddress(0), //and while I got that right for the SingleWriter call, I missed it on the SingleReader. //This is because we streamlined it to no longer expose RecordAccessor.IsReadCacheAddress, and I missed it here. // test that the record retrieved on Read variants that do find the record in the readCache //pass Constants.kInvalidAddress as the ‘address’ parameter to SingleReader. // Reading the same record using Read(…, ref RecordInfo…) //and ReadFlags.SkipReadCache should return a valid record there. //For now, write the same test, and instead of testing for address == kInvalidAddress, //test for (address & Constants.kReadCacheBitMask) != 0. //var status = session.ReadAtAddress(invalidAddress, ref input, ref output, ReadFlags.SkipReadCache); var status = session.ReadAtAddress(readAtAddress, ref input, ref output, ReadFlags.SkipReadCache); if (status == Status.PENDING) { session.CompletePending(true); } else { Assert.IsTrue(status == Status.OK); } Assert.IsTrue(output.value.vfield1 == value.vfield1); Assert.IsTrue(output.value.vfield2 == value.vfield2); Assert.IsTrue(13 == key1.kfield1); Assert.IsTrue(14 == key1.kfield2); }
public void BlittableLogCompactionCustomFunctionsTest2() { // Update: irrelevant as session compaction no longer uses Copy/CopyInPlace // This test checks if CopyInPlace returning false triggers call to Copy using var session = fht.For(new FunctionsCompaction()).NewSession <FunctionsCompaction>(); var key = new KeyStruct { kfield1 = 100, kfield2 = 101 }; var value = new ValueStruct { vfield1 = 10, vfield2 = 20 }; session.Upsert(ref key, ref value, 0, 0); fht.Log.Flush(true); value = new ValueStruct { vfield1 = 11, vfield2 = 21 }; session.Upsert(ref key, ref value, 0, 0); fht.Log.Flush(true); var compactionFunctions = new Test2CompactionFunctions(); session.Compact(fht.Log.TailAddress, true, compactionFunctions); Assert.IsFalse(compactionFunctions.CopyCalled); var input = default(InputStruct); var output = default(OutputStruct); var status = session.Read(ref key, ref input, ref output, 0, 0); if (status == Status.PENDING) { session.CompletePending(true); } else { Assert.IsTrue(status == Status.OK); Assert.IsTrue(output.value.vfield1 == value.vfield1); Assert.IsTrue(output.value.vfield2 == value.vfield2); } }
public void NativeInMemWriteReadDelete([Values] TestUtils.DeviceType deviceType) { string filename = path + "NativeInMemWriteReadDelete" + deviceType.ToString() + ".log"; log = TestUtils.CreateTestDevice(deviceType, filename); fht = new FasterKV <KeyStruct, ValueStruct> (128, new LogSettings { LogDevice = log, PageSizeBits = 10, MemorySizeBits = 12, SegmentSizeBits = 22 }); session = fht.For(new Functions()).NewSession <Functions>(); InputStruct input = default; OutputStruct output = default; var key1 = new KeyStruct { kfield1 = 13, kfield2 = 14 }; var value = new ValueStruct { vfield1 = 23, vfield2 = 24 }; session.Upsert(ref key1, ref value, Empty.Default, 0); var status = session.Read(ref key1, ref input, ref output, Empty.Default, 0); AssertCompleted(Status.OK, status); session.Delete(ref key1, Empty.Default, 0); status = session.Read(ref key1, ref input, ref output, Empty.Default, 0); AssertCompleted(Status.NOTFOUND, status); var key2 = new KeyStruct { kfield1 = 14, kfield2 = 15 }; var value2 = new ValueStruct { vfield1 = 24, vfield2 = 25 }; session.Upsert(ref key2, ref value2, Empty.Default, 0); status = session.Read(ref key2, ref input, ref output, Empty.Default, 0); AssertCompleted(Status.OK, status); Assert.AreEqual(value2.vfield1, output.value.vfield1); Assert.AreEqual(value2.vfield2, output.value.vfield2); }
public void UpsertSerialNumberTest() { // Simple Upsert of Serial Number test so one device is enough deviceType = TestUtils.DeviceType.MLSD; string filename = path + "UpsertSerialNumberTest" + deviceType.ToString() + ".log"; log = TestUtils.CreateTestDevice(deviceType, filename); fht = new FasterKV <KeyStruct, ValueStruct> (128, new LogSettings { LogDevice = log, MemorySizeBits = 29 }); session = fht.For(new Functions()).NewSession <Functions>(); int numKeys = 100; int keyMod = 10; int maxLap = numKeys / keyMod; InputStruct input = default; OutputStruct output = default; var value = new ValueStruct { vfield1 = 23, vfield2 = 24 }; var key = new KeyStruct { kfield1 = 13, kfield2 = 14 }; for (int i = 0; i < numKeys; i++) { // lap is used to illustrate the changing values var lap = i / keyMod; session.Upsert(ref key, ref value, serialNo: lap); } // Now verify for (int j = 0; j < numKeys; j++) { var status = session.Read(ref key, ref input, ref output, serialNo: maxLap + 1); AssertCompleted(Status.OK, status); Assert.AreEqual(value.vfield1, output.value.vfield1); Assert.AreEqual(value.vfield2, output.value.vfield2); } }
public void BlittableLogCompactionCustomFunctionsTest2([Values] CompactionType compactionType) { // Update: irrelevant as session compaction no longer uses Copy/CopyInPlace // This test checks if CopyInPlace returning false triggers call to Copy using var session = fht.For(new FunctionsCompaction()).NewSession <FunctionsCompaction>(); var key = new KeyStruct { kfield1 = 100, kfield2 = 101 }; var value = new ValueStruct { vfield1 = 10, vfield2 = 20 }; session.Upsert(ref key, ref value, 0, 0); fht.Log.Flush(true); value = new ValueStruct { vfield1 = 11, vfield2 = 21 }; session.Upsert(ref key, ref value, 0, 0); fht.Log.Flush(true); var compactUntil = session.Compact(fht.Log.TailAddress, compactionType); fht.Log.Truncate(); var input = default(InputStruct); var output = default(OutputStruct); var status = session.Read(ref key, ref input, ref output, 0, 0); if (status.IsPending) { session.CompletePending(true); } else { Assert.IsTrue(status.Found); Assert.AreEqual(value.vfield1, output.value.vfield1); Assert.AreEqual(value.vfield2, output.value.vfield2); } }
public void BlittableDiskWriteScan() { const int totalRecords = 2000; var start = fht.Log.TailAddress; for (int i = 0; i < totalRecords; i++) { var key1 = new KeyStruct { kfield1 = i, kfield2 = i + 1 }; var value = new ValueStruct { vfield1 = i, vfield2 = i + 1 }; fht.Upsert(ref key1, ref value, Empty.Default, 0); } fht.Log.FlushAndEvict(true); var iter = fht.Log.Scan(start, fht.Log.TailAddress, ScanBufferingMode.SinglePageBuffering); int val = 0; while (iter.GetNext(out KeyStruct key, out ValueStruct value)) { Assert.IsTrue(key.kfield1 == val); Assert.IsTrue(key.kfield2 == val + 1); Assert.IsTrue(value.vfield1 == val); Assert.IsTrue(value.vfield2 == val + 1); val++; } Assert.IsTrue(totalRecords == val); iter = fht.Log.Scan(start, fht.Log.TailAddress, ScanBufferingMode.DoublePageBuffering); val = 0; while (iter.GetNext(out KeyStruct key, out ValueStruct value)) { Assert.IsTrue(key.kfield1 == val); Assert.IsTrue(key.kfield2 == val + 1); Assert.IsTrue(value.vfield1 == val); Assert.IsTrue(value.vfield2 == val + 1); val++; } Assert.IsTrue(totalRecords == val); }
public void NativeDiskWriteRead() { InputStruct input = default(InputStruct); Random r = new Random(10); for (int i = 0; i < 2000; i++) { var key1 = new KeyStruct { kfield1 = i, kfield2 = i + 1 }; var value = new ValueStruct { vfield1 = i, vfield2 = i + 1 }; fht.Upsert(ref key1, ref value, Empty.Default, 0); } fht.CompletePending(true); r = new Random(10); for (int i = 0; i < 2000; i++) { OutputStruct output = default(OutputStruct); var key1 = new KeyStruct { kfield1 = i, kfield2 = i + 1 }; var value = new ValueStruct { vfield1 = i, vfield2 = i + 1 }; if (fht.Read(ref key1, ref input, ref output, Empty.Default, 0) == Status.PENDING) { fht.CompletePending(true); } else { Assert.IsTrue(output.value.vfield1 == value.vfield1); Assert.IsTrue(output.value.vfield2 == value.vfield2); } } }
public void UpsertSerialNumberTest() { int numKeys = 100; int keyMod = 10; int maxLap = numKeys / keyMod; InputStruct input = default; OutputStruct output = default; var value = new ValueStruct { vfield1 = 23, vfield2 = 24 }; var key = new KeyStruct { kfield1 = 13, kfield2 = 14 }; for (int i = 0; i < numKeys; i++) { // lap is used to illustrate the changing values var lap = i / keyMod; session.Upsert(ref key, ref value, serialNo: lap); } // Now verify for (int j = 0; j < numKeys; j++) { var status = session.Read(ref key, ref input, ref output, serialNo: maxLap + 1); if (status == Status.PENDING) { session.CompletePending(true); } else { Assert.IsTrue(status == Status.OK); } Assert.IsTrue(output.value.vfield1 == value.vfield1); Assert.IsTrue(output.value.vfield2 == value.vfield2); } }
public void NativeInMemWriteReadDelete([Values] TestUtils.DeviceType deviceType) { Setup(128, new LogSettings { PageSizeBits = 10, MemorySizeBits = 12, SegmentSizeBits = 22 }, deviceType); InputStruct input = default; OutputStruct output = default; var key1 = new KeyStruct { kfield1 = 13, kfield2 = 14 }; var value = new ValueStruct { vfield1 = 23, vfield2 = 24 }; session.Upsert(ref key1, ref value, Empty.Default, 0); var status = session.Read(ref key1, ref input, ref output, Empty.Default, 0); AssertCompleted(new(StatusCode.Found), status); session.Delete(ref key1, Empty.Default, 0); status = session.Read(ref key1, ref input, ref output, Empty.Default, 0); AssertCompleted(new(StatusCode.NotFound), status); var key2 = new KeyStruct { kfield1 = 14, kfield2 = 15 }; var value2 = new ValueStruct { vfield1 = 24, vfield2 = 25 }; session.Upsert(ref key2, ref value2, Empty.Default, 0); status = session.Read(ref key2, ref input, ref output, Empty.Default, 0); AssertCompleted(new(StatusCode.Found), status); Assert.AreEqual(value2.vfield1, output.value.vfield1); Assert.AreEqual(value2.vfield2, output.value.vfield2); }
public void UpsertSerialNumberTest() { // Simple Upsert of Serial Number test so one device is enough deviceType = TestUtils.DeviceType.MLSD; Setup(128, new LogSettings { MemorySizeBits = 29 }, deviceType); int numKeys = 100; int keyMod = 10; int maxLap = numKeys / keyMod; InputStruct input = default; OutputStruct output = default; var value = new ValueStruct { vfield1 = 23, vfield2 = 24 }; var key = new KeyStruct { kfield1 = 13, kfield2 = 14 }; for (int i = 0; i < numKeys; i++) { // lap is used to illustrate the changing values var lap = i / keyMod; session.Upsert(ref key, ref value, serialNo: lap); } // Now verify for (int j = 0; j < numKeys; j++) { var status = session.Read(ref key, ref input, ref output, serialNo: maxLap + 1); AssertCompleted(new(StatusCode.Found), status); Assert.AreEqual(value.vfield1, output.value.vfield1); Assert.AreEqual(value.vfield2, output.value.vfield2); } }
public unsafe void NativeInMemWriteRead2() { Random r = new Random(10); for (int c = 0; c < 1000; c++) { var i = r.Next(10000); var key1 = new KeyStruct { kfield1 = i, kfield2 = i + 1 }; var value = new ValueStruct { vfield1 = i, vfield2 = i + 1 }; fht.Upsert(&key1, &value, null, 0); } r = new Random(10); for (int c = 0; c < 1000; c++) { var i = r.Next(10000); OutputStruct output = default(OutputStruct); var key1 = new KeyStruct { kfield1 = i, kfield2 = i + 1 }; var value = new ValueStruct { vfield1 = i, vfield2 = i + 1 }; if (fht.Read(&key1, null, &output, null, 0) == Status.PENDING) { fht.CompletePending(true); } Assert.IsTrue(output.value.vfield1 == value.vfield1); Assert.IsTrue(output.value.vfield2 == value.vfield2); } }
public void ReadBareMinParams([Values] TestUtils.DeviceType deviceType) { Setup(128, new LogSettings { MemorySizeBits = 22, SegmentSizeBits = 22, PageSizeBits = 10 }, deviceType); var key1 = new KeyStruct { kfield1 = 13, kfield2 = 14 }; var value = new ValueStruct { vfield1 = 23, vfield2 = 24 }; session.Upsert(ref key1, ref value, Empty.Default, 0); var(status, output) = session.Read(key1); AssertCompleted(new(StatusCode.Found), status); Assert.AreEqual(value.vfield1, output.value.vfield1); Assert.AreEqual(value.vfield2, output.value.vfield2); Assert.AreEqual(key1.kfield1, 13); Assert.AreEqual(key1.kfield2, 14); }
public void ShouldCreateNewRecordIfConcurrentWriterReturnsFalse() { var copyOnWrite = new FunctionsCopyOnWrite(); // FunctionsCopyOnWrite var log = default(IDevice); try { log = Devices.CreateLogDevice(TestUtils.MethodTestDir + "/hlog1.log", deleteOnClose: true); using var fht = new FasterKV <KeyStruct, ValueStruct> (128, new LogSettings { LogDevice = log, MemorySizeBits = 29 }); using var session = fht.NewSession(copyOnWrite); var key = default(KeyStruct); var value = default(ValueStruct); var input = default(InputStruct); var output = default(OutputStruct); key = new KeyStruct() { kfield1 = 1, kfield2 = 2 }; value = new ValueStruct() { vfield1 = 1000, vfield2 = 2000 }; var status = session.Upsert(ref key, ref input, ref value, ref output, out RecordMetadata recordMetadata1); Assert.IsTrue(!status.Found && status.Record.Created, status.ToString()); // ConcurrentWriter returns false, so we create a new record (and leave the old one sealed). value = new ValueStruct() { vfield1 = 1001, vfield2 = 2002 }; status = session.Upsert(ref key, ref input, ref value, ref output, out RecordMetadata recordMetadata2); Assert.IsTrue(!status.Found && status.Record.Created, status.ToString()); Assert.Greater(recordMetadata2.Address, recordMetadata1.Address); var recordCount = 0; using (var iterator = fht.Log.Scan(fht.Log.BeginAddress, fht.Log.TailAddress)) { // We seal before copying and leave it sealed after copying, so we only get one record. while (iterator.GetNext(out var info)) { recordCount++; } } Assert.AreEqual(1, copyOnWrite.ConcurrentWriterCallCount); Assert.AreEqual(1, recordCount); } finally { if (log != null) { log.Dispose(); } } }
public void NativeDiskWriteReadCache() { InputStruct input = default(InputStruct); for (int i = 0; i < 2000; i++) { var key1 = new KeyStruct { kfield1 = i, kfield2 = i + 1 }; var value = new ValueStruct { vfield1 = i, vfield2 = i + 1 }; fht.Upsert(ref key1, ref value, Empty.Default, 0); } fht.CompletePending(true); // Evict all records from main memory of hybrid log fht.Log.FlushAndEvict(true); // Read 2000 keys - all should be served from disk, populating and evicting the read cache FIFO for (int i = 0; i < 2000; i++) { OutputStruct output = default(OutputStruct); var key1 = new KeyStruct { kfield1 = i, kfield2 = i + 1 }; var value = new ValueStruct { vfield1 = i, vfield2 = i + 1 }; var status = fht.Read(ref key1, ref input, ref output, Empty.Default, 0); Assert.IsTrue(status == Status.PENDING); fht.CompletePending(true); } // Read last 100 keys - all should be served from cache for (int i = 1900; i < 2000; i++) { OutputStruct output = default(OutputStruct); var key1 = new KeyStruct { kfield1 = i, kfield2 = i + 1 }; var value = new ValueStruct { vfield1 = i, vfield2 = i + 1 }; var status = fht.Read(ref key1, ref input, ref output, Empty.Default, 0); Assert.IsTrue(status == Status.OK); Assert.IsTrue(output.value.vfield1 == value.vfield1); Assert.IsTrue(output.value.vfield2 == value.vfield2); } // Evict the read cache entirely fht.ReadCache.FlushAndEvict(true); // Read 100 keys - all should be served from disk, populating cache for (int i = 1900; i < 2000; i++) { OutputStruct output = default(OutputStruct); var key1 = new KeyStruct { kfield1 = i, kfield2 = i + 1 }; var value = new ValueStruct { vfield1 = i, vfield2 = i + 1 }; var status = fht.Read(ref key1, ref input, ref output, Empty.Default, 0); Assert.IsTrue(status == Status.PENDING); fht.CompletePending(true); } // Read 100 keys - all should be served from cache for (int i = 1900; i < 2000; i++) { OutputStruct output = default(OutputStruct); var key1 = new KeyStruct { kfield1 = i, kfield2 = i + 1 }; var value = new ValueStruct { vfield1 = i, vfield2 = i + 1 }; var status = fht.Read(ref key1, ref input, ref output, Empty.Default, 0); Assert.IsTrue(status == Status.OK); Assert.IsTrue(output.value.vfield1 == value.vfield1); Assert.IsTrue(output.value.vfield2 == value.vfield2); } // Upsert to overwrite the read cache for (int i = 1900; i < 1950; i++) { var key1 = new KeyStruct { kfield1 = i, kfield2 = i + 1 }; var value = new ValueStruct { vfield1 = i + 1, vfield2 = i + 2 }; fht.Upsert(ref key1, ref value, Empty.Default, 0); } // RMW to overwrite the read cache for (int i = 1950; i < 2000; i++) { var key1 = new KeyStruct { kfield1 = i, kfield2 = i + 1 }; input = new InputStruct { ifield1 = 1, ifield2 = 1 }; var status = fht.RMW(ref key1, ref input, Empty.Default, 0); if (status == Status.PENDING) { fht.CompletePending(true); } } // Read 100 keys for (int i = 1900; i < 2000; i++) { OutputStruct output = default(OutputStruct); var key1 = new KeyStruct { kfield1 = i, kfield2 = i + 1 }; var value = new ValueStruct { vfield1 = i + 1, vfield2 = i + 2 }; var status = fht.Read(ref key1, ref input, ref output, Empty.Default, 0); Assert.IsTrue(status == Status.OK); Assert.IsTrue(output.value.vfield1 == value.vfield1); Assert.IsTrue(output.value.vfield2 == value.vfield2); } }