/// <summary>
        /// Creates a buffer of the specified fixed capacity. Depending on the required capacity, either a SingleChunkBuffer or a MultiChunkBuffer will be created.
        /// </summary>
        /// <param name="chunkPool">The chunk pool.</param>
        /// <param name="fixedCapacity">The required capacity.</param>
        /// <returns>A buffer.</returns>
        public static IByteBuffer Create(BsonChunkPool chunkPool, int fixedCapacity)
        {
            if (chunkPool == null)
            {
                throw new ArgumentNullException("pool");
            }
            if (fixedCapacity <= 0)
            {
                throw new ArgumentOutOfRangeException("capacity");
            }

            if (fixedCapacity < chunkPool.ChunkSize)
            {
                var chunk = chunkPool.AcquireChunk();
                return(new SingleChunkBuffer(chunk, 0, 0, false));
            }
            else
            {
                var chunksNeeded = ((fixedCapacity - 1) / chunkPool.ChunkSize) + 1;
                var chunks       = new List <BsonChunk>(chunksNeeded);
                for (int i = 0; i < chunksNeeded; i++)
                {
                    chunks.Add(chunkPool.AcquireChunk());
                }
                return(new MultiChunkBuffer(chunks, 0, 0, false));
            }
        }
        /// <summary>
        /// Creates a buffer of the specified length. Depending on the length, either a SingleChunkBuffer or a MultiChunkBuffer will be created.
        /// </summary>
        /// <param name="chunkPool">The chunk pool.</param>
        /// <param name="length">The length.</param>
        /// <returns>A buffer.</returns>
        public static IByteBuffer Create(BsonChunkPool chunkPool, int length)
        {
            if (chunkPool == null)
            {
                throw new ArgumentNullException("pool");
            }
            if (length <= 0)
            {
                throw new ArgumentOutOfRangeException("length");
            }

            if (length < chunkPool.ChunkSize)
            {
                var chunk = chunkPool.AcquireChunk();
                return new SingleChunkBuffer(chunk, 0, length, false);
            }
            else
            {
                var chunksNeeded = ((length - 1) / chunkPool.ChunkSize) + 1;
                var chunks = new List<BsonChunk>(chunksNeeded);
                for (int i = 0; i < chunksNeeded; i++)
                {
                    chunks.Add(chunkPool.AcquireChunk());
                }
                return new MultiChunkBuffer(chunks, 0, length, false);
            }
        }
        public void ChunkSize_get_should_return_expected_result()
        {
            var subject = new BsonChunkPool(1, 16);

            var result = subject.ChunkSize;

            result.Should().Be(16);
        }
        public void Create_should_return_expected_result(
            [Values(1, 63, 64, 65, 128)]
            int minimumCapacity)
        {
            var chunkSource = new BsonChunkPool(1, 64);

            var result = ByteBufferFactory.Create(chunkSource, minimumCapacity);

            result.Capacity.Should().BeGreaterOrEqualTo(minimumCapacity);
        }
        public void Create_should_return_MultiChunkBuffer_when_multiple_chunks_are_required(
            [Values(65, 128)]
            int minimumCapacity)
        {
            var chunkSource = new BsonChunkPool(1, 64);

            var result = ByteBufferFactory.Create(chunkSource, minimumCapacity);

            result.Should().BeOfType<MultiChunkBuffer>();
        }
        public void Create_should_return_SingleChunkBuffer_when_a_single_chunk_is_sufficient(
            [Values(1, 63, 64)]
            int minimumCapacity)
        {
            var chunkSource = new BsonChunkPool(1, 64);

            var result = ByteBufferFactory.Create(chunkSource, minimumCapacity);

            result.Should().BeOfType<SingleChunkBuffer>();
        }
        public void constructor_should_initialize_subject()
        {
            var maxChunkCount = 1;
            var chunkSize = 16;

            var subject = new BsonChunkPool(maxChunkCount, chunkSize);

            var reflector = new Reflector(subject);
            subject.MaxChunkCount.Should().Be(maxChunkCount);
            subject.ChunkSize.Should().Be(chunkSize);
            reflector._disposed.Should().BeFalse();
        }
        // constructors
        /// <summary>
        /// Initializes a new instance of the <see cref="MultiChunkBuffer"/> class.
        /// </summary>
        /// <param name="chunkPool">The chunk pool.</param>
        /// <exception cref="System.ArgumentNullException">chunkPool</exception>
        public MultiChunkBuffer(BsonChunkPool chunkPool)
        {
            if (chunkPool == null)
            {
                throw new ArgumentNullException("chunkPool");
            }

            _chunkPool = chunkPool;
            _chunks = new List<BsonChunk>();
            _chunkSize = chunkPool.ChunkSize;
            _origin = 0;
            _length = 0;
        }
        // constructors
        /// <summary>
        /// Initializes a new instance of the <see cref="MultiChunkBuffer"/> class.
        /// </summary>
        /// <param name="chunkPool">The chunk pool.</param>
        /// <exception cref="System.ArgumentNullException">chunkPool</exception>
        public MultiChunkBuffer(BsonChunkPool chunkPool)
        {
            if (chunkPool == null)
            {
                throw new ArgumentNullException("chunkPool");
            }

            _chunkPool = chunkPool;
            _chunks    = new List <BsonChunk>();
            _chunkSize = chunkPool.ChunkSize;
            _origin    = 0;
            _length    = 0;
        }
