Represents a large fixed-length memory block where smaller variable-length memory blocks are dynamically allocated
Inheritance: IMemorySlab
示例#1
0
        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);
        }
示例#2
0
        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();
        }
示例#3
0
        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));
        }
示例#4
0
        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);
        }
示例#5
0
        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();
        }
示例#6
0
        /// <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);
        }
示例#7
0
        public void LengthTest()
        {
            MemorySlab slab = new MemorySlab(blockSize * 3, null);

            ManagedBuffer target = GetNewBuffer(slab);
            Assert.AreEqual<long>(blockSize, target.Size);
            target.Dispose();
        }
示例#8
0
 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);
 }
示例#9
0
 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);
 }
示例#10
0
        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();
            }
        }
示例#11
0
        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);

            }
        }
示例#12
0
        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);

            }
        }
示例#13
0
        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);
            }
        }
示例#14
0
        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);

            }
        }
示例#15
0
        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);
            }
        }
示例#16
0
        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);
        }
示例#17
0
        /// <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));
        }
示例#18
0
 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];
 }
示例#19
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;
            }

        }
示例#20
0
        public void IsDisposedTest()
        {
            MemorySlab slab = new MemorySlab(blockSize * 3, null);

            ManagedBuffer target = GetNewBuffer(slab);
            Assert.IsFalse(target.IsDisposed);
            target.Dispose();
            Assert.IsTrue(target.IsDisposed);
        }
示例#21
0
 internal virtual IMemorySlab CreateIMemorySlab()
 {
     IMemorySlab target = new MemorySlab(totalSize, null);
     return target;
 }
示例#22
0
 internal virtual IMemorySlab CreateInvalidMemorySlab2()
 {
     IMemorySlab target = new MemorySlab(0, null);
     return target;
 }
示例#23
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;
            }
        }