コード例 #1
0
ファイル: ByteBufChunkTest.cs プロジェクト: jthelin/SparkCLR
        private void AllocateFreeBufChunkTest(ByteBufChunk chunk)
        {
            // Verify allocation
            ByteBuf byteBuf1;
            Assert.IsTrue(chunk.Allocate(out byteBuf1));
            Assert.AreEqual(25, chunk.Usage);
            ByteBuf byteBuf2;
            Assert.IsTrue(chunk.Allocate(out byteBuf2));
            Assert.AreEqual(50, chunk.Usage);
            ByteBuf byteBuf3;
            Assert.IsTrue(chunk.Allocate(out byteBuf3));
            Assert.AreEqual(75, chunk.Usage);
            ByteBuf byteBuf4;
            Assert.IsTrue(chunk.Allocate(out byteBuf4));
            Assert.AreEqual(100, chunk.Usage);
            ByteBuf byteBuf5;
            Assert.IsFalse(chunk.Allocate(out byteBuf5)); // Usage is 100%, cannot allocate
            Assert.IsNull(byteBuf5);

            // Verify Free()
            chunk.Free(byteBuf1);
            Assert.AreEqual(75, chunk.Usage);
            chunk.Free(byteBuf2);
            Assert.AreEqual(50, chunk.Usage);
            chunk.Free(byteBuf3);
            Assert.AreEqual(25, chunk.Usage);
            chunk.Free(byteBuf4);
            Assert.AreEqual(0, chunk.Usage);
        }
コード例 #2
0
        public ByteBuf Allocate()
        {
            ByteBuf byteBuf;

            if (q050.Allocate(out byteBuf) || q025.Allocate(out byteBuf) ||
                q000.Allocate(out byteBuf) || qInit.Allocate(out byteBuf) ||
                q075.Allocate(out byteBuf))
            {
                return(byteBuf);
            }

            // Add a new chunk and allocate a segment from it.
            try
            {
                var chunk = ByteBufChunk.NewChunk(this, SegmentSize, ChunkSize, isUnsafe);
                if (!chunk.Allocate(out byteBuf))
                {
                    logger.LogError("Failed to allocate a ByteBuf from a new ByteBufChunk - isUnsafe [{0}].", isUnsafe);
                    return(null);
                }
                qInit.Add(chunk);
                return(byteBuf);
            }
            catch (Exception e)
            {
                logger.LogException(e);
                return(null);
            }
        }
コード例 #3
0
ファイル: ByteBuf.cs プロジェクト: smartpcr/SparkCLR
        /// <summary>
        /// We borrow some ideas from Netty's ByteBuf.
        /// ByteBuf provides two pointer variables to support sequential read and write operations
        ///  - readerIndex for a read operation and writerIndex for a write operation respectively.
        /// The following diagram shows how a buffer is segmented into three areas by the two
        /// pointers:
        ///
        ///      +-------------------+------------------+------------------+
        ///      | discardable bytes |  readable bytes  |  writable bytes  |
        ///      |                   |     (CONTENT)    |                  |
        ///      +-------------------+------------------+------------------+
        ///      |                   |                  |                  |
        ///      0       ==     readerIndex   ==   writerIndex    ==    capacity
        /// </summary>
        internal ByteBuf(ByteBufChunk chunk, int offset, int capacity)
        {
            if (offset < 0)
            {
                throw new ArgumentOutOfRangeException("offset", "Offset is less than zero.");
            }
            if (capacity < 0)
            {
                throw new ArgumentOutOfRangeException("capacity", "Count is less than zero.");
            }
            if (chunk == null)
            {
                throw new ArgumentNullException("chunk");
            }
            if (chunk.Size - offset < capacity)
            {
                throw new ArgumentException(
                          "Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.");
            }

            Capacity     = capacity;
            Offset       = offset;
            ByteBufChunk = chunk;
            readerIndex  = writerIndex = 0;
            Status       = 0;
        }
コード例 #4
0
ファイル: ByteBufChunkList.cs プロジェクト: jthelin/SparkCLR
        /// <summary>
        /// Add the ByteBufChunk to this ByteBufChunkList linked-list based on ByteBufChunk's usage.
        /// So it will be moved to the right ByteBufChunkList that has the correct minUsage/maxUsage.
        /// </summary>
        /// <param name="chunk">The ByteBufChunk to be added</param>
        public void Add(ByteBufChunk chunk)
        {
            if (chunk.Usage >= maxUsage)
            {
                NextList.Add(chunk);
                return;
            }

            AddInternal(chunk);
        }