Esempio n. 10
0
        // constructors
        /// <summary>
        /// Initializes a new instance of the <see cref="BsonChunk"/> class.
        /// </summary>
        /// <param name="bytes">The bytes.</param>
        /// <param name="chunkPool">The chunk pool.</param>
        /// <exception cref="System.ArgumentNullException">
        /// bytes
        /// or
        /// pool
        /// </exception>
        public BsonChunk(byte[] bytes, BsonChunkPool chunkPool)
        {
            if (bytes == null)
            {
                throw new ArgumentNullException("bytes");
            }
            if (chunkPool == null)
            {
                throw new ArgumentNullException("chunkPool");
            }

            _bytes     = bytes;
            _chunkPool = chunkPool;
        }
Esempio n. 11
0
        // constructors
        /// <summary>
        /// Initializes a new instance of the <see cref="BsonChunk"/> class.
        /// </summary>
        /// <param name="bytes">The bytes.</param>
        /// <param name="chunkPool">The chunk pool.</param>
        /// <exception cref="System.ArgumentNullException">
        /// bytes
        /// or
        /// pool
        /// </exception>
        public BsonChunk(byte[] bytes, BsonChunkPool chunkPool)
        {
            if (bytes == null)
            {
                throw new ArgumentNullException("bytes");
            }
            if (chunkPool == null)
            {
                throw new ArgumentNullException("chunkPool");
            }

            _bytes = bytes;
            _chunkPool = chunkPool;
        }
        // constructors
        /// <summary>
        /// Initializes a new instance of the <see cref="MultiChunkBuffer"/> class.
        /// </summary>
        /// <param name="chunkPool">The chunk pool.</param>
        /// <exception cref="System.ArgumentNullException">chunkPool</exception>
        public MultiChunkBuffer(BsonChunkPool chunkPool)
        {
            if (chunkPool == null)
            {
                throw new ArgumentNullException("chunkPool");
            }

            _chunkPool = chunkPool;
            _chunks = new List<BsonChunk>();
            _chunkSize = chunkPool.ChunkSize;
            _sliceOffset = 0;

            _capacity = 0; // EnsureSpaceAvailable will add capacity as needed
            _length = 0;
            _position = 0;
        }
