예제 #1
0
        /// <summary>
        /// Copy to given SpanByteAndMemory (header length and payload copied to actual span/memory)
        /// </summary>
        /// <param name="src"></param>
        /// <param name="dst"></param>
        /// <param name="memoryPool"></param>
        private unsafe void CopyWithHeaderTo(ref SpanByte src, ref SpanByteAndMemory dst, MemoryPool <byte> memoryPool)
        {
            if (dst.IsSpanByte)
            {
                if (dst.Length >= src.TotalSize)
                {
                    dst.Length = src.TotalSize;
                    var span = dst.SpanByte.AsSpan();

                    fixed(byte *ptr = span)
                    * (int *)ptr = src.Length;

                    src.AsReadOnlySpan().CopyTo(span.Slice(sizeof(int)));
                    return;
                }
                dst.ConvertToHeap();
            }

            dst.Length = src.TotalSize;
            dst.Memory = memoryPool.Rent(src.TotalSize);
            dst.Length = src.TotalSize;

            fixed(byte *ptr = dst.Memory.Memory.Span)
            * (int *)ptr = src.Length;

            src.AsReadOnlySpan().CopyTo(dst.Memory.Memory.Span.Slice(sizeof(int)));
        }
예제 #2
0
        public unsafe void SpanByteTest1()
        {
            Span <byte> output = stackalloc byte[20];
            SpanByte    input  = default;

            using var log = Devices.CreateLogDevice(TestContext.CurrentContext.TestDirectory + "/hlog1.log", deleteOnClose: true);
            using var fht = new FasterKV <SpanByte, SpanByte>
                                (128, new LogSettings { LogDevice = log, MemorySizeBits = 17, PageSizeBits = 12 });
            using var s = fht.NewSession(new SpanByteFunctions <Empty>());

            var key1    = MemoryMarshal.Cast <char, byte>("key1".AsSpan());
            var value1  = MemoryMarshal.Cast <char, byte>("value1".AsSpan());
            var output1 = SpanByteAndMemory.FromFixedSpan(output);

            s.Upsert(key1, value1);

            s.Read(key1, ref input, ref output1);

            Assert.IsTrue(output1.IsSpanByte);
            Assert.IsTrue(output1.SpanByte.AsReadOnlySpan().SequenceEqual(value1));

            var key2    = MemoryMarshal.Cast <char, byte>("key2".AsSpan());
            var value2  = MemoryMarshal.Cast <char, byte>("value2value2value2".AsSpan());
            var output2 = SpanByteAndMemory.FromFixedSpan(output);

            s.Upsert(key2, value2);

            s.Read(key2, ref input, ref output2);

            Assert.IsTrue(!output2.IsSpanByte);
            Assert.IsTrue(output2.Memory.Memory.Span.Slice(0, output2.Length).SequenceEqual(value2));
        }
예제 #3
0
 /// <inheritdoc />
 public unsafe override void ConcurrentReader(ref SpanByte key, ref SpanByte input, ref SpanByte value, ref SpanByteAndMemory dst)
 {
     if (wireFormat != WireFormat.ASCII)
     {
         CopyWithHeaderTo(ref value, ref dst, memoryPool);
     }
 }
예제 #4
0
 /// <inheritdoc />
 public override void ConcurrentReader(ref SpanByte key, ref SpanByte input, ref SpanByte value, ref SpanByteAndMemory dst, ref RecordInfo recordInfo, long address) => CopyWithHeaderTo(ref value, ref dst, memoryPool);
예제 #5
0
 /// <inheritdoc />
 public override void SingleReader(ref SpanByte key, ref SpanByte input, ref SpanByte value, ref SpanByteAndMemory dst, long address) => CopyWithHeaderTo(ref value, ref dst, memoryPool);
예제 #6
0
        /// <inheritdoc/>
        public override void CopyUpdater(ref SpanByte key, ref SpanByte input, ref SpanByte oldValue, ref SpanByte newValue, ref SpanByteAndMemory output)
        {
            long curr = Utils.BytesToLong(oldValue.AsSpan());
            long next = curr + Utils.BytesToLong(input.AsSpan());

            Debug.Assert(Utils.NumDigits(next) == newValue.Length, "Unexpected destination length in CopyUpdater");
            Utils.LongToBytes(next, newValue.AsSpan());
        }