コード例 #5
0
        /// <summary>
        /// Add the ByteBufChunk to this ByteBufChunkList linked-list based on ByteBufChunk's usage.
        /// So it will be moved to the right ByteBufChunkList that has the correct minUsage/maxUsage.
        /// </summary>
        /// <param name="chunk">The ByteBufChunk to be added</param>
        public void Add(ByteBufChunk chunk)
        {
            if (chunk.Usage >= maxUsage)
            {
                NextList.Add(chunk);
                return;
            }

            AddInternal(chunk);
        }
コード例 #6
0
        private bool Move(ByteBufChunk chunk)
        {
            if (chunk.Usage < minUsage)
            {
                // Move the ByteBufChunk down the ByteBufChunkList linked-list
                return(MoveInternal(chunk));
            }

            // ByteBufChunk fits into this ByteBufChunkList, adding it here.
            AddInternal(chunk);
            return(true);
        }
コード例 #7
0
        /// <summary>
        /// Releases the segment back to its ByteBufChunk.
        /// </summary>
        /// <param name="chunk">The ByteBufChunk that contains the ByteBuf</param>
        /// <param name="byteBuf">The ByteBuf to be released.</param>
        /// <returns>
        /// true, if the ByteBuf be released and NOT need to destroy the
        /// ByteBufChunk (its usage is 0); otherwise, false.
        /// </returns>
        public bool Free(ByteBufChunk chunk, ByteBuf byteBuf)
        {
            chunk.Free(byteBuf);
            if (chunk.Usage >= minUsage)
            {
                return(true);
            }

            Remove(chunk);
            // Move the ByteBufChunk down the ByteBufChunkList linked-list.
            return(MoveInternal(chunk));
        }
コード例 #8
0
        /// <summary>
        /// Moves the ByteBufChunk down the ByteBufChunkList linked-list so it will end up in the right
        /// ByteBufChunkList that has the correct minUsage/maxUsage in respect to ByteBufChunk.Usage.
        /// </summary>
        private bool MoveInternal(ByteBufChunk chunk)
        {
            if (PrevList == null)
            {
                // If there is no previous ByteBufChunkList so return false which result in
                // having the ByteBufChunk destroyed and memory associated with the ByteBufChunk
                // will be released.
                Debug.Assert(chunk.Usage == 0);
                return(false);
            }

            return(PrevList.Move(chunk));
        }
コード例 #9
0
 /// <summary>
 /// Adds the ByteBufChunk to this ByteBufChunkList
 /// </summary>
 private void AddInternal(ByteBufChunk chunk)
 {
     chunk.Parent = this;
     if (head == null)
     {
         head       = chunk;
         chunk.Prev = null;
         chunk.Next = null;
     }
     else
     {
         chunk.Prev = null;
         chunk.Next = head;
         head.Prev  = chunk;
         head       = chunk;
     }
 }
コード例 #10
0
ファイル: ByteBufChunk.cs プロジェクト: zwffff2015/Mobius
        public static ByteBufChunk NewChunk(ByteBufPool pool, int segmentSize, int chunkSize, bool isUnsafe)
        {
            ByteBufChunk chunk = null;

            if (!isUnsafe)
            {
                chunk = new ByteBufChunk(pool, new byte[chunkSize], segmentSize, chunkSize);
                return(chunk);
            }

            // allocate buffers from process heap
            var token = HeapAlloc(GetProcessHeap(), 0, chunkSize);

            if (token == IntPtr.Zero)
            {
                throw new OutOfMemoryException("Failed to allocate memory by calling HeapAlloc()");
            }

            // register this heap buffer to RIO buffer
            var bufferId = RioNative.RegisterRIOBuffer(token, (uint)chunkSize);

            if (bufferId == IntPtr.Zero)
            {
                FreeToProcessHeap(token);
                throw new Exception(string.Format("Failed to register RIO buffer with error code {0}", Marshal.GetLastWin32Error()));
            }

            try
            {
                chunk    = new ByteBufChunk(pool, token, bufferId, segmentSize, chunkSize);
                token    = IntPtr.Zero;
                bufferId = IntPtr.Zero;
                return(chunk);
            }
            finally
            {
                if (chunk == null && token != IntPtr.Zero)
                {
                    if (bufferId != IntPtr.Zero)
                    {
                        RioNative.DeregisterRIOBuffer(bufferId);
                    }
                    FreeToProcessHeap(token);
                }
            }
        }
