public void CopyToTests() { byte[] array = new byte[16] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; SpanByte span = new SpanByte(array); // First a copy to with the full span SpanByte toCopy = new byte[span.Length]; span.CopyTo(toCopy); for (int i = 0; i < span.Length; i++) { Assert.Equal(toCopy[i], span[i], "SpanByte value should be the same as from the original array"); } // Now create a larger span toCopy = new byte[span.Length + 1]; span.CopyTo(toCopy); for (int i = 0; i < span.Length; i++) { Assert.Equal(toCopy[i], span[i], "SpanByte value should be the same as from the original array"); } Assert.Equal(toCopy[span.Length], (byte)0); }
/// <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); } }
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)); }
public void ConstructorsOfAllKindsTests() { // Empty span SpanByte span = new SpanByte(); Assert.Equal(span.Length, 0, "Empty SpanByte should have length of 0"); Assert.True(span.IsEmpty, "Empty SpanByte should be IsEmpty"); // Empty span span = new SpanByte(null, 0, 0); Assert.Equal(span.Length, 0, "Empty SpanByte should have length of 0"); Assert.True(span.IsEmpty, "Empty SpanByte should be IsEmpty"); // Empty span span = SpanByte.Empty; Assert.Equal(span.Length, 0, "Empty SpanByte should have length of 0"); Assert.True(span.IsEmpty, "Empty SpanByte should be IsEmpty"); // Span from normal array byte[] array = new byte[16] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; span = new SpanByte(array); Assert.Equal(span.Length, array.Length, $"SpanByte should have length of the array it takes: {array.Length}"); Assert.False(span.IsEmpty, "SpanByte should NOT be IsEmpty"); // Span from normal array with different start and length span = new SpanByte(array, 2, 8); Assert.Equal(span.Length, 8, $"SpanByte should have length of 8"); Assert.False(span.IsEmpty, "SpanByte should NOT be IsEmpty"); }
/// <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); } }
private bool SendRequest(CommandSet cmd, byte dataHi, byte dataLo) { msg[3] = (byte)cmd; msg[5] = dataHi; msg[6] = dataLo; var data = new SpanByte(msg, 1, msg.Length - 1); UInt16 chk = CalcCheckSum(data, msg[2]); msg[7] = (byte)(chk >> 8); msg[8] = (byte)(chk & 0x00ff); outputDataWriter.WriteBytes(msg); outputDataWriter.Store(); bufIdx = 0; Thread.Sleep(20); timeSent = DateTime.UtcNow; status.Code = StatusCode.STS_OK; waitResponse = true; do { Thread.Sleep(10); } while (!Check()); return(true); }
/// <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))); }
/// <inheritdoc/> public override void CopyUpdater(ref SpanByte key, ref SpanByte input, ref SpanByte oldValue, ref SpanByte newValue) { 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()); }
public unsafe void MultiReadSpanByteKeyTest() { using var log = Devices.CreateLogDevice(TestContext.CurrentContext.TestDirectory + "/MultiReadSpanByteKeyTest.log", deleteOnClose: true); using var fht = new FasterKV <SpanByte, long>( size: 1L << 20, new LogSettings { LogDevice = log, MemorySizeBits = 15, PageSizeBits = 12 }); using var session = fht.For(new MultiReadSpanByteKeyTestFunctions()).NewSession <MultiReadSpanByteKeyTestFunctions>(); for (int i = 0; i < 3000; i++) { var key = MemoryMarshal.Cast <char, byte>($"{i}".AsSpan()); fixed(byte *_ = key) session.Upsert(SpanByte.FromFixedSpan(key), i); } // Evict all records to disk fht.Log.FlushAndEvict(true); for (long key = 0; key < 50; key++) { // read each key multiple times for (int i = 0; i < 10; i++) { Assert.AreEqual(key, ReadKey($"{key}")); } } long ReadKey(string keyString) { Status status; var key = MemoryMarshal.Cast <char, byte>(keyString.AsSpan()); fixed(byte *_ = key) status = session.Read(key: SpanByte.FromFixedSpan(key), out var unused); // All keys need to be fetched from disk Assert.AreEqual(Status.PENDING, status); session.CompletePendingWithOutputs(out var completedOutputs, wait: true); var count = 0; var value = 0L; using (completedOutputs) { while (completedOutputs.Next()) { count++; Assert.AreEqual(Status.OK, completedOutputs.Current.Status); value = completedOutputs.Current.Output; } } Assert.AreEqual(1, count); return(value); } }
/// <summary> /// Reads an System.Int32 from the beginning of a read-only span of bytes, as little endian. /// </summary> /// <param name="source">The read-only span to read.</param> /// <returns>The little endian value.</returns> public static int ReadInt32LittleEndian(SpanByte source) { if (source.Length < 4) { throw new ArgumentOutOfRangeException($"source is too small to contain an System.Int32."); } return((int)(source[3] << 24 | source[2] << 16 | source[1] << 8 | source[0])); }
/// <summary> /// Reads an System.Int16 from the beginning of a read-only span of bytes, as little endian. /// </summary> /// <param name="source">The read-only span to read.</param> /// <returns>The little endian value.</returns> public static short ReadInt16LittleEndian(SpanByte source) { if (source.Length < 2) { throw new ArgumentOutOfRangeException($"source is too small to contain an System.Int16."); } return((short)(source[1] << 8 | source[0])); }
/// <inheritdoc/> public override bool CopyUpdater(ref SpanByte key, ref SpanByte input, ref SpanByte oldValue, ref SpanByte newValue, ref SpanByteAndMemory output, ref RMWInfo rmwInfo) { 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()); return(true); }
public void ToArrayTest() { byte[] array = new byte[16] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; SpanByte span = new SpanByte(array); byte[] toArray = span.ToArray(); Assert.Equal(array, toArray, "Original array and SpanByte.ToArray should be the same"); }
/// <summary> /// Reads an System.Int64 from the beginning of a read-only span of bytes, as little endian. /// </summary> /// <param name="source">The read-only span to read.</param> /// <returns>The little endian value.</returns> public static long ReadInt64LittleEndian(SpanByte source) { if (source.Length < 8) { throw new ArgumentOutOfRangeException($"source is too small to contain an System.Int64."); } return((long)source[0] << 56 | (long)source[1] << 48 | (long)source[2] << 40 | (long)source[3] << 32 | (long)source[4] << 24 | (long)source[5] << 16 | (long)source[6] << 8 | (long)source[7]); }
/// <summary> /// Writes a System.UInt16 into a span of bytes, as little endian. /// </summary> /// <param name="destination">The span of bytes where the value is to be written, as little endian.</param> /// <param name="value">The value to write into the span of bytes.</param> public static void WriteUInt16LittleEndian(SpanByte destination, ushort value) { if (destination.Length < 2) { throw new ArgumentOutOfRangeException($"destination is too small to contain an System.Int16."); } destination[1] = (byte)(value >> 8); destination[0] = (byte)value; }
public void RaisingExceptionsOfAllKindsTests() { // Should raise an exception on creation Assert.Throws(typeof(ArgumentOutOfRangeException), () => { SpanByte span = new SpanByte(null, 1, 2); }, "ArgumentOutOfRangeException when array is null, start is 1 and length is 2"); Assert.Throws(typeof(ArgumentOutOfRangeException), () => { SpanByte span = new SpanByte(new byte[1], 1, 2); }, "ArgumentOutOfRangeException when array is new byte[1], start is 1 and length is 2"); Assert.Throws(typeof(ArgumentOutOfRangeException), () => { SpanByte span = new SpanByte(new byte[1], 0, 2); }, "ArgumentOutOfRangeException when array is new byte[1], start is 0 and length is 2"); Assert.Throws(typeof(ArgumentOutOfRangeException), () => { SpanByte span = new SpanByte(new byte[1], 2, 0); }, "ArgumentOutOfRangeException when array is new byte[1], start is 2 and length is 0"); // Exception on index access byte[] array = new byte[16] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; Assert.Throws(typeof(ArgumentOutOfRangeException), () => { SpanByte span = new SpanByte(array); var data = span[span.Length]; }); Assert.Throws(typeof(IndexOutOfRangeException), () => { SpanByte span = new SpanByte(array); var data = span[-1]; }); // Copy to with too small destination Assert.Throws(typeof(ArgumentException), () => { SpanByte span = new SpanByte(array); SpanByte destination = new byte[span.Length - 1]; span.CopyTo(destination); }); // Slicing arguments Assert.Throws(typeof(ArgumentOutOfRangeException), () => { SpanByte span = new SpanByte(array); var sliced = span.Slice(span.Length + 1); }); Assert.Throws(typeof(ArgumentOutOfRangeException), () => { SpanByte span = new SpanByte(array); var sliced = span.Slice(1, span.Length); }); Assert.Throws(typeof(ArgumentOutOfRangeException), () => { SpanByte span = new SpanByte(array); var sliced = span.Slice(-1, span.Length); }); Assert.Throws(typeof(ArgumentOutOfRangeException), () => { SpanByte span = new SpanByte(array); var sliced = span.Slice(1, -1); }); }
// Low level code private UInt16 CalcCheckSum(SpanByte data, int len) { UInt16 sum = 0; for (int i = 0; i < len; i++) { sum += data[i]; } return((UInt16)(-sum)); }
/// <inheritdoc/> public override bool InPlaceUpdater(ref SpanByte key, ref SpanByte input, ref SpanByte value) { 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); }
/// <summary> /// Writes a System.UInt32 into a span of bytes, as big endian. /// </summary> /// <param name="destination">The span of bytes where the value is to be written, as big endian.</param> /// <param name="value">The value to write into the span of bytes.</param> public static void WriteUInt32BigEndian(SpanByte destination, uint value) { if (destination.Length < 4) { throw new ArgumentOutOfRangeException($"destination is too small to contain an System.Int32."); } destination[0] = (byte)(value >> 24); destination[1] = (byte)(value >> 16); destination[2] = (byte)(value >> 8); destination[3] = (byte)value; }
/// <summary> /// Copies the contents of this System.Span into a destination System.Span. /// </summary> /// <param name="destination"> The destination System.Span object.</param> /// <exception cref="System.ArgumentException"> /// destination is shorter than the source System.Span. /// </exception> public void CopyTo(SpanByte destination) { if (destination.Length < _length) { throw new ArgumentException($"Destination too small"); } for (int i = 0; i < _length; i++) { destination[i] = _array[_start + i]; } }
public MpuValue(SpanByte arr) { AccelX = (short)((arr[0] << 8) | arr[1]); AccelY = (short)((arr[2] << 8) | arr[3]); AccelZ = (short)((arr[4] << 8) | arr[5]); //skip 6, 7 GyroX = (short)((arr[8] << 8) | arr[9]); GyroY = (short)((arr[10] << 8) | arr[11]); GyroZ = (short)((arr[12] << 8) | arr[13]); }
public void EmptySpanTests() { // Empty span SpanByte span = SpanByte.Empty; // Create a destination span larger SpanByte destination = new byte[1]; span.CopyTo(destination); // Now also empty destination = SpanByte.Empty; span.CopyTo(destination); }
/// <summary> /// Copies the contents of this System.Span into a destination System.Span. /// </summary> /// <param name="destination"> The destination System.Span object.</param> /// <exception cref="System.ArgumentException"> /// destination is shorter than the source <see cref="SpanByte"/>. /// </exception> public void CopyTo(SpanByte destination) { if (destination.Length < _length) { #pragma warning disable S3928 // Parameter names used into ArgumentException constructors should match an existing one throw new ArgumentException(); #pragma warning restore S3928 // Parameter names used into ArgumentException constructors should match an existing one } for (int i = 0; i < _length; i++) { destination[i] = _array[_start + i]; } }
/// <summary> /// Writes a System.UInt64 into a span of bytes, as little endian. /// </summary> /// <param name="destination">The span of bytes where the value is to be written, as little endian.</param> /// <param name="value">The value to write into the span of bytes.</param> public static void WriteUInt64LittleEndian(SpanByte destination, ulong value) { if (destination.Length < 8) { throw new ArgumentOutOfRangeException($"destination is too small to contain an System.Int64."); } destination[7] = (byte)(value >> 56); destination[6] = (byte)(value >> 48); destination[5] = (byte)(value >> 40); destination[4] = (byte)(value >> 32); destination[3] = (byte)(value >> 24); destination[2] = (byte)(value >> 16); destination[1] = (byte)(value >> 8); destination[0] = (byte)value; }
/// <summary> /// Puts a new record or replace the existing one in the store. /// </summary> /// <param name="key">The key of the record.</param> /// <param name="value">The record value.</param> public void Put(ulong key, ref Span <byte> value) { var status = Status.OK; var context = Context.WithUpsert(s => { status = s; }); var fixedSpan = SpanByte.FromFixedSpan(value); status = _session?.Upsert(ref key, ref fixedSpan, context, 0) ?? Status.ERROR; if (status == Status.PENDING) { _session?.CompletePending(true); } if (status == Status.ERROR) { throw new InvalidOperationException("Error ocurred when inserting data."); } }
// Read completion callback public override void ReadCompletionCallback(ref SpanByte key, ref SpanByte input, ref byte[] output, byte ctx, Status status, RecordMetadata recordMetadata) { if (!status.Found) { Console.WriteLine("Error!"); return; } for (int i = 0; i < output.Length; i++) { if (output[i] != ctx) { Console.WriteLine("Error!"); return; } } }
public unsafe void SpanByteUnitTest1() { Span <byte> payload = stackalloc byte[20]; Span <byte> serialized = stackalloc byte[24]; SpanByte sb = SpanByte.FromFixedSpan(payload); Assert.IsFalse(sb.Serialized); Assert.AreEqual(20, sb.Length); Assert.AreEqual(24, sb.TotalSize); Assert.AreEqual(20, sb.AsSpan().Length); Assert.AreEqual(20, sb.AsReadOnlySpan().Length); fixed(byte *ptr = serialized) sb.CopyTo(ptr); ref SpanByte ssb = ref SpanByte.ReinterpretWithoutLength(serialized);
public void SliceTests() { // Span from normal array byte[] array = new byte[16] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; SpanByte span = new SpanByte(array); // Slice 2 elements and check var sliced = span.Slice(0, 2); Assert.Equal(sliced.Length, 2, "Sliced span lenght must be 2"); Assert.Equal(sliced[0], (byte)0x00, "Sliced first element must be value 0"); Assert.Equal(sliced[1], (byte)0x01, "Sliced first element must be value 1"); // Slide 4 elements starting at index 2 and check sliced = span.Slice(2, 4); Assert.Equal(sliced.Length, 4, "Sliced span lenght must be 4"); Assert.Equal(sliced[0], (byte)0x02, "Sliced first element must be value 2"); Assert.Equal(sliced[1], (byte)0x03, "Sliced first element must be value 3"); Assert.Equal(sliced[2], (byte)0x04, "Sliced first element must be value 4"); Assert.Equal(sliced[3], (byte)0x05, "Sliced first element must be value 5"); // Slide starting 4 at element check sliced = span.Slice(4); Assert.Equal(sliced.Length, 12, "Sliced span lenght must be 12"); for (int i = 0; i < sliced.Length; i++) { Assert.Equal(sliced[i], span[i + 4], "SpanByte value should be the same as from the original span"); } // Slice of slice var secondSliced = sliced.Slice(2, 4); Assert.Equal(secondSliced.Length, 4, "Sliced span lenght must be 12"); for (int i = 0; i < secondSliced.Length; i++) { Assert.Equal(secondSliced[i], sliced[i + 2], "SpanByte value should be the same as from the original span"); } // Should be an empty one var empty = span.Slice(span.Length); Assert.Equal(empty.Length, 0, "slicing all the span should result in an empty span"); Assert.True(empty.IsEmpty, "Empty span should be empty"); }
public void GetElementsTests() { // Span from normal array byte[] array = new byte[16] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; SpanByte span = new SpanByte(array); for (int i = 0; i < span.Length; i++) { Assert.Equal(span[i], array[i], "SpanByte value should be the same as from the original array"); } // Partial span span = new SpanByte(array, 2, 8); for (int i = 0; i < span.Length; i++) { Assert.Equal(span[i], array[i + 2], "SpanByte value should be the same as from the original array"); } }
public void ConcurrentReader(ref SpanByte key, ref TValue input, ref TValue value, ref TValue dst) { dst = value; }