/// <summary> /// Allocates a ByteBuf from this ByteBufChunkList if it is not empty. /// </summary> /// <param name="byteBuf">The allocated ByteBuf</param> /// <returns>true, if the ByteBuf be allocated; otherwise, false.</returns> public bool Allocate(out ByteBuf byteBuf) { if (head == null) { // This ByteBufChunkList is empty byteBuf = default(ByteBuf); return false; } for (var cur = head; ;) { if (!cur.Allocate(out byteBuf)) { cur = cur.Next; if (cur == null) { return false; } } else { if (cur.Usage < maxUsage) return true; Remove(cur); NextList.Add(cur); return true; } } }
/// <summary> /// Sends data to this socket with a ByteBuf object that contains data to be sent. /// </summary> /// <param name="data">A ByteBuf object that contains data to be sent</param> public void Send(ByteBuf data) { EnsureAccessible(); if (!isConnected) { throw new InvalidOperationException("The operation is not allowed on non-connected sockets."); } if (!data.IsReadable()) { throw new ArgumentException("The parameter {0} must contain one or more elements.", "data"); } var dataToken = new SockDataToken(this, data); if (parent != null) { parent.DoSend(dataToken); } else { DoSend(dataToken); } var status = sendStatusQueue.Take(); if (status == (int)SocketError.Success) { return; } // throw a SocketException if theres is an error. dataToken.Reset(); Dispose(true); var socketException = new SocketException(status); throw socketException; }
/// <summary> /// Releases the ByteBuf back to this ByteChunk /// </summary> /// <param name="byteBuf">The ByteBuf to be released.</param> public void Free(ByteBuf byteBuf) { segmentQueue.Enqueue(new Segment(byteBuf.Offset, byteBuf.Capacity)); FreeBytes += segmentSize; }
/// <summary> /// Allocates a ByteBuf from this ByteChunk. /// </summary> /// <param name="byteBuf">The ByteBuf be allocated</param> /// <returns>true, if succeed to allocate a ByteBuf; otherwise, false</returns> public bool Allocate(out ByteBuf byteBuf) { if (segmentQueue.Count > 0) { var segment = segmentQueue.Dequeue(); FreeBytes -= segmentSize; byteBuf = new ByteBuf(this, segment.Offset, segment.Count); return true; } byteBuf = default(ByteBuf); return false; }
/// <summary> /// Sends data to this socket with a ByteBuf object that contains data to be sent. /// </summary> /// <param name="data">A ByteBuf object that contains data to be sent</param> public void Send(ByteBuf data) { EnsureAccessible(); if (!isConnected) { throw new InvalidOperationException("The operation is not allowed on non-connected sockets."); } if (!data.IsReadable()) { throw new ArgumentException("The parameter {0} must contain one or more elements.", "data"); } var dataToken = new SockDataToken(this, data); if (parent != null) { parent.DoSend(dataToken); } else { DoSend(dataToken); } var status = sendStatusQueue.Take(); if (status == (int) SocketError.Success) return; // throw a SocketException if theres is an error. dataToken.Reset(); Dispose(true); var socketException = new SocketException(status); throw socketException; }
/// <summary> /// Writes data to the stream. /// </summary> /// <param name="buffer">Buffer to write from.</param> /// <param name="offset">Offset into the buffer from where we'll start writing.</param> /// <param name="count">Number of bytes to write.</param> public override void Write(byte[] buffer, int offset, int count) { try { var remainingBytes = count; var newOffset = offset; while (0 < remainingBytes) { if (sendDataCache == null) { sendDataCache = bufPool.Allocate(); } if (sendDataCache.WritableBytes > remainingBytes) { sendDataCache.WriteBytes(buffer, newOffset, remainingBytes); return; } var sendCount = sendDataCache.WritableBytes; sendDataCache.WriteBytes(buffer, newOffset, sendCount); streamSocket.Send(sendDataCache); sendDataCache = null; newOffset += sendCount; remainingBytes -= sendCount; } } catch (Exception e) { if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) { throw; } // some sort of error occurred on the socked call, // set the SocketException as InnerException and throw throw new IOException(string.Format("Unable to write data to the transport connection: {0}.", e.Message), e); } }
/// <summary> /// Sends data to this socket with a ByteBuf object that contains data to be sent. /// /// The DefaultSocketWrapper does not support this function. /// </summary> /// <param name="data">A ByteBuf object that contains data to be sent</param> public void Send(ByteBuf data) { throw new NotImplementedException(); }
/// <summary> /// Flushes data in send cache to the stream. /// </summary> public override void Flush() { if (sendDataCache != null && sendDataCache.IsReadable()) { try { streamSocket.Send(sendDataCache); sendDataCache = null; } catch (Exception e) { if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) { throw; } // some sort of error occurred on the socked call, // set the SocketException as InnerException and throw throw new IOException(string.Format("Unable to write data to the transport connection: {0}.", e.Message), e); } } }
/// <summary> /// Reads a byte from the stream and advances the position within the stream by one byte, or returns -1 if at the end of the stream. /// </summary> /// <returns> /// The unsigned byte cast to an Int32, or -1 if at the end of the stream. /// </returns> public override int ReadByte() { if (recvDataCache == null || !recvDataCache.IsReadable()) { recvDataCache = streamSocket.Receive(); } return recvDataCache.ReadByte(); }
/// <summary> /// Deallocates a ByteBuf back to this ByteBufPool. /// </summary> /// <param name="byteBuf">The ByteBuf to be release.</param> public void Free(ByteBuf byteBuf) { if (byteBuf.ByteBufChunk == null || byteBuf.Capacity == 0 || byteBuf.ByteBufChunk.Size < byteBuf.Offset + byteBuf.Capacity) { throw new Exception("Attempt to free invalid byteBuf"); } if (byteBuf.Capacity != SegmentSize) { throw new ArgumentException("Segment was not from the same byte arena", "byteBuf"); } bool mustDestroyChunk; var chunk = byteBuf.ByteBufChunk; lock (this) { mustDestroyChunk = !chunk.Parent.Free(chunk, byteBuf); } if (!mustDestroyChunk) return; // Destroy chunk not need to be called while holding the synchronized lock. chunk.Parent = null; chunk.Dispose(); }
public RequestContext(SocketOperation operation, ByteBuf data) { Operation = operation; Data = data; }
/// <summary> /// Sends data to this socket with a ByteBuf object that contains data to be sent. /// </summary> /// <param name="data">A ByteBuf object that contains data to be sent</param> public void Send(ByteBuf data) { EnsureAccessible(); if (!isConnected) { throw new InvalidOperationException("The operation is not allowed on non-connected sockets."); } if (!data.IsReadable()) { throw new ArgumentException("The parameter {0} must contain one or more elements.", "data"); } var context = new RequestContext(SocketOperation.Send, data); DoSend(GenerateUniqueKey(), context); var status = sendStatusQueue.Take(); if (status == (int)SocketError.Success) return; // throw a SocketException if theres is an error. Dispose(true); var socketException = new SocketException(status); throw socketException; }
/// <summary> /// Reads data from the stream. /// </summary> /// <param name="buffer">Buffer to read into.</param> /// <param name="offset">Offset into the buffer where we're to read.</param> /// <param name="count">Number of bytes to read.</param> /// <returns>Number of bytes we read.</returns> public override int Read(byte[] buffer, int offset, int count) { try { if (recvDataCache == null) { recvDataCache = streamSocket.Receive(); } if (!recvDataCache.IsReadable()) { recvDataCache.Release(); recvDataCache = null; return 0; } var bytesRemaining = count; while (recvDataCache != null && recvDataCache.IsReadable() && bytesRemaining > 0) { var bytesToRead = Math.Min(bytesRemaining, recvDataCache.ReadableBytes); bytesRemaining -= recvDataCache.ReadBytes(buffer, offset + count - bytesRemaining, bytesToRead); if (recvDataCache.IsReadable()) continue; recvDataCache.Release(); recvDataCache = null; if (streamSocket.HasData) { recvDataCache = streamSocket.Receive(); } } return count - bytesRemaining; } catch (Exception e) { if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) { throw; } // some sort of error occurred on the socket call, // set the SocketException as InnerException and throw throw new IOException(string.Format("Unable to read data from the transport connection: {0}.", e.Message), e); } }
/// <summary> /// Reads a byte from the stream and advances the position within the stream by one byte, or returns -1 if at the end of the stream. /// </summary> /// <returns> /// The unsigned byte cast to an Int32, or -1 if at the end of the stream. /// </returns> public override int ReadByte() { if (recvDataCache == null || !recvDataCache.IsReadable()) { recvDataCache = streamSocket.Receive(); } var v = recvDataCache.ReadByte(); if (recvDataCache.IsReadable()) return v; // Release cache if it is not readable. If we do not reset the cache here, // the cache will be used in next Read() that caused 0 bytes return. recvDataCache.Release(); recvDataCache = null; return v; }
private void WriteReadByteBufTest(ByteBuf byteBuf) { var initWriteIndex = byteBuf.WriterIndex; var initReadIndex = byteBuf.WriterIndex; Assert.AreEqual(initWriteIndex, initReadIndex); Assert.AreEqual(byteBuf.Capacity, byteBuf.WritableBytes); Assert.AreEqual(0, byteBuf.ReadableBytes); Assert.IsFalse(byteBuf.IsReadable()); Assert.IsTrue(byteBuf.IsWritable()); // Verify WriteBytes() function const string writeStr = "Write bytes to ByteBuf."; var writeBytes = Encoding.UTF8.GetBytes(writeStr); byteBuf.WriteBytes(writeBytes, 0, writeBytes.Length); Assert.AreEqual(initWriteIndex + writeBytes.Length, byteBuf.WriterIndex); Assert.AreEqual(byteBuf.Capacity - writeBytes.Length, byteBuf.WritableBytes); Assert.AreEqual(writeBytes.Length, byteBuf.ReadableBytes); Assert.AreEqual(initReadIndex, byteBuf.ReaderIndex); Assert.IsTrue(byteBuf.IsReadable()); // Verify ReadBytes() function var readBytes = new byte[writeBytes.Length]; var ret = byteBuf.ReadBytes(readBytes, 0, readBytes.Length); Assert.AreEqual(writeBytes.Length, ret); var readStr = Encoding.UTF8.GetString(readBytes, 0, ret); Assert.AreEqual(writeStr, readStr); Assert.AreEqual(initWriteIndex + writeBytes.Length, byteBuf.WriterIndex); Assert.AreEqual(byteBuf.Capacity - writeBytes.Length, byteBuf.WritableBytes); Assert.AreEqual(0, byteBuf.ReadableBytes); Assert.AreEqual(initReadIndex + ret, byteBuf.ReaderIndex); // Verify ReadByte() function byteBuf.WriteBytes(writeBytes, 0, 1); var retByte = byteBuf.ReadByte(); Assert.AreEqual(writeBytes[0], retByte); // Verify clear() function byteBuf.Clear(); Assert.AreEqual(0, byteBuf.ReaderIndex); Assert.AreEqual(0, byteBuf.WriterIndex); }
/// <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); }