예제 #7
0
        public static void Run()
        {
            const bool useRmw     = true;
            const int  baseNumber = 45;

            // VarLen types do not need an object log
            using var log = Devices.CreateLogDevice("hlog.log", deleteOnClose: true);

            // Create store
            // For custom varlen (not SpanByte), you need to provide IVariableLengthStructSettings and IFasterEqualityComparer.
            // For this test we require record-level locking
            using var store = new FasterKV <SpanByte, SpanByte>(
                      size: 1L << 20,
                          logSettings: new LogSettings { LogDevice = log, MemorySizeBits = 15, PageSizeBits = 12 }, disableLocking: false);

            // Create session for ASCII sums. We require two callback function types to be provided:
            //    AsciiSumSpanByteFunctions implements RMW callback functions
            //    AsciiSumVLS implements the callback for computing the length of the result new value, given an old value and an input
            using var s = store.For(new AsciiSumSpanByteFunctions()).NewSession <AsciiSumSpanByteFunctions>
                              (sessionVariableLengthStructSettings: new SessionVariableLengthStructSettings <SpanByte, SpanByte> { valueLength = new AsciiSumVLS() });

            // Create key
            Span <byte> key = stackalloc byte[10];

            key.Fill(23);
            var _key = SpanByte.FromFixedSpan(key);

            // Create input
            Span <byte> input       = stackalloc byte[10];
            int         inputLength = Utils.LongToBytes(baseNumber, input);
            var         _input      = SpanByte.FromFixedSpan(input.Slice(0, inputLength));

            if (useRmw)
            {
                s.RMW(_key, _input);               // InitialUpdater to 45 (baseNumber)
                s.RMW(_key, _input);               // InPlaceUpdater to 90
                s.RMW(_key, _input);               // CopyUpdater to 135 (due to value size increase)
                s.RMW(_key, _input);               // InPlaceUpdater to 180

                store.Log.Flush(true);             // Flush by moving ReadOnly address to Tail (retain records in memory)
                s.RMW(_key, _input);               // CopyUpdater to 225 (due to immutable source value in read-only region)

                store.Log.FlushAndEvict(true);     // Flush and evict all records to disk
                var _status = s.RMW(_key, _input); // CopyUpdater to 270 (due to immutable source value on disk)

                if (_status.IsPending)
                {
                    Console.WriteLine("Error!");
                    return;
                }
                s.CompletePending(true); // Wait for IO completion
            }
            else
            {
                s.Upsert(_key, _input);
            }

            // Create output space
            Span <byte> output        = stackalloc byte[10];
            var         outputWrapper = new SpanByteAndMemory(SpanByte.FromFixedSpan(output));

            var status = s.Read(ref _key, ref outputWrapper);

            // Read does not go pending, and the output should fit in the provided space (10 bytes)
            // Hence, no Memory will be allocated by FASTER
            if (!status.Found || !outputWrapper.IsSpanByte)
            {
                Console.WriteLine("Error!");
                return;
            }

            // Check result value correctness
            if (useRmw)
            {
                inputLength = Utils.LongToBytes(baseNumber * 6, input);
            }

            if (!outputWrapper.SpanByte.AsReadOnlySpan().SequenceEqual(input.Slice(0, inputLength)))
            {
                Console.WriteLine("Error!");
                return;
            }

            Console.WriteLine("AsciiSumSample: Success!");
        }
예제 #8
0
 /// <inheritdoc/>
 public override void InitialUpdater(ref SpanByte key, ref SpanByte input, ref SpanByte value, ref SpanByteAndMemory output)
 {
     input.CopyTo(ref value);
 }
예제 #9
0
        /// <inheritdoc/>
        public override bool InPlaceUpdater(ref SpanByte key, ref SpanByte input, ref SpanByte value, ref SpanByteAndMemory output)
        {
            long curr = Utils.BytesToLong(value.AsSpan());
            long next = curr + Utils.BytesToLong(input.AsSpan());

            if (Utils.NumDigits(next) > value.Length)
            {
                return(false);
            }
            Utils.LongToBytes(next, value.AsSpan());
            return(true);
        }
 /// <inheritdoc />
 public unsafe override void SingleReader(ref SpanByte key, ref SpanByte input, ref SpanByte value, ref SpanByteAndMemory dst)
 {
     if (wireFormat == WireFormat.Binary)
     {
         CopyWithHeaderTo(ref value, ref dst, memoryPool);
     }
 }
예제 #11
0
 /// <inheritdoc />
 public override void ConcurrentReader(ref SpanByte key, ref SpanByte input, ref SpanByte value, ref SpanByteAndMemory dst) => CopyWithHeaderTo(ref value, ref dst, memoryPool);
예제 #12
0
 /// <inheritdoc />
 public override void SingleReader(ref SpanByte key, ref SpanByte input, ref SpanByte value, ref SpanByteAndMemory dst) => ConcurrentReader(ref key, ref input, ref value, ref dst);
 /// <inheritdoc/>
 public override bool InitialUpdater(ref SpanByte key, ref SpanByte input, ref SpanByte value, ref SpanByteAndMemory output, ref RMWInfo rmwInfo)
 {
     input.CopyTo(ref value);
     return(true);
 }
 /// <inheritdoc />
 public override bool SingleReader(ref SpanByte key, ref SpanByte input, ref SpanByte value, ref SpanByteAndMemory dst, ref ReadInfo readInfo) => CopyWithHeaderTo(ref value, ref dst, memoryPool);