Esempio n. 13
0
        // constructors
        /// <summary>
        /// Initializes a new instance of the <see cref="MultiChunkBuffer"/> class.
        /// </summary>
        /// <param name="chunkPool">The chunk pool.</param>
        /// <exception cref="System.ArgumentNullException">chunkPool</exception>
        public MultiChunkBuffer(BsonChunkPool chunkPool)
        {
            if (chunkPool == null)
            {
                throw new ArgumentNullException("chunkPool");
            }

            _chunkPool   = chunkPool;
            _chunks      = new List <BsonChunk>();
            _chunkSize   = chunkPool.ChunkSize;
            _sliceOffset = 0;

            _capacity = 0; // EnsureSpaceAvailable will add capacity as needed
            _length   = 0;
            _position = 0;
        }
Esempio n. 14
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MultiChunkBuffer"/> class.
        /// </summary>
        /// <param name="chunks">The chunks.</param>
        /// <param name="sliceOffset">The slice offset.</param>
        /// <param name="length">The length.</param>
        /// <param name="isReadOnly">Whether the buffer is read only.</param>
        /// <exception cref="System.ArgumentNullException">chunks</exception>
        internal MultiChunkBuffer(IEnumerable <BsonChunk> chunks, int sliceOffset, int length, bool isReadOnly)
        {
            if (chunks == null)
            {
                throw new ArgumentNullException("chunks");
            }

            _chunks = new List <BsonChunk>(chunks);
            if (_chunks.Count == 0)
            {
                throw new ArgumentException("No chunks where provided.", "chunks");
            }

            _chunkSize = _chunks[0].Bytes.Length;
            foreach (var chunk in _chunks)
            {
                if (chunk.Bytes.Length != _chunkSize)
                {
                    throw new ArgumentException("The chunks are not all the same size.");
                }
            }

            if (sliceOffset < 0)
            {
                throw new ArgumentOutOfRangeException("sliceOffset");
            }
            _sliceOffset = sliceOffset;

            var maxCapacity = _chunks.Count * _chunkSize - _sliceOffset;

            if (length < 0 || length > maxCapacity)
            {
                throw new ArgumentOutOfRangeException("length");
            }
            _capacity = isReadOnly ? length : maxCapacity;  // the capacity is fixed
            _length   = length;

            _chunkPool  = null;
            _isReadOnly = isReadOnly;
            _position   = 0;

            foreach (var chunk in _chunks)
            {
                chunk.IncrementReferenceCount();
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="MultiChunkBuffer"/> class.
        /// </summary>
        /// <param name="chunks">The chunks.</param>
        /// <param name="origin">The slice offset.</param>
        /// <param name="length">The length.</param>
        /// <param name="isReadOnly">Whether the buffer is read only.</param>
        /// <exception cref="System.ArgumentNullException">chunks</exception>
        internal MultiChunkBuffer(IEnumerable <BsonChunk> chunks, int origin, int length, bool isReadOnly)
        {
            if (chunks == null)
            {
                throw new ArgumentNullException("chunks");
            }

            _chunks = new List <BsonChunk>(chunks);
            if (_chunks.Count == 0)
            {
                throw new ArgumentException("No chunks where provided.", "chunks");
            }

            _chunkSize = _chunks[0].Bytes.Length;
            if (_chunks.Any(c => c.Bytes.Length != _chunkSize))
            {
                throw new ArgumentException("The chunks are not all the same size.");
            }
            _capacity = _chunks.Count * _chunkSize;

            if (origin < 0 || origin > _capacity)
            {
                throw new ArgumentOutOfRangeException("origin");
            }
            _origin = origin;

            if (length < 0 || _origin + length > _capacity)
            {
                throw new ArgumentOutOfRangeException("length");
            }
            _length = length;

            _chunkPool  = null;
            _isReadOnly = isReadOnly;

            foreach (var chunk in _chunks)
            {
                chunk.IncrementReferenceCount();
            }
        }
        public void GetChunk_should_return_expected_result(
            [Values(1, 15, 16, 17, 32)]
            int requestedSize)
        {
            var subject = new BsonChunkPool(1, 16);

            var result = subject.GetChunk(requestedSize);

            result.Bytes.Count.Should().Be(16);
        }
 public ReferenceCountedChunk(byte[] chunk, BsonChunkPool pool)
 {
     _chunk = chunk;
     _pool = pool;
 }
        /// <summary>
        /// Initializes a new instance of the <see cref="MultiChunkBuffer"/> class.
        /// </summary>
        /// <param name="chunks">The chunks.</param>
        /// <param name="origin">The slice offset.</param>
        /// <param name="length">The length.</param>
        /// <param name="isReadOnly">Whether the buffer is read only.</param>
        /// <exception cref="System.ArgumentNullException">chunks</exception>
        internal MultiChunkBuffer(IEnumerable<BsonChunk> chunks, int origin, int length, bool isReadOnly)
        {
            if (chunks == null)
            {
                throw new ArgumentNullException("chunks");
            }

            _chunks = new List<BsonChunk>(chunks);
            if (_chunks.Count == 0)
            {
                throw new ArgumentException("No chunks where provided.", "chunks");
            }

            _chunkSize = _chunks[0].Bytes.Length;
            if (_chunks.Any(c => c.Bytes.Length != _chunkSize))
            {
                throw new ArgumentException("The chunks are not all the same size.");
            }
            _capacity = _chunks.Count * _chunkSize;

            if (origin < 0 || origin > _capacity)
            {
                throw new ArgumentOutOfRangeException("origin");
            }
            _origin = origin;

            if (length < 0 || _origin + length > _capacity)
            {
                throw new ArgumentOutOfRangeException("length");
            }
            _length = length;

            _chunkPool = null;
            _isReadOnly = isReadOnly;

            foreach (var chunk in _chunks)
            {
                chunk.IncrementReferenceCount();
            }
        }
        public void GetChunk_should_return_pooled_chunk_when_one_is_availabe()
        {
            var subject = new BsonChunkPool(1, 16);
            var pooledChunk = subject.GetChunk(1);
            var expectedArray = pooledChunk.Bytes.Array;
            var expectedOffset = pooledChunk.Bytes.Offset;
            pooledChunk.Dispose();

            var result = subject.GetChunk(1);

            result.Bytes.Array.Should().BeSameAs(expectedArray);
            result.Bytes.Offset.Should().Be(expectedOffset);
            result.Bytes.Count.Should().Be(16);
        }
        public void Dispose_should_dispose_subject()
        {
            var pool = new BsonChunkPool(1, 16);
            var subject = pool.GetChunk(1);

            subject.Dispose();

            var reflector = new Reflector(subject);
            reflector._disposed.Should().BeTrue();
        }
        public void Default_set_should_have_expected_effect()
        {
            var originalDefaultPool = BsonChunkPool.Default;
            try
            {
                var newDefaultPool = new BsonChunkPool(1, 16);

                BsonChunkPool.Default = newDefaultPool;

                BsonChunkPool.Default.Should().BeSameAs(newDefaultPool);
            }
            finally
            {
                BsonChunkPool.Default = originalDefaultPool;
            }
        }
        public void MaxChunkCount_get_should_return_expected_result()
        {
            var subject = new BsonChunkPool(1, 16);

            var result = subject.MaxChunkCount;

            result.Should().Be(1);
        }
 public Reflector(BsonChunkPool instance)
 {
     _instance = instance;
 }
        public void Fork_should_throw_when_subject_is_disposed()
        {
            var pool = new BsonChunkPool(1, 16);
            var subject = pool.GetChunk(1);
            subject.Dispose();

            Action action = () => subject.Fork();

            action.ShouldThrow<ObjectDisposedException>().And.ObjectName.Should().Be("DisposableChunk");
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="MultiChunkBuffer"/> class.
        /// </summary>
        /// <param name="chunks">The chunks.</param>
        /// <param name="sliceOffset">The slice offset.</param>
        /// <param name="length">The length.</param>
        /// <param name="isReadOnly">Whether the buffer is read only.</param>
        /// <exception cref="System.ArgumentNullException">chunks</exception>
        internal MultiChunkBuffer(IEnumerable<BsonChunk> chunks, int sliceOffset, int length, bool isReadOnly)
        {
            if (chunks == null)
            {
                throw new ArgumentNullException("chunks");
            }

            _chunks = new List<BsonChunk>(chunks);
            if (_chunks.Count == 0)
            {
                throw new ArgumentException("No chunks where provided.", "chunks");
            }

            _chunkSize = _chunks[0].Bytes.Length;
            foreach (var chunk in _chunks)
            {
                if (chunk.Bytes.Length != _chunkSize) { throw new ArgumentException("The chunks are not all the same size."); }
            }

            if (sliceOffset < 0)
            {
                throw new ArgumentOutOfRangeException("sliceOffset");
            }
            _sliceOffset = sliceOffset;

            var maxCapacity = _chunks.Count * _chunkSize - _sliceOffset;
            if (length < 0 || length > maxCapacity)
            {
                throw new ArgumentOutOfRangeException("length");
            }
            _capacity =  isReadOnly ? length : maxCapacity; // the capacity is fixed
            _length = length;

            _chunkPool = null;
            _isReadOnly = isReadOnly;
            _position = 0;

            foreach (var chunk in _chunks)
            {
                chunk.IncrementReferenceCount();
            }
        }
        public void Bytes_get_should_return_expected_result()
        {
            var pool = new BsonChunkPool(1, 16);
            var subject = pool.GetChunk(1);

            var result = subject.Bytes;

            result.Array.Length.Should().Be(16);
            result.Offset.Should().Be(0);
            result.Count.Should().Be(16);
        }
        public void Dispose_should_return_chunk_to_the_pool()
        {
            var pool = new BsonChunkPool(1, 16);
            var subject = pool.GetChunk(1);

            subject.Dispose();

            pool.ChunkCount.Should().Be(1);
        }
        public void GetChunk_should_throw_when_subject_is_disposed()
        {
            var subject = new BsonChunkPool(1, 16);
            subject.Dispose();

            Action action = () => subject.GetChunk(1);

            action.ShouldThrow<ObjectDisposedException>().And.ObjectName.Should().Be("BsonChunkPool");
        }
        public void Dispose_should_return_chunk_to_the_pool_after_all_handles_have_been_disposed(
            [Values(0, 1, 2, 3, 4, 16)]
            int numberOfHandles,
            [Values(false, true)]
            bool disposeSubjectLast)
        {
            var pool = new BsonChunkPool(1, 16);
            var subject = pool.GetChunk(1);

            var handles = new List<IBsonChunk>();
            for (var n = 0; n < numberOfHandles; n++)
            {
                handles.Add(subject.Fork());
            }

            if (disposeSubjectLast)
            {
                handles.Add(subject);
            }
            else
            {
                handles.Insert(0, subject);
            }

            foreach (var handle in handles)
            {
                pool.ChunkCount.Should().Be(0);
                handle.Dispose();
            }

            pool.ChunkCount.Should().Be(1);
        }
        public void Dispose_can_be_called_more_than_once()
        {
            var pool = new BsonChunkPool(1, 16);
            var subject = pool.GetChunk(1);

            subject.Dispose();
            subject.Dispose();
        }
Esempio n. 31
0
 public ReferenceCountedChunk(byte[] chunk, BsonChunkPool pool)
 {
     _chunk = chunk;
     _pool  = pool;
 }
        public void Fork_should_return_expected_result()
        {
            var pool = new BsonChunkPool(1, 16);
            var subject = pool.GetChunk(1);

            var handle = subject.Fork();

            handle.Bytes.Array.Should().BeSameAs(subject.Bytes.Array);
            handle.Bytes.Offset.Should().Be(subject.Bytes.Offset);
            handle.Bytes.Count.Should().Be(subject.Bytes.Count);
        }