コード例 #11
0
ファイル: ByteBuf.cs プロジェクト: jthelin/SparkCLR
        /// <summary>
        /// We borrow some ideas from Netty's ByteBuf. 
        /// ByteBuf provides two pointer variables to support sequential read and write operations
        ///  - readerIndex for a read operation and writerIndex for a write operation respectively.
        /// The following diagram shows how a buffer is segmented into three areas by the two
        /// pointers:
        /// 
        ///      +-------------------+------------------+------------------+
        ///      | discardable bytes |  readable bytes  |  writable bytes  |
        ///      |                   |     (CONTENT)    |                  |
        ///      +-------------------+------------------+------------------+
        ///      |                   |                  |                  |
        ///      0       ==     readerIndex   ==   writerIndex    ==    capacity
        /// </summary>
        internal ByteBuf(ByteBufChunk chunk, int offset, int capacity)
        {
            if (offset < 0)
                throw new ArgumentOutOfRangeException("offset", "Offset is less than zero.");
            if (capacity < 0)
                throw new ArgumentOutOfRangeException("capacity", "Count is less than zero.");
            if (chunk == null)
                throw new ArgumentNullException("chunk");
            if (chunk.Size - offset < capacity)
                throw new ArgumentException(
                    "Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.");

            Capacity = capacity;
            Offset = offset;
            ByteBufChunk = chunk;
            readerIndex = writerIndex = 0;
            Status = 0;
        }
コード例 #12
0
 /// <summary>
 /// Remove the ByteBufChunk from this ByteBufChunkList
 /// </summary>
 private void Remove(ByteBufChunk chunk)
 {
     Debug.Assert(chunk != null);
     if (chunk == head)
     {
         head = chunk.Next;
         if (head != null)
         {
             head.Prev = null;
         }
     }
     else
     {
         var next = chunk.Next;
         chunk.Prev.Next = next;
         if (next != null)
         {
             next.Prev = chunk.Prev;
         }
     }
 }
コード例 #13
0
ファイル: ByteBufPool.cs プロジェクト: zwffff2015/Mobius
        public ByteBuf Allocate()
        {
            var     trial = 0;
            ByteBuf byteBuf;

            do
            {
                if (q050.Allocate(out byteBuf) || q025.Allocate(out byteBuf) ||
                    q000.Allocate(out byteBuf) || qInit.Allocate(out byteBuf) ||
                    q075.Allocate(out byteBuf))
                {
                    return(byteBuf);
                }

                // Issues a pause instruction on each loop iteration,
                // and not fall back to a more expensive wait on.
                Thread.Sleep(0);
                trial++;
            } while (trial < TrialsCount);

            // Add a new chunk and allocate a segment from it.
            try
            {
                var chunk = ByteBufChunk.NewChunk(this, SegmentSize, ChunkSize, isUnsafe);
                if (!chunk.Allocate(out byteBuf))
                {
                    logger.LogError("Failed to allocate a ByteBuf from a new ByteBufChunk - isUnsafe [{0}].",
                                    isUnsafe);
                    return(null);
                }

                qInit.Add(chunk);
                return(byteBuf);
            }
            catch (Exception e)
            {
                logger.LogException(e);
                return(null);
            }
        }
コード例 #14
0
ファイル: ByteBufChunkList.cs プロジェクト: jthelin/SparkCLR
        /// <summary>
        /// Releases the segment back to its ByteBufChunk.
        /// </summary>
        /// <param name="chunk">The ByteBufChunk that contains the ByteBuf</param>
        /// <param name="byteBuf">The ByteBuf to be released.</param>
        /// <returns>
        /// true, if the ByteBuf be released and NOT need to destroy the
        /// ByteBufChunk (its usage is 0); otherwise, false.
        /// </returns>
        public bool Free(ByteBufChunk chunk, ByteBuf byteBuf)
        {
            chunk.Free(byteBuf);
            if (chunk.Usage >= minUsage) return true;

            Remove(chunk);
            // Move the ByteBufChunk down the ByteBufChunkList linked-list.
            return MoveInternal(chunk);
        }
