示例#1
0
        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);
        }
示例#2
0
        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);
        }
示例#3
0
        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);
        }
示例#4
0
        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);
        }
示例#5
0
        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);
        }
示例#6
0
        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);
            }
        }
示例#7
0
        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);
            }
        }
示例#8
0
 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);
 }
示例#9
0
 // 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);
 }
示例#10
0
        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);
                }
            }
        }
示例#12
0
        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();
                }
            }
        }
示例#13
0
        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);
        }
示例#15
0
        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();
        }
示例#17
0
        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);
            }
        }
示例#19
0
        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);
        }
示例#20
0
        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);
            }
        }
示例#22
0
        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);
        }
示例#23
0
        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);
                }
            }
        }
示例#24
0
        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);
            }
        }
示例#25
0
        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);
        }
示例#26
0
        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);
            }
        }
示例#27
0
        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);
            }
        }
示例#28
0
        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);
        }
示例#29
0
        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();
                }
            }
        }
示例#30
0
        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);
            }
        }