public void CopyFromTest2() { MemorySlab slab = new MemorySlab(blockSize * 3, null); ManagedBuffer target = GetNewBuffer(slab); //Source Array is larger than buffer size long blockSizeMore = blockSize + 1; byte[] SourceArray = GetRandomizedByteArray(blockSizeMore); target.FillWith(SourceArray); }
public void CopyFromTest() { MemorySlab slab = new MemorySlab(blockSize * 3, null); ManagedBuffer target1, target2; { ManagedBuffer target = GetNewBuffer(slab); target1 = target; byte[] SourceArray = GetRandomizedByteArray(blockSize); target.CopyFrom(SourceArray); byte[] copyOfDestination = new byte[blockSize]; Array.Copy(target.GetSegments()[0].Array, target.GetSegments()[0].Offset, copyOfDestination, 0, copyOfDestination.LongLength); Assert.IsTrue(ArraysMatch(SourceArray, copyOfDestination)); //Source Array is smaller than ManagedBuffer Size long blockSizeLess = blockSize - 100; SourceArray = GetRandomizedByteArray(blockSizeLess); target.CopyFrom(SourceArray); copyOfDestination = new byte[blockSizeLess]; Array.Copy(target.GetSegments()[0].Array, target.GetSegments()[0].Offset, copyOfDestination, 0, copyOfDestination.LongLength); Assert.IsTrue(ArraysMatch(SourceArray, copyOfDestination)); } //Repeat test with a new buffer to confirm that offsets within slab arrays are accurately tracked //and to make sure there is no off by 1 error { ManagedBuffer target = GetNewBuffer(slab); target2 = target; byte[] SourceArray = GetRandomizedByteArray(blockSize); target.CopyFrom(SourceArray); byte[] copyOfDestination = new byte[blockSize]; Array.Copy(target.GetSegments()[0].Array, target.GetSegments()[0].Offset, copyOfDestination, 0, copyOfDestination.LongLength); Assert.IsTrue(ArraysMatch(SourceArray, copyOfDestination)); //Source Array is smaller than ManagedBuffer Size long blockSizeLess = blockSize - 1; SourceArray = GetRandomizedByteArray(blockSizeLess); target.CopyFrom(SourceArray); copyOfDestination = new byte[blockSizeLess]; Array.Copy(target.GetSegments()[0].Array, target.GetSegments()[0].Offset, copyOfDestination, 0, copyOfDestination.LongLength); Assert.IsTrue(ArraysMatch(SourceArray, copyOfDestination)); } target2.Dispose(); target1.Dispose(); }
public void CopyToTest3() { MemorySlab slab = new MemorySlab(blockSize * 3, null); ManagedBuffer target = GetNewBuffer(slab); target.CopyFrom(GetRandomizedByteArray(blockSize)); byte[] DestArray = new byte[blockSize]; target.CopyTo(DestArray, 1, blockSize - 2); byte[] copyOfSource = new byte[blockSize - 2]; byte[] copyOfDestination = new byte[blockSize - 2]; Array.Copy(DestArray, 1, copyOfDestination, 0, copyOfDestination.LongLength); Array.Copy(target.GetSegments()[0].Array, target.GetSegments()[0].Offset, copyOfSource, 0, copyOfSource.LongLength); Assert.IsTrue(ArraysMatch(copyOfSource, copyOfDestination)); }
public void CopyToTest2() { MemorySlab slab = new MemorySlab(blockSize * 3, null); ManagedBuffer target = GetNewBuffer(slab); //Destination array is smaller than buffer size byte[] DestArray = new byte[blockSize - 1]; target.CopyTo(DestArray); }
public void CopyToTest() { MemorySlab slab = new MemorySlab(blockSize * 3, null); ManagedBuffer target1, target2; { ManagedBuffer target = GetNewBuffer(slab); target1 = target; target.CopyFrom(GetRandomizedByteArray(blockSize)); byte[] DestArray = new byte[blockSize]; target.CopyTo(DestArray); byte[] copyOfSource = new byte[blockSize]; byte[] copyOfDestination = new byte[blockSize]; Array.Copy(DestArray, 0, copyOfDestination, 0, copyOfDestination.LongLength); Array.Copy(target.GetSegments()[0].Array, target.GetSegments()[0].Offset, copyOfSource, 0, copyOfSource.LongLength); Assert.IsTrue(ArraysMatch(copyOfSource, copyOfDestination)); //Destination Array is larger than ManagedBuffer Size target.CopyFrom(GetRandomizedByteArray(blockSize)); DestArray = new byte[blockSize + 100]; target.CopyTo(DestArray); copyOfSource = new byte[blockSize]; copyOfDestination = new byte[blockSize]; Array.Copy(DestArray, 0, copyOfDestination, 0, copyOfDestination.LongLength); Array.Copy(target.GetSegments()[0].Array, target.GetSegments()[0].Offset, copyOfSource, 0, copyOfSource.LongLength); Assert.IsTrue(ArraysMatch(copyOfSource, copyOfDestination)); } //Repeat test with a new buffer to confirm that offsets within slab arrays are accurately tracked //and to make sure there is no off by 1 error { ManagedBuffer target = GetNewBuffer(slab); target2 = target; target.CopyFrom(GetRandomizedByteArray(blockSize)); byte[] DestArray = new byte[blockSize]; target.CopyTo(DestArray); byte[] copyOfSource = new byte[blockSize]; byte[] copyOfDestination = new byte[blockSize]; Array.Copy(DestArray, 0, copyOfDestination, 0, copyOfDestination.LongLength); Array.Copy(target.GetSegments()[0].Array, target.GetSegments()[0].Offset, copyOfSource, 0, copyOfSource.LongLength); Assert.IsTrue(ArraysMatch(copyOfSource, copyOfDestination)); //Destination Array is larger than ManagedBuffer Size target.CopyFrom(GetRandomizedByteArray(blockSize)); DestArray = new byte[blockSize + 1]; target.CopyTo(DestArray); copyOfSource = new byte[blockSize]; copyOfDestination = new byte[blockSize]; Array.Copy(DestArray, 0, copyOfDestination, 0, copyOfDestination.LongLength); Array.Copy(target.GetSegments()[0].Array, target.GetSegments()[0].Offset, copyOfSource, 0, copyOfSource.LongLength); Assert.IsTrue(ArraysMatch(copyOfSource, copyOfDestination)); } target2.Dispose(); target1.Dispose(); }
/// <summary> /// Creates a buffer of the specified size /// </summary> /// <param name="size">Buffer size, in bytes</param> /// <returns>IBuffer object of requested size</returns> public IBuffer GetBuffer(long size) { if (size < 0) throw new ArgumentException("Length must be greater than 0"); if (size == 0) return new ManagedBuffer(firstSlab); //Return an empty buffer IMemoryBlock allocatedBlock; IMemorySlab[] slabArr; if (singleSlabPool == -1) { //Optimization: Chances are that there'll be just one slab in a pool, so access it directly //and avoid the lock statement involved while creating an array of slabs. //Note that even if singleSlabPool is inaccurate, this method will still work properly. //The optimization is effective because singleSlabPool will be accurate majority of the time. slabArr = new IMemorySlab[] { firstSlab }; if (TryAllocateBlockInSlabs(size, slabArr, out allocatedBlock)) { return new ManagedBuffer(allocatedBlock); } Interlocked.Exchange(ref singleSlabPool, 0); // Slab count will soon be incremented } else { lock (sync_slabList) { slabArr = slabs.ToArray(); } if (TryAllocateBlockInSlabs(size, slabArr, out allocatedBlock)) { return new ManagedBuffer(allocatedBlock); } } lock (sync_newSlab) { //Look again for free block lock (sync_slabList) { slabArr = slabs.ToArray(); } if (TryAllocateBlockInSlabs(size, slabArr, out allocatedBlock)) { //found it -- leave return new ManagedBuffer(allocatedBlock); } //Unable to find available free space, so create new slab MemorySlab newSlab = new MemorySlab(slabSize, this); newSlab.TryAllocate(size, out allocatedBlock); lock (sync_slabList) { //Add new Slab to collection slabs.Add(newSlab); //Add extra slabs as requested in object properties for (int i = 0; i < subsequentSlabs - 1; i++) { slabs.Add(new MemorySlab(slabSize, this)); } } } return new ManagedBuffer(allocatedBlock); }
public void LengthTest() { MemorySlab slab = new MemorySlab(blockSize * 3, null); ManagedBuffer target = GetNewBuffer(slab); Assert.AreEqual<long>(blockSize, target.Size); target.Dispose(); }
public void GetArraySegmentTest8() { MemorySlab slab = new MemorySlab(blockSize * 3, null); ManagedBuffer target = GetNewBuffer(slab); ArraySegment<byte> actual; actual = target.GetSegments()[0]; Assert.AreEqual<long>(actual.Offset, target.memoryBlock.StartLocation); Assert.AreEqual<long>(actual.Count, Math.Min(target.Size, int.MaxValue )); Assert.AreEqual<byte[]>(actual.Array, target.memoryBlock.Slab.Array); }
public void GetArraySegmentTest6() { MemorySlab slab = new MemorySlab(blockSize * 3, null); ManagedBuffer target = GetNewBuffer(slab); int Length = 0; ArraySegment<byte> actual; actual = target.GetSegments(Length)[0]; Assert.AreEqual<long>(actual.Offset, 0 + target.memoryBlock.StartLocation); Assert.AreEqual<long>(actual.Count, Length); Assert.AreEqual<byte[]>(actual.Array, target.memoryBlock.Slab.Array); }
public void NewBufferIsFreshTest() { MemorySlab slab = new MemorySlab(blockSize * 3, null); //Save some random junk into a buffer and dispose it. { ManagedBuffer target1 = GetNewBuffer(slab); byte[] SourceArray = GetRandomizedByteArray(blockSize); target1.FillWith(SourceArray); target1.Dispose(); } //Get a fresh buffer and confirm that it's zero-filled. { ManagedBuffer target2 = GetNewBuffer(slab); byte[] DestArray = new byte[blockSize]; target2.CopyTo(DestArray); Assert.IsTrue(ArraysMatch(DestArray, new byte[blockSize])); target2.Dispose(); } }
public void GetSegmentsTest8() { //Single slab test: { MemorySlab slab = new MemorySlab(blockSize * 3, null); ManagedBuffer target = GetNewBuffer(slab); var actual = target.GetSegments(); Assert.AreEqual<int>(1, actual.Count); Assert.AreEqual<long>(target.MemoryBlocks[0].StartLocation, actual[0].Offset); Assert.AreEqual<long>(target.Size, actual[0].Count); Assert.AreEqual<byte[]>(target.MemoryBlocks[0].Slab.Array, actual[0].Array); } //Multi slab test: { MemorySlab[] slabs = { new MemorySlab(blockSize * 2, null), new MemorySlab(blockSize * 2, null), new MemorySlab(blockSize * 2, null) }; ManagedBuffer target = GetNewBuffer(slabs); var actual = target.GetSegments(); Assert.AreEqual(3, actual.Count); Assert.AreEqual<long>(target.MemoryBlocks[0].StartLocation, actual[0].Offset); Assert.AreEqual<long>(target.MemoryBlocks[1].StartLocation, actual[1].Offset); Assert.AreEqual<long>(target.MemoryBlocks[2].StartLocation, actual[2].Offset); Assert.AreEqual<long>(target.Size, actual[0].Count + actual[1].Count + actual[2].Count); Assert.AreEqual<byte[]>(target.MemoryBlocks[0].Slab.Array, actual[0].Array); Assert.AreEqual<byte[]>(target.MemoryBlocks[1].Slab.Array, actual[1].Array); Assert.AreEqual<byte[]>(target.MemoryBlocks[2].Slab.Array, actual[2].Array); } }
public void GetSegmentsTest5() { //Single slab test: { MemorySlab slab = new MemorySlab(blockSize * 3, null); ManagedBuffer target = GetNewBuffer(slab); int Length = (int)(blockSize - 1); var actual = target.GetSegments(Length); Assert.AreEqual(1, actual.Count); Assert.AreEqual<long>(target.MemoryBlocks[0].StartLocation, actual[0].Offset); Assert.AreEqual<long>(Length, actual[0].Count); Assert.AreEqual<byte[]>(target.MemoryBlocks[0].Slab.Array, actual[0].Array); //Test again for full blocksize Length = (int)(blockSize); actual = target.GetSegments(Length); Assert.AreEqual(1, actual.Count); Assert.AreEqual<long>(actual[0].Offset, target.MemoryBlocks[0].StartLocation); Assert.AreEqual<long>(actual[0].Count, Length); Assert.AreEqual<byte[]>(actual[0].Array, target.MemoryBlocks[0].Slab.Array); } //Multi slab test: { MemorySlab[] slabs = { new MemorySlab(blockSize * 2, null), new MemorySlab(blockSize * 2, null), new MemorySlab(blockSize * 2, null) }; ManagedBuffer target = GetNewBuffer(slabs); int Length = (int)(blockSize - 1); var actual = target.GetSegments(Length); Assert.AreEqual(1, actual.Count); Assert.AreEqual<long>(target.MemoryBlocks[0].StartLocation, actual[0].Offset); Assert.AreEqual<long>(Length, actual[0].Count); Assert.AreEqual<byte[]>(target.MemoryBlocks[0].Slab.Array, actual[0].Array); //Test for full blocksize Length = (int)blockSize; actual = target.GetSegments(Length); Assert.AreEqual(1, actual.Count); Assert.AreEqual<long>(target.MemoryBlocks[0].StartLocation, actual[0].Offset); Assert.AreEqual<long>(Length, actual[0].Count); Assert.AreEqual<byte[]>(target.MemoryBlocks[0].Slab.Array, actual[0].Array); //Test that blocksize plus 1 flows into another segment Length = (int)(blockSize + 1); actual = target.GetSegments(Length); Assert.AreEqual(2, actual.Count); Assert.AreEqual<long>(target.MemoryBlocks[0].StartLocation, actual[0].Offset); Assert.AreEqual<long>(target.MemoryBlocks[1].StartLocation, actual[1].Offset); Assert.AreEqual(1, actual[1].Count); Assert.AreEqual<long>(Length, actual[0].Count + actual[1].Count); Assert.AreEqual<byte[]>(target.MemoryBlocks[0].Slab.Array, actual[0].Array); Assert.AreEqual<byte[]>(target.MemoryBlocks[1].Slab.Array, actual[1].Array); //Test that (blocksize * 2) - 1 stays in two segments Length = (int)(blockSize * 2 - 1); actual = target.GetSegments(Length); Assert.AreEqual(2, actual.Count); Assert.AreEqual<long>(target.MemoryBlocks[0].StartLocation, actual[0].Offset); Assert.AreEqual<long>(target.MemoryBlocks[1].StartLocation, actual[1].Offset); Assert.AreEqual(blockSize - 1, actual[1].Count); Assert.AreEqual<long>(Length, actual[0].Count + actual[1].Count); Assert.AreEqual<byte[]>(target.MemoryBlocks[0].Slab.Array, actual[0].Array); Assert.AreEqual<byte[]>(target.MemoryBlocks[1].Slab.Array, actual[1].Array); //Test that (blocksize * 2) stays in two segments Length = (int)(blockSize * 2); actual = target.GetSegments(Length); Assert.AreEqual(2, actual.Count); Assert.AreEqual<long>(target.MemoryBlocks[0].StartLocation, actual[0].Offset); Assert.AreEqual<long>(target.MemoryBlocks[1].StartLocation, actual[1].Offset); Assert.AreEqual(blockSize, actual[1].Count); Assert.AreEqual<long>(Length, actual[0].Count + actual[1].Count); Assert.AreEqual<byte[]>(target.MemoryBlocks[0].Slab.Array, actual[0].Array); Assert.AreEqual<byte[]>(target.MemoryBlocks[1].Slab.Array, actual[1].Array); //Test that (blocksize * 2) + 1 flows into the third segment Length = (int)(blockSize * 2 + 1); actual = target.GetSegments(Length); Assert.AreEqual(3, actual.Count); Assert.AreEqual<long>(target.MemoryBlocks[0].StartLocation, actual[0].Offset); Assert.AreEqual<long>(target.MemoryBlocks[1].StartLocation, actual[1].Offset); Assert.AreEqual<long>(target.MemoryBlocks[2].StartLocation, actual[2].Offset); Assert.AreEqual(1, actual[2].Count); Assert.AreEqual<long>(Length, actual[0].Count + actual[1].Count + actual[2].Count); Assert.AreEqual<byte[]>(target.MemoryBlocks[0].Slab.Array, actual[0].Array); Assert.AreEqual<byte[]>(target.MemoryBlocks[1].Slab.Array, actual[1].Array); Assert.AreEqual<byte[]>(target.MemoryBlocks[2].Slab.Array, actual[2].Array); } }
public void GetSegmentsTest2() { //Single Slab test { MemorySlab slab = new MemorySlab(blockSize * 3, null); ManagedBuffer target = GetNewBuffer(slab); int Offset = 0; int Length = 0; var actual = target.GetSegments(Offset, Length); Assert.AreEqual<int>(1, actual.Count); Assert.AreEqual<long>(Offset + target.MemoryBlocks[0].StartLocation, actual[0].Offset); Assert.AreEqual<long>(Length, actual[0].Count); Assert.AreEqual<byte[]>(target.MemoryBlocks[0].Slab.Array, actual[0].Array); //Test again at a different offset Offset = 10; Length = 0; actual = target.GetSegments(Offset, Length); Assert.AreEqual<int>(1, actual.Count); Assert.AreEqual<long>(Offset + target.MemoryBlocks[0].StartLocation, actual[0].Offset); Assert.AreEqual<long>(Length, actual[0].Count); Assert.AreEqual<byte[]>(target.MemoryBlocks[0].Slab.Array, actual[0].Array); } //Multi slab test: { MemorySlab[] slabs = { new MemorySlab(blockSize * 2, null), new MemorySlab(blockSize * 2, null), new MemorySlab(blockSize * 2, null) }; ManagedBuffer target = GetNewBuffer(slabs); int Offset = 0; int Length = 0; var actual = target.GetSegments(Offset, Length); Assert.AreEqual(1, actual.Count); Assert.AreEqual<long>(Offset + target.MemoryBlocks[0].StartLocation, actual[0].Offset); Assert.AreEqual<long>(Length, actual[0].Count); Assert.AreEqual<byte[]>(target.MemoryBlocks[0].Slab.Array, actual[0].Array); //Test again at a different offset Offset = 10; Length = 0; actual = target.GetSegments(Offset, Length); Assert.AreEqual<int>(1, actual.Count); Assert.AreEqual<long>(Offset + target.MemoryBlocks[0].StartLocation, actual[0].Offset); Assert.AreEqual<long>(Length, actual[0].Count); Assert.AreEqual<byte[]>(target.MemoryBlocks[0].Slab.Array, actual[0].Array); } }
public void GetSegmentsTest() { //Single Slab tests: { MemorySlab slab = new MemorySlab(blockSize * 3, null); ManagedBuffer target = GetNewBuffer(slab); int Offset = 0; int Length = (int)(blockSize - 1); ArraySegment<byte> actual; actual = target.GetSegments(Offset, Length)[0]; Assert.AreEqual<long>(actual.Offset, Offset + target.MemoryBlocks[0].StartLocation); Assert.AreEqual<long>(actual.Count, Length); Assert.AreEqual<byte[]>(actual.Array, target.MemoryBlocks[0].Slab.Array); //Test for full blocksize Offset = 0; Length = (int)blockSize; actual = target.GetSegments(Offset, Length)[0]; Assert.AreEqual<long>(actual.Offset, Offset + target.MemoryBlocks[0].StartLocation); Assert.AreEqual<long>(actual.Count, Length); Assert.AreEqual<byte[]>(actual.Array, target.MemoryBlocks[0].Slab.Array); //Test for offset of 1 Offset = 1; Length = (int)(blockSize - 1); actual = target.GetSegments(Offset, Length)[0]; Assert.AreEqual<long>(actual.Offset, Offset + target.MemoryBlocks[0].StartLocation); Assert.AreEqual<long>(actual.Count, Length); Assert.AreEqual<byte[]>(actual.Array, target.MemoryBlocks[0].Slab.Array); } //Multi-Slab tests: { MemorySlab[] slabs = { new MemorySlab(blockSize * 2, null), new MemorySlab(blockSize * 2, null), new MemorySlab(blockSize * 2, null) }; ManagedBuffer target = GetNewBuffer(slabs); int Offset = 0; int Length = (int)(blockSize - 1); var actual = target.GetSegments(Offset, Length); Assert.AreEqual(1, actual.Count); Assert.AreEqual<long>(Offset + target.MemoryBlocks[0].StartLocation, actual[0].Offset); Assert.AreEqual<long>(Length, actual[0].Count); Assert.AreEqual<byte[]>(target.MemoryBlocks[0].Slab.Array,actual[0].Array); //Test for full blocksize Offset = 0; Length = (int)blockSize; actual = target.GetSegments(Offset, Length); Assert.AreEqual(1, actual.Count); Assert.AreEqual<long>(Offset + target.MemoryBlocks[0].StartLocation, actual[0].Offset); Assert.AreEqual<long>(Length, actual[0].Count); Assert.AreEqual<byte[]>(target.MemoryBlocks[0].Slab.Array, actual[0].Array); //Test for offset of 1 Offset = 1; Length = (int)(blockSize - 1); actual = target.GetSegments(Offset, Length); Assert.AreEqual(1, actual.Count); Assert.AreEqual<long>(Offset + target.MemoryBlocks[0].StartLocation, actual[0].Offset); Assert.AreEqual<long>(Length, actual[0].Count); Assert.AreEqual<byte[]>(target.MemoryBlocks[0].Slab.Array, actual[0].Array); //Test that offset of 1 plus blocksize flows into another segment Offset = 1; Length = (int)(blockSize); actual = target.GetSegments(Offset, Length); Assert.AreEqual(2, actual.Count); Assert.AreEqual<long>(Offset + target.MemoryBlocks[0].StartLocation, actual[0].Offset); Assert.AreEqual<long>(target.MemoryBlocks[1].StartLocation, actual[1].Offset); Assert.AreEqual(1, actual[1].Count); Assert.AreEqual<long>(Length, actual[0].Count + actual[1].Count); Assert.AreEqual<byte[]>(target.MemoryBlocks[0].Slab.Array, actual[0].Array); Assert.AreEqual<byte[]>(target.MemoryBlocks[1].Slab.Array, actual[1].Array); //Test that offset of 1 plus (blocksize * 2) - 2 stays in two segments Offset = 1; Length = (int)(blockSize * 2 - 2); actual = target.GetSegments(Offset, Length); Assert.AreEqual(2, actual.Count); Assert.AreEqual<long>(Offset + target.MemoryBlocks[0].StartLocation, actual[0].Offset); Assert.AreEqual<long>(target.MemoryBlocks[1].StartLocation, actual[1].Offset); Assert.AreEqual(blockSize - 1, actual[1].Count); Assert.AreEqual<long>(Length, actual[0].Count + actual[1].Count); Assert.AreEqual<byte[]>(target.MemoryBlocks[0].Slab.Array, actual[0].Array); Assert.AreEqual<byte[]>(target.MemoryBlocks[1].Slab.Array, actual[1].Array); //Test that offset of 1 plus (blocksize * 2) - 1 stays in two segments Offset = 1; Length = (int)(blockSize * 2 - 1); actual = target.GetSegments(Offset, Length); Assert.AreEqual(2, actual.Count); Assert.AreEqual<long>(Offset + target.MemoryBlocks[0].StartLocation, actual[0].Offset); Assert.AreEqual<long>(target.MemoryBlocks[1].StartLocation, actual[1].Offset); Assert.AreEqual(blockSize, actual[1].Count); Assert.AreEqual<long>(Length, actual[0].Count + actual[1].Count); Assert.AreEqual<byte[]>(target.MemoryBlocks[0].Slab.Array, actual[0].Array); Assert.AreEqual<byte[]>(target.MemoryBlocks[1].Slab.Array, actual[1].Array); //Test that offset of 0 plus (blocksize * 2) stays in two segments Offset = 0; Length = (int)(blockSize * 2); actual = target.GetSegments(Offset, Length); Assert.AreEqual(2, actual.Count); Assert.AreEqual<long>(Offset + target.MemoryBlocks[0].StartLocation, actual[0].Offset); Assert.AreEqual<long>(target.MemoryBlocks[1].StartLocation, actual[1].Offset); Assert.AreEqual(blockSize, actual[1].Count); Assert.AreEqual<long>(Length, actual[0].Count + actual[1].Count); Assert.AreEqual<byte[]>(target.MemoryBlocks[0].Slab.Array, actual[0].Array); Assert.AreEqual<byte[]>(target.MemoryBlocks[1].Slab.Array, actual[1].Array); //Test that offset of 1 plus (blocksize * 2) flows into the third segment Offset = 1; Length = (int)(blockSize * 2); actual = target.GetSegments(Offset, Length); Assert.AreEqual(3, actual.Count); Assert.AreEqual<long>(Offset + target.MemoryBlocks[0].StartLocation, actual[0].Offset); Assert.AreEqual<long>(target.MemoryBlocks[1].StartLocation, actual[1].Offset); Assert.AreEqual<long>(target.MemoryBlocks[2].StartLocation, actual[2].Offset); Assert.AreEqual(1, actual[2].Count); Assert.AreEqual<long>(Length, actual[0].Count + actual[1].Count + actual[2].Count); Assert.AreEqual<byte[]>(target.MemoryBlocks[0].Slab.Array, actual[0].Array); Assert.AreEqual<byte[]>(target.MemoryBlocks[1].Slab.Array, actual[1].Array); Assert.AreEqual<byte[]>(target.MemoryBlocks[2].Slab.Array, actual[2].Array); } }
public void DisposeTest() { MemorySlab slab = new MemorySlab(blockSize * 3, null); ManagedBuffer target = GetNewBuffer(slab); target.Dispose(); //Call Dispose again, shouldn't cause any exceptions to be thrown target.Dispose(); //Try to work with disposed object. should throw exceptions { bool exceptionThrown = false; try { target.CopyFrom(new byte[] { 0, 1, 2 }); } catch (ObjectDisposedException) { exceptionThrown = true; } Assert.IsTrue(exceptionThrown); } { bool exceptionThrown = false; try { target.CopyTo(new byte[] { 0, 1, 2 }); } catch (ObjectDisposedException) { exceptionThrown = true; } Assert.IsTrue(exceptionThrown); } { bool exceptionThrown = false; try { target.GetSegments(); } catch (ObjectDisposedException) { exceptionThrown = true; } Assert.IsTrue(exceptionThrown); } }
public void GetArraySegmentTest() { MemorySlab slab = new MemorySlab(blockSize * 3, null); ManagedBuffer target = GetNewBuffer(slab); int Offset = 0; int Length = (int)(blockSize - 1); ArraySegment<byte> actual; actual = target.GetSegments(Offset, Length)[0]; Assert.AreEqual<long>(actual.Offset, Offset + target.memoryBlock.StartLocation); Assert.AreEqual<long>(actual.Count, Length); Assert.AreEqual<byte[]>(actual.Array, target.memoryBlock.Slab.Array); //Test for full blocksize Offset = 0; Length = (int)blockSize; actual = target.GetSegments(Offset, Length)[0]; Assert.AreEqual<long>(actual.Offset, Offset + target.memoryBlock.StartLocation); Assert.AreEqual<long>(actual.Count, Length); Assert.AreEqual<byte[]>(actual.Array, target.memoryBlock.Slab.Array); //Test for offset of 1 Offset = 1; Length = (int)(blockSize - 1); actual = target.GetSegments(Offset, Length)[0]; Assert.AreEqual<long>(actual.Offset, Offset + target.memoryBlock.StartLocation); Assert.AreEqual<long>(actual.Count, Length); Assert.AreEqual<byte[]>(actual.Array, target.memoryBlock.Slab.Array); }
/// <summary> /// Creates a buffer of the specified size /// </summary> /// <param name="size">Buffer size, in bytes</param> /// <returns>IBuffer object of requested size</returns> public IBuffer GetBuffer(long size) { if (size < 0) { throw new ArgumentException("Length must be greater than 0"); } if (size == 0) { return(new ManagedBuffer(firstSlab)); //Return an empty buffer } IMemoryBlock allocatedBlock; IMemorySlab[] slabArr; if (singleSlabPool == -1) { //Optimization: Chances are that there'll be just one slab in a pool, so access it directly //and avoid the lock statement involved while creating an array of slabs. //Note that even if singleSlabPool is inaccurate, this method will still work properly. //The optimization is effective because singleSlabPool will be accurate majority of the time. slabArr = new IMemorySlab[] { firstSlab }; if (TryAllocateBlockInSlabs(size, slabArr, out allocatedBlock)) { return(new ManagedBuffer(allocatedBlock)); } Interlocked.Exchange(ref singleSlabPool, 0); // Slab count will soon be incremented } else { lock (sync_slabList) { slabArr = slabs.ToArray(); } if (TryAllocateBlockInSlabs(size, slabArr, out allocatedBlock)) { return(new ManagedBuffer(allocatedBlock)); } } lock (sync_newSlab) { //Look again for free block lock (sync_slabList) { slabArr = slabs.ToArray(); } if (TryAllocateBlockInSlabs(size, slabArr, out allocatedBlock)) { //found it -- leave return(new ManagedBuffer(allocatedBlock)); } //Unable to find available free space, so create new slab MemorySlab newSlab = new MemorySlab(slabSize, this); newSlab.TryAllocate(size, out allocatedBlock); lock (sync_slabList) { //Add new Slab to collection slabs.Add(newSlab); //Add extra slabs as requested in object properties for (int i = 0; i < subsequentSlabs - 1; i++) { slabs.Add(new MemorySlab(slabSize, this)); } } } return(new ManagedBuffer(allocatedBlock)); }
public void GetArraySegmentTest7() { MemorySlab slab = new MemorySlab(blockSize * 3, null); ManagedBuffer target = GetNewBuffer(slab); int Length = -1; ArraySegment<byte> actual; actual = target.GetSegments(Length)[0]; }
/// <summary> /// Creates a buffer of the specified size, filled with the contents of a specified byte array /// </summary> /// <param name="size">Buffer size, in bytes</param> /// <param name="filledWith">Byte array to copy to buffer</param> /// <returns>IBuffer object of requested size</returns> public IBuffer GetBuffer(long size, byte[] filledWith) { if (size < 0) throw new ArgumentException("size must be greater than 0"); //TODO: If size is larger than 16 * SlabSize (or MaxNumberOfSegments * SlabSize) then throw exception saying you can't have a buffer greater than 16 times Slab size //Write test for this //Make sure filledWith can fit into the requested buffer, so that we do not allocate a buffer and then //an exception is thrown (when IBuffer.FillWith() is called) before the buffer is returned. if (filledWith != null) { if (filledWith.LongLength > size) throw new ArgumentException("Length of filledWith array cannot be larger than desired buffer size"); if (filledWith.LongLength == 0) filledWith = null; //TODO: Write test that will test that IBuffer.FillWith() doesn't throw an exception (and that buffers aren't allocated) in this method } if (size == 0) { //Return an empty buffer return new ManagedBuffer(firstSlab); } List<IMemoryBlock> allocatedBlocks = new List<IMemoryBlock>(); //TODO: Consider the performance penalty involved in making the try-catch below a constrained region //RuntimeHelpers.PrepareConstrainedRegions(); try { IMemorySlab[] slabArr; long allocdLengthTally = 0; if (GetSingleSlabPool()) { //Optimization: Chances are that there'll be just one slab in a pool, so access it directly //and avoid the lock statement involved while creating an array of slabs. //Note that even if singleSlabPool is inaccurate, this method will still work properly. //The optimization is effective because singleSlabPool will be accurate majority of the time. slabArr = new IMemorySlab[] { firstSlab }; allocdLengthTally = TryAllocateBlocksInSlabs(size, MAX_SEGMENTS_PER_BUFFER, slabArr, ref allocatedBlocks); if (allocdLengthTally == size) { //We got the entire length we are looking for, so leave return GetFilledBuffer(allocatedBlocks, filledWith); } SetSingleSlabPool(false); // Slab count will soon be incremented } else { lock (syncSlabList) { slabArr = slabs.ToArray(); } allocdLengthTally = TryAllocateBlocksInSlabs(size, MAX_SEGMENTS_PER_BUFFER, slabArr, ref allocatedBlocks); if (allocdLengthTally == size) { //We got the entire length we are looking for, so leave return GetFilledBuffer(allocatedBlocks, filledWith); } } //Try to create new slab lock (syncNewSlab) { //Look again for free block lock (syncSlabList) { slabArr = slabs.ToArray(); } allocdLengthTally += TryAllocateBlocksInSlabs(size - allocdLengthTally, MAX_SEGMENTS_PER_BUFFER - allocatedBlocks.Count, slabArr, ref allocatedBlocks); if (allocdLengthTally == size) { //found it -- leave return GetFilledBuffer(allocatedBlocks, filledWith); } List<IMemorySlab> newSlabList = new List<IMemorySlab>(); do { //Unable to find available free space, so create new slab MemorySlab newSlab = new MemorySlab(slabSize, this); IMemoryBlock allocdBlk; if (slabSize > size - allocdLengthTally) { //Allocate remnant newSlab.TryAllocate(size - allocdLengthTally, out allocdBlk); } else { //Allocate entire slab newSlab.TryAllocate(slabSize, out allocdBlk); } newSlabList.Add(newSlab); allocatedBlocks.Add(allocdBlk); allocdLengthTally += allocdBlk.Length; } while (allocdLengthTally < size); lock (syncSlabList) { //Add new slabs to collection slabs.AddRange(newSlabList); //Add extra slabs as requested in object properties for (int i = 0; i < subsequentSlabs - 1; i++) { slabs.Add(new MemorySlab(slabSize, this)); } } } return GetFilledBuffer(allocatedBlocks, filledWith); } catch { //OOM, Thread abort exceptions and other ugly things can happen so roll back any allocated blocks. //This will prevent a limbo situation where those blocks are allocated but caller is unaware and can't deallocate them. //NOTE: This try-catch block should not be within a lock as it calls MemorySlab.Free which takes locks, //and in turn calls BufferPool.TryFreeSlabs which takes other locks and can lead to a dead-lock/race condition. //TODO: Write rollback test. for (int b = 0; b < allocatedBlocks.Count; b++) { allocatedBlocks[b].Slab.Free(allocatedBlocks[b]); } throw; } }
public void IsDisposedTest() { MemorySlab slab = new MemorySlab(blockSize * 3, null); ManagedBuffer target = GetNewBuffer(slab); Assert.IsFalse(target.IsDisposed); target.Dispose(); Assert.IsTrue(target.IsDisposed); }
internal virtual IMemorySlab CreateIMemorySlab() { IMemorySlab target = new MemorySlab(totalSize, null); return target; }
internal virtual IMemorySlab CreateInvalidMemorySlab2() { IMemorySlab target = new MemorySlab(0, null); return target; }
/// <summary> /// Creates a buffer of the specified size, filled with the contents of a specified byte array /// </summary> /// <param name="size">Buffer size, in bytes</param> /// <param name="filledWith">Byte array to copy to buffer</param> /// <returns>IBuffer object of requested size</returns> public IBuffer GetBuffer(long size, byte[] filledWith) { if (size < 0) { throw new ArgumentException("size must be greater than 0"); } //TODO: If size is larger than 16 * SlabSize (or MaxNumberOfSegments * SlabSize) then throw exception saying you can't have a buffer greater than 16 times Slab size //Write test for this //Make sure filledWith can fit into the requested buffer, so that we do not allocate a buffer and then //an exception is thrown (when IBuffer.FillWith() is called) before the buffer is returned. if (filledWith != null) { if (filledWith.LongLength > size) { throw new ArgumentException("Length of filledWith array cannot be larger than desired buffer size"); } if (filledWith.LongLength == 0) { filledWith = null; } //TODO: Write test that will test that IBuffer.FillWith() doesn't throw an exception (and that buffers aren't allocated) in this method } if (size == 0) { //Return an empty buffer return(new ManagedBuffer(firstSlab)); } List <IMemoryBlock> allocatedBlocks = new List <IMemoryBlock>(); //TODO: Consider the performance penalty involved in making the try-catch below a constrained region //RuntimeHelpers.PrepareConstrainedRegions(); try { IMemorySlab[] slabArr; long allocdLengthTally = 0; if (GetSingleSlabPool()) { //Optimization: Chances are that there'll be just one slab in a pool, so access it directly //and avoid the lock statement involved while creating an array of slabs. //Note that even if singleSlabPool is inaccurate, this method will still work properly. //The optimization is effective because singleSlabPool will be accurate majority of the time. slabArr = new IMemorySlab[] { firstSlab }; allocdLengthTally = TryAllocateBlocksInSlabs(size, MAX_SEGMENTS_PER_BUFFER, slabArr, ref allocatedBlocks); if (allocdLengthTally == size) { //We got the entire length we are looking for, so leave return(GetFilledBuffer(allocatedBlocks, filledWith)); } SetSingleSlabPool(false); // Slab count will soon be incremented } else { lock (syncSlabList) { slabArr = slabs.ToArray(); } allocdLengthTally = TryAllocateBlocksInSlabs(size, MAX_SEGMENTS_PER_BUFFER, slabArr, ref allocatedBlocks); if (allocdLengthTally == size) { //We got the entire length we are looking for, so leave return(GetFilledBuffer(allocatedBlocks, filledWith)); } } //Try to create new slab lock (syncNewSlab) { //Look again for free block lock (syncSlabList) { slabArr = slabs.ToArray(); } allocdLengthTally += TryAllocateBlocksInSlabs(size - allocdLengthTally, MAX_SEGMENTS_PER_BUFFER - allocatedBlocks.Count, slabArr, ref allocatedBlocks); if (allocdLengthTally == size) { //found it -- leave return(GetFilledBuffer(allocatedBlocks, filledWith)); } List <IMemorySlab> newSlabList = new List <IMemorySlab>(); do { //Unable to find available free space, so create new slab MemorySlab newSlab = new MemorySlab(slabSize, this); IMemoryBlock allocdBlk; if (slabSize > size - allocdLengthTally) { //Allocate remnant newSlab.TryAllocate(size - allocdLengthTally, out allocdBlk); } else { //Allocate entire slab newSlab.TryAllocate(slabSize, out allocdBlk); } newSlabList.Add(newSlab); allocatedBlocks.Add(allocdBlk); allocdLengthTally += allocdBlk.Length; }while (allocdLengthTally < size); lock (syncSlabList) { //Add new slabs to collection slabs.AddRange(newSlabList); //Add extra slabs as requested in object properties for (int i = 0; i < subsequentSlabs - 1; i++) { slabs.Add(new MemorySlab(slabSize, this)); } } } return(GetFilledBuffer(allocatedBlocks, filledWith)); } catch { //OOM, Thread abort exceptions and other ugly things can happen so roll back any allocated blocks. //This will prevent a limbo situation where those blocks are allocated but caller is unaware and can't deallocate them. //NOTE: This try-catch block should not be within a lock as it calls MemorySlab.Free which takes locks, //and in turn calls BufferPool.TryFreeSlabs which takes other locks and can lead to a dead-lock/race condition. //TODO: Write rollback test. for (int b = 0; b < allocatedBlocks.Count; b++) { allocatedBlocks[b].Slab.Free(allocatedBlocks[b]); } throw; } }