コード例 #15
0
ファイル: ByteBufChunkList.cs プロジェクト: jthelin/SparkCLR
        private bool Move(ByteBufChunk chunk)
        {
            if (chunk.Usage < minUsage)
            {
                // Move the ByteBufChunk down the ByteBufChunkList linked-list
                return MoveInternal(chunk);
            }

            // ByteBufChunk fits into this ByteBufChunkList, adding it here.
            AddInternal(chunk);
            return true;
        }
コード例 #16
0
ファイル: ByteBufChunk.cs プロジェクト: qintao1976/Mobius
        public static ByteBufChunk NewChunk(ByteBufPool pool, int segmentSize, int chunkSize, bool isUnsafe)
        {
            ByteBufChunk chunk = null;
            if (!isUnsafe)
            {
                chunk = new ByteBufChunk(pool, new byte[chunkSize], segmentSize, chunkSize);
                return chunk;
            }

            // allocate buffers from process heap
            var token = HeapAlloc(GetProcessHeap(), 0, chunkSize);
            if (token == IntPtr.Zero)
            {
                throw new OutOfMemoryException("Failed to allocate memory by calling HeapAlloc()");
            }

            // register this heap buffer to RIO buffer
            var bufferId = RioNative.RegisterRIOBuffer(token, (uint)chunkSize);
            if (bufferId == IntPtr.Zero)
            {
                FreeToProcessHeap(token);
                throw new Exception(string.Format("Failed to register RIO buffer with error code {0}", Marshal.GetLastWin32Error()));
            }

            try
            {
                chunk = new ByteBufChunk(pool, token, bufferId, segmentSize, chunkSize);
                token = IntPtr.Zero;
                bufferId = IntPtr.Zero;
                return chunk;
            }
            finally
            {
                if (chunk == null && token != IntPtr.Zero)
                {
                    if (bufferId != IntPtr.Zero)
                    {
                        RioNative.DeregisterRIOBuffer(bufferId);
                    }
                    FreeToProcessHeap(token);
                }
            }
        }
コード例 #17
0
ファイル: ByteBufChunkList.cs プロジェクト: jthelin/SparkCLR
        /// <summary>
        /// Moves the ByteBufChunk down the ByteBufChunkList linked-list so it will end up in the right
        /// ByteBufChunkList that has the correct minUsage/maxUsage in respect to ByteBufChunk.Usage.
        /// </summary>
        private bool MoveInternal(ByteBufChunk chunk)
        {
            if (PrevList == null)
            {
                // If there is no previous ByteBufChunkList so return false which result in
                // having the ByteBufChunk destroyed and memory associated with the ByteBufChunk
                // will be released.
                Debug.Assert(chunk.Usage == 0);
                return false;
            }

            return PrevList.Move(chunk);
        }
コード例 #18
0
ファイル: ByteBuf.cs プロジェクト: jthelin/SparkCLR
        /// <summary>
        /// Release the ByteBuf back to the ByteBufPool
        /// </summary>
        public void Release()
        {
            if (ByteBufChunk == null || ByteBufChunk.IsDisposed)
            {
                return;
            }

            var byteBufPool = ByteBufChunk.Pool;
            byteBufPool.Free(this);
            ByteBufChunk = null;
        }
コード例 #19
0
ファイル: ByteBufChunkList.cs プロジェクト: jthelin/SparkCLR
 /// <summary>
 /// Remove the ByteBufChunk from this ByteBufChunkList
 /// </summary>
 private void Remove(ByteBufChunk chunk)
 {
     Debug.Assert(chunk != null);
     if (chunk == head)
     {
         head = chunk.Next;
         if (head != null)
         {
             head.Prev = null;
         }
     }
     else
     {
         var next = chunk.Next;
         chunk.Prev.Next = next;
         if (next != null)
         {
             next.Prev = chunk.Prev;
         }
     }
 }
コード例 #20
0
ファイル: ByteBufChunkList.cs プロジェクト: jthelin/SparkCLR
 /// <summary>
 /// Adds the ByteBufChunk to this ByteBufChunkList
 /// </summary>
 private void AddInternal(ByteBufChunk chunk)
 {
     chunk.Parent = this;
     if (head == null)
     {
         head = chunk;
         chunk.Prev = null;
         chunk.Next = null;
     }
     else
     {
         chunk.Prev = null;
         chunk.Next = head;
         head.Prev = chunk;
         head = chunk;
     }
 }