From 0e9901222e4ea1bd2f6bf77167d6b62a5a681bf1 Mon Sep 17 00:00:00 2001 From: wusheng Date: Thu, 10 Mar 2016 14:04:18 +0800 Subject: [PATCH] =?UTF-8?q?1.=E9=87=87=E7=94=A8=E6=96=B0=E7=9A=84=E4=BE=9D?= =?UTF-8?q?=E8=B5=96=E7=BC=96=E8=AF=91=E6=A8=A1=E5=BC=8F=202.=E7=A7=BB?= =?UTF-8?q?=E9=99=A4io.netty=E6=BA=90=E4=BB=A3=E7=A0=81=203.=E5=BC=95?= =?UTF-8?q?=E5=85=A5net.bytebuddy/asm=E6=BA=90=E4=BB=A3=E7=A0=81=EF=BC=8C?= =?UTF-8?q?=E6=8F=90=E4=BE=9B=E6=96=B0=E7=9A=84=E4=BB=A3=E7=A0=81=E7=BA=A7?= =?UTF-8?q?=E5=88=87=E9=9D=A2=E7=9A=84=E5=8F=AF=E8=83=BD=204.bytebuddy?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E4=BB=A3=E7=A0=81=EF=BC=8C=E6=8F=90=E4=BE=9B?= =?UTF-8?q?java=20source=E7=BA=A7=E5=88=AB=E7=9A=84=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E6=9B=BF=E6=8D=A2=E3=80=82=E7=90=86=E8=AE=BA=E4=B8=8A=EF=BC=8C?= =?UTF-8?q?=E5=85=81=E8=AE=B8=E6=8E=A5=E7=AE=A1=E6=89=80=E6=9C=89=E7=B1=BB?= =?UTF-8?q?=E5=92=8C=E6=96=B9=E6=B3=95=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- skywalking-api/pom.xml | 102 +- .../io/netty/bootstrap/AbstractBootstrap.java | 487 -- .../cloud/io/netty/bootstrap/Bootstrap.java | 245 - .../io/netty/bootstrap/ChannelFactory.java | 29 - .../io/netty/bootstrap/ServerBootstrap.java | 334 - .../io/netty/bootstrap/package-info.java | 21 - .../io/netty/buffer/AbstractByteBuf.java | 1202 ---- .../buffer/AbstractByteBufAllocator.java | 219 - .../netty/buffer/AbstractDerivedByteBuf.java | 67 - .../AbstractReferenceCountedByteBuf.java | 140 - .../buffer/AbstractUnsafeSwappedByteBuf.java | 169 - .../buffer/AdvancedLeakAwareByteBuf.java | 746 -- .../com/ai/cloud/io/netty/buffer/ByteBuf.java | 1895 ----- .../io/netty/buffer/ByteBufAllocator.java | 128 - .../cloud/io/netty/buffer/ByteBufHolder.java | 45 - .../io/netty/buffer/ByteBufInputStream.java | 257 - .../io/netty/buffer/ByteBufOutputStream.java | 146 - .../io/netty/buffer/ByteBufProcessor.java | 126 - .../ai/cloud/io/netty/buffer/ByteBufUtil.java | 792 --- .../io/netty/buffer/CompositeByteBuf.java | 1667 ----- .../io/netty/buffer/DefaultByteBufHolder.java | 93 - .../buffer/DuplicatedAbstractByteBuf.java | 80 - .../io/netty/buffer/DuplicatedByteBuf.java | 307 - .../cloud/io/netty/buffer/EmptyByteBuf.java | 870 --- .../netty/buffer/FixedCompositeByteBuf.java | 572 -- .../io/netty/buffer/HeapByteBufUtil.java | 89 - .../ai/cloud/io/netty/buffer/PoolArena.java | 688 -- .../io/netty/buffer/PoolArenaMetric.java | 130 - .../ai/cloud/io/netty/buffer/PoolChunk.java | 454 -- .../cloud/io/netty/buffer/PoolChunkList.java | 167 - .../io/netty/buffer/PoolChunkListMetric.java | 32 - .../io/netty/buffer/PoolChunkMetric.java | 37 - .../ai/cloud/io/netty/buffer/PoolSubpage.java | 230 - .../io/netty/buffer/PoolSubpageMetric.java | 43 - .../io/netty/buffer/PoolThreadCache.java | 479 -- .../cloud/io/netty/buffer/PooledByteBuf.java | 170 - .../netty/buffer/PooledByteBufAllocator.java | 426 -- .../io/netty/buffer/PooledDirectByteBuf.java | 376 - .../io/netty/buffer/PooledHeapByteBuf.java | 274 - .../buffer/PooledUnsafeDirectByteBuf.java | 299 - .../netty/buffer/PooledUnsafeHeapByteBuf.java | 102 - .../io/netty/buffer/ReadOnlyByteBuf.java | 317 - .../netty/buffer/ReadOnlyByteBufferBuf.java | 335 - .../buffer/ReadOnlyUnsafeDirectByteBuf.java | 129 - .../netty/buffer/SimpleLeakAwareByteBuf.java | 79 - .../netty/buffer/SlicedAbstractByteBuf.java | 81 - .../cloud/io/netty/buffer/SlicedByteBuf.java | 301 - .../cloud/io/netty/buffer/SwappedByteBuf.java | 852 --- .../ai/cloud/io/netty/buffer/Unpooled.java | 865 --- .../buffer/UnpooledByteBufAllocator.java | 63 - .../netty/buffer/UnpooledDirectByteBuf.java | 599 -- .../io/netty/buffer/UnpooledHeapByteBuf.java | 424 -- .../buffer/UnpooledUnsafeDirectByteBuf.java | 429 -- .../buffer/UnpooledUnsafeHeapByteBuf.java | 156 - .../io/netty/buffer/UnreleasableByteBuf.java | 87 - .../io/netty/buffer/UnsafeByteBufUtil.java | 389 -- .../buffer/UnsafeDirectSwappedByteBuf.java | 67 - .../buffer/UnsafeHeapSwappedByteBuf.java | 63 - .../cloud/io/netty/buffer/WrappedByteBuf.java | 834 --- .../cloud/io/netty/buffer/package-info.java | 128 - .../io/netty/channel/AbstractChannel.java | 970 --- .../AbstractChannelHandlerContext.java | 1063 --- .../netty/channel/AbstractServerChannel.java | 85 - .../channel/AdaptiveRecvByteBufAllocator.java | 182 - .../io/netty/channel/AddressedEnvelope.java | 44 - .../ai/cloud/io/netty/channel/Channel.java | 520 -- .../cloud/io/netty/channel/ChannelConfig.java | 252 - .../netty/channel/ChannelDuplexHandler.java | 119 - .../io/netty/channel/ChannelException.java | 51 - .../channel/ChannelFlushPromiseNotifier.java | 275 - .../cloud/io/netty/channel/ChannelFuture.java | 196 - .../netty/channel/ChannelFutureListener.java | 75 - .../io/netty/channel/ChannelHandler.java | 214 - .../netty/channel/ChannelHandlerAdapter.java | 81 - .../netty/channel/ChannelHandlerContext.java | 495 -- .../netty/channel/ChannelInboundHandler.java | 74 - .../channel/ChannelInboundHandlerAdapter.java | 133 - .../io/netty/channel/ChannelInitializer.java | 88 - .../io/netty/channel/ChannelMetadata.java | 46 - .../cloud/io/netty/channel/ChannelOption.java | 148 - .../netty/channel/ChannelOutboundBuffer.java | 831 --- .../netty/channel/ChannelOutboundHandler.java | 99 - .../ChannelOutboundHandlerAdapter.java | 117 - .../io/netty/channel/ChannelPipeline.java | 879 --- .../channel/ChannelPipelineException.java | 52 - .../channel/ChannelProgressiveFuture.java | 49 - .../ChannelProgressiveFutureListener.java | 28 - .../channel/ChannelProgressivePromise.java | 62 - .../io/netty/channel/ChannelPromise.java | 63 - .../channel/ChannelPromiseAggregator.java | 34 - .../netty/channel/ChannelPromiseNotifier.java | 35 - .../channel/CombinedChannelDuplexHandler.java | 204 - .../netty/channel/CompleteChannelFuture.java | 107 - .../channel/ConnectTimeoutException.java | 33 - .../channel/DefaultAddressedEnvelope.java | 115 - .../netty/channel/DefaultChannelConfig.java | 360 - .../channel/DefaultChannelHandlerContext.java | 45 - .../netty/channel/DefaultChannelPipeline.java | 1135 --- .../DefaultChannelProgressivePromise.java | 169 - .../netty/channel/DefaultChannelPromise.java | 160 - .../io/netty/channel/DefaultFileRegion.java | 163 - .../channel/DefaultMessageSizeEstimator.java | 72 - .../ai/cloud/io/netty/channel/EventLoop.java | 30 - .../io/netty/channel/EventLoopException.java | 41 - .../io/netty/channel/EventLoopGroup.java | 43 - .../io/netty/channel/FailedChannelFuture.java | 65 - .../ai/cloud/io/netty/channel/FileRegion.java | 83 - .../channel/FixedRecvByteBufAllocator.java | 69 - .../netty/channel/MessageSizeEstimator.java | 39 - .../channel/MultithreadEventLoopGroup.java | 71 - .../io/netty/channel/PendingWriteQueue.java | 304 - .../netty/channel/RecvByteBufAllocator.java | 54 - .../cloud/io/netty/channel/ServerChannel.java | 27 - .../channel/SimpleChannelInboundHandler.java | 129 - .../netty/channel/SingleThreadEventLoop.java | 73 - .../netty/channel/SucceededChannelFuture.java | 45 - .../channel/ThreadPerChannelEventLoop.java | 81 - .../ThreadPerChannelEventLoopGroup.java | 295 - .../io/netty/channel/VoidChannelPromise.java | 205 - .../channel/embedded/EmbeddedChannel.java | 421 -- .../channel/embedded/EmbeddedEventLoop.java | 143 - .../embedded/EmbeddedSocketAddress.java | 27 - .../netty/channel/embedded/package-info.java | 22 - .../channel/epoll/AbstractEpollChannel.java | 398 -- .../epoll/AbstractEpollServerChannel.java | 168 - .../epoll/AbstractEpollStreamChannel.java | 1081 --- .../cloud/io/netty/channel/epoll/Epoll.java | 92 - .../channel/epoll/EpollChannelConfig.java | 167 - .../channel/epoll/EpollChannelOption.java | 48 - .../channel/epoll/EpollDatagramChannel.java | 616 -- .../epoll/EpollDatagramChannelConfig.java | 311 - .../epoll/EpollDomainSocketChannel.java | 222 - .../epoll/EpollDomainSocketChannelConfig.java | 140 - .../netty/channel/epoll/EpollEventArray.java | 104 - .../netty/channel/epoll/EpollEventLoop.java | 381 - .../channel/epoll/EpollEventLoopGroup.java | 78 - .../io/netty/channel/epoll/EpollMode.java | 36 - .../epoll/EpollServerChannelConfig.java | 203 - .../epoll/EpollServerDomainSocketChannel.java | 111 - .../epoll/EpollServerSocketChannel.java | 131 - .../epoll/EpollServerSocketChannelConfig.java | 197 - .../channel/epoll/EpollSocketChannel.java | 234 - .../epoll/EpollSocketChannelConfig.java | 412 -- .../io/netty/channel/epoll/EpollTcpInfo.java | 193 - .../io/netty/channel/epoll/IovArray.java | 223 - .../channel/epoll/IovArrayThreadLocal.java | 61 - .../cloud/io/netty/channel/epoll/Native.java | 257 - .../epoll/NativeDatagramPacketArray.java | 160 - .../io/netty/channel/epoll/TcpMd5Util.java | 77 - .../io/netty/channel/epoll/package-info.java | 21 - .../io/netty/channel/group/ChannelGroup.java | 236 - .../channel/group/ChannelGroupException.java | 52 - .../channel/group/ChannelGroupFuture.java | 175 - .../group/ChannelGroupFutureListener.java | 28 - .../netty/channel/group/ChannelMatcher.java | 32 - .../netty/channel/group/ChannelMatchers.java | 169 - .../netty/channel/group/CombinedIterator.java | 76 - .../channel/group/DefaultChannelGroup.java | 440 -- .../group/DefaultChannelGroupFuture.java | 264 - .../io/netty/channel/group/package-info.java | 21 - .../io/netty/channel/local/LocalAddress.java | 94 - .../io/netty/channel/local/LocalChannel.java | 484 -- .../channel/local/LocalChannelRegistry.java | 62 - .../netty/channel/local/LocalEventLoop.java | 42 - .../channel/local/LocalEventLoopGroup.java | 59 - .../channel/local/LocalServerChannel.java | 165 - .../io/netty/channel/local/package-info.java | 21 - .../channel/nio/AbstractNioByteChannel.java | 352 - .../netty/channel/nio/AbstractNioChannel.java | 472 -- .../nio/AbstractNioMessageChannel.java | 188 - .../io/netty/channel/nio/NioEventLoop.java | 692 -- .../netty/channel/nio/NioEventLoopGroup.java | 89 - .../cloud/io/netty/channel/nio/NioTask.java | 41 - .../channel/nio/SelectedSelectionKeySet.java | 110 - .../io/netty/channel/nio/package-info.java | 21 - .../channel/oio/AbstractOioByteChannel.java | 261 - .../netty/channel/oio/AbstractOioChannel.java | 113 - .../oio/AbstractOioMessageChannel.java | 106 - .../channel/oio/OioByteStreamChannel.java | 168 - .../netty/channel/oio/OioEventLoopGroup.java | 69 - .../io/netty/channel/oio/package-info.java | 21 - .../cloud/io/netty/channel/package-info.java | 22 - .../pool/AbstractChannelPoolHandler.java | 44 - .../channel/pool/AbstractChannelPoolMap.java | 100 - .../channel/pool/ChannelHealthChecker.java | 47 - .../io/netty/channel/pool/ChannelPool.java | 56 - .../channel/pool/ChannelPoolHandler.java | 48 - .../io/netty/channel/pool/ChannelPoolMap.java | 39 - .../netty/channel/pool/FixedChannelPool.java | 424 -- .../netty/channel/pool/SimpleChannelPool.java | 346 - .../io/netty/channel/pool/package-info.java | 20 - .../socket/ChannelInputShutdownEvent.java | 36 - .../netty/channel/socket/DatagramChannel.java | 165 - .../channel/socket/DatagramChannelConfig.java | 182 - .../netty/channel/socket/DatagramPacket.java | 66 - .../socket/DefaultDatagramChannelConfig.java | 421 -- .../DefaultServerSocketChannelConfig.java | 201 - .../socket/DefaultSocketChannelConfig.java | 341 - .../socket/InternetProtocolFamily.java | 24 - .../channel/socket/ServerSocketChannel.java | 32 - .../socket/ServerSocketChannelConfig.java | 107 - .../netty/channel/socket/SocketChannel.java | 62 - .../channel/socket/SocketChannelConfig.java | 183 - .../socket/nio/NioDatagramChannel.java | 589 -- .../socket/nio/NioDatagramChannelConfig.java | 199 - .../socket/nio/NioServerSocketChannel.java | 197 - .../channel/socket/nio/NioSocketChannel.java | 353 - .../socket/nio/ProtocolFamilyConverter.java | 45 - .../channel/socket/nio/package-info.java | 21 - .../DefaultOioServerSocketChannelConfig.java | 183 - .../oio/DefaultOioSocketChannelConfig.java | 211 - .../socket/oio/OioDatagramChannel.java | 435 -- .../socket/oio/OioServerSocketChannel.java | 202 - .../oio/OioServerSocketChannelConfig.java | 95 - .../channel/socket/oio/OioSocketChannel.java | 240 - .../socket/oio/OioSocketChannelConfig.java | 110 - .../channel/socket/oio/package-info.java | 21 - .../io/netty/channel/socket/package-info.java | 20 - .../channel/unix/DatagramSocketAddress.java | 40 - .../channel/unix/DomainSocketAddress.java | 67 - .../channel/unix/DomainSocketChannel.java | 31 - .../unix/DomainSocketChannelConfig.java | 73 - .../channel/unix/DomainSocketReadMode.java | 32 - .../cloud/io/netty/channel/unix/Errors.java | 134 - .../io/netty/channel/unix/FileDescriptor.java | 189 - .../netty/channel/unix/NativeInetAddress.java | 107 - .../unix/ServerDomainSocketChannel.java | 30 - .../cloud/io/netty/channel/unix/Socket.java | 363 - .../io/netty/channel/unix/UnixChannel.java | 28 - .../io/netty/channel/unix/package-info.java | 20 - .../handler/codec/ByteToMessageCodec.java | 171 - .../handler/codec/ByteToMessageDecoder.java | 437 -- .../netty/handler/codec/CodecException.java | 51 - .../io/netty/handler/codec/CodecUtil.java | 32 - .../codec/CorruptedFrameException.java | 52 - .../netty/handler/codec/DecoderException.java | 51 - .../io/netty/handler/codec/DecoderResult.java | 81 - .../codec/DelimiterBasedFrameDecoder.java | 355 - .../io/netty/handler/codec/Delimiters.java | 49 - .../netty/handler/codec/EncoderException.java | 51 - .../codec/FixedLengthFrameDecoder.java | 80 - .../codec/LengthFieldBasedFrameDecoder.java | 508 -- .../handler/codec/LengthFieldPrepender.java | 208 - .../handler/codec/LineBasedFrameDecoder.java | 166 - .../handler/codec/MessageToByteEncoder.java | 156 - .../handler/codec/MessageToMessageCodec.java | 148 - .../codec/MessageToMessageDecoder.java | 119 - .../codec/MessageToMessageEncoder.java | 145 - .../PrematureChannelClosureException.java | 54 - .../codec/ProtocolDetectionResult.java | 80 - .../handler/codec/ProtocolDetectionState.java | 36 - .../netty/handler/codec/ReplayingDecoder.java | 434 -- .../codec/ReplayingDecoderByteBuf.java | 1006 --- .../handler/codec/TooLongFrameException.java | 52 - .../UnsupportedMessageTypeException.java | 63 - .../io/netty/handler/codec/base64/Base64.java | 303 - .../handler/codec/base64/Base64Decoder.java | 66 - .../handler/codec/base64/Base64Dialect.java | 207 - .../handler/codec/base64/Base64Encoder.java | 69 - .../handler/codec/base64/package-info.java | 23 - .../handler/codec/bytes/ByteArrayDecoder.java | 60 - .../handler/codec/bytes/ByteArrayEncoder.java | 59 - .../handler/codec/bytes/package-info.java | 21 - .../compression/CompressionException.java | 53 - .../handler/codec/compression/Crc32c.java | 126 - .../compression/DecompressionException.java | 53 - .../codec/compression/JZlibDecoder.java | 174 - .../codec/compression/JZlibEncoder.java | 410 -- .../codec/compression/JdkZlibDecoder.java | 393 -- .../codec/compression/JdkZlibEncoder.java | 325 - .../handler/codec/compression/Snappy.java | 674 -- .../compression/SnappyFramedDecoder.java | 212 - .../compression/SnappyFramedEncoder.java | 124 - .../codec/compression/ZlibCodecFactory.java | 128 - .../codec/compression/ZlibDecoder.java | 31 - .../codec/compression/ZlibEncoder.java | 53 - .../handler/codec/compression/ZlibUtil.java | 85 - .../codec/compression/ZlibWrapper.java | 40 - .../codec/compression/package-info.java | 24 - .../handler/codec/haproxy/HAProxyCommand.java | 70 - .../codec/haproxy/HAProxyConstants.java | 60 - .../handler/codec/haproxy/HAProxyMessage.java | 429 -- .../codec/haproxy/HAProxyMessageDecoder.java | 402 -- .../haproxy/HAProxyProtocolException.java | 52 - .../codec/haproxy/HAProxyProtocolVersion.java | 70 - .../codec/haproxy/HAProxyProxiedProtocol.java | 239 - .../handler/codec/haproxy/package-info.java | 22 - .../codec/http/ClientCookieEncoder.java | 59 - .../codec/http/ComposedLastHttpContent.java | 86 - .../io/netty/handler/codec/http/Cookie.java | 219 - .../handler/codec/http/CookieDecoder.java | 375 - .../netty/handler/codec/http/CookieUtil.java | 104 - .../handler/codec/http/DefaultCookie.java | 195 - .../codec/http/DefaultFullHttpRequest.java | 125 - .../codec/http/DefaultFullHttpResponse.java | 121 - .../codec/http/DefaultHttpContent.java | 85 - .../codec/http/DefaultHttpHeaders.java | 504 -- .../codec/http/DefaultHttpMessage.java | 59 - .../handler/codec/http/DefaultHttpObject.java | 40 - .../codec/http/DefaultHttpRequest.java | 95 - .../codec/http/DefaultHttpResponse.java | 74 - .../codec/http/DefaultLastHttpContent.java | 113 - .../handler/codec/http/FullHttpMessage.java | 31 - .../handler/codec/http/FullHttpRequest.java | 40 - .../handler/codec/http/FullHttpResponse.java | 37 - .../handler/codec/http/HttpChunkedInput.java | 99 - .../handler/codec/http/HttpClientCodec.java | 224 - .../handler/codec/http/HttpConstants.java | 82 - .../netty/handler/codec/http/HttpContent.java | 41 - .../codec/http/HttpContentCompressor.java | 167 - .../codec/http/HttpContentDecoder.java | 243 - .../codec/http/HttpContentDecompressor.java | 67 - .../codec/http/HttpContentEncoder.java | 348 - .../http/HttpExpectationFailedEvent.java | 25 - .../codec/http/HttpHeaderDateFormat.java | 101 - .../handler/codec/http/HttpHeaderEntity.java | 78 - .../netty/handler/codec/http/HttpHeaders.java | 1683 ----- .../netty/handler/codec/http/HttpMessage.java | 45 - .../handler/codec/http/HttpMessageUtil.java | 114 - .../netty/handler/codec/http/HttpMethod.java | 205 - .../netty/handler/codec/http/HttpObject.java | 31 - .../codec/http/HttpObjectAggregator.java | 534 -- .../handler/codec/http/HttpObjectDecoder.java | 835 --- .../handler/codec/http/HttpObjectEncoder.java | 212 - .../netty/handler/codec/http/HttpRequest.java | 66 - .../codec/http/HttpRequestDecoder.java | 96 - .../codec/http/HttpRequestEncoder.java | 78 - .../handler/codec/http/HttpResponse.java | 52 - .../codec/http/HttpResponseDecoder.java | 127 - .../codec/http/HttpResponseEncoder.java | 41 - .../codec/http/HttpResponseStatus.java | 560 -- .../handler/codec/http/HttpServerCodec.java | 53 - .../io/netty/handler/codec/http/HttpUtil.java | 45 - .../netty/handler/codec/http/HttpVersion.java | 281 - .../handler/codec/http/LastHttpContent.java | 103 - .../codec/http/QueryStringDecoder.java | 385 - .../codec/http/QueryStringEncoder.java | 132 - .../codec/http/ServerCookieEncoder.java | 101 - .../http/cookie/ClientCookieDecoder.java | 261 - .../http/cookie/ClientCookieEncoder.java | 140 - .../handler/codec/http/cookie/Cookie.java | 141 - .../codec/http/cookie/CookieDecoder.java | 84 - .../codec/http/cookie/CookieEncoder.java | 51 - .../codec/http/cookie/CookieHeaderNames.java | 34 - .../handler/codec/http/cookie/CookieUtil.java | 158 - .../codec/http/cookie/DefaultCookie.java | 268 - .../http/cookie/ServerCookieDecoder.java | 157 - .../http/cookie/ServerCookieEncoder.java | 179 - .../codec/http/cookie/package-info.java | 20 - .../handler/codec/http/cors/CorsConfig.java | 575 -- .../handler/codec/http/cors/CorsHandler.java | 209 - .../handler/codec/http/cors/package-info.java | 20 - .../http/multipart/AbstractDiskHttpData.java | 424 -- .../http/multipart/AbstractHttpData.java | 113 - .../multipart/AbstractMemoryHttpData.java | 257 - .../codec/http/multipart/Attribute.java | 45 - .../multipart/CaseIgnoringComparator.java | 56 - .../multipart/DefaultHttpDataFactory.java | 195 - .../codec/http/multipart/DiskAttribute.java | 184 - .../codec/http/multipart/DiskFileUpload.java | 207 - .../codec/http/multipart/FileUpload.java | 70 - .../codec/http/multipart/HttpData.java | 191 - .../codec/http/multipart/HttpDataFactory.java | 66 - .../http/multipart/HttpPostBodyUtil.java | 224 - .../HttpPostMultipartRequestDecoder.java | 1835 ----- .../multipart/HttpPostRequestDecoder.java | 393 -- .../multipart/HttpPostRequestEncoder.java | 1234 ---- .../HttpPostStandardRequestDecoder.java | 731 -- .../http/multipart/InterfaceHttpData.java | 38 - .../InterfaceHttpPostRequestDecoder.java | 139 - .../http/multipart/InternalAttribute.java | 128 - .../codec/http/multipart/MemoryAttribute.java | 145 - .../http/multipart/MemoryFileUpload.java | 174 - .../codec/http/multipart/MixedAttribute.java | 243 - .../codec/http/multipart/MixedFileUpload.java | 287 - .../codec/http/multipart/package-info.java | 20 - .../handler/codec/http/package-info.java | 20 - .../io/netty/handler/codec/package-info.java | 22 - .../netty/handler/codec/rtsp/RtspDecoder.java | 174 - .../netty/handler/codec/rtsp/RtspEncoder.java | 76 - .../netty/handler/codec/rtsp/RtspHeaders.java | 388 -- .../netty/handler/codec/rtsp/RtspMethods.java | 139 - .../handler/codec/rtsp/RtspObjectDecoder.java | 90 - .../handler/codec/rtsp/RtspObjectEncoder.java | 44 - .../codec/rtsp/RtspRequestDecoder.java | 23 - .../codec/rtsp/RtspRequestEncoder.java | 23 - .../codec/rtsp/RtspResponseDecoder.java | 23 - .../codec/rtsp/RtspResponseEncoder.java | 23 - .../codec/rtsp/RtspResponseStatuses.java | 292 - .../handler/codec/rtsp/RtspVersions.java | 51 - .../handler/codec/rtsp/package-info.java | 21 - .../serialization/CachingClassResolver.java | 46 - .../ClassLoaderClassResolver.java | 35 - .../codec/serialization/ClassResolver.java | 25 - .../codec/serialization/ClassResolvers.java | 104 - .../CompactObjectInputStream.java | 75 - .../CompactObjectOutputStream.java | 49 - .../CompatibleObjectEncoder.java | 103 - .../codec/serialization/ObjectDecoder.java | 84 - .../ObjectDecoderInputStream.java | 243 - .../codec/serialization/ObjectEncoder.java | 55 - .../ObjectEncoderOutputStream.java | 178 - .../codec/serialization/ReferenceMap.java | 102 - .../codec/serialization/SoftReferenceMap.java | 33 - .../codec/serialization/WeakReferenceMap.java | 33 - .../codec/serialization/package-info.java | 22 - .../handler/codec/socks/SocksAddressType.java | 52 - .../handler/codec/socks/SocksAuthRequest.java | 83 - .../codec/socks/SocksAuthRequestDecoder.java | 81 - .../codec/socks/SocksAuthResponse.java | 52 - .../codec/socks/SocksAuthResponseDecoder.java | 72 - .../handler/codec/socks/SocksAuthScheme.java | 52 - .../handler/codec/socks/SocksAuthStatus.java | 50 - .../handler/codec/socks/SocksCmdRequest.java | 138 - .../codec/socks/SocksCmdRequestDecoder.java | 106 - .../handler/codec/socks/SocksCmdResponse.java | 177 - .../codec/socks/SocksCmdResponseDecoder.java | 105 - .../handler/codec/socks/SocksCmdStatus.java | 57 - .../handler/codec/socks/SocksCmdType.java | 52 - .../handler/codec/socks/SocksCommonUtils.java | 106 - .../handler/codec/socks/SocksInitRequest.java | 57 - .../codec/socks/SocksInitRequestDecoder.java | 78 - .../codec/socks/SocksInitResponse.java | 51 - .../codec/socks/SocksInitResponseDecoder.java | 73 - .../handler/codec/socks/SocksMessage.java | 62 - .../codec/socks/SocksMessageEncoder.java | 46 - .../handler/codec/socks/SocksMessageType.java | 23 - .../codec/socks/SocksProtocolVersion.java | 50 - .../handler/codec/socks/SocksRequest.java | 46 - .../handler/codec/socks/SocksRequestType.java | 27 - .../handler/codec/socks/SocksResponse.java | 46 - .../codec/socks/SocksResponseType.java | 27 - .../socks/SocksSubnegotiationVersion.java | 50 - .../codec/socks/UnknownSocksRequest.java | 37 - .../codec/socks/UnknownSocksResponse.java | 37 - .../handler/codec/socks/package-info.java | 21 - .../handler/codec/string/StringDecoder.java | 81 - .../handler/codec/string/StringEncoder.java | 82 - .../handler/codec/string/package-info.java | 21 - .../ipfilter/AbstractRemoteAddressFilter.java | 109 - .../netty/handler/ipfilter/IpFilterRule.java | 36 - .../handler/ipfilter/IpFilterRuleType.java | 24 - .../handler/ipfilter/IpSubnetFilterRule.java | 169 - .../handler/ipfilter/RuleBasedIpFilter.java | 60 - .../handler/ipfilter/UniqueIpFilter.java | 54 - .../netty/handler/ipfilter/package-info.java | 20 - .../io/netty/handler/logging/LogLevel.java | 36 - .../netty/handler/logging/LoggingHandler.java | 327 - .../netty/handler/logging/package-info.java | 20 - .../io/netty/handler/stream/ChunkedFile.java | 164 - .../io/netty/handler/stream/ChunkedInput.java | 50 - .../netty/handler/stream/ChunkedNioFile.java | 175 - .../handler/stream/ChunkedNioStream.java | 131 - .../netty/handler/stream/ChunkedStream.java | 129 - .../handler/stream/ChunkedWriteHandler.java | 379 - .../io/netty/handler/stream/package-info.java | 22 - .../io/netty/handler/timeout/IdleState.java | 37 - .../netty/handler/timeout/IdleStateEvent.java | 52 - .../handler/timeout/IdleStateHandler.java | 466 -- .../handler/timeout/ReadTimeoutException.java | 29 - .../handler/timeout/ReadTimeoutHandler.java | 234 - .../handler/timeout/TimeoutException.java | 34 - .../timeout/WriteTimeoutException.java | 29 - .../handler/timeout/WriteTimeoutHandler.java | 149 - .../netty/handler/timeout/package-info.java | 21 - .../AbstractTrafficShapingHandler.java | 653 -- .../traffic/ChannelTrafficShapingHandler.java | 231 - .../traffic/GlobalChannelTrafficCounter.java | 129 - .../GlobalChannelTrafficShapingHandler.java | 775 -- .../traffic/GlobalTrafficShapingHandler.java | 394 -- .../netty/handler/traffic/TrafficCounter.java | 624 -- .../netty/handler/traffic/package-info.java | 57 - .../netty/util/AbstractReferenceCounted.java | 134 - .../com/ai/cloud/io/netty/util/Attribute.java | 73 - .../ai/cloud/io/netty/util/AttributeKey.java | 85 - .../ai/cloud/io/netty/util/AttributeMap.java | 29 - .../ai/cloud/io/netty/util/CharsetUtil.java | 117 - .../io/netty/util/DefaultAttributeMap.java | 184 - .../io/netty/util/DomainNameMapping.java | 144 - .../cloud/io/netty/util/HashedWheelTimer.java | 740 -- .../util/IllegalReferenceCountException.java | 48 - .../com/ai/cloud/io/netty/util/Mapping.java | 27 - .../com/ai/cloud/io/netty/util/NetUtil.java | 1020 --- .../com/ai/cloud/io/netty/util/Recycler.java | 413 -- .../io/netty/util/ReferenceCountUtil.java | 161 - .../cloud/io/netty/util/ReferenceCounted.java | 63 - .../ai/cloud/io/netty/util/ResourceLeak.java | 32 - .../io/netty/util/ResourceLeakDetector.java | 407 -- .../io/netty/util/ResourceLeakException.java | 71 - .../com/ai/cloud/io/netty/util/Signal.java | 77 - .../io/netty/util/ThreadDeathWatcher.java | 241 - .../com/ai/cloud/io/netty/util/Timeout.java | 54 - .../com/ai/cloud/io/netty/util/Timer.java | 46 - .../com/ai/cloud/io/netty/util/TimerTask.java | 33 - .../ai/cloud/io/netty/util/UniqueName.java | 119 - .../com/ai/cloud/io/netty/util/Version.java | 203 - .../util/collection/IntObjectHashMap.java | 552 -- .../netty/util/collection/IntObjectMap.java | 123 - .../netty/util/collection/package-info.java | 20 - .../concurrent/AbstractEventExecutor.java | 157 - .../AbstractEventExecutorGroup.java | 116 - .../netty/util/concurrent/AbstractFuture.java | 51 - .../AbstractScheduledEventExecutor.java | 214 - .../BlockingOperationException.java | 41 - .../netty/util/concurrent/CompleteFuture.java | 147 - .../util/concurrent/DefaultEventExecutor.java | 45 - .../concurrent/DefaultEventExecutorGroup.java | 48 - .../concurrent/DefaultFutureListeners.java | 86 - .../concurrent/DefaultProgressivePromise.java | 130 - .../netty/util/concurrent/DefaultPromise.java | 882 --- .../util/concurrent/DefaultThreadFactory.java | 143 - .../netty/util/concurrent/EventExecutor.java | 72 - .../util/concurrent/EventExecutorGroup.java | 112 - .../netty/util/concurrent/FailedFuture.java | 69 - .../util/concurrent/FastThreadLocal.java | 244 - .../concurrent/FastThreadLocalThread.java | 72 - .../io/netty/util/concurrent/Future.java | 169 - .../netty/util/concurrent/FutureListener.java | 28 - .../concurrent/GenericFutureListener.java | 32 - .../GenericProgressiveFutureListener.java | 28 - .../util/concurrent/GlobalEventExecutor.java | 278 - .../concurrent/ImmediateEventExecutor.java | 121 - .../util/concurrent/ImmediateExecutor.java | 37 - .../MultithreadEventExecutorGroup.java | 233 - .../util/concurrent/ProgressiveFuture.java | 47 - .../util/concurrent/ProgressivePromise.java | 65 - .../io/netty/util/concurrent/Promise.java | 90 - .../util/concurrent/PromiseAggregator.java | 112 - .../util/concurrent/PromiseNotifier.java | 70 - .../io/netty/util/concurrent/PromiseTask.java | 137 - .../util/concurrent/ScheduledFuture.java | 23 - .../util/concurrent/ScheduledFutureTask.java | 175 - .../concurrent/SingleThreadEventExecutor.java | 777 --- .../util/concurrent/SucceededFuture.java | 50 - .../util/concurrent/ThreadProperties.java | 61 - .../netty/util/concurrent/package-info.java | 20 - .../util/internal/AppendableCharSequence.java | 170 - .../io/netty/util/internal/Cleaner0.java | 75 - .../ConcurrentCircularArrayQueue.java | 207 - .../io/netty/util/internal/ConcurrentSet.java | 65 - .../io/netty/util/internal/EmptyArrays.java | 44 - .../io/netty/util/internal/IntegerHolder.java | 21 - .../util/internal/InternalThreadLocalMap.java | 310 - ...avassistTypeParameterMatcherGenerator.java | 100 - .../io/netty/util/internal/LongCounter.java | 26 - .../io/netty/util/internal/MathUtil.java | 51 - .../netty/util/internal/MpscArrayQueue.java | 331 - .../netty/util/internal/MpscLinkedQueue.java | 378 - .../util/internal/MpscLinkedQueueHeadRef.java | 54 - .../util/internal/MpscLinkedQueueNode.java | 65 - .../util/internal/MpscLinkedQueuePad0.java | 22 - .../util/internal/MpscLinkedQueuePad1.java | 25 - .../util/internal/MpscLinkedQueueTailRef.java | 54 - .../util/internal/NativeLibraryLoader.java | 228 - .../internal/NoOpTypeParameterMatcher.java | 24 - .../io/netty/util/internal/ObjectUtil.java | 35 - .../io/netty/util/internal/OneTimeTask.java | 32 - .../io/netty/util/internal/PendingWrite.java | 97 - .../util/internal/PlatformDependent.java | 958 --- .../util/internal/PlatformDependent0.java | 341 - .../netty/util/internal/ReadOnlyIterator.java | 45 - .../util/internal/RecyclableArrayList.java | 157 - .../RecyclableMpscLinkedQueueNode.java | 45 - .../io/netty/util/internal/StringUtil.java | 397 -- .../util/internal/SystemPropertyUtil.java | 223 - .../util/internal/ThreadLocalRandom.java | 336 - .../util/internal/TypeParameterMatcher.java | 176 - .../UnpaddedInternalThreadLocalMap.java | 57 - .../UnsafeAtomicIntegerFieldUpdater.java | 61 - .../UnsafeAtomicLongFieldUpdater.java | 61 - .../UnsafeAtomicReferenceFieldUpdater.java | 62 - .../internal/chmv8/ConcurrentHashMapV8.java | 6205 ----------------- .../util/internal/chmv8/CountedCompleter.java | 769 -- .../util/internal/chmv8/ForkJoinPool.java | 3359 --------- .../util/internal/chmv8/ForkJoinTask.java | 1560 ----- .../internal/chmv8/ForkJoinWorkerThread.java | 140 - .../util/internal/chmv8/LongAdderV8.java | 225 - .../netty/util/internal/chmv8/Striped64.java | 351 - .../logging/AbstractInternalLogger.java | 190 - .../util/internal/logging/CommonsLogger.java | 564 -- .../logging/CommonsLoggerFactory.java | 37 - .../internal/logging/FormattingTuple.java | 88 - .../internal/logging/InternalLogLevel.java | 42 - .../util/internal/logging/InternalLogger.java | 444 -- .../logging/InternalLoggerFactory.java | 91 - .../util/internal/logging/JdkLogger.java | 647 -- .../internal/logging/JdkLoggerFactory.java | 32 - .../util/internal/logging/Log4JLogger.java | 597 -- .../internal/logging/Log4JLoggerFactory.java | 31 - .../internal/logging/MessageFormatter.java | 428 -- .../util/internal/logging/Slf4JLogger.java | 183 - .../internal/logging/Slf4JLoggerFactory.java | 69 - .../util/internal/logging/package-info.java | 20 - .../io/netty/util/internal/package-info.java | 21 - .../ai/cloud/io/netty/util/package-info.java | 20 - .../java/com/ai/cloud/io/netty/version.md | 10 - .../cloud/skywalking/sender/DataSender.java | 31 +- .../test/ai/cloud/bytebuddy/Interceptor.java | 22 + .../test/ai/cloud/bytebuddy/SimulateMain.java | 49 + .../test/ai/cloud/bytebuddy/TestClass.java | 8 + 600 files changed, 139 insertions(+), 122661 deletions(-) delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/bootstrap/AbstractBootstrap.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/bootstrap/Bootstrap.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/bootstrap/ChannelFactory.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/bootstrap/ServerBootstrap.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/bootstrap/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/AbstractByteBuf.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/AbstractByteBufAllocator.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/AbstractDerivedByteBuf.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/AbstractReferenceCountedByteBuf.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/AbstractUnsafeSwappedByteBuf.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/AdvancedLeakAwareByteBuf.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ByteBuf.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ByteBufAllocator.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ByteBufHolder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ByteBufInputStream.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ByteBufOutputStream.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ByteBufProcessor.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ByteBufUtil.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/CompositeByteBuf.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/DefaultByteBufHolder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/DuplicatedAbstractByteBuf.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/DuplicatedByteBuf.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/EmptyByteBuf.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/FixedCompositeByteBuf.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/HeapByteBufUtil.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolArena.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolArenaMetric.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolChunk.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolChunkList.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolChunkListMetric.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolChunkMetric.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolSubpage.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolSubpageMetric.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolThreadCache.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PooledByteBuf.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PooledByteBufAllocator.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PooledDirectByteBuf.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PooledHeapByteBuf.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PooledUnsafeDirectByteBuf.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PooledUnsafeHeapByteBuf.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ReadOnlyByteBuf.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ReadOnlyByteBufferBuf.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ReadOnlyUnsafeDirectByteBuf.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/SimpleLeakAwareByteBuf.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/SlicedAbstractByteBuf.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/SlicedByteBuf.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/SwappedByteBuf.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/Unpooled.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnpooledByteBufAllocator.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnpooledDirectByteBuf.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnpooledHeapByteBuf.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnpooledUnsafeDirectByteBuf.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnpooledUnsafeHeapByteBuf.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnreleasableByteBuf.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnsafeByteBufUtil.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnsafeDirectSwappedByteBuf.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnsafeHeapSwappedByteBuf.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/WrappedByteBuf.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/AbstractChannel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/AbstractChannelHandlerContext.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/AbstractServerChannel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/AdaptiveRecvByteBufAllocator.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/AddressedEnvelope.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/Channel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelConfig.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelDuplexHandler.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelException.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelFlushPromiseNotifier.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelFuture.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelFutureListener.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelHandler.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelHandlerAdapter.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelHandlerContext.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelInboundHandler.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelInboundHandlerAdapter.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelInitializer.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelMetadata.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelOption.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelOutboundBuffer.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelOutboundHandler.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelOutboundHandlerAdapter.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelPipeline.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelPipelineException.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelProgressiveFuture.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelProgressiveFutureListener.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelProgressivePromise.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelPromise.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelPromiseAggregator.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelPromiseNotifier.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/CombinedChannelDuplexHandler.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/CompleteChannelFuture.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ConnectTimeoutException.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/DefaultAddressedEnvelope.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/DefaultChannelConfig.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/DefaultChannelHandlerContext.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/DefaultChannelPipeline.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/DefaultChannelProgressivePromise.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/DefaultChannelPromise.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/DefaultFileRegion.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/DefaultMessageSizeEstimator.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/EventLoop.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/EventLoopException.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/EventLoopGroup.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/FailedChannelFuture.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/FileRegion.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/FixedRecvByteBufAllocator.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/MessageSizeEstimator.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/MultithreadEventLoopGroup.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/PendingWriteQueue.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/RecvByteBufAllocator.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ServerChannel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/SimpleChannelInboundHandler.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/SingleThreadEventLoop.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/SucceededChannelFuture.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ThreadPerChannelEventLoop.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ThreadPerChannelEventLoopGroup.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/VoidChannelPromise.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/embedded/EmbeddedChannel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/embedded/EmbeddedEventLoop.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/embedded/EmbeddedSocketAddress.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/embedded/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/AbstractEpollChannel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/AbstractEpollServerChannel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/AbstractEpollStreamChannel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/Epoll.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollChannelConfig.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollChannelOption.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollDatagramChannel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollDatagramChannelConfig.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollDomainSocketChannel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollDomainSocketChannelConfig.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollEventArray.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollEventLoop.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollEventLoopGroup.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollMode.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollServerChannelConfig.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollServerDomainSocketChannel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollServerSocketChannel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollServerSocketChannelConfig.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollSocketChannel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollSocketChannelConfig.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollTcpInfo.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/IovArray.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/IovArrayThreadLocal.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/Native.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/NativeDatagramPacketArray.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/TcpMd5Util.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/ChannelGroup.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/ChannelGroupException.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/ChannelGroupFuture.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/ChannelGroupFutureListener.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/ChannelMatcher.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/ChannelMatchers.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/CombinedIterator.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/DefaultChannelGroup.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/DefaultChannelGroupFuture.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/local/LocalAddress.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/local/LocalChannel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/local/LocalChannelRegistry.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/local/LocalEventLoop.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/local/LocalEventLoopGroup.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/local/LocalServerChannel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/local/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/nio/AbstractNioByteChannel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/nio/AbstractNioChannel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/nio/AbstractNioMessageChannel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/nio/NioEventLoop.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/nio/NioEventLoopGroup.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/nio/NioTask.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/nio/SelectedSelectionKeySet.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/nio/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/oio/AbstractOioByteChannel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/oio/AbstractOioChannel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/oio/AbstractOioMessageChannel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/oio/OioByteStreamChannel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/oio/OioEventLoopGroup.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/oio/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/AbstractChannelPoolHandler.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/AbstractChannelPoolMap.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/ChannelHealthChecker.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/ChannelPool.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/ChannelPoolHandler.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/ChannelPoolMap.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/FixedChannelPool.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/SimpleChannelPool.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/ChannelInputShutdownEvent.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/DatagramChannel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/DatagramChannelConfig.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/DatagramPacket.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/DefaultDatagramChannelConfig.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/DefaultServerSocketChannelConfig.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/DefaultSocketChannelConfig.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/InternetProtocolFamily.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/ServerSocketChannel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/ServerSocketChannelConfig.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/SocketChannel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/SocketChannelConfig.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/nio/NioDatagramChannel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/nio/NioDatagramChannelConfig.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/nio/NioServerSocketChannel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/nio/NioSocketChannel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/nio/ProtocolFamilyConverter.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/nio/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/oio/DefaultOioServerSocketChannelConfig.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/oio/DefaultOioSocketChannelConfig.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/oio/OioDatagramChannel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/oio/OioServerSocketChannel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/oio/OioServerSocketChannelConfig.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/oio/OioSocketChannel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/oio/OioSocketChannelConfig.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/oio/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/DatagramSocketAddress.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/DomainSocketAddress.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/DomainSocketChannel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/DomainSocketChannelConfig.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/DomainSocketReadMode.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/Errors.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/FileDescriptor.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/NativeInetAddress.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/ServerDomainSocketChannel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/Socket.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/UnixChannel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/ByteToMessageCodec.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/ByteToMessageDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/CodecException.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/CodecUtil.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/CorruptedFrameException.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/DecoderException.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/DecoderResult.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/DelimiterBasedFrameDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/Delimiters.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/EncoderException.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/FixedLengthFrameDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/LengthFieldBasedFrameDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/LengthFieldPrepender.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/LineBasedFrameDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/MessageToByteEncoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/MessageToMessageCodec.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/MessageToMessageDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/MessageToMessageEncoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/PrematureChannelClosureException.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/ProtocolDetectionResult.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/ProtocolDetectionState.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/ReplayingDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/ReplayingDecoderByteBuf.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/TooLongFrameException.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/UnsupportedMessageTypeException.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/base64/Base64.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/base64/Base64Decoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/base64/Base64Dialect.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/base64/Base64Encoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/base64/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/bytes/ByteArrayDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/bytes/ByteArrayEncoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/bytes/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/CompressionException.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/Crc32c.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/DecompressionException.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/JZlibDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/JZlibEncoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/JdkZlibDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/JdkZlibEncoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/Snappy.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/SnappyFramedDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/SnappyFramedEncoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/ZlibCodecFactory.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/ZlibDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/ZlibEncoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/ZlibUtil.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/ZlibWrapper.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/haproxy/HAProxyCommand.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/haproxy/HAProxyConstants.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/haproxy/HAProxyMessage.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/haproxy/HAProxyMessageDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/haproxy/HAProxyProtocolException.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/haproxy/HAProxyProtocolVersion.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/haproxy/HAProxyProxiedProtocol.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/haproxy/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/ClientCookieEncoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/ComposedLastHttpContent.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/Cookie.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/CookieDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/CookieUtil.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultCookie.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultFullHttpRequest.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultFullHttpResponse.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultHttpContent.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultHttpHeaders.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultHttpMessage.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultHttpObject.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultHttpRequest.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultHttpResponse.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultLastHttpContent.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/FullHttpMessage.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/FullHttpRequest.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/FullHttpResponse.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpChunkedInput.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpClientCodec.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpConstants.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpContent.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpContentCompressor.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpContentDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpContentDecompressor.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpContentEncoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpExpectationFailedEvent.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpHeaderDateFormat.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpHeaderEntity.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpHeaders.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpMessage.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpMessageUtil.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpMethod.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpObject.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpObjectAggregator.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpObjectDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpObjectEncoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpRequest.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpRequestDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpRequestEncoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpResponse.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpResponseDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpResponseEncoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpResponseStatus.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpServerCodec.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpUtil.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpVersion.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/LastHttpContent.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/QueryStringDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/QueryStringEncoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/ServerCookieEncoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/ClientCookieDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/ClientCookieEncoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/Cookie.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/CookieDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/CookieEncoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/CookieHeaderNames.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/CookieUtil.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/DefaultCookie.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/ServerCookieDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/ServerCookieEncoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cors/CorsConfig.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cors/CorsHandler.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cors/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/AbstractDiskHttpData.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/AbstractHttpData.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/AbstractMemoryHttpData.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/Attribute.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/CaseIgnoringComparator.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/DefaultHttpDataFactory.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/DiskAttribute.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/DiskFileUpload.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/FileUpload.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/HttpData.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/HttpDataFactory.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/HttpPostBodyUtil.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/HttpPostMultipartRequestDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/HttpPostRequestDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/HttpPostRequestEncoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/HttpPostStandardRequestDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/InterfaceHttpData.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/InterfaceHttpPostRequestDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/InternalAttribute.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/MemoryAttribute.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/MemoryFileUpload.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/MixedAttribute.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/MixedFileUpload.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspEncoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspHeaders.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspMethods.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspObjectDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspObjectEncoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspRequestDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspRequestEncoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspResponseDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspResponseEncoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspResponseStatuses.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspVersions.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/CachingClassResolver.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/ClassLoaderClassResolver.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/ClassResolver.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/ClassResolvers.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/CompactObjectInputStream.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/CompactObjectOutputStream.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/CompatibleObjectEncoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/ObjectDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/ObjectDecoderInputStream.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/ObjectEncoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/ObjectEncoderOutputStream.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/ReferenceMap.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/SoftReferenceMap.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/WeakReferenceMap.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksAddressType.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksAuthRequest.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksAuthRequestDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksAuthResponse.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksAuthResponseDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksAuthScheme.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksAuthStatus.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksCmdRequest.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksCmdRequestDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksCmdResponse.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksCmdResponseDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksCmdStatus.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksCmdType.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksCommonUtils.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksInitRequest.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksInitRequestDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksInitResponse.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksInitResponseDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksMessage.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksMessageEncoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksMessageType.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksProtocolVersion.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksRequest.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksRequestType.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksResponse.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksResponseType.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksSubnegotiationVersion.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/UnknownSocksRequest.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/UnknownSocksResponse.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/string/StringDecoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/string/StringEncoder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/string/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/ipfilter/AbstractRemoteAddressFilter.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/ipfilter/IpFilterRule.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/ipfilter/IpFilterRuleType.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/ipfilter/IpSubnetFilterRule.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/ipfilter/RuleBasedIpFilter.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/ipfilter/UniqueIpFilter.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/ipfilter/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/logging/LogLevel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/logging/LoggingHandler.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/logging/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/stream/ChunkedFile.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/stream/ChunkedInput.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/stream/ChunkedNioFile.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/stream/ChunkedNioStream.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/stream/ChunkedStream.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/stream/ChunkedWriteHandler.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/stream/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/IdleState.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/IdleStateEvent.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/IdleStateHandler.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/ReadTimeoutException.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/ReadTimeoutHandler.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/TimeoutException.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/WriteTimeoutException.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/WriteTimeoutHandler.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/traffic/AbstractTrafficShapingHandler.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/traffic/ChannelTrafficShapingHandler.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/traffic/GlobalChannelTrafficCounter.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/traffic/GlobalChannelTrafficShapingHandler.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/traffic/GlobalTrafficShapingHandler.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/traffic/TrafficCounter.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/traffic/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/AbstractReferenceCounted.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/Attribute.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/AttributeKey.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/AttributeMap.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/CharsetUtil.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/DefaultAttributeMap.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/DomainNameMapping.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/HashedWheelTimer.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/IllegalReferenceCountException.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/Mapping.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/NetUtil.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/Recycler.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/ReferenceCountUtil.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/ReferenceCounted.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/ResourceLeak.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/ResourceLeakDetector.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/ResourceLeakException.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/Signal.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/ThreadDeathWatcher.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/Timeout.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/Timer.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/TimerTask.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/UniqueName.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/Version.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/collection/IntObjectHashMap.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/collection/IntObjectMap.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/collection/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/AbstractEventExecutor.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/AbstractEventExecutorGroup.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/AbstractFuture.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/AbstractScheduledEventExecutor.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/BlockingOperationException.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/CompleteFuture.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/DefaultEventExecutor.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/DefaultEventExecutorGroup.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/DefaultFutureListeners.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/DefaultProgressivePromise.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/DefaultPromise.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/DefaultThreadFactory.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/EventExecutor.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/EventExecutorGroup.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/FailedFuture.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/FastThreadLocal.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/FastThreadLocalThread.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/Future.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/FutureListener.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/GenericFutureListener.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/GenericProgressiveFutureListener.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/GlobalEventExecutor.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/ImmediateEventExecutor.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/ImmediateExecutor.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/MultithreadEventExecutorGroup.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/ProgressiveFuture.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/ProgressivePromise.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/Promise.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/PromiseAggregator.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/PromiseNotifier.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/PromiseTask.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/ScheduledFuture.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/ScheduledFutureTask.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/SingleThreadEventExecutor.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/SucceededFuture.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/ThreadProperties.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/AppendableCharSequence.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/Cleaner0.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/ConcurrentCircularArrayQueue.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/ConcurrentSet.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/EmptyArrays.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/IntegerHolder.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/InternalThreadLocalMap.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/JavassistTypeParameterMatcherGenerator.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/LongCounter.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/MathUtil.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/MpscArrayQueue.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/MpscLinkedQueue.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/MpscLinkedQueueHeadRef.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/MpscLinkedQueueNode.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/MpscLinkedQueuePad0.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/MpscLinkedQueuePad1.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/MpscLinkedQueueTailRef.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/NativeLibraryLoader.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/NoOpTypeParameterMatcher.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/ObjectUtil.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/OneTimeTask.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/PendingWrite.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/PlatformDependent.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/PlatformDependent0.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/ReadOnlyIterator.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/RecyclableArrayList.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/RecyclableMpscLinkedQueueNode.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/StringUtil.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/SystemPropertyUtil.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/ThreadLocalRandom.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/TypeParameterMatcher.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/UnpaddedInternalThreadLocalMap.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/UnsafeAtomicIntegerFieldUpdater.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/UnsafeAtomicLongFieldUpdater.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/UnsafeAtomicReferenceFieldUpdater.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/chmv8/ConcurrentHashMapV8.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/chmv8/CountedCompleter.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/chmv8/ForkJoinPool.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/chmv8/ForkJoinTask.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/chmv8/ForkJoinWorkerThread.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/chmv8/LongAdderV8.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/chmv8/Striped64.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/AbstractInternalLogger.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/CommonsLogger.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/CommonsLoggerFactory.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/FormattingTuple.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/InternalLogLevel.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/InternalLogger.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/InternalLoggerFactory.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/JdkLogger.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/JdkLoggerFactory.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/Log4JLogger.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/Log4JLoggerFactory.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/MessageFormatter.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/Slf4JLogger.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/Slf4JLoggerFactory.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/package-info.java delete mode 100755 skywalking-api/src/main/java/com/ai/cloud/io/netty/util/package-info.java delete mode 100644 skywalking-api/src/main/java/com/ai/cloud/io/netty/version.md create mode 100644 skywalking-api/src/test/java/test/ai/cloud/bytebuddy/Interceptor.java create mode 100644 skywalking-api/src/test/java/test/ai/cloud/bytebuddy/SimulateMain.java create mode 100644 skywalking-api/src/test/java/test/ai/cloud/bytebuddy/TestClass.java diff --git a/skywalking-api/pom.xml b/skywalking-api/pom.xml index fcf5ce51ee..9521f94c26 100644 --- a/skywalking-api/pom.xml +++ b/skywalking-api/pom.xml @@ -12,6 +12,11 @@ UTF-8 + 2.4.1 + net.bytebuddy + com.ai.cloud.skywalking.api.dependencies.net.bytebuddy + io.netty + com.ai.cloud.skywalking.api.dependencies.io.netty @@ -20,75 +25,26 @@ skywalking-protocol 1.0-SNAPSHOT - - - org.apache.logging.log4j - log4j-core - 2.4.1 - provided - - com.jcraft - jzlib - 1.1.3 - compile + net.bytebuddy + byte-buddy + 1.3.0 - org.javassist - javassist - 3.19.0-GA - compile + io.netty + netty-all + 4.0.33.Final - commons-logging - commons-logging - 1.1.3 - compile - - - - org.osgi - org.osgi.core - 4.3.1 + org.apache.logging.log4j + log4j-core + 2.4.1 provided - - log4j - log4j - 1.2.17 - - - mail - javax.mail - - - jms - javax.jms - - - jmxtools - com.sun.jdmk - - - jmxri - com.sun.jmx - - - compile - true - - - - org.slf4j - slf4j-api - 1.7.5 - compile - - junit junit @@ -132,6 +88,36 @@ + + + org.apache.maven.plugins + maven-shade-plugin + ${version.plugin.shade} + + + package + + shade + + + false + true + true + true + + + ${shade.net.bytebuddy.source} + ${shade.net.bytebuddy.target} + + + ${shade.io.netty.source} + ${shade.io.netty.target} + + + + + + diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/bootstrap/AbstractBootstrap.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/bootstrap/AbstractBootstrap.java deleted file mode 100755 index b76158be3c..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/bootstrap/AbstractBootstrap.java +++ /dev/null @@ -1,487 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.bootstrap; - -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.util.LinkedHashMap; -import java.util.Map; - -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelException; -import com.ai.cloud.io.netty.channel.ChannelFuture; -import com.ai.cloud.io.netty.channel.ChannelFutureListener; -import com.ai.cloud.io.netty.channel.ChannelHandler; -import com.ai.cloud.io.netty.channel.ChannelOption; -import com.ai.cloud.io.netty.channel.ChannelPromise; -import com.ai.cloud.io.netty.channel.DefaultChannelPromise; -import com.ai.cloud.io.netty.channel.EventLoop; -import com.ai.cloud.io.netty.channel.EventLoopGroup; -import com.ai.cloud.io.netty.util.AttributeKey; -import com.ai.cloud.io.netty.util.concurrent.EventExecutor; -import com.ai.cloud.io.netty.util.concurrent.GlobalEventExecutor; -import com.ai.cloud.io.netty.util.internal.StringUtil; - -/** - * {@link AbstractBootstrap} is a helper class that makes it easy to bootstrap a {@link Channel}. It support - * method-chaining to provide an easy way to configure the {@link AbstractBootstrap}. - * - *

When not used in a {@link ServerBootstrap} context, the {@link #bind()} methods are useful for connectionless - * transports such as datagram (UDP).

- */ -public abstract class AbstractBootstrap, C extends Channel> implements Cloneable { - - volatile EventLoopGroup group; - private volatile ChannelFactory channelFactory; - private volatile SocketAddress localAddress; - private final Map, Object> options = new LinkedHashMap, Object>(); - private final Map, Object> attrs = new LinkedHashMap, Object>(); - private volatile ChannelHandler handler; - - AbstractBootstrap() { - // Disallow extending from a different package. - } - - AbstractBootstrap(AbstractBootstrap bootstrap) { - group = bootstrap.group; - channelFactory = bootstrap.channelFactory; - handler = bootstrap.handler; - localAddress = bootstrap.localAddress; - synchronized (bootstrap.options) { - options.putAll(bootstrap.options); - } - synchronized (bootstrap.attrs) { - attrs.putAll(bootstrap.attrs); - } - } - - /** - * The {@link EventLoopGroup} which is used to handle all the events for the to-be-created - * {@link Channel} - */ - @SuppressWarnings("unchecked") - public B group(EventLoopGroup group) { - if (group == null) { - throw new NullPointerException("group"); - } - if (this.group != null) { - throw new IllegalStateException("group set already"); - } - this.group = group; - return (B) this; - } - - /** - * The {@link Class} which is used to create {@link Channel} instances from. - * You either use this or {@link #channelFactory(ChannelFactory)} if your - * {@link Channel} implementation has no no-args constructor. - */ - public B channel(Class channelClass) { - if (channelClass == null) { - throw new NullPointerException("channelClass"); - } - return channelFactory(new BootstrapChannelFactory(channelClass)); - } - - /** - * {@link ChannelFactory} which is used to create {@link Channel} instances from - * when calling {@link #bind()}. This method is usually only used if {@link #channel(Class)} - * is not working for you because of some more complex needs. If your {@link Channel} implementation - * has a no-args constructor, its highly recommend to just use {@link #channel(Class)} for - * simplify your code. - */ - @SuppressWarnings("unchecked") - public B channelFactory(ChannelFactory channelFactory) { - if (channelFactory == null) { - throw new NullPointerException("channelFactory"); - } - if (this.channelFactory != null) { - throw new IllegalStateException("channelFactory set already"); - } - - this.channelFactory = channelFactory; - return (B) this; - } - - /** - * The {@link SocketAddress} which is used to bind the local "end" to. - * - */ - @SuppressWarnings("unchecked") - public B localAddress(SocketAddress localAddress) { - this.localAddress = localAddress; - return (B) this; - } - - /** - * @see {@link #localAddress(SocketAddress)} - */ - public B localAddress(int inetPort) { - return localAddress(new InetSocketAddress(inetPort)); - } - - /** - * @see {@link #localAddress(SocketAddress)} - */ - public B localAddress(String inetHost, int inetPort) { - return localAddress(new InetSocketAddress(inetHost, inetPort)); - } - - /** - * @see {@link #localAddress(SocketAddress)} - */ - public B localAddress(InetAddress inetHost, int inetPort) { - return localAddress(new InetSocketAddress(inetHost, inetPort)); - } - - /** - * Allow to specify a {@link ChannelOption} which is used for the {@link Channel} instances once they got - * created. Use a value of {@code null} to remove a previous set {@link ChannelOption}. - */ - @SuppressWarnings("unchecked") - public B option(ChannelOption option, T value) { - if (option == null) { - throw new NullPointerException("option"); - } - if (value == null) { - synchronized (options) { - options.remove(option); - } - } else { - synchronized (options) { - options.put(option, value); - } - } - return (B) this; - } - - /** - * Allow to specify an initial attribute of the newly created {@link Channel}. If the {@code value} is - * {@code null}, the attribute of the specified {@code key} is removed. - */ - @SuppressWarnings("unchecked") - public B attr(AttributeKey key, T value) { - if (key == null) { - throw new NullPointerException("key"); - } - if (value == null) { - synchronized (attrs) { - attrs.remove(key); - } - } else { - synchronized (attrs) { - attrs.put(key, value); - } - } - return (B) this; - } - - /** - * Validate all the parameters. Sub-classes may override this, but should - * call the super method in that case. - */ - @SuppressWarnings("unchecked") - public B validate() { - if (group == null) { - throw new IllegalStateException("group not set"); - } - if (channelFactory == null) { - throw new IllegalStateException("channel or channelFactory not set"); - } - return (B) this; - } - - /** - * Returns a deep clone of this bootstrap which has the identical configuration. This method is useful when making - * multiple {@link Channel}s with similar settings. Please note that this method does not clone the - * {@link EventLoopGroup} deeply but shallowly, making the group a shared resource. - */ - @Override - @SuppressWarnings("CloneDoesntDeclareCloneNotSupportedException") - public abstract B clone(); - - /** - * Create a new {@link Channel} and register it with an {@link EventLoop}. - */ - public ChannelFuture register() { - validate(); - return initAndRegister(); - } - - /** - * Create a new {@link Channel} and bind it. - */ - public ChannelFuture bind() { - validate(); - SocketAddress localAddress = this.localAddress; - if (localAddress == null) { - throw new IllegalStateException("localAddress not set"); - } - return doBind(localAddress); - } - - /** - * Create a new {@link Channel} and bind it. - */ - public ChannelFuture bind(int inetPort) { - return bind(new InetSocketAddress(inetPort)); - } - - /** - * Create a new {@link Channel} and bind it. - */ - public ChannelFuture bind(String inetHost, int inetPort) { - return bind(new InetSocketAddress(inetHost, inetPort)); - } - - /** - * Create a new {@link Channel} and bind it. - */ - public ChannelFuture bind(InetAddress inetHost, int inetPort) { - return bind(new InetSocketAddress(inetHost, inetPort)); - } - - /** - * Create a new {@link Channel} and bind it. - */ - public ChannelFuture bind(SocketAddress localAddress) { - validate(); - if (localAddress == null) { - throw new NullPointerException("localAddress"); - } - return doBind(localAddress); - } - - private ChannelFuture doBind(final SocketAddress localAddress) { - final ChannelFuture regFuture = initAndRegister(); - final Channel channel = regFuture.channel(); - if (regFuture.cause() != null) { - return regFuture; - } - - if (regFuture.isDone()) { - // At this point we know that the registration was complete and successful. - ChannelPromise promise = channel.newPromise(); - doBind0(regFuture, channel, localAddress, promise); - return promise; - } else { - // Registration future is almost always fulfilled already, but just in case it's not. - final PendingRegistrationPromise promise = new PendingRegistrationPromise(channel); - regFuture.addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - Throwable cause = future.cause(); - if (cause != null) { - // Registration on the EventLoop failed so fail the ChannelPromise directly to not cause an - // IllegalStateException once we try to access the EventLoop of the Channel. - promise.setFailure(cause); - } else { - // Registration was successful, so set the correct executor to use. - // See https://github.com/netty/netty/issues/2586 - promise.executor = channel.eventLoop(); - } - doBind0(regFuture, channel, localAddress, promise); - } - }); - return promise; - } - } - - final ChannelFuture initAndRegister() { - final Channel channel = channelFactory().newChannel(); - try { - init(channel); - } catch (Throwable t) { - channel.unsafe().closeForcibly(); - // as the Channel is not registered yet we need to force the usage of the GlobalEventExecutor - return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t); - } - - ChannelFuture regFuture = group().register(channel); - if (regFuture.cause() != null) { - if (channel.isRegistered()) { - channel.close(); - } else { - channel.unsafe().closeForcibly(); - } - } - - // If we are here and the promise is not failed, it's one of the following cases: - // 1) If we attempted registration from the event loop, the registration has been completed at this point. - // i.e. It's safe to attempt bind() or connect() now because the channel has been registered. - // 2) If we attempted registration from the other thread, the registration request has been successfully - // added to the event loop's task queue for later execution. - // i.e. It's safe to attempt bind() or connect() now: - // because bind() or connect() will be executed *after* the scheduled registration task is executed - // because register(), bind(), and connect() are all bound to the same thread. - - return regFuture; - } - - abstract void init(Channel channel) throws Exception; - - private static void doBind0( - final ChannelFuture regFuture, final Channel channel, - final SocketAddress localAddress, final ChannelPromise promise) { - - // This method is invoked before channelRegistered() is triggered. Give user handlers a chance to set up - // the pipeline in its channelRegistered() implementation. - channel.eventLoop().execute(new Runnable() { - @Override - public void run() { - if (regFuture.isSuccess()) { - channel.bind(localAddress, promise).addListener(ChannelFutureListener.CLOSE_ON_FAILURE); - } else { - promise.setFailure(regFuture.cause()); - } - } - }); - } - - /** - * the {@link ChannelHandler} to use for serving the requests. - */ - @SuppressWarnings("unchecked") - public B handler(ChannelHandler handler) { - if (handler == null) { - throw new NullPointerException("handler"); - } - this.handler = handler; - return (B) this; - } - - final SocketAddress localAddress() { - return localAddress; - } - - final ChannelFactory channelFactory() { - return channelFactory; - } - - final ChannelHandler handler() { - return handler; - } - - /** - * Return the configured {@link EventLoopGroup} or {@code null} if non is configured yet. - */ - public EventLoopGroup group() { - return group; - } - - final Map, Object> options() { - return options; - } - - final Map, Object> attrs() { - return attrs; - } - - @Override - public String toString() { - StringBuilder buf = new StringBuilder() - .append(StringUtil.simpleClassName(this)) - .append('('); - if (group != null) { - buf.append("group: ") - .append(StringUtil.simpleClassName(group)) - .append(", "); - } - if (channelFactory != null) { - buf.append("channelFactory: ") - .append(channelFactory) - .append(", "); - } - if (localAddress != null) { - buf.append("localAddress: ") - .append(localAddress) - .append(", "); - } - synchronized (options) { - if (!options.isEmpty()) { - buf.append("options: ") - .append(options) - .append(", "); - } - } - synchronized (attrs) { - if (!attrs.isEmpty()) { - buf.append("attrs: ") - .append(attrs) - .append(", "); - } - } - if (handler != null) { - buf.append("handler: ") - .append(handler) - .append(", "); - } - if (buf.charAt(buf.length() - 1) == '(') { - buf.append(')'); - } else { - buf.setCharAt(buf.length() - 2, ')'); - buf.setLength(buf.length() - 1); - } - return buf.toString(); - } - - private static final class BootstrapChannelFactory implements ChannelFactory { - private final Class clazz; - - BootstrapChannelFactory(Class clazz) { - this.clazz = clazz; - } - - @Override - public T newChannel() { - try { - return clazz.newInstance(); - } catch (Throwable t) { - throw new ChannelException("Unable to create Channel from class " + clazz, t); - } - } - - @Override - public String toString() { - return StringUtil.simpleClassName(clazz) + ".class"; - } - } - - private static final class PendingRegistrationPromise extends DefaultChannelPromise { - // Is set to the correct EventExecutor once the registration was successful. Otherwise it will - // stay null and so the GlobalEventExecutor.INSTANCE will be used for notifications. - private volatile EventExecutor executor; - - private PendingRegistrationPromise(Channel channel) { - super(channel); - } - - @Override - protected EventExecutor executor() { - EventExecutor executor = this.executor; - if (executor != null) { - // If the registration was a success executor is set. - // - // See https://github.com/netty/netty/issues/2586 - return executor; - } - // The registration failed so we can only use the GlobalEventExecutor as last resort to notify. - return GlobalEventExecutor.INSTANCE; - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/bootstrap/Bootstrap.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/bootstrap/Bootstrap.java deleted file mode 100755 index ce3b51f7cc..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/bootstrap/Bootstrap.java +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.bootstrap; - -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.util.Map; -import java.util.Map.Entry; - -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelFuture; -import com.ai.cloud.io.netty.channel.ChannelFutureListener; -import com.ai.cloud.io.netty.channel.ChannelOption; -import com.ai.cloud.io.netty.channel.ChannelPipeline; -import com.ai.cloud.io.netty.channel.ChannelPromise; -import com.ai.cloud.io.netty.channel.EventLoopGroup; -import com.ai.cloud.io.netty.util.AttributeKey; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * A {@link Bootstrap} that makes it easy to bootstrap a {@link Channel} to use - * for clients. - * - *

The {@link #bind()} methods are useful in combination with connectionless transports such as datagram (UDP). - * For regular TCP connections, please use the provided {@link #connect()} methods.

- */ -public class Bootstrap extends AbstractBootstrap { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(Bootstrap.class); - - private volatile SocketAddress remoteAddress; - - public Bootstrap() { } - - private Bootstrap(Bootstrap bootstrap) { - super(bootstrap); - remoteAddress = bootstrap.remoteAddress; - } - - /** - * The {@link SocketAddress} to connect to once the {@link #connect()} method - * is called. - */ - public Bootstrap remoteAddress(SocketAddress remoteAddress) { - this.remoteAddress = remoteAddress; - return this; - } - - /** - * @see {@link #remoteAddress(SocketAddress)} - */ - public Bootstrap remoteAddress(String inetHost, int inetPort) { - remoteAddress = new InetSocketAddress(inetHost, inetPort); - return this; - } - - /** - * @see {@link #remoteAddress(SocketAddress)} - */ - public Bootstrap remoteAddress(InetAddress inetHost, int inetPort) { - remoteAddress = new InetSocketAddress(inetHost, inetPort); - return this; - } - - /** - * Connect a {@link Channel} to the remote peer. - */ - public ChannelFuture connect() { - validate(); - SocketAddress remoteAddress = this.remoteAddress; - if (remoteAddress == null) { - throw new IllegalStateException("remoteAddress not set"); - } - - return doConnect(remoteAddress, localAddress()); - } - - /** - * Connect a {@link Channel} to the remote peer. - */ - public ChannelFuture connect(String inetHost, int inetPort) { - return connect(new InetSocketAddress(inetHost, inetPort)); - } - - /** - * Connect a {@link Channel} to the remote peer. - */ - public ChannelFuture connect(InetAddress inetHost, int inetPort) { - return connect(new InetSocketAddress(inetHost, inetPort)); - } - - /** - * Connect a {@link Channel} to the remote peer. - */ - public ChannelFuture connect(SocketAddress remoteAddress) { - if (remoteAddress == null) { - throw new NullPointerException("remoteAddress"); - } - - validate(); - return doConnect(remoteAddress, localAddress()); - } - - /** - * Connect a {@link Channel} to the remote peer. - */ - public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress) { - if (remoteAddress == null) { - throw new NullPointerException("remoteAddress"); - } - validate(); - return doConnect(remoteAddress, localAddress); - } - - /** - * @see {@link #connect()} - */ - private ChannelFuture doConnect(final SocketAddress remoteAddress, final SocketAddress localAddress) { - final ChannelFuture regFuture = initAndRegister(); - final Channel channel = regFuture.channel(); - if (regFuture.cause() != null) { - return regFuture; - } - - final ChannelPromise promise = channel.newPromise(); - if (regFuture.isDone()) { - doConnect0(regFuture, channel, remoteAddress, localAddress, promise); - } else { - regFuture.addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - doConnect0(regFuture, channel, remoteAddress, localAddress, promise); - } - }); - } - - return promise; - } - - private static void doConnect0( - final ChannelFuture regFuture, final Channel channel, - final SocketAddress remoteAddress, final SocketAddress localAddress, final ChannelPromise promise) { - - // This method is invoked before channelRegistered() is triggered. Give user handlers a chance to set up - // the pipeline in its channelRegistered() implementation. - channel.eventLoop().execute(new Runnable() { - @Override - public void run() { - if (regFuture.isSuccess()) { - if (localAddress == null) { - channel.connect(remoteAddress, promise); - } else { - channel.connect(remoteAddress, localAddress, promise); - } - promise.addListener(ChannelFutureListener.CLOSE_ON_FAILURE); - } else { - promise.setFailure(regFuture.cause()); - } - } - }); - } - - @Override - @SuppressWarnings("unchecked") - void init(Channel channel) throws Exception { - ChannelPipeline p = channel.pipeline(); - p.addLast(handler()); - - final Map, Object> options = options(); - synchronized (options) { - for (Entry, Object> e: options.entrySet()) { - try { - if (!channel.config().setOption((ChannelOption) e.getKey(), e.getValue())) { - logger.warn("Unknown channel option: " + e); - } - } catch (Throwable t) { - logger.warn("Failed to set a channel option: " + channel, t); - } - } - } - - final Map, Object> attrs = attrs(); - synchronized (attrs) { - for (Entry, Object> e: attrs.entrySet()) { - channel.attr((AttributeKey) e.getKey()).set(e.getValue()); - } - } - } - - @Override - public Bootstrap validate() { - super.validate(); - if (handler() == null) { - throw new IllegalStateException("handler not set"); - } - return this; - } - - @Override - @SuppressWarnings("CloneDoesntCallSuperClone") - public Bootstrap clone() { - return new Bootstrap(this); - } - - /** - * Returns a deep clone of this bootstrap which has the identical configuration except that it uses - * the given {@link EventLoopGroup}. This method is useful when making multiple {@link Channel}s with similar - * settings. - */ - public Bootstrap clone(EventLoopGroup group) { - Bootstrap bs = new Bootstrap(this); - bs.group = group; - return bs; - } - - @Override - public String toString() { - if (remoteAddress == null) { - return super.toString(); - } - - StringBuilder buf = new StringBuilder(super.toString()); - buf.setLength(buf.length() - 1); - - return buf.append(", remoteAddress: ") - .append(remoteAddress) - .append(')') - .toString(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/bootstrap/ChannelFactory.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/bootstrap/ChannelFactory.java deleted file mode 100755 index 0a500967e0..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/bootstrap/ChannelFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.bootstrap; - -import com.ai.cloud.io.netty.channel.Channel; - -/** - * Factory that creates a new {@link Channel} on {@link Bootstrap#bind()}, {@link Bootstrap#connect()}, and - * {@link ServerBootstrap#bind()}. - */ -public interface ChannelFactory { - /** - * Creates a new channel. - */ - T newChannel(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/bootstrap/ServerBootstrap.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/bootstrap/ServerBootstrap.java deleted file mode 100755 index 4428881aff..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/bootstrap/ServerBootstrap.java +++ /dev/null @@ -1,334 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.bootstrap; - -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.TimeUnit; - -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelConfig; -import com.ai.cloud.io.netty.channel.ChannelFuture; -import com.ai.cloud.io.netty.channel.ChannelFutureListener; -import com.ai.cloud.io.netty.channel.ChannelHandler; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelInboundHandlerAdapter; -import com.ai.cloud.io.netty.channel.ChannelInitializer; -import com.ai.cloud.io.netty.channel.ChannelOption; -import com.ai.cloud.io.netty.channel.ChannelPipeline; -import com.ai.cloud.io.netty.channel.EventLoopGroup; -import com.ai.cloud.io.netty.channel.ServerChannel; -import com.ai.cloud.io.netty.util.AttributeKey; -import com.ai.cloud.io.netty.util.internal.StringUtil; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * {@link Bootstrap} sub-class which allows easy bootstrap of {@link ServerChannel} - * - */ -public class ServerBootstrap extends AbstractBootstrap { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(ServerBootstrap.class); - - private final Map, Object> childOptions = new LinkedHashMap, Object>(); - private final Map, Object> childAttrs = new LinkedHashMap, Object>(); - private volatile EventLoopGroup childGroup; - private volatile ChannelHandler childHandler; - - public ServerBootstrap() { } - - private ServerBootstrap(ServerBootstrap bootstrap) { - super(bootstrap); - childGroup = bootstrap.childGroup; - childHandler = bootstrap.childHandler; - synchronized (bootstrap.childOptions) { - childOptions.putAll(bootstrap.childOptions); - } - synchronized (bootstrap.childAttrs) { - childAttrs.putAll(bootstrap.childAttrs); - } - } - - /** - * Specify the {@link EventLoopGroup} which is used for the parent (acceptor) and the child (client). - */ - @Override - public ServerBootstrap group(EventLoopGroup group) { - return group(group, group); - } - - /** - * Set the {@link EventLoopGroup} for the parent (acceptor) and the child (client). These - * {@link EventLoopGroup}'s are used to handle all the events and IO for {@link ServerChannel} and - * {@link Channel}'s. - */ - public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) { - super.group(parentGroup); - if (childGroup == null) { - throw new NullPointerException("childGroup"); - } - if (this.childGroup != null) { - throw new IllegalStateException("childGroup set already"); - } - this.childGroup = childGroup; - return this; - } - - /** - * Allow to specify a {@link ChannelOption} which is used for the {@link Channel} instances once they get created - * (after the acceptor accepted the {@link Channel}). Use a value of {@code null} to remove a previous set - * {@link ChannelOption}. - */ - public ServerBootstrap childOption(ChannelOption childOption, T value) { - if (childOption == null) { - throw new NullPointerException("childOption"); - } - if (value == null) { - synchronized (childOptions) { - childOptions.remove(childOption); - } - } else { - synchronized (childOptions) { - childOptions.put(childOption, value); - } - } - return this; - } - - /** - * Set the specific {@link AttributeKey} with the given value on every child {@link Channel}. If the value is - * {@code null} the {@link AttributeKey} is removed - */ - public ServerBootstrap childAttr(AttributeKey childKey, T value) { - if (childKey == null) { - throw new NullPointerException("childKey"); - } - if (value == null) { - childAttrs.remove(childKey); - } else { - childAttrs.put(childKey, value); - } - return this; - } - - /** - * Set the {@link ChannelHandler} which is used to serve the request for the {@link Channel}'s. - */ - public ServerBootstrap childHandler(ChannelHandler childHandler) { - if (childHandler == null) { - throw new NullPointerException("childHandler"); - } - this.childHandler = childHandler; - return this; - } - - /** - * Return the configured {@link EventLoopGroup} which will be used for the child channels or {@code null} - * if non is configured yet. - */ - public EventLoopGroup childGroup() { - return childGroup; - } - - @Override - void init(Channel channel) throws Exception { - final Map, Object> options = options(); - synchronized (options) { - channel.config().setOptions(options); - } - - final Map, Object> attrs = attrs(); - synchronized (attrs) { - for (Entry, Object> e: attrs.entrySet()) { - @SuppressWarnings("unchecked") - AttributeKey key = (AttributeKey) e.getKey(); - channel.attr(key).set(e.getValue()); - } - } - - ChannelPipeline p = channel.pipeline(); - - final EventLoopGroup currentChildGroup = childGroup; - final ChannelHandler currentChildHandler = childHandler; - final Entry, Object>[] currentChildOptions; - final Entry, Object>[] currentChildAttrs; - synchronized (childOptions) { - currentChildOptions = childOptions.entrySet().toArray(newOptionArray(childOptions.size())); - } - synchronized (childAttrs) { - currentChildAttrs = childAttrs.entrySet().toArray(newAttrArray(childAttrs.size())); - } - - p.addLast(new ChannelInitializer() { - @Override - public void initChannel(Channel ch) throws Exception { - ChannelPipeline pipeline = ch.pipeline(); - ChannelHandler handler = handler(); - if (handler != null) { - pipeline.addLast(handler); - } - pipeline.addLast(new ServerBootstrapAcceptor( - currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs)); - } - }); - } - - @Override - public ServerBootstrap validate() { - super.validate(); - if (childHandler == null) { - throw new IllegalStateException("childHandler not set"); - } - if (childGroup == null) { - logger.warn("childGroup is not set. Using parentGroup instead."); - childGroup = group(); - } - return this; - } - - @SuppressWarnings("unchecked") - private static Entry, Object>[] newOptionArray(int size) { - return new Entry[size]; - } - - @SuppressWarnings("unchecked") - private static Entry, Object>[] newAttrArray(int size) { - return new Entry[size]; - } - - private static class ServerBootstrapAcceptor extends ChannelInboundHandlerAdapter { - - private final EventLoopGroup childGroup; - private final ChannelHandler childHandler; - private final Entry, Object>[] childOptions; - private final Entry, Object>[] childAttrs; - - ServerBootstrapAcceptor( - EventLoopGroup childGroup, ChannelHandler childHandler, - Entry, Object>[] childOptions, Entry, Object>[] childAttrs) { - this.childGroup = childGroup; - this.childHandler = childHandler; - this.childOptions = childOptions; - this.childAttrs = childAttrs; - } - - @Override - @SuppressWarnings("unchecked") - public void channelRead(ChannelHandlerContext ctx, Object msg) { - final Channel child = (Channel) msg; - - child.pipeline().addLast(childHandler); - - for (Entry, Object> e: childOptions) { - try { - if (!child.config().setOption((ChannelOption) e.getKey(), e.getValue())) { - logger.warn("Unknown channel option: " + e); - } - } catch (Throwable t) { - logger.warn("Failed to set a channel option: " + child, t); - } - } - - for (Entry, Object> e: childAttrs) { - child.attr((AttributeKey) e.getKey()).set(e.getValue()); - } - - try { - childGroup.register(child).addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - if (!future.isSuccess()) { - forceClose(child, future.cause()); - } - } - }); - } catch (Throwable t) { - forceClose(child, t); - } - } - - private static void forceClose(Channel child, Throwable t) { - child.unsafe().closeForcibly(); - logger.warn("Failed to register an accepted channel: " + child, t); - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - final ChannelConfig config = ctx.channel().config(); - if (config.isAutoRead()) { - // stop accept new connections for 1 second to allow the channel to recover - // See https://github.com/netty/netty/issues/1328 - config.setAutoRead(false); - ctx.channel().eventLoop().schedule(new Runnable() { - @Override - public void run() { - config.setAutoRead(true); - } - }, 1, TimeUnit.SECONDS); - } - // still let the exceptionCaught event flow through the pipeline to give the user - // a chance to do something with it - ctx.fireExceptionCaught(cause); - } - } - - @Override - @SuppressWarnings("CloneDoesntCallSuperClone") - public ServerBootstrap clone() { - return new ServerBootstrap(this); - } - - @Override - public String toString() { - StringBuilder buf = new StringBuilder(super.toString()); - buf.setLength(buf.length() - 1); - buf.append(", "); - if (childGroup != null) { - buf.append("childGroup: "); - buf.append(StringUtil.simpleClassName(childGroup)); - buf.append(", "); - } - synchronized (childOptions) { - if (!childOptions.isEmpty()) { - buf.append("childOptions: "); - buf.append(childOptions); - buf.append(", "); - } - } - synchronized (childAttrs) { - if (!childAttrs.isEmpty()) { - buf.append("childAttrs: "); - buf.append(childAttrs); - buf.append(", "); - } - } - if (childHandler != null) { - buf.append("childHandler: "); - buf.append(childHandler); - buf.append(", "); - } - if (buf.charAt(buf.length() - 1) == '(') { - buf.append(')'); - } else { - buf.setCharAt(buf.length() - 2, ')'); - buf.setLength(buf.length() - 1); - } - - return buf.toString(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/bootstrap/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/bootstrap/package-info.java deleted file mode 100755 index 3937fcf214..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/bootstrap/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * The helper classes with fluent API which enable an easy implementation of - * typical client side and server side channel initialization. - */ -package com.ai.cloud.io.netty.bootstrap; diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/AbstractByteBuf.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/AbstractByteBuf.java deleted file mode 100755 index a34de3e1b2..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/AbstractByteBuf.java +++ /dev/null @@ -1,1202 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; -import java.nio.charset.Charset; - -import com.ai.cloud.io.netty.util.IllegalReferenceCountException; -import com.ai.cloud.io.netty.util.ResourceLeakDetector; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; -import com.ai.cloud.io.netty.util.internal.StringUtil; -import com.ai.cloud.io.netty.util.internal.SystemPropertyUtil; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -import static com.ai.cloud.io.netty.util.internal.MathUtil.isOutOfBounds; - -/** - * A skeletal implementation of a buffer. - */ -public abstract class AbstractByteBuf extends ByteBuf { - private static final InternalLogger logger = InternalLoggerFactory.getInstance(AbstractByteBuf.class); - private static final String PROP_MODE = "io.netty.buffer.bytebuf.checkAccessible"; - private static final boolean checkAccessible; - - static { - checkAccessible = SystemPropertyUtil.getBoolean(PROP_MODE, true); - if (logger.isDebugEnabled()) { - logger.debug("-D{}: {}", PROP_MODE, checkAccessible); - } - } - - static final ResourceLeakDetector leakDetector = new ResourceLeakDetector(ByteBuf.class); - - int readerIndex; - int writerIndex; - private int markedReaderIndex; - private int markedWriterIndex; - - private int maxCapacity; - - private SwappedByteBuf swappedBuf; - - protected AbstractByteBuf(int maxCapacity) { - if (maxCapacity < 0) { - throw new IllegalArgumentException("maxCapacity: " + maxCapacity + " (expected: >= 0)"); - } - this.maxCapacity = maxCapacity; - } - - @Override - public int maxCapacity() { - return maxCapacity; - } - - protected final void maxCapacity(int maxCapacity) { - this.maxCapacity = maxCapacity; - } - - @Override - public int readerIndex() { - return readerIndex; - } - - @Override - public ByteBuf readerIndex(int readerIndex) { - if (readerIndex < 0 || readerIndex > writerIndex) { - throw new IndexOutOfBoundsException(String.format( - "readerIndex: %d (expected: 0 <= readerIndex <= writerIndex(%d))", readerIndex, writerIndex)); - } - this.readerIndex = readerIndex; - return this; - } - - @Override - public int writerIndex() { - return writerIndex; - } - - @Override - public ByteBuf writerIndex(int writerIndex) { - if (writerIndex < readerIndex || writerIndex > capacity()) { - throw new IndexOutOfBoundsException(String.format( - "writerIndex: %d (expected: readerIndex(%d) <= writerIndex <= capacity(%d))", - writerIndex, readerIndex, capacity())); - } - this.writerIndex = writerIndex; - return this; - } - - @Override - public ByteBuf setIndex(int readerIndex, int writerIndex) { - if (readerIndex < 0 || readerIndex > writerIndex || writerIndex > capacity()) { - throw new IndexOutOfBoundsException(String.format( - "readerIndex: %d, writerIndex: %d (expected: 0 <= readerIndex <= writerIndex <= capacity(%d))", - readerIndex, writerIndex, capacity())); - } - setIndex0(readerIndex, writerIndex); - return this; - } - - @Override - public ByteBuf clear() { - readerIndex = writerIndex = 0; - return this; - } - - @Override - public boolean isReadable() { - return writerIndex > readerIndex; - } - - @Override - public boolean isReadable(int numBytes) { - return writerIndex - readerIndex >= numBytes; - } - - @Override - public boolean isWritable() { - return capacity() > writerIndex; - } - - @Override - public boolean isWritable(int numBytes) { - return capacity() - writerIndex >= numBytes; - } - - @Override - public int readableBytes() { - return writerIndex - readerIndex; - } - - @Override - public int writableBytes() { - return capacity() - writerIndex; - } - - @Override - public int maxWritableBytes() { - return maxCapacity() - writerIndex; - } - - @Override - public ByteBuf markReaderIndex() { - markedReaderIndex = readerIndex; - return this; - } - - @Override - public ByteBuf resetReaderIndex() { - readerIndex(markedReaderIndex); - return this; - } - - @Override - public ByteBuf markWriterIndex() { - markedWriterIndex = writerIndex; - return this; - } - - @Override - public ByteBuf resetWriterIndex() { - writerIndex = markedWriterIndex; - return this; - } - - @Override - public ByteBuf discardReadBytes() { - ensureAccessible(); - if (readerIndex == 0) { - return this; - } - - if (readerIndex != writerIndex) { - setBytes(0, this, readerIndex, writerIndex - readerIndex); - writerIndex -= readerIndex; - adjustMarkers(readerIndex); - readerIndex = 0; - } else { - adjustMarkers(readerIndex); - writerIndex = readerIndex = 0; - } - return this; - } - - @Override - public ByteBuf discardSomeReadBytes() { - ensureAccessible(); - if (readerIndex == 0) { - return this; - } - - if (readerIndex == writerIndex) { - adjustMarkers(readerIndex); - writerIndex = readerIndex = 0; - return this; - } - - if (readerIndex >= capacity() >>> 1) { - setBytes(0, this, readerIndex, writerIndex - readerIndex); - writerIndex -= readerIndex; - adjustMarkers(readerIndex); - readerIndex = 0; - } - return this; - } - - protected final void adjustMarkers(int decrement) { - int markedReaderIndex = this.markedReaderIndex; - if (markedReaderIndex <= decrement) { - this.markedReaderIndex = 0; - int markedWriterIndex = this.markedWriterIndex; - if (markedWriterIndex <= decrement) { - this.markedWriterIndex = 0; - } else { - this.markedWriterIndex = markedWriterIndex - decrement; - } - } else { - this.markedReaderIndex = markedReaderIndex - decrement; - markedWriterIndex -= decrement; - } - } - - @Override - public ByteBuf ensureWritable(int minWritableBytes) { - if (minWritableBytes < 0) { - throw new IllegalArgumentException(String.format( - "minWritableBytes: %d (expected: >= 0)", minWritableBytes)); - } - ensureWritable0(minWritableBytes); - return this; - } - - private void ensureWritable0(int minWritableBytes) { - if (minWritableBytes <= writableBytes()) { - return; - } - - if (minWritableBytes > maxCapacity - writerIndex) { - throw new IndexOutOfBoundsException(String.format( - "writerIndex(%d) + minWritableBytes(%d) exceeds maxCapacity(%d): %s", - writerIndex, minWritableBytes, maxCapacity, this)); - } - - // Normalize the current capacity to the power of 2. - int newCapacity = calculateNewCapacity(writerIndex + minWritableBytes); - - // Adjust to the new capacity. - capacity(newCapacity); - } - - @Override - public int ensureWritable(int minWritableBytes, boolean force) { - if (minWritableBytes < 0) { - throw new IllegalArgumentException(String.format( - "minWritableBytes: %d (expected: >= 0)", minWritableBytes)); - } - - if (minWritableBytes <= writableBytes()) { - return 0; - } - - if (minWritableBytes > maxCapacity - writerIndex) { - if (force) { - if (capacity() == maxCapacity()) { - return 1; - } - - capacity(maxCapacity()); - return 3; - } - } - - // Normalize the current capacity to the power of 2. - int newCapacity = calculateNewCapacity(writerIndex + minWritableBytes); - - // Adjust to the new capacity. - capacity(newCapacity); - return 2; - } - - private int calculateNewCapacity(int minNewCapacity) { - final int maxCapacity = this.maxCapacity; - final int threshold = 1048576 * 4; // 4 MiB page - - if (minNewCapacity == threshold) { - return threshold; - } - - // If over threshold, do not double but just increase by threshold. - if (minNewCapacity > threshold) { - int newCapacity = minNewCapacity / threshold * threshold; - if (newCapacity > maxCapacity - threshold) { - newCapacity = maxCapacity; - } else { - newCapacity += threshold; - } - return newCapacity; - } - - // Not over threshold. Double up to 4 MiB, starting from 64. - int newCapacity = 64; - while (newCapacity < minNewCapacity) { - newCapacity <<= 1; - } - - return Math.min(newCapacity, maxCapacity); - } - - @Override - public ByteBuf order(ByteOrder endianness) { - if (endianness == null) { - throw new NullPointerException("endianness"); - } - if (endianness == order()) { - return this; - } - - SwappedByteBuf swappedBuf = this.swappedBuf; - if (swappedBuf == null) { - this.swappedBuf = swappedBuf = newSwappedByteBuf(); - } - return swappedBuf; - } - - /** - * Creates a new {@link SwappedByteBuf} for this {@link ByteBuf} instance. - */ - protected SwappedByteBuf newSwappedByteBuf() { - return new SwappedByteBuf(this); - } - - @Override - public byte getByte(int index) { - checkIndex(index); - return _getByte(index); - } - - protected abstract byte _getByte(int index); - - @Override - public boolean getBoolean(int index) { - return getByte(index) != 0; - } - - @Override - public short getUnsignedByte(int index) { - return (short) (getByte(index) & 0xFF); - } - - @Override - public short getShort(int index) { - checkIndex(index, 2); - return _getShort(index); - } - - protected abstract short _getShort(int index); - - @Override - public int getUnsignedShort(int index) { - return getShort(index) & 0xFFFF; - } - - @Override - public int getUnsignedMedium(int index) { - checkIndex(index, 3); - return _getUnsignedMedium(index); - } - - protected abstract int _getUnsignedMedium(int index); - - @Override - public int getMedium(int index) { - int value = getUnsignedMedium(index); - if ((value & 0x800000) != 0) { - value |= 0xff000000; - } - return value; - } - - @Override - public int getInt(int index) { - checkIndex(index, 4); - return _getInt(index); - } - - protected abstract int _getInt(int index); - - @Override - public long getUnsignedInt(int index) { - return getInt(index) & 0xFFFFFFFFL; - } - - @Override - public long getLong(int index) { - checkIndex(index, 8); - return _getLong(index); - } - - protected abstract long _getLong(int index); - - @Override - public char getChar(int index) { - return (char) getShort(index); - } - - @Override - public float getFloat(int index) { - return Float.intBitsToFloat(getInt(index)); - } - - @Override - public double getDouble(int index) { - return Double.longBitsToDouble(getLong(index)); - } - - @Override - public ByteBuf getBytes(int index, byte[] dst) { - getBytes(index, dst, 0, dst.length); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst) { - getBytes(index, dst, dst.writableBytes()); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int length) { - getBytes(index, dst, dst.writerIndex(), length); - dst.writerIndex(dst.writerIndex() + length); - return this; - } - - @Override - public ByteBuf setByte(int index, int value) { - checkIndex(index); - _setByte(index, value); - return this; - } - - protected abstract void _setByte(int index, int value); - - @Override - public ByteBuf setBoolean(int index, boolean value) { - setByte(index, value? 1 : 0); - return this; - } - - @Override - public ByteBuf setShort(int index, int value) { - checkIndex(index, 2); - _setShort(index, value); - return this; - } - - protected abstract void _setShort(int index, int value); - - @Override - public ByteBuf setChar(int index, int value) { - setShort(index, value); - return this; - } - - @Override - public ByteBuf setMedium(int index, int value) { - checkIndex(index, 3); - _setMedium(index, value); - return this; - } - - protected abstract void _setMedium(int index, int value); - - @Override - public ByteBuf setInt(int index, int value) { - checkIndex(index, 4); - _setInt(index, value); - return this; - } - - protected abstract void _setInt(int index, int value); - - @Override - public ByteBuf setFloat(int index, float value) { - setInt(index, Float.floatToRawIntBits(value)); - return this; - } - - @Override - public ByteBuf setLong(int index, long value) { - checkIndex(index, 8); - _setLong(index, value); - return this; - } - - protected abstract void _setLong(int index, long value); - - @Override - public ByteBuf setDouble(int index, double value) { - setLong(index, Double.doubleToRawLongBits(value)); - return this; - } - - @Override - public ByteBuf setBytes(int index, byte[] src) { - setBytes(index, src, 0, src.length); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src) { - setBytes(index, src, src.readableBytes()); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int length) { - checkIndex(index, length); - if (src == null) { - throw new NullPointerException("src"); - } - if (length > src.readableBytes()) { - throw new IndexOutOfBoundsException(String.format( - "length(%d) exceeds src.readableBytes(%d) where src is: %s", length, src.readableBytes(), src)); - } - - setBytes(index, src, src.readerIndex(), length); - src.readerIndex(src.readerIndex() + length); - return this; - } - - @Override - public ByteBuf setZero(int index, int length) { - if (length == 0) { - return this; - } - - checkIndex(index, length); - - int nLong = length >>> 3; - int nBytes = length & 7; - for (int i = nLong; i > 0; i --) { - _setLong(index, 0); - index += 8; - } - if (nBytes == 4) { - _setInt(index, 0); - // Not need to update the index as we not will use it after this. - } else if (nBytes < 4) { - for (int i = nBytes; i > 0; i --) { - _setByte(index, (byte) 0); - index ++; - } - } else { - _setInt(index, 0); - index += 4; - for (int i = nBytes - 4; i > 0; i --) { - _setByte(index, (byte) 0); - index ++; - } - } - return this; - } - - @Override - public byte readByte() { - checkReadableBytes0(1); - int i = readerIndex; - byte b = _getByte(i); - readerIndex = i + 1; - return b; - } - - @Override - public boolean readBoolean() { - return readByte() != 0; - } - - @Override - public short readUnsignedByte() { - return (short) (readByte() & 0xFF); - } - - @Override - public short readShort() { - checkReadableBytes0(2); - short v = _getShort(readerIndex); - readerIndex += 2; - return v; - } - - @Override - public int readUnsignedShort() { - return readShort() & 0xFFFF; - } - - @Override - public int readMedium() { - int value = readUnsignedMedium(); - if ((value & 0x800000) != 0) { - value |= 0xff000000; - } - return value; - } - - @Override - public int readUnsignedMedium() { - checkReadableBytes0(3); - int v = _getUnsignedMedium(readerIndex); - readerIndex += 3; - return v; - } - - @Override - public int readInt() { - checkReadableBytes0(4); - int v = _getInt(readerIndex); - readerIndex += 4; - return v; - } - - @Override - public long readUnsignedInt() { - return readInt() & 0xFFFFFFFFL; - } - - @Override - public long readLong() { - checkReadableBytes0(8); - long v = _getLong(readerIndex); - readerIndex += 8; - return v; - } - - @Override - public char readChar() { - return (char) readShort(); - } - - @Override - public float readFloat() { - return Float.intBitsToFloat(readInt()); - } - - @Override - public double readDouble() { - return Double.longBitsToDouble(readLong()); - } - - @Override - public ByteBuf readBytes(int length) { - checkReadableBytes(length); - if (length == 0) { - return Unpooled.EMPTY_BUFFER; - } - - // Use an unpooled heap buffer because there's no way to mandate a user to free the returned buffer. - ByteBuf buf = Unpooled.buffer(length, maxCapacity); - buf.writeBytes(this, readerIndex, length); - readerIndex += length; - return buf; - } - - @Override - public ByteBuf readSlice(int length) { - ByteBuf slice = slice(readerIndex, length); - readerIndex += length; - return slice; - } - - @Override - public ByteBuf readBytes(byte[] dst, int dstIndex, int length) { - checkReadableBytes(length); - getBytes(readerIndex, dst, dstIndex, length); - readerIndex += length; - return this; - } - - @Override - public ByteBuf readBytes(byte[] dst) { - readBytes(dst, 0, dst.length); - return this; - } - - @Override - public ByteBuf readBytes(ByteBuf dst) { - readBytes(dst, dst.writableBytes()); - return this; - } - - @Override - public ByteBuf readBytes(ByteBuf dst, int length) { - if (length > dst.writableBytes()) { - throw new IndexOutOfBoundsException(String.format( - "length(%d) exceeds dst.writableBytes(%d) where dst is: %s", length, dst.writableBytes(), dst)); - } - readBytes(dst, dst.writerIndex(), length); - dst.writerIndex(dst.writerIndex() + length); - return this; - } - - @Override - public ByteBuf readBytes(ByteBuf dst, int dstIndex, int length) { - checkReadableBytes(length); - getBytes(readerIndex, dst, dstIndex, length); - readerIndex += length; - return this; - } - - @Override - public ByteBuf readBytes(ByteBuffer dst) { - int length = dst.remaining(); - checkReadableBytes(length); - getBytes(readerIndex, dst); - readerIndex += length; - return this; - } - - @Override - public int readBytes(GatheringByteChannel out, int length) - throws IOException { - checkReadableBytes(length); - int readBytes = getBytes(readerIndex, out, length); - readerIndex += readBytes; - return readBytes; - } - - @Override - public ByteBuf readBytes(OutputStream out, int length) throws IOException { - checkReadableBytes(length); - getBytes(readerIndex, out, length); - readerIndex += length; - return this; - } - - @Override - public ByteBuf skipBytes(int length) { - checkReadableBytes(length); - readerIndex += length; - return this; - } - - @Override - public ByteBuf writeBoolean(boolean value) { - writeByte(value ? 1 : 0); - return this; - } - - @Override - public ByteBuf writeByte(int value) { - ensureAccessible(); - ensureWritable0(1); - _setByte(writerIndex++, value); - return this; - } - - @Override - public ByteBuf writeShort(int value) { - ensureAccessible(); - ensureWritable0(2); - _setShort(writerIndex, value); - writerIndex += 2; - return this; - } - - @Override - public ByteBuf writeMedium(int value) { - ensureAccessible(); - ensureWritable0(3); - _setMedium(writerIndex, value); - writerIndex += 3; - return this; - } - - @Override - public ByteBuf writeInt(int value) { - ensureAccessible(); - ensureWritable0(4); - _setInt(writerIndex, value); - writerIndex += 4; - return this; - } - - @Override - public ByteBuf writeLong(long value) { - ensureAccessible(); - ensureWritable0(8); - _setLong(writerIndex, value); - writerIndex += 8; - return this; - } - - @Override - public ByteBuf writeChar(int value) { - writeShort(value); - return this; - } - - @Override - public ByteBuf writeFloat(float value) { - writeInt(Float.floatToRawIntBits(value)); - return this; - } - - @Override - public ByteBuf writeDouble(double value) { - writeLong(Double.doubleToRawLongBits(value)); - return this; - } - - @Override - public ByteBuf writeBytes(byte[] src, int srcIndex, int length) { - ensureAccessible(); - ensureWritable(length); - setBytes(writerIndex, src, srcIndex, length); - writerIndex += length; - return this; - } - - @Override - public ByteBuf writeBytes(byte[] src) { - writeBytes(src, 0, src.length); - return this; - } - - @Override - public ByteBuf writeBytes(ByteBuf src) { - writeBytes(src, src.readableBytes()); - return this; - } - - @Override - public ByteBuf writeBytes(ByteBuf src, int length) { - if (length > src.readableBytes()) { - throw new IndexOutOfBoundsException(String.format( - "length(%d) exceeds src.readableBytes(%d) where src is: %s", length, src.readableBytes(), src)); - } - writeBytes(src, src.readerIndex(), length); - src.readerIndex(src.readerIndex() + length); - return this; - } - - @Override - public ByteBuf writeBytes(ByteBuf src, int srcIndex, int length) { - ensureAccessible(); - ensureWritable(length); - setBytes(writerIndex, src, srcIndex, length); - writerIndex += length; - return this; - } - - @Override - public ByteBuf writeBytes(ByteBuffer src) { - ensureAccessible(); - int length = src.remaining(); - ensureWritable(length); - setBytes(writerIndex, src); - writerIndex += length; - return this; - } - - @Override - public int writeBytes(InputStream in, int length) - throws IOException { - ensureAccessible(); - ensureWritable(length); - int writtenBytes = setBytes(writerIndex, in, length); - if (writtenBytes > 0) { - writerIndex += writtenBytes; - } - return writtenBytes; - } - - @Override - public int writeBytes(ScatteringByteChannel in, int length) throws IOException { - ensureAccessible(); - ensureWritable(length); - int writtenBytes = setBytes(writerIndex, in, length); - if (writtenBytes > 0) { - writerIndex += writtenBytes; - } - return writtenBytes; - } - - @Override - public ByteBuf writeZero(int length) { - if (length == 0) { - return this; - } - - ensureWritable(length); - int wIndex = writerIndex; - checkIndex(wIndex, length); - - int nLong = length >>> 3; - int nBytes = length & 7; - for (int i = nLong; i > 0; i --) { - _setLong(wIndex, 0); - wIndex += 8; - } - if (nBytes == 4) { - _setInt(wIndex, 0); - wIndex += 4; - } else if (nBytes < 4) { - for (int i = nBytes; i > 0; i --) { - _setByte(wIndex, (byte) 0); - wIndex++; - } - } else { - _setInt(wIndex, 0); - wIndex += 4; - for (int i = nBytes - 4; i > 0; i --) { - _setByte(wIndex, (byte) 0); - wIndex++; - } - } - writerIndex = wIndex; - return this; - } - - @Override - public ByteBuf copy() { - return copy(readerIndex, readableBytes()); - } - - @Override - public ByteBuf duplicate() { - return new DuplicatedAbstractByteBuf(this); - } - - @Override - public ByteBuf slice() { - return slice(readerIndex, readableBytes()); - } - - @Override - public ByteBuf slice(int index, int length) { - return new SlicedAbstractByteBuf(this, index, length); - } - - @Override - public ByteBuffer nioBuffer() { - return nioBuffer(readerIndex, readableBytes()); - } - - @Override - public ByteBuffer[] nioBuffers() { - return nioBuffers(readerIndex, readableBytes()); - } - - @Override - public String toString(Charset charset) { - return toString(readerIndex, readableBytes(), charset); - } - - @Override - public String toString(int index, int length, Charset charset) { - return ByteBufUtil.decodeString(this, index, length, charset); - } - - @Override - public int indexOf(int fromIndex, int toIndex, byte value) { - return ByteBufUtil.indexOf(this, fromIndex, toIndex, value); - } - - @Override - public int bytesBefore(byte value) { - return bytesBefore(readerIndex(), readableBytes(), value); - } - - @Override - public int bytesBefore(int length, byte value) { - checkReadableBytes(length); - return bytesBefore(readerIndex(), length, value); - } - - @Override - public int bytesBefore(int index, int length, byte value) { - int endIndex = indexOf(index, index + length, value); - if (endIndex < 0) { - return -1; - } - return endIndex - index; - } - - @Override - public int forEachByte(ByteBufProcessor processor) { - int index = readerIndex; - int length = writerIndex - index; - ensureAccessible(); - return forEachByteAsc0(index, length, processor); - } - - @Override - public int forEachByte(int index, int length, ByteBufProcessor processor) { - checkIndex(index, length); - return forEachByteAsc0(index, length, processor); - } - - private int forEachByteAsc0(int index, int length, ByteBufProcessor processor) { - if (processor == null) { - throw new NullPointerException("processor"); - } - - if (length == 0) { - return -1; - } - - final int endIndex = index + length; - int i = index; - try { - do { - if (processor.process(_getByte(i))) { - i ++; - } else { - return i; - } - } while (i < endIndex); - } catch (Exception e) { - PlatformDependent.throwException(e); - } - - return -1; - } - - @Override - public int forEachByteDesc(ByteBufProcessor processor) { - int index = readerIndex; - int length = writerIndex - index; - ensureAccessible(); - return forEachByteDesc0(index, length, processor); - } - - @Override - public int forEachByteDesc(int index, int length, ByteBufProcessor processor) { - checkIndex(index, length); - - return forEachByteDesc0(index, length, processor); - } - - private int forEachByteDesc0(int index, int length, ByteBufProcessor processor) { - - if (processor == null) { - throw new NullPointerException("processor"); - } - - if (length == 0) { - return -1; - } - - int i = index + length - 1; - try { - do { - if (processor.process(_getByte(i))) { - i --; - } else { - return i; - } - } while (i >= index); - } catch (Exception e) { - PlatformDependent.throwException(e); - } - - return -1; - } - - @Override - public int hashCode() { - return ByteBufUtil.hashCode(this); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o instanceof ByteBuf) { - return ByteBufUtil.equals(this, (ByteBuf) o); - } - return false; - } - - @Override - public int compareTo(ByteBuf that) { - return ByteBufUtil.compare(this, that); - } - - @Override - public String toString() { - if (refCnt() == 0) { - return StringUtil.simpleClassName(this) + "(freed)"; - } - - StringBuilder buf = new StringBuilder() - .append(StringUtil.simpleClassName(this)) - .append("(ridx: ").append(readerIndex) - .append(", widx: ").append(writerIndex) - .append(", cap: ").append(capacity()); - if (maxCapacity != Integer.MAX_VALUE) { - buf.append('/').append(maxCapacity); - } - - ByteBuf unwrapped = unwrap(); - if (unwrapped != null) { - buf.append(", unwrapped: ").append(unwrapped); - } - buf.append(')'); - return buf.toString(); - } - - protected final void checkIndex(int index) { - checkIndex(index, 1); - } - - protected final void checkIndex(int index, int fieldLength) { - ensureAccessible(); - checkIndex0(index, fieldLength); - } - - final void checkIndex0(int index, int fieldLength) { - if (isOutOfBounds(index, fieldLength, capacity())) { - throw new IndexOutOfBoundsException(String.format( - "index: %d, length: %d (expected: range(0, %d))", index, fieldLength, capacity())); - } - } - - protected final void checkSrcIndex(int index, int length, int srcIndex, int srcCapacity) { - checkIndex(index, length); - if (isOutOfBounds(srcIndex, length, srcCapacity)) { - throw new IndexOutOfBoundsException(String.format( - "srcIndex: %d, length: %d (expected: range(0, %d))", srcIndex, length, srcCapacity)); - } - } - - protected final void checkDstIndex(int index, int length, int dstIndex, int dstCapacity) { - checkIndex(index, length); - if (isOutOfBounds(dstIndex, length, dstCapacity)) { - throw new IndexOutOfBoundsException(String.format( - "dstIndex: %d, length: %d (expected: range(0, %d))", dstIndex, length, dstCapacity)); - } - } - - /** - * Throws an {@link IndexOutOfBoundsException} if the current - * {@linkplain #readableBytes() readable bytes} of this buffer is less - * than the specified value. - */ - protected final void checkReadableBytes(int minimumReadableBytes) { - if (minimumReadableBytes < 0) { - throw new IllegalArgumentException("minimumReadableBytes: " + minimumReadableBytes + " (expected: >= 0)"); - } - checkReadableBytes0(minimumReadableBytes); - } - - private void checkReadableBytes0(int minimumReadableBytes) { - ensureAccessible(); - if (readerIndex > writerIndex - minimumReadableBytes) { - throw new IndexOutOfBoundsException(String.format( - "readerIndex(%d) + length(%d) exceeds writerIndex(%d): %s", - readerIndex, minimumReadableBytes, writerIndex, this)); - } - } - - /** - * Should be called by every method that tries to access the buffers content to check - * if the buffer was released before. - */ - protected final void ensureAccessible() { - if (checkAccessible && refCnt() == 0) { - throw new IllegalReferenceCountException(0); - } - } - - final void setIndex0(int readerIndex, int writerIndex) { - this.readerIndex = readerIndex; - this.writerIndex = writerIndex; - } - - final void discardMarks() { - markedReaderIndex = markedWriterIndex = 0; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/AbstractByteBufAllocator.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/AbstractByteBufAllocator.java deleted file mode 100755 index 50296b292e..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/AbstractByteBufAllocator.java +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.buffer; - -import com.ai.cloud.io.netty.util.ResourceLeak; -import com.ai.cloud.io.netty.util.ResourceLeakDetector; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; -import com.ai.cloud.io.netty.util.internal.StringUtil; - -/** - * Skeletal {@link ByteBufAllocator} implementation to extend. - */ -public abstract class AbstractByteBufAllocator implements ByteBufAllocator { - private static final int DEFAULT_INITIAL_CAPACITY = 256; - private static final int DEFAULT_MAX_COMPONENTS = 16; - - protected static ByteBuf toLeakAwareBuffer(ByteBuf buf) { - ResourceLeak leak; - switch (ResourceLeakDetector.getLevel()) { - case SIMPLE: - leak = AbstractByteBuf.leakDetector.open(buf); - if (leak != null) { - buf = new SimpleLeakAwareByteBuf(buf, leak); - } - break; - case ADVANCED: - case PARANOID: - leak = AbstractByteBuf.leakDetector.open(buf); - if (leak != null) { - buf = new AdvancedLeakAwareByteBuf(buf, leak); - } - break; - } - return buf; - } - - private final boolean directByDefault; - private final ByteBuf emptyBuf; - - /** - * Instance use heap buffers by default - */ - protected AbstractByteBufAllocator() { - this(false); - } - - /** - * Create new instance - * - * @param preferDirect {@code true} if {@link #buffer(int)} should try to allocate a direct buffer rather than - * a heap buffer - */ - protected AbstractByteBufAllocator(boolean preferDirect) { - directByDefault = preferDirect && PlatformDependent.hasUnsafe(); - emptyBuf = new EmptyByteBuf(this); - } - - @Override - public ByteBuf buffer() { - if (directByDefault) { - return directBuffer(); - } - return heapBuffer(); - } - - @Override - public ByteBuf buffer(int initialCapacity) { - if (directByDefault) { - return directBuffer(initialCapacity); - } - return heapBuffer(initialCapacity); - } - - @Override - public ByteBuf buffer(int initialCapacity, int maxCapacity) { - if (directByDefault) { - return directBuffer(initialCapacity, maxCapacity); - } - return heapBuffer(initialCapacity, maxCapacity); - } - - @Override - public ByteBuf ioBuffer() { - if (PlatformDependent.hasUnsafe()) { - return directBuffer(DEFAULT_INITIAL_CAPACITY); - } - return heapBuffer(DEFAULT_INITIAL_CAPACITY); - } - - @Override - public ByteBuf ioBuffer(int initialCapacity) { - if (PlatformDependent.hasUnsafe()) { - return directBuffer(initialCapacity); - } - return heapBuffer(initialCapacity); - } - - @Override - public ByteBuf ioBuffer(int initialCapacity, int maxCapacity) { - if (PlatformDependent.hasUnsafe()) { - return directBuffer(initialCapacity, maxCapacity); - } - return heapBuffer(initialCapacity, maxCapacity); - } - - @Override - public ByteBuf heapBuffer() { - return heapBuffer(DEFAULT_INITIAL_CAPACITY, Integer.MAX_VALUE); - } - - @Override - public ByteBuf heapBuffer(int initialCapacity) { - return heapBuffer(initialCapacity, Integer.MAX_VALUE); - } - - @Override - public ByteBuf heapBuffer(int initialCapacity, int maxCapacity) { - if (initialCapacity == 0 && maxCapacity == 0) { - return emptyBuf; - } - validate(initialCapacity, maxCapacity); - return newHeapBuffer(initialCapacity, maxCapacity); - } - - @Override - public ByteBuf directBuffer() { - return directBuffer(DEFAULT_INITIAL_CAPACITY, Integer.MAX_VALUE); - } - - @Override - public ByteBuf directBuffer(int initialCapacity) { - return directBuffer(initialCapacity, Integer.MAX_VALUE); - } - - @Override - public ByteBuf directBuffer(int initialCapacity, int maxCapacity) { - if (initialCapacity == 0 && maxCapacity == 0) { - return emptyBuf; - } - validate(initialCapacity, maxCapacity); - return newDirectBuffer(initialCapacity, maxCapacity); - } - - @Override - public CompositeByteBuf compositeBuffer() { - if (directByDefault) { - return compositeDirectBuffer(); - } - return compositeHeapBuffer(); - } - - @Override - public CompositeByteBuf compositeBuffer(int maxNumComponents) { - if (directByDefault) { - return compositeDirectBuffer(maxNumComponents); - } - return compositeHeapBuffer(maxNumComponents); - } - - @Override - public CompositeByteBuf compositeHeapBuffer() { - return compositeHeapBuffer(DEFAULT_MAX_COMPONENTS); - } - - @Override - public CompositeByteBuf compositeHeapBuffer(int maxNumComponents) { - return new CompositeByteBuf(this, false, maxNumComponents); - } - - @Override - public CompositeByteBuf compositeDirectBuffer() { - return compositeDirectBuffer(DEFAULT_MAX_COMPONENTS); - } - - @Override - public CompositeByteBuf compositeDirectBuffer(int maxNumComponents) { - return new CompositeByteBuf(this, true, maxNumComponents); - } - - private static void validate(int initialCapacity, int maxCapacity) { - if (initialCapacity < 0) { - throw new IllegalArgumentException("initialCapacity: " + initialCapacity + " (expectd: 0+)"); - } - if (initialCapacity > maxCapacity) { - throw new IllegalArgumentException(String.format( - "initialCapacity: %d (expected: not greater than maxCapacity(%d)", - initialCapacity, maxCapacity)); - } - } - - /** - * Create a heap {@link ByteBuf} with the given initialCapacity and maxCapacity. - */ - protected abstract ByteBuf newHeapBuffer(int initialCapacity, int maxCapacity); - - /** - * Create a direct {@link ByteBuf} with the given initialCapacity and maxCapacity. - */ - protected abstract ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity); - - @Override - public String toString() { - return StringUtil.simpleClassName(this) + "(directByDefault: " + directByDefault + ')'; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/AbstractDerivedByteBuf.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/AbstractDerivedByteBuf.java deleted file mode 100755 index 77119b7cff..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/AbstractDerivedByteBuf.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.buffer; - -import java.nio.ByteBuffer; - -/** - * Abstract base class for {@link ByteBuf} implementations that wrap another - * {@link ByteBuf}. - */ -public abstract class AbstractDerivedByteBuf extends AbstractByteBuf { - - protected AbstractDerivedByteBuf(int maxCapacity) { - super(maxCapacity); - } - - @Override - public final int refCnt() { - return unwrap().refCnt(); - } - - @Override - public final ByteBuf retain() { - unwrap().retain(); - return this; - } - - @Override - public final ByteBuf retain(int increment) { - unwrap().retain(increment); - return this; - } - - @Override - public final boolean release() { - return unwrap().release(); - } - - @Override - public final boolean release(int decrement) { - return unwrap().release(decrement); - } - - @Override - public ByteBuffer internalNioBuffer(int index, int length) { - return nioBuffer(index, length); - } - - @Override - public ByteBuffer nioBuffer(int index, int length) { - return unwrap().nioBuffer(index, length); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/AbstractReferenceCountedByteBuf.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/AbstractReferenceCountedByteBuf.java deleted file mode 100755 index 1ac0d5a17e..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/AbstractReferenceCountedByteBuf.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.buffer; - -import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; - -import com.ai.cloud.io.netty.util.IllegalReferenceCountException; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - -/** - * Abstract base class for {@link ByteBuf} implementations that count references. - */ -public abstract class AbstractReferenceCountedByteBuf extends AbstractByteBuf { - - private static final AtomicIntegerFieldUpdater refCntUpdater; - - static { - AtomicIntegerFieldUpdater updater = - PlatformDependent.newAtomicIntegerFieldUpdater(AbstractReferenceCountedByteBuf.class, "refCnt"); - if (updater == null) { - updater = AtomicIntegerFieldUpdater.newUpdater(AbstractReferenceCountedByteBuf.class, "refCnt"); - } - refCntUpdater = updater; - } - - private volatile int refCnt = 1; - - protected AbstractReferenceCountedByteBuf(int maxCapacity) { - super(maxCapacity); - } - - @Override - public final int refCnt() { - return refCnt; - } - - /** - * An unsafe operation intended for use by a subclass that sets the reference count of the buffer directly - */ - protected final void setRefCnt(int refCnt) { - this.refCnt = refCnt; - } - - @Override - public ByteBuf retain() { - for (;;) { - int refCnt = this.refCnt; - if (refCnt == 0) { - throw new IllegalReferenceCountException(0, 1); - } - if (refCnt == Integer.MAX_VALUE) { - throw new IllegalReferenceCountException(Integer.MAX_VALUE, 1); - } - if (refCntUpdater.compareAndSet(this, refCnt, refCnt + 1)) { - break; - } - } - return this; - } - - @Override - public ByteBuf retain(int increment) { - if (increment <= 0) { - throw new IllegalArgumentException("increment: " + increment + " (expected: > 0)"); - } - - for (;;) { - int refCnt = this.refCnt; - if (refCnt == 0) { - throw new IllegalReferenceCountException(0, increment); - } - if (refCnt > Integer.MAX_VALUE - increment) { - throw new IllegalReferenceCountException(refCnt, increment); - } - if (refCntUpdater.compareAndSet(this, refCnt, refCnt + increment)) { - break; - } - } - return this; - } - - @Override - public final boolean release() { - for (;;) { - int refCnt = this.refCnt; - if (refCnt == 0) { - throw new IllegalReferenceCountException(0, -1); - } - - if (refCntUpdater.compareAndSet(this, refCnt, refCnt - 1)) { - if (refCnt == 1) { - deallocate(); - return true; - } - return false; - } - } - } - - @Override - public final boolean release(int decrement) { - if (decrement <= 0) { - throw new IllegalArgumentException("decrement: " + decrement + " (expected: > 0)"); - } - - for (;;) { - int refCnt = this.refCnt; - if (refCnt < decrement) { - throw new IllegalReferenceCountException(refCnt, -decrement); - } - - if (refCntUpdater.compareAndSet(this, refCnt, refCnt - decrement)) { - if (refCnt == decrement) { - deallocate(); - return true; - } - return false; - } - } - } - - /** - * Called once {@link #refCnt()} is equals 0. - */ - protected abstract void deallocate(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/AbstractUnsafeSwappedByteBuf.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/AbstractUnsafeSwappedByteBuf.java deleted file mode 100755 index 1e75bd9baf..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/AbstractUnsafeSwappedByteBuf.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.buffer; - -import java.nio.ByteOrder; - -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - -/** - * Special {@link SwappedByteBuf} for {@link ByteBuf}s that is using unsafe. - */ -abstract class AbstractUnsafeSwappedByteBuf extends SwappedByteBuf { - private final boolean nativeByteOrder; - private final AbstractByteBuf wrapped; - - AbstractUnsafeSwappedByteBuf(AbstractByteBuf buf) { - super(buf); - assert PlatformDependent.isUnaligned(); - wrapped = buf; - nativeByteOrder = UnsafeByteBufUtil.BIG_ENDIAN_NATIVE_ORDER == (order() == ByteOrder.BIG_ENDIAN); - } - - @Override - public final long getLong(int index) { - wrapped.checkIndex(index, 8); - long v = _getLong(wrapped, index); - return nativeByteOrder ? v : Long.reverseBytes(v); - } - - @Override - public final float getFloat(int index) { - return Float.intBitsToFloat(getInt(index)); - } - - @Override - public final double getDouble(int index) { - return Double.longBitsToDouble(getLong(index)); - } - - @Override - public final char getChar(int index) { - return (char) getShort(index); - } - - @Override - public final long getUnsignedInt(int index) { - return getInt(index) & 0xFFFFFFFFL; - } - - @Override - public final int getInt(int index) { - wrapped.checkIndex0(index, 4); - int v = _getInt(wrapped, index); - return nativeByteOrder ? v : Integer.reverseBytes(v); - } - - @Override - public final int getUnsignedShort(int index) { - return getShort(index) & 0xFFFF; - } - - @Override - public final short getShort(int index) { - wrapped.checkIndex0(index, 2); - short v = _getShort(wrapped, index); - return nativeByteOrder ? v : Short.reverseBytes(v); - } - - @Override - public final ByteBuf setShort(int index, int value) { - wrapped.checkIndex0(index, 2); - _setShort(wrapped, index, nativeByteOrder ? (short) value : Short.reverseBytes((short) value)); - return this; - } - - @Override - public final ByteBuf setInt(int index, int value) { - wrapped.checkIndex0(index, 4); - _setInt(wrapped, index, nativeByteOrder ? value : Integer.reverseBytes(value)); - return this; - } - - @Override - public final ByteBuf setLong(int index, long value) { - wrapped.checkIndex(index, 8); - _setLong(wrapped, index, nativeByteOrder ? value : Long.reverseBytes(value)); - return this; - } - - @Override - public final ByteBuf setChar(int index, int value) { - setShort(index, value); - return this; - } - - @Override - public final ByteBuf setFloat(int index, float value) { - setInt(index, Float.floatToRawIntBits(value)); - return this; - } - - @Override - public final ByteBuf setDouble(int index, double value) { - setLong(index, Double.doubleToRawLongBits(value)); - return this; - } - - @Override - public final ByteBuf writeShort(int value) { - wrapped.ensureWritable(2); - _setShort(wrapped, wrapped.writerIndex, nativeByteOrder ? (short) value : Short.reverseBytes((short) value)); - wrapped.writerIndex += 2; - return this; - } - - @Override - public final ByteBuf writeInt(int value) { - wrapped.ensureWritable(4); - _setInt(wrapped, wrapped.writerIndex, nativeByteOrder ? value : Integer.reverseBytes(value)); - wrapped.writerIndex += 4; - return this; - } - - @Override - public final ByteBuf writeLong(long value) { - wrapped.ensureWritable(8); - _setLong(wrapped, wrapped.writerIndex, nativeByteOrder ? value : Long.reverseBytes(value)); - wrapped.writerIndex += 8; - return this; - } - - @Override - public final ByteBuf writeChar(int value) { - writeShort(value); - return this; - } - - @Override - public final ByteBuf writeFloat(float value) { - writeInt(Float.floatToRawIntBits(value)); - return this; - } - - @Override - public final ByteBuf writeDouble(double value) { - writeLong(Double.doubleToRawLongBits(value)); - return this; - } - - protected abstract short _getShort(AbstractByteBuf wrapped, int index); - protected abstract int _getInt(AbstractByteBuf wrapped, int index); - protected abstract long _getLong(AbstractByteBuf wrapped, int index); - protected abstract void _setShort(AbstractByteBuf wrapped, int index, short value); - protected abstract void _setInt(AbstractByteBuf wrapped, int index, int value); - protected abstract void _setLong(AbstractByteBuf wrapped, int index, long value); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/AdvancedLeakAwareByteBuf.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/AdvancedLeakAwareByteBuf.java deleted file mode 100755 index 2cfea16417..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/AdvancedLeakAwareByteBuf.java +++ /dev/null @@ -1,746 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; -import java.nio.charset.Charset; - -import com.ai.cloud.io.netty.util.ResourceLeak; -import com.ai.cloud.io.netty.util.internal.SystemPropertyUtil; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -final class AdvancedLeakAwareByteBuf extends WrappedByteBuf { - - private static final String PROP_ACQUIRE_AND_RELEASE_ONLY = "io.netty.leakDetection.acquireAndReleaseOnly"; - private static final boolean ACQUIRE_AND_RELEASE_ONLY; - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(AdvancedLeakAwareByteBuf.class); - - static { - ACQUIRE_AND_RELEASE_ONLY = SystemPropertyUtil.getBoolean(PROP_ACQUIRE_AND_RELEASE_ONLY, false); - - if (logger.isDebugEnabled()) { - logger.debug("-D{}: {}", PROP_ACQUIRE_AND_RELEASE_ONLY, ACQUIRE_AND_RELEASE_ONLY); - } - } - - private final ResourceLeak leak; - - AdvancedLeakAwareByteBuf(ByteBuf buf, ResourceLeak leak) { - super(buf); - this.leak = leak; - } - - @Override - public boolean release() { - boolean deallocated = super.release(); - if (deallocated) { - leak.close(); - } else { - leak.record(); - } - return deallocated; - } - - @Override - public boolean release(int decrement) { - boolean deallocated = super.release(decrement); - if (deallocated) { - leak.close(); - } else { - leak.record(); - } - return deallocated; - } - - private void recordLeakNonRefCountingOperation() { - if (!ACQUIRE_AND_RELEASE_ONLY) { - leak.record(); - } - } - - @Override - public ByteBuf order(ByteOrder endianness) { - recordLeakNonRefCountingOperation(); - if (order() == endianness) { - return this; - } else { - return new AdvancedLeakAwareByteBuf(super.order(endianness), leak); - } - } - - @Override - public ByteBuf slice() { - recordLeakNonRefCountingOperation(); - return new AdvancedLeakAwareByteBuf(super.slice(), leak); - } - - @Override - public ByteBuf slice(int index, int length) { - recordLeakNonRefCountingOperation(); - return new AdvancedLeakAwareByteBuf(super.slice(index, length), leak); - } - - @Override - public ByteBuf duplicate() { - recordLeakNonRefCountingOperation(); - return new AdvancedLeakAwareByteBuf(super.duplicate(), leak); - } - - @Override - public ByteBuf readSlice(int length) { - recordLeakNonRefCountingOperation(); - return new AdvancedLeakAwareByteBuf(super.readSlice(length), leak); - } - - @Override - public ByteBuf discardReadBytes() { - recordLeakNonRefCountingOperation(); - return super.discardReadBytes(); - } - - @Override - public ByteBuf discardSomeReadBytes() { - recordLeakNonRefCountingOperation(); - return super.discardSomeReadBytes(); - } - - @Override - public ByteBuf ensureWritable(int minWritableBytes) { - recordLeakNonRefCountingOperation(); - return super.ensureWritable(minWritableBytes); - } - - @Override - public int ensureWritable(int minWritableBytes, boolean force) { - recordLeakNonRefCountingOperation(); - return super.ensureWritable(minWritableBytes, force); - } - - @Override - public boolean getBoolean(int index) { - recordLeakNonRefCountingOperation(); - return super.getBoolean(index); - } - - @Override - public byte getByte(int index) { - recordLeakNonRefCountingOperation(); - return super.getByte(index); - } - - @Override - public short getUnsignedByte(int index) { - recordLeakNonRefCountingOperation(); - return super.getUnsignedByte(index); - } - - @Override - public short getShort(int index) { - recordLeakNonRefCountingOperation(); - return super.getShort(index); - } - - @Override - public int getUnsignedShort(int index) { - recordLeakNonRefCountingOperation(); - return super.getUnsignedShort(index); - } - - @Override - public int getMedium(int index) { - recordLeakNonRefCountingOperation(); - return super.getMedium(index); - } - - @Override - public int getUnsignedMedium(int index) { - recordLeakNonRefCountingOperation(); - return super.getUnsignedMedium(index); - } - - @Override - public int getInt(int index) { - recordLeakNonRefCountingOperation(); - return super.getInt(index); - } - - @Override - public long getUnsignedInt(int index) { - recordLeakNonRefCountingOperation(); - return super.getUnsignedInt(index); - } - - @Override - public long getLong(int index) { - recordLeakNonRefCountingOperation(); - return super.getLong(index); - } - - @Override - public char getChar(int index) { - recordLeakNonRefCountingOperation(); - return super.getChar(index); - } - - @Override - public float getFloat(int index) { - recordLeakNonRefCountingOperation(); - return super.getFloat(index); - } - - @Override - public double getDouble(int index) { - recordLeakNonRefCountingOperation(); - return super.getDouble(index); - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst) { - recordLeakNonRefCountingOperation(); - return super.getBytes(index, dst); - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int length) { - recordLeakNonRefCountingOperation(); - return super.getBytes(index, dst, length); - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - recordLeakNonRefCountingOperation(); - return super.getBytes(index, dst, dstIndex, length); - } - - @Override - public ByteBuf getBytes(int index, byte[] dst) { - recordLeakNonRefCountingOperation(); - return super.getBytes(index, dst); - } - - @Override - public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - recordLeakNonRefCountingOperation(); - return super.getBytes(index, dst, dstIndex, length); - } - - @Override - public ByteBuf getBytes(int index, ByteBuffer dst) { - recordLeakNonRefCountingOperation(); - return super.getBytes(index, dst); - } - - @Override - public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException { - recordLeakNonRefCountingOperation(); - return super.getBytes(index, out, length); - } - - @Override - public int getBytes(int index, GatheringByteChannel out, int length) throws IOException { - recordLeakNonRefCountingOperation(); - return super.getBytes(index, out, length); - } - - @Override - public ByteBuf setBoolean(int index, boolean value) { - recordLeakNonRefCountingOperation(); - return super.setBoolean(index, value); - } - - @Override - public ByteBuf setByte(int index, int value) { - recordLeakNonRefCountingOperation(); - return super.setByte(index, value); - } - - @Override - public ByteBuf setShort(int index, int value) { - recordLeakNonRefCountingOperation(); - return super.setShort(index, value); - } - - @Override - public ByteBuf setMedium(int index, int value) { - recordLeakNonRefCountingOperation(); - return super.setMedium(index, value); - } - - @Override - public ByteBuf setInt(int index, int value) { - recordLeakNonRefCountingOperation(); - return super.setInt(index, value); - } - - @Override - public ByteBuf setLong(int index, long value) { - recordLeakNonRefCountingOperation(); - return super.setLong(index, value); - } - - @Override - public ByteBuf setChar(int index, int value) { - recordLeakNonRefCountingOperation(); - return super.setChar(index, value); - } - - @Override - public ByteBuf setFloat(int index, float value) { - recordLeakNonRefCountingOperation(); - return super.setFloat(index, value); - } - - @Override - public ByteBuf setDouble(int index, double value) { - recordLeakNonRefCountingOperation(); - return super.setDouble(index, value); - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src) { - recordLeakNonRefCountingOperation(); - return super.setBytes(index, src); - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int length) { - recordLeakNonRefCountingOperation(); - return super.setBytes(index, src, length); - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { - recordLeakNonRefCountingOperation(); - return super.setBytes(index, src, srcIndex, length); - } - - @Override - public ByteBuf setBytes(int index, byte[] src) { - recordLeakNonRefCountingOperation(); - return super.setBytes(index, src); - } - - @Override - public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { - recordLeakNonRefCountingOperation(); - return super.setBytes(index, src, srcIndex, length); - } - - @Override - public ByteBuf setBytes(int index, ByteBuffer src) { - recordLeakNonRefCountingOperation(); - return super.setBytes(index, src); - } - - @Override - public int setBytes(int index, InputStream in, int length) throws IOException { - recordLeakNonRefCountingOperation(); - return super.setBytes(index, in, length); - } - - @Override - public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException { - recordLeakNonRefCountingOperation(); - return super.setBytes(index, in, length); - } - - @Override - public ByteBuf setZero(int index, int length) { - recordLeakNonRefCountingOperation(); - return super.setZero(index, length); - } - - @Override - public boolean readBoolean() { - recordLeakNonRefCountingOperation(); - return super.readBoolean(); - } - - @Override - public byte readByte() { - recordLeakNonRefCountingOperation(); - return super.readByte(); - } - - @Override - public short readUnsignedByte() { - recordLeakNonRefCountingOperation(); - return super.readUnsignedByte(); - } - - @Override - public short readShort() { - recordLeakNonRefCountingOperation(); - return super.readShort(); - } - - @Override - public int readUnsignedShort() { - recordLeakNonRefCountingOperation(); - return super.readUnsignedShort(); - } - - @Override - public int readMedium() { - recordLeakNonRefCountingOperation(); - return super.readMedium(); - } - - @Override - public int readUnsignedMedium() { - recordLeakNonRefCountingOperation(); - return super.readUnsignedMedium(); - } - - @Override - public int readInt() { - recordLeakNonRefCountingOperation(); - return super.readInt(); - } - - @Override - public long readUnsignedInt() { - recordLeakNonRefCountingOperation(); - return super.readUnsignedInt(); - } - - @Override - public long readLong() { - recordLeakNonRefCountingOperation(); - return super.readLong(); - } - - @Override - public char readChar() { - recordLeakNonRefCountingOperation(); - return super.readChar(); - } - - @Override - public float readFloat() { - recordLeakNonRefCountingOperation(); - return super.readFloat(); - } - - @Override - public double readDouble() { - recordLeakNonRefCountingOperation(); - return super.readDouble(); - } - - @Override - public ByteBuf readBytes(int length) { - recordLeakNonRefCountingOperation(); - return super.readBytes(length); - } - - @Override - public ByteBuf readBytes(ByteBuf dst) { - recordLeakNonRefCountingOperation(); - return super.readBytes(dst); - } - - @Override - public ByteBuf readBytes(ByteBuf dst, int length) { - recordLeakNonRefCountingOperation(); - return super.readBytes(dst, length); - } - - @Override - public ByteBuf readBytes(ByteBuf dst, int dstIndex, int length) { - recordLeakNonRefCountingOperation(); - return super.readBytes(dst, dstIndex, length); - } - - @Override - public ByteBuf readBytes(byte[] dst) { - recordLeakNonRefCountingOperation(); - return super.readBytes(dst); - } - - @Override - public ByteBuf readBytes(byte[] dst, int dstIndex, int length) { - recordLeakNonRefCountingOperation(); - return super.readBytes(dst, dstIndex, length); - } - - @Override - public ByteBuf readBytes(ByteBuffer dst) { - recordLeakNonRefCountingOperation(); - return super.readBytes(dst); - } - - @Override - public ByteBuf readBytes(OutputStream out, int length) throws IOException { - recordLeakNonRefCountingOperation(); - return super.readBytes(out, length); - } - - @Override - public int readBytes(GatheringByteChannel out, int length) throws IOException { - recordLeakNonRefCountingOperation(); - return super.readBytes(out, length); - } - - @Override - public ByteBuf skipBytes(int length) { - recordLeakNonRefCountingOperation(); - return super.skipBytes(length); - } - - @Override - public ByteBuf writeBoolean(boolean value) { - recordLeakNonRefCountingOperation(); - return super.writeBoolean(value); - } - - @Override - public ByteBuf writeByte(int value) { - recordLeakNonRefCountingOperation(); - return super.writeByte(value); - } - - @Override - public ByteBuf writeShort(int value) { - recordLeakNonRefCountingOperation(); - return super.writeShort(value); - } - - @Override - public ByteBuf writeMedium(int value) { - recordLeakNonRefCountingOperation(); - return super.writeMedium(value); - } - - @Override - public ByteBuf writeInt(int value) { - recordLeakNonRefCountingOperation(); - return super.writeInt(value); - } - - @Override - public ByteBuf writeLong(long value) { - recordLeakNonRefCountingOperation(); - return super.writeLong(value); - } - - @Override - public ByteBuf writeChar(int value) { - recordLeakNonRefCountingOperation(); - return super.writeChar(value); - } - - @Override - public ByteBuf writeFloat(float value) { - recordLeakNonRefCountingOperation(); - return super.writeFloat(value); - } - - @Override - public ByteBuf writeDouble(double value) { - recordLeakNonRefCountingOperation(); - return super.writeDouble(value); - } - - @Override - public ByteBuf writeBytes(ByteBuf src) { - recordLeakNonRefCountingOperation(); - return super.writeBytes(src); - } - - @Override - public ByteBuf writeBytes(ByteBuf src, int length) { - recordLeakNonRefCountingOperation(); - return super.writeBytes(src, length); - } - - @Override - public ByteBuf writeBytes(ByteBuf src, int srcIndex, int length) { - recordLeakNonRefCountingOperation(); - return super.writeBytes(src, srcIndex, length); - } - - @Override - public ByteBuf writeBytes(byte[] src) { - recordLeakNonRefCountingOperation(); - return super.writeBytes(src); - } - - @Override - public ByteBuf writeBytes(byte[] src, int srcIndex, int length) { - recordLeakNonRefCountingOperation(); - return super.writeBytes(src, srcIndex, length); - } - - @Override - public ByteBuf writeBytes(ByteBuffer src) { - recordLeakNonRefCountingOperation(); - return super.writeBytes(src); - } - - @Override - public int writeBytes(InputStream in, int length) throws IOException { - recordLeakNonRefCountingOperation(); - return super.writeBytes(in, length); - } - - @Override - public int writeBytes(ScatteringByteChannel in, int length) throws IOException { - recordLeakNonRefCountingOperation(); - return super.writeBytes(in, length); - } - - @Override - public ByteBuf writeZero(int length) { - recordLeakNonRefCountingOperation(); - return super.writeZero(length); - } - - @Override - public int indexOf(int fromIndex, int toIndex, byte value) { - recordLeakNonRefCountingOperation(); - return super.indexOf(fromIndex, toIndex, value); - } - - @Override - public int bytesBefore(byte value) { - recordLeakNonRefCountingOperation(); - return super.bytesBefore(value); - } - - @Override - public int bytesBefore(int length, byte value) { - recordLeakNonRefCountingOperation(); - return super.bytesBefore(length, value); - } - - @Override - public int bytesBefore(int index, int length, byte value) { - recordLeakNonRefCountingOperation(); - return super.bytesBefore(index, length, value); - } - - @Override - public int forEachByte(ByteBufProcessor processor) { - recordLeakNonRefCountingOperation(); - return super.forEachByte(processor); - } - - @Override - public int forEachByte(int index, int length, ByteBufProcessor processor) { - recordLeakNonRefCountingOperation(); - return super.forEachByte(index, length, processor); - } - - @Override - public int forEachByteDesc(ByteBufProcessor processor) { - recordLeakNonRefCountingOperation(); - return super.forEachByteDesc(processor); - } - - @Override - public int forEachByteDesc(int index, int length, ByteBufProcessor processor) { - recordLeakNonRefCountingOperation(); - return super.forEachByteDesc(index, length, processor); - } - - @Override - public ByteBuf copy() { - recordLeakNonRefCountingOperation(); - return super.copy(); - } - - @Override - public ByteBuf copy(int index, int length) { - recordLeakNonRefCountingOperation(); - return super.copy(index, length); - } - - @Override - public int nioBufferCount() { - recordLeakNonRefCountingOperation(); - return super.nioBufferCount(); - } - - @Override - public ByteBuffer nioBuffer() { - recordLeakNonRefCountingOperation(); - return super.nioBuffer(); - } - - @Override - public ByteBuffer nioBuffer(int index, int length) { - recordLeakNonRefCountingOperation(); - return super.nioBuffer(index, length); - } - - @Override - public ByteBuffer[] nioBuffers() { - recordLeakNonRefCountingOperation(); - return super.nioBuffers(); - } - - @Override - public ByteBuffer[] nioBuffers(int index, int length) { - recordLeakNonRefCountingOperation(); - return super.nioBuffers(index, length); - } - - @Override - public ByteBuffer internalNioBuffer(int index, int length) { - recordLeakNonRefCountingOperation(); - return super.internalNioBuffer(index, length); - } - - @Override - public String toString(Charset charset) { - recordLeakNonRefCountingOperation(); - return super.toString(charset); - } - - @Override - public String toString(int index, int length, Charset charset) { - recordLeakNonRefCountingOperation(); - return super.toString(index, length, charset); - } - - @Override - public ByteBuf retain() { - leak.record(); - return super.retain(); - } - - @Override - public ByteBuf retain(int increment) { - leak.record(); - return super.retain(increment); - } - - @Override - public ByteBuf capacity(int newCapacity) { - recordLeakNonRefCountingOperation(); - return super.capacity(newCapacity); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ByteBuf.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ByteBuf.java deleted file mode 100755 index 4ea6f4e281..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ByteBuf.java +++ /dev/null @@ -1,1895 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; -import java.nio.charset.Charset; -import java.nio.charset.UnsupportedCharsetException; - -import com.ai.cloud.io.netty.util.ReferenceCounted; - -/** - * A random and sequential accessible sequence of zero or more bytes (octets). - * This interface provides an abstract view for one or more primitive byte - * arrays ({@code byte[]}) and {@linkplain ByteBuffer NIO buffers}. - * - *

Creation of a buffer

- * - * It is recommended to create a new buffer using the helper methods in - * {@link Unpooled} rather than calling an individual implementation's - * constructor. - * - *

Random Access Indexing

- * - * Just like an ordinary primitive byte array, {@link ByteBuf} uses - * zero-based indexing. - * It means the index of the first byte is always {@code 0} and the index of the last byte is - * always {@link #capacity() capacity - 1}. For example, to iterate all bytes of a buffer, you - * can do the following, regardless of its internal implementation: - * - *
- * {@link ByteBuf} buffer = ...;
- * for (int i = 0; i < buffer.capacity(); i ++) {
- *     byte b = buffer.getByte(i);
- *     System.out.println((char) b);
- * }
- * 
- * - *

Sequential Access Indexing

- * - * {@link ByteBuf} provides two pointer variables to support sequential - * read and write operations - {@link #readerIndex() readerIndex} for a read - * operation and {@link #writerIndex() 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
- * 
- * - *

Readable bytes (the actual content)

- * - * This segment is where the actual data is stored. Any operation whose name - * starts with {@code read} or {@code skip} will get or skip the data at the - * current {@link #readerIndex() readerIndex} and increase it by the number of - * read bytes. If the argument of the read operation is also a - * {@link ByteBuf} and no destination index is specified, the specified - * buffer's {@link #writerIndex() writerIndex} is increased together. - *

- * If there's not enough content left, {@link IndexOutOfBoundsException} is - * raised. The default value of newly allocated, wrapped or copied buffer's - * {@link #readerIndex() readerIndex} is {@code 0}. - * - *

- * // Iterates the readable bytes of a buffer.
- * {@link ByteBuf} buffer = ...;
- * while (buffer.isReadable()) {
- *     System.out.println(buffer.readByte());
- * }
- * 
- * - *

Writable bytes

- * - * This segment is a undefined space which needs to be filled. Any operation - * whose name ends with {@code write} will write the data at the current - * {@link #writerIndex() writerIndex} and increase it by the number of written - * bytes. If the argument of the write operation is also a {@link ByteBuf}, - * and no source index is specified, the specified buffer's - * {@link #readerIndex() readerIndex} is increased together. - *

- * If there's not enough writable bytes left, {@link IndexOutOfBoundsException} - * is raised. The default value of newly allocated buffer's - * {@link #writerIndex() writerIndex} is {@code 0}. The default value of - * wrapped or copied buffer's {@link #writerIndex() writerIndex} is the - * {@link #capacity() capacity} of the buffer. - * - *

- * // Fills the writable bytes of a buffer with random integers.
- * {@link ByteBuf} buffer = ...;
- * while (buffer.maxWritableBytes() >= 4) {
- *     buffer.writeInt(random.nextInt());
- * }
- * 
- * - *

Discardable bytes

- * - * This segment contains the bytes which were read already by a read operation. - * Initially, the size of this segment is {@code 0}, but its size increases up - * to the {@link #writerIndex() writerIndex} as read operations are executed. - * The read bytes can be discarded by calling {@link #discardReadBytes()} to - * reclaim unused area as depicted by the following diagram: - * - *
- *  BEFORE discardReadBytes()
- *
- *      +-------------------+------------------+------------------+
- *      | discardable bytes |  readable bytes  |  writable bytes  |
- *      +-------------------+------------------+------------------+
- *      |                   |                  |                  |
- *      0      <=      readerIndex   <=   writerIndex    <=    capacity
- *
- *
- *  AFTER discardReadBytes()
- *
- *      +------------------+--------------------------------------+
- *      |  readable bytes  |    writable bytes (got more space)   |
- *      +------------------+--------------------------------------+
- *      |                  |                                      |
- * readerIndex (0) <= writerIndex (decreased)        <=        capacity
- * 
- * - * Please note that there is no guarantee about the content of writable bytes - * after calling {@link #discardReadBytes()}. The writable bytes will not be - * moved in most cases and could even be filled with completely different data - * depending on the underlying buffer implementation. - * - *

Clearing the buffer indexes

- * - * You can set both {@link #readerIndex() readerIndex} and - * {@link #writerIndex() writerIndex} to {@code 0} by calling {@link #clear()}. - * It does not clear the buffer content (e.g. filling with {@code 0}) but just - * clears the two pointers. Please also note that the semantic of this - * operation is different from {@link ByteBuffer#clear()}. - * - *
- *  BEFORE clear()
- *
- *      +-------------------+------------------+------------------+
- *      | discardable bytes |  readable bytes  |  writable bytes  |
- *      +-------------------+------------------+------------------+
- *      |                   |                  |                  |
- *      0      <=      readerIndex   <=   writerIndex    <=    capacity
- *
- *
- *  AFTER clear()
- *
- *      +---------------------------------------------------------+
- *      |             writable bytes (got more space)             |
- *      +---------------------------------------------------------+
- *      |                                                         |
- *      0 = readerIndex = writerIndex            <=            capacity
- * 
- * - *

Search operations

- * - * For simple single-byte searches, use {@link #indexOf(int, int, byte)} and {@link #bytesBefore(int, int, byte)}. - * {@link #bytesBefore(byte)} is especially useful when you deal with a {@code NUL}-terminated string. - * For complicated searches, use {@link #forEachByte(int, int, ByteBufProcessor)} with a {@link ByteBufProcessor} - * implementation. - * - *

Mark and reset

- * - * There are two marker indexes in every buffer. One is for storing - * {@link #readerIndex() readerIndex} and the other is for storing - * {@link #writerIndex() writerIndex}. You can always reposition one of the - * two indexes by calling a reset method. It works in a similar fashion to - * the mark and reset methods in {@link InputStream} except that there's no - * {@code readlimit}. - * - *

Derived buffers

- * - * You can create a view of an existing buffer by calling either - * {@link #duplicate()}, {@link #slice()} or {@link #slice(int, int)}. - * A derived buffer will have an independent {@link #readerIndex() readerIndex}, - * {@link #writerIndex() writerIndex} and marker indexes, while it shares - * other internal data representation, just like a NIO buffer does. - *

- * In case a completely fresh copy of an existing buffer is required, please - * call {@link #copy()} method instead. - *

- * Also be aware that obtaining derived buffers will NOT call {@link #retain()} and so the - * reference count will NOT be increased. - * - *

Conversion to existing JDK types

- * - *

Byte array

- * - * If a {@link ByteBuf} is backed by a byte array (i.e. {@code byte[]}), - * you can access it directly via the {@link #array()} method. To determine - * if a buffer is backed by a byte array, {@link #hasArray()} should be used. - * - *

NIO Buffers

- * - * If a {@link ByteBuf} can be converted into an NIO {@link ByteBuffer} which shares its - * content (i.e. view buffer), you can get it via the {@link #nioBuffer()} method. To determine - * if a buffer can be converted into an NIO buffer, use {@link #nioBufferCount()}. - * - *

Strings

- * - * Various {@link #toString(Charset)} methods convert a {@link ByteBuf} - * into a {@link String}. Please note that {@link #toString()} is not a - * conversion method. - * - *

I/O Streams

- * - * Please refer to {@link ByteBufInputStream} and - * {@link ByteBufOutputStream}. - */ -@SuppressWarnings("ClassMayBeInterface") -public abstract class ByteBuf implements ReferenceCounted, Comparable { - - /** - * Returns the number of bytes (octets) this buffer can contain. - */ - public abstract int capacity(); - - /** - * Adjusts the capacity of this buffer. If the {@code newCapacity} is less than the current - * capacity, the content of this buffer is truncated. If the {@code newCapacity} is greater - * than the current capacity, the buffer is appended with unspecified data whose length is - * {@code (newCapacity - currentCapacity)}. - */ - public abstract ByteBuf capacity(int newCapacity); - - /** - * Returns the maximum allowed capacity of this buffer. If a user attempts to increase the - * capacity of this buffer beyond the maximum capacity using {@link #capacity(int)} or - * {@link #ensureWritable(int)}, those methods will raise an - * {@link IllegalArgumentException}. - */ - public abstract int maxCapacity(); - - /** - * Returns the {@link ByteBufAllocator} which created this buffer. - */ - public abstract ByteBufAllocator alloc(); - - /** - * Returns the endianness - * of this buffer. - */ - public abstract ByteOrder order(); - - /** - * Returns a buffer with the specified {@code endianness} which shares the whole region, - * indexes, and marks of this buffer. Modifying the content, the indexes, or the marks of the - * returned buffer or this buffer affects each other's content, indexes, and marks. If the - * specified {@code endianness} is identical to this buffer's byte order, this method can - * return {@code this}. This method does not modify {@code readerIndex} or {@code writerIndex} - * of this buffer. - */ - public abstract ByteBuf order(ByteOrder endianness); - - /** - * Return the underlying buffer instance if this buffer is a wrapper of another buffer. - * - * @return {@code null} if this buffer is not a wrapper - */ - public abstract ByteBuf unwrap(); - - /** - * Returns {@code true} if and only if this buffer is backed by an - * NIO direct buffer. - */ - public abstract boolean isDirect(); - - /** - * Returns the {@code readerIndex} of this buffer. - */ - public abstract int readerIndex(); - - /** - * Sets the {@code readerIndex} of this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code readerIndex} is - * less than {@code 0} or - * greater than {@code this.writerIndex} - */ - public abstract ByteBuf readerIndex(int readerIndex); - - /** - * Returns the {@code writerIndex} of this buffer. - */ - public abstract int writerIndex(); - - /** - * Sets the {@code writerIndex} of this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code writerIndex} is - * less than {@code this.readerIndex} or - * greater than {@code this.capacity} - */ - public abstract ByteBuf writerIndex(int writerIndex); - - /** - * Sets the {@code readerIndex} and {@code writerIndex} of this buffer - * in one shot. This method is useful when you have to worry about the - * invocation order of {@link #readerIndex(int)} and {@link #writerIndex(int)} - * methods. For example, the following code will fail: - * - *
-     * // Create a buffer whose readerIndex, writerIndex and capacity are
-     * // 0, 0 and 8 respectively.
-     * {@link ByteBuf} buf = {@link Unpooled}.buffer(8);
-     *
-     * // IndexOutOfBoundsException is thrown because the specified
-     * // readerIndex (2) cannot be greater than the current writerIndex (0).
-     * buf.readerIndex(2);
-     * buf.writerIndex(4);
-     * 
- * - * The following code will also fail: - * - *
-     * // Create a buffer whose readerIndex, writerIndex and capacity are
-     * // 0, 8 and 8 respectively.
-     * {@link ByteBuf} buf = {@link Unpooled}.wrappedBuffer(new byte[8]);
-     *
-     * // readerIndex becomes 8.
-     * buf.readLong();
-     *
-     * // IndexOutOfBoundsException is thrown because the specified
-     * // writerIndex (4) cannot be less than the current readerIndex (8).
-     * buf.writerIndex(4);
-     * buf.readerIndex(2);
-     * 
- * - * By contrast, this method guarantees that it never - * throws an {@link IndexOutOfBoundsException} as long as the specified - * indexes meet basic constraints, regardless what the current index - * values of the buffer are: - * - *
-     * // No matter what the current state of the buffer is, the following
-     * // call always succeeds as long as the capacity of the buffer is not
-     * // less than 4.
-     * buf.setIndex(2, 4);
-     * 
- * - * @throws IndexOutOfBoundsException - * if the specified {@code readerIndex} is less than 0, - * if the specified {@code writerIndex} is less than the specified - * {@code readerIndex} or if the specified {@code writerIndex} is - * greater than {@code this.capacity} - */ - public abstract ByteBuf setIndex(int readerIndex, int writerIndex); - - /** - * Returns the number of readable bytes which is equal to - * {@code (this.writerIndex - this.readerIndex)}. - */ - public abstract int readableBytes(); - - /** - * Returns the number of writable bytes which is equal to - * {@code (this.capacity - this.writerIndex)}. - */ - public abstract int writableBytes(); - - /** - * Returns the maximum possible number of writable bytes, which is equal to - * {@code (this.maxCapacity - this.writerIndex)}. - */ - public abstract int maxWritableBytes(); - - /** - * Returns {@code true} - * if and only if {@code (this.writerIndex - this.readerIndex)} is greater - * than {@code 0}. - */ - public abstract boolean isReadable(); - - /** - * Returns {@code true} if and only if this buffer contains equal to or more than the specified number of elements. - */ - public abstract boolean isReadable(int size); - - /** - * Returns {@code true} - * if and only if {@code (this.capacity - this.writerIndex)} is greater - * than {@code 0}. - */ - public abstract boolean isWritable(); - - /** - * Returns {@code true} if and only if this buffer has enough room to allow writing the specified number of - * elements. - */ - public abstract boolean isWritable(int size); - - /** - * Sets the {@code readerIndex} and {@code writerIndex} of this buffer to - * {@code 0}. - * This method is identical to {@link #setIndex(int, int) setIndex(0, 0)}. - *

- * Please note that the behavior of this method is different - * from that of NIO buffer, which sets the {@code limit} to - * the {@code capacity} of the buffer. - */ - public abstract ByteBuf clear(); - - /** - * Marks the current {@code readerIndex} in this buffer. You can - * reposition the current {@code readerIndex} to the marked - * {@code readerIndex} by calling {@link #resetReaderIndex()}. - * The initial value of the marked {@code readerIndex} is {@code 0}. - */ - public abstract ByteBuf markReaderIndex(); - - /** - * Repositions the current {@code readerIndex} to the marked - * {@code readerIndex} in this buffer. - * - * @throws IndexOutOfBoundsException - * if the current {@code writerIndex} is less than the marked - * {@code readerIndex} - */ - public abstract ByteBuf resetReaderIndex(); - - /** - * Marks the current {@code writerIndex} in this buffer. You can - * reposition the current {@code writerIndex} to the marked - * {@code writerIndex} by calling {@link #resetWriterIndex()}. - * The initial value of the marked {@code writerIndex} is {@code 0}. - */ - public abstract ByteBuf markWriterIndex(); - - /** - * Repositions the current {@code writerIndex} to the marked - * {@code writerIndex} in this buffer. - * - * @throws IndexOutOfBoundsException - * if the current {@code readerIndex} is greater than the marked - * {@code writerIndex} - */ - public abstract ByteBuf resetWriterIndex(); - - /** - * Discards the bytes between the 0th index and {@code readerIndex}. - * It moves the bytes between {@code readerIndex} and {@code writerIndex} - * to the 0th index, and sets {@code readerIndex} and {@code writerIndex} - * to {@code 0} and {@code oldWriterIndex - oldReaderIndex} respectively. - *

- * Please refer to the class documentation for more detailed explanation. - */ - public abstract ByteBuf discardReadBytes(); - - /** - * Similar to {@link ByteBuf#discardReadBytes()} except that this method might discard - * some, all, or none of read bytes depending on its internal implementation to reduce - * overall memory bandwidth consumption at the cost of potentially additional memory - * consumption. - */ - public abstract ByteBuf discardSomeReadBytes(); - - /** - * Makes sure the number of {@linkplain #writableBytes() the writable bytes} - * is equal to or greater than the specified value. If there is enough - * writable bytes in this buffer, this method returns with no side effect. - * Otherwise, it raises an {@link IllegalArgumentException}. - * - * @param minWritableBytes - * the expected minimum number of writable bytes - * @throws IndexOutOfBoundsException - * if {@link #writerIndex()} + {@code minWritableBytes} > {@link #maxCapacity()} - */ - public abstract ByteBuf ensureWritable(int minWritableBytes); - - /** - * Tries to make sure the number of {@linkplain #writableBytes() the writable bytes} - * is equal to or greater than the specified value. Unlike {@link #ensureWritable(int)}, - * this method does not raise an exception but returns a code. - * - * @param minWritableBytes - * the expected minimum number of writable bytes - * @param force - * When {@link #writerIndex()} + {@code minWritableBytes} > {@link #maxCapacity()}: - *

    - *
  • {@code true} - the capacity of the buffer is expanded to {@link #maxCapacity()}
  • - *
  • {@code false} - the capacity of the buffer is unchanged
  • - *
- * @return {@code 0} if the buffer has enough writable bytes, and its capacity is unchanged. - * {@code 1} if the buffer does not have enough bytes, and its capacity is unchanged. - * {@code 2} if the buffer has enough writable bytes, and its capacity has been increased. - * {@code 3} if the buffer does not have enough bytes, but its capacity has been - * increased to its maximum. - */ - public abstract int ensureWritable(int minWritableBytes, boolean force); - - /** - * Gets a boolean at the specified absolute (@code index) in this buffer. - * This method does not modify the {@code readerIndex} or {@code writerIndex} - * of this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 1} is greater than {@code this.capacity} - */ - public abstract boolean getBoolean(int index); - - /** - * Gets a byte at the specified absolute {@code index} in this buffer. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 1} is greater than {@code this.capacity} - */ - public abstract byte getByte(int index); - - /** - * Gets an unsigned byte at the specified absolute {@code index} in this - * buffer. This method does not modify {@code readerIndex} or - * {@code writerIndex} of this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 1} is greater than {@code this.capacity} - */ - public abstract short getUnsignedByte(int index); - - /** - * Gets a 16-bit short integer at the specified absolute {@code index} in - * this buffer. This method does not modify {@code readerIndex} or - * {@code writerIndex} of this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 2} is greater than {@code this.capacity} - */ - public abstract short getShort(int index); - - /** - * Gets an unsigned 16-bit short integer at the specified absolute - * {@code index} in this buffer. This method does not modify - * {@code readerIndex} or {@code writerIndex} of this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 2} is greater than {@code this.capacity} - */ - public abstract int getUnsignedShort(int index); - - /** - * Gets a 24-bit medium integer at the specified absolute {@code index} in - * this buffer. This method does not modify {@code readerIndex} or - * {@code writerIndex} of this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 3} is greater than {@code this.capacity} - */ - public abstract int getMedium(int index); - - /** - * Gets an unsigned 24-bit medium integer at the specified absolute - * {@code index} in this buffer. This method does not modify - * {@code readerIndex} or {@code writerIndex} of this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 3} is greater than {@code this.capacity} - */ - public abstract int getUnsignedMedium(int index); - - /** - * Gets a 32-bit integer at the specified absolute {@code index} in - * this buffer. This method does not modify {@code readerIndex} or - * {@code writerIndex} of this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 4} is greater than {@code this.capacity} - */ - public abstract int getInt(int index); - - /** - * Gets an unsigned 32-bit integer at the specified absolute {@code index} - * in this buffer. This method does not modify {@code readerIndex} or - * {@code writerIndex} of this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 4} is greater than {@code this.capacity} - */ - public abstract long getUnsignedInt(int index); - - /** - * Gets a 64-bit long integer at the specified absolute {@code index} in - * this buffer. This method does not modify {@code readerIndex} or - * {@code writerIndex} of this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 8} is greater than {@code this.capacity} - */ - public abstract long getLong(int index); - - /** - * Gets a 2-byte UTF-16 character at the specified absolute - * {@code index} in this buffer. This method does not modify - * {@code readerIndex} or {@code writerIndex} of this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 2} is greater than {@code this.capacity} - */ - public abstract char getChar(int index); - - /** - * Gets a 32-bit floating point number at the specified absolute - * {@code index} in this buffer. This method does not modify - * {@code readerIndex} or {@code writerIndex} of this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 4} is greater than {@code this.capacity} - */ - public abstract float getFloat(int index); - - /** - * Gets a 64-bit floating point number at the specified absolute - * {@code index} in this buffer. This method does not modify - * {@code readerIndex} or {@code writerIndex} of this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 8} is greater than {@code this.capacity} - */ - public abstract double getDouble(int index); - - /** - * Transfers this buffer's data to the specified destination starting at - * the specified absolute {@code index} until the destination becomes - * non-writable. This method is basically same with - * {@link #getBytes(int, ByteBuf, int, int)}, except that this - * method increases the {@code writerIndex} of the destination by the - * number of the transferred bytes while - * {@link #getBytes(int, ByteBuf, int, int)} does not. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * the source buffer (i.e. {@code this}). - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * if {@code index + dst.writableBytes} is greater than - * {@code this.capacity} - */ - public abstract ByteBuf getBytes(int index, ByteBuf dst); - - /** - * Transfers this buffer's data to the specified destination starting at - * the specified absolute {@code index}. This method is basically same - * with {@link #getBytes(int, ByteBuf, int, int)}, except that this - * method increases the {@code writerIndex} of the destination by the - * number of the transferred bytes while - * {@link #getBytes(int, ByteBuf, int, int)} does not. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * the source buffer (i.e. {@code this}). - * - * @param length the number of bytes to transfer - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0}, - * if {@code index + length} is greater than - * {@code this.capacity}, or - * if {@code length} is greater than {@code dst.writableBytes} - */ - public abstract ByteBuf getBytes(int index, ByteBuf dst, int length); - - /** - * Transfers this buffer's data to the specified destination starting at - * the specified absolute {@code index}. - * This method does not modify {@code readerIndex} or {@code writerIndex} - * of both the source (i.e. {@code this}) and the destination. - * - * @param dstIndex the first index of the destination - * @param length the number of bytes to transfer - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0}, - * if the specified {@code dstIndex} is less than {@code 0}, - * if {@code index + length} is greater than - * {@code this.capacity}, or - * if {@code dstIndex + length} is greater than - * {@code dst.capacity} - */ - public abstract ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length); - - /** - * Transfers this buffer's data to the specified destination starting at - * the specified absolute {@code index}. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * if {@code index + dst.length} is greater than - * {@code this.capacity} - */ - public abstract ByteBuf getBytes(int index, byte[] dst); - - /** - * Transfers this buffer's data to the specified destination starting at - * the specified absolute {@code index}. - * This method does not modify {@code readerIndex} or {@code writerIndex} - * of this buffer. - * - * @param dstIndex the first index of the destination - * @param length the number of bytes to transfer - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0}, - * if the specified {@code dstIndex} is less than {@code 0}, - * if {@code index + length} is greater than - * {@code this.capacity}, or - * if {@code dstIndex + length} is greater than - * {@code dst.length} - */ - public abstract ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length); - - /** - * Transfers this buffer's data to the specified destination starting at - * the specified absolute {@code index} until the destination's position - * reaches its limit. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer while the destination's {@code position} will be increased. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * if {@code index + dst.remaining()} is greater than - * {@code this.capacity} - */ - public abstract ByteBuf getBytes(int index, ByteBuffer dst); - - /** - * Transfers this buffer's data to the specified stream starting at the - * specified absolute {@code index}. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @param length the number of bytes to transfer - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * if {@code index + length} is greater than - * {@code this.capacity} - * @throws IOException - * if the specified stream threw an exception during I/O - */ - public abstract ByteBuf getBytes(int index, OutputStream out, int length) throws IOException; - - /** - * Transfers this buffer's data to the specified channel starting at the - * specified absolute {@code index}. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @param length the maximum number of bytes to transfer - * - * @return the actual number of bytes written out to the specified channel - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * if {@code index + length} is greater than - * {@code this.capacity} - * @throws IOException - * if the specified channel threw an exception during I/O - */ - public abstract int getBytes(int index, GatheringByteChannel out, int length) throws IOException; - - /** - * Sets the specified boolean at the specified absolute {@code index} in this - * buffer. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 1} is greater than {@code this.capacity} - */ - public abstract ByteBuf setBoolean(int index, boolean value); - - /** - * Sets the specified byte at the specified absolute {@code index} in this - * buffer. The 24 high-order bits of the specified value are ignored. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 1} is greater than {@code this.capacity} - */ - public abstract ByteBuf setByte(int index, int value); - - /** - * Sets the specified 16-bit short integer at the specified absolute - * {@code index} in this buffer. The 16 high-order bits of the specified - * value are ignored. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 2} is greater than {@code this.capacity} - */ - public abstract ByteBuf setShort(int index, int value); - - /** - * Sets the specified 24-bit medium integer at the specified absolute - * {@code index} in this buffer. Please note that the most significant - * byte is ignored in the specified value. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 3} is greater than {@code this.capacity} - */ - public abstract ByteBuf setMedium(int index, int value); - - /** - * Sets the specified 32-bit integer at the specified absolute - * {@code index} in this buffer. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 4} is greater than {@code this.capacity} - */ - public abstract ByteBuf setInt(int index, int value); - - /** - * Sets the specified 64-bit long integer at the specified absolute - * {@code index} in this buffer. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 8} is greater than {@code this.capacity} - */ - public abstract ByteBuf setLong(int index, long value); - - /** - * Sets the specified 2-byte UTF-16 character at the specified absolute - * {@code index} in this buffer. - * The 16 high-order bits of the specified value are ignored. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 2} is greater than {@code this.capacity} - */ - public abstract ByteBuf setChar(int index, int value); - - /** - * Sets the specified 32-bit floating-point number at the specified - * absolute {@code index} in this buffer. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 4} is greater than {@code this.capacity} - */ - public abstract ByteBuf setFloat(int index, float value); - - /** - * Sets the specified 64-bit floating-point number at the specified - * absolute {@code index} in this buffer. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * {@code index + 8} is greater than {@code this.capacity} - */ - public abstract ByteBuf setDouble(int index, double value); - - /** - * Transfers the specified source buffer's data to this buffer starting at - * the specified absolute {@code index} until the source buffer becomes - * unreadable. This method is basically same with - * {@link #setBytes(int, ByteBuf, int, int)}, except that this - * method increases the {@code readerIndex} of the source buffer by - * the number of the transferred bytes while - * {@link #setBytes(int, ByteBuf, int, int)} does not. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * the source buffer (i.e. {@code this}). - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * if {@code index + src.readableBytes} is greater than - * {@code this.capacity} - */ - public abstract ByteBuf setBytes(int index, ByteBuf src); - - /** - * Transfers the specified source buffer's data to this buffer starting at - * the specified absolute {@code index}. This method is basically same - * with {@link #setBytes(int, ByteBuf, int, int)}, except that this - * method increases the {@code readerIndex} of the source buffer by - * the number of the transferred bytes while - * {@link #setBytes(int, ByteBuf, int, int)} does not. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * the source buffer (i.e. {@code this}). - * - * @param length the number of bytes to transfer - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0}, - * if {@code index + length} is greater than - * {@code this.capacity}, or - * if {@code length} is greater than {@code src.readableBytes} - */ - public abstract ByteBuf setBytes(int index, ByteBuf src, int length); - - /** - * Transfers the specified source buffer's data to this buffer starting at - * the specified absolute {@code index}. - * This method does not modify {@code readerIndex} or {@code writerIndex} - * of both the source (i.e. {@code this}) and the destination. - * - * @param srcIndex the first index of the source - * @param length the number of bytes to transfer - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0}, - * if the specified {@code srcIndex} is less than {@code 0}, - * if {@code index + length} is greater than - * {@code this.capacity}, or - * if {@code srcIndex + length} is greater than - * {@code src.capacity} - */ - public abstract ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length); - - /** - * Transfers the specified source array's data to this buffer starting at - * the specified absolute {@code index}. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * if {@code index + src.length} is greater than - * {@code this.capacity} - */ - public abstract ByteBuf setBytes(int index, byte[] src); - - /** - * Transfers the specified source array's data to this buffer starting at - * the specified absolute {@code index}. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0}, - * if the specified {@code srcIndex} is less than {@code 0}, - * if {@code index + length} is greater than - * {@code this.capacity}, or - * if {@code srcIndex + length} is greater than {@code src.length} - */ - public abstract ByteBuf setBytes(int index, byte[] src, int srcIndex, int length); - - /** - * Transfers the specified source buffer's data to this buffer starting at - * the specified absolute {@code index} until the source buffer's position - * reaches its limit. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * if {@code index + src.remaining()} is greater than - * {@code this.capacity} - */ - public abstract ByteBuf setBytes(int index, ByteBuffer src); - - /** - * Transfers the content of the specified source stream to this buffer - * starting at the specified absolute {@code index}. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @param length the number of bytes to transfer - * - * @return the actual number of bytes read in from the specified channel. - * {@code -1} if the specified channel is closed. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * if {@code index + length} is greater than {@code this.capacity} - * @throws IOException - * if the specified stream threw an exception during I/O - */ - public abstract int setBytes(int index, InputStream in, int length) throws IOException; - - /** - * Transfers the content of the specified source channel to this buffer - * starting at the specified absolute {@code index}. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @param length the maximum number of bytes to transfer - * - * @return the actual number of bytes read in from the specified channel. - * {@code -1} if the specified channel is closed. - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * if {@code index + length} is greater than {@code this.capacity} - * @throws IOException - * if the specified channel threw an exception during I/O - */ - public abstract int setBytes(int index, ScatteringByteChannel in, int length) throws IOException; - - /** - * Fills this buffer with NUL (0x00) starting at the specified - * absolute {@code index}. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @param length the number of NULs to write to the buffer - * - * @throws IndexOutOfBoundsException - * if the specified {@code index} is less than {@code 0} or - * if {@code index + length} is greater than {@code this.capacity} - */ - public abstract ByteBuf setZero(int index, int length); - - /** - * Gets a boolean at the current {@code readerIndex} and increases - * the {@code readerIndex} by {@code 1} in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.readableBytes} is less than {@code 1} - */ - public abstract boolean readBoolean(); - - /** - * Gets a byte at the current {@code readerIndex} and increases - * the {@code readerIndex} by {@code 1} in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.readableBytes} is less than {@code 1} - */ - public abstract byte readByte(); - - /** - * Gets an unsigned byte at the current {@code readerIndex} and increases - * the {@code readerIndex} by {@code 1} in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.readableBytes} is less than {@code 1} - */ - public abstract short readUnsignedByte(); - - /** - * Gets a 16-bit short integer at the current {@code readerIndex} - * and increases the {@code readerIndex} by {@code 2} in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.readableBytes} is less than {@code 2} - */ - public abstract short readShort(); - - /** - * Gets an unsigned 16-bit short integer at the current {@code readerIndex} - * and increases the {@code readerIndex} by {@code 2} in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.readableBytes} is less than {@code 2} - */ - public abstract int readUnsignedShort(); - - /** - * Gets a 24-bit medium integer at the current {@code readerIndex} - * and increases the {@code readerIndex} by {@code 3} in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.readableBytes} is less than {@code 3} - */ - public abstract int readMedium(); - - /** - * Gets an unsigned 24-bit medium integer at the current {@code readerIndex} - * and increases the {@code readerIndex} by {@code 3} in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.readableBytes} is less than {@code 3} - */ - public abstract int readUnsignedMedium(); - - /** - * Gets a 32-bit integer at the current {@code readerIndex} - * and increases the {@code readerIndex} by {@code 4} in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.readableBytes} is less than {@code 4} - */ - public abstract int readInt(); - - /** - * Gets an unsigned 32-bit integer at the current {@code readerIndex} - * and increases the {@code readerIndex} by {@code 4} in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.readableBytes} is less than {@code 4} - */ - public abstract long readUnsignedInt(); - - /** - * Gets a 64-bit integer at the current {@code readerIndex} - * and increases the {@code readerIndex} by {@code 8} in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.readableBytes} is less than {@code 8} - */ - public abstract long readLong(); - - /** - * Gets a 2-byte UTF-16 character at the current {@code readerIndex} - * and increases the {@code readerIndex} by {@code 2} in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.readableBytes} is less than {@code 2} - */ - public abstract char readChar(); - - /** - * Gets a 32-bit floating point number at the current {@code readerIndex} - * and increases the {@code readerIndex} by {@code 4} in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.readableBytes} is less than {@code 4} - */ - public abstract float readFloat(); - - /** - * Gets a 64-bit floating point number at the current {@code readerIndex} - * and increases the {@code readerIndex} by {@code 8} in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.readableBytes} is less than {@code 8} - */ - public abstract double readDouble(); - - /** - * Transfers this buffer's data to a newly created buffer starting at - * the current {@code readerIndex} and increases the {@code readerIndex} - * by the number of the transferred bytes (= {@code length}). - * The returned buffer's {@code readerIndex} and {@code writerIndex} are - * {@code 0} and {@code length} respectively. - * - * @param length the number of bytes to transfer - * - * @return the newly created buffer which contains the transferred bytes - * - * @throws IndexOutOfBoundsException - * if {@code length} is greater than {@code this.readableBytes} - */ - public abstract ByteBuf readBytes(int length); - - /** - * Returns a new slice of this buffer's sub-region starting at the current - * {@code readerIndex} and increases the {@code readerIndex} by the size - * of the new slice (= {@code length}). - *

- * Also be aware that this method will NOT call {@link #retain()} and so the - * reference count will NOT be increased. - * - * @param length the size of the new slice - * - * @return the newly created slice - * - * @throws IndexOutOfBoundsException - * if {@code length} is greater than {@code this.readableBytes} - */ - public abstract ByteBuf readSlice(int length); - - /** - * Transfers this buffer's data to the specified destination starting at - * the current {@code readerIndex} until the destination becomes - * non-writable, and increases the {@code readerIndex} by the number of the - * transferred bytes. This method is basically same with - * {@link #readBytes(ByteBuf, int, int)}, except that this method - * increases the {@code writerIndex} of the destination by the number of - * the transferred bytes while {@link #readBytes(ByteBuf, int, int)} - * does not. - * - * @throws IndexOutOfBoundsException - * if {@code dst.writableBytes} is greater than - * {@code this.readableBytes} - */ - public abstract ByteBuf readBytes(ByteBuf dst); - - /** - * Transfers this buffer's data to the specified destination starting at - * the current {@code readerIndex} and increases the {@code readerIndex} - * by the number of the transferred bytes (= {@code length}). This method - * is basically same with {@link #readBytes(ByteBuf, int, int)}, - * except that this method increases the {@code writerIndex} of the - * destination by the number of the transferred bytes (= {@code length}) - * while {@link #readBytes(ByteBuf, int, int)} does not. - * - * @throws IndexOutOfBoundsException - * if {@code length} is greater than {@code this.readableBytes} or - * if {@code length} is greater than {@code dst.writableBytes} - */ - public abstract ByteBuf readBytes(ByteBuf dst, int length); - - /** - * Transfers this buffer's data to the specified destination starting at - * the current {@code readerIndex} and increases the {@code readerIndex} - * by the number of the transferred bytes (= {@code length}). - * - * @param dstIndex the first index of the destination - * @param length the number of bytes to transfer - * - * @throws IndexOutOfBoundsException - * if the specified {@code dstIndex} is less than {@code 0}, - * if {@code length} is greater than {@code this.readableBytes}, or - * if {@code dstIndex + length} is greater than - * {@code dst.capacity} - */ - public abstract ByteBuf readBytes(ByteBuf dst, int dstIndex, int length); - - /** - * Transfers this buffer's data to the specified destination starting at - * the current {@code readerIndex} and increases the {@code readerIndex} - * by the number of the transferred bytes (= {@code dst.length}). - * - * @throws IndexOutOfBoundsException - * if {@code dst.length} is greater than {@code this.readableBytes} - */ - public abstract ByteBuf readBytes(byte[] dst); - - /** - * Transfers this buffer's data to the specified destination starting at - * the current {@code readerIndex} and increases the {@code readerIndex} - * by the number of the transferred bytes (= {@code length}). - * - * @param dstIndex the first index of the destination - * @param length the number of bytes to transfer - * - * @throws IndexOutOfBoundsException - * if the specified {@code dstIndex} is less than {@code 0}, - * if {@code length} is greater than {@code this.readableBytes}, or - * if {@code dstIndex + length} is greater than {@code dst.length} - */ - public abstract ByteBuf readBytes(byte[] dst, int dstIndex, int length); - - /** - * Transfers this buffer's data to the specified destination starting at - * the current {@code readerIndex} until the destination's position - * reaches its limit, and increases the {@code readerIndex} by the - * number of the transferred bytes. - * - * @throws IndexOutOfBoundsException - * if {@code dst.remaining()} is greater than - * {@code this.readableBytes} - */ - public abstract ByteBuf readBytes(ByteBuffer dst); - - /** - * Transfers this buffer's data to the specified stream starting at the - * current {@code readerIndex}. - * - * @param length the number of bytes to transfer - * - * @throws IndexOutOfBoundsException - * if {@code length} is greater than {@code this.readableBytes} - * @throws IOException - * if the specified stream threw an exception during I/O - */ - public abstract ByteBuf readBytes(OutputStream out, int length) throws IOException; - - /** - * Transfers this buffer's data to the specified stream starting at the - * current {@code readerIndex}. - * - * @param length the maximum number of bytes to transfer - * - * @return the actual number of bytes written out to the specified channel - * - * @throws IndexOutOfBoundsException - * if {@code length} is greater than {@code this.readableBytes} - * @throws IOException - * if the specified channel threw an exception during I/O - */ - public abstract int readBytes(GatheringByteChannel out, int length) throws IOException; - - /** - * Increases the current {@code readerIndex} by the specified - * {@code length} in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code length} is greater than {@code this.readableBytes} - */ - public abstract ByteBuf skipBytes(int length); - - /** - * Sets the specified boolean at the current {@code writerIndex} - * and increases the {@code writerIndex} by {@code 1} in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.writableBytes} is less than {@code 1} - */ - public abstract ByteBuf writeBoolean(boolean value); - - /** - * Sets the specified byte at the current {@code writerIndex} - * and increases the {@code writerIndex} by {@code 1} in this buffer. - * The 24 high-order bits of the specified value are ignored. - * - * @throws IndexOutOfBoundsException - * if {@code this.writableBytes} is less than {@code 1} - */ - public abstract ByteBuf writeByte(int value); - - /** - * Sets the specified 16-bit short integer at the current - * {@code writerIndex} and increases the {@code writerIndex} by {@code 2} - * in this buffer. The 16 high-order bits of the specified value are ignored. - * - * @throws IndexOutOfBoundsException - * if {@code this.writableBytes} is less than {@code 2} - */ - public abstract ByteBuf writeShort(int value); - - /** - * Sets the specified 24-bit medium integer at the current - * {@code writerIndex} and increases the {@code writerIndex} by {@code 3} - * in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.writableBytes} is less than {@code 3} - */ - public abstract ByteBuf writeMedium(int value); - - /** - * Sets the specified 32-bit integer at the current {@code writerIndex} - * and increases the {@code writerIndex} by {@code 4} in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.writableBytes} is less than {@code 4} - */ - public abstract ByteBuf writeInt(int value); - - /** - * Sets the specified 64-bit long integer at the current - * {@code writerIndex} and increases the {@code writerIndex} by {@code 8} - * in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.writableBytes} is less than {@code 8} - */ - public abstract ByteBuf writeLong(long value); - - /** - * Sets the specified 2-byte UTF-16 character at the current - * {@code writerIndex} and increases the {@code writerIndex} by {@code 2} - * in this buffer. The 16 high-order bits of the specified value are ignored. - * - * @throws IndexOutOfBoundsException - * if {@code this.writableBytes} is less than {@code 2} - */ - public abstract ByteBuf writeChar(int value); - - /** - * Sets the specified 32-bit floating point number at the current - * {@code writerIndex} and increases the {@code writerIndex} by {@code 4} - * in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.writableBytes} is less than {@code 4} - */ - public abstract ByteBuf writeFloat(float value); - - /** - * Sets the specified 64-bit floating point number at the current - * {@code writerIndex} and increases the {@code writerIndex} by {@code 8} - * in this buffer. - * - * @throws IndexOutOfBoundsException - * if {@code this.writableBytes} is less than {@code 8} - */ - public abstract ByteBuf writeDouble(double value); - - /** - * Transfers the specified source buffer's data to this buffer starting at - * the current {@code writerIndex} until the source buffer becomes - * unreadable, and increases the {@code writerIndex} by the number of - * the transferred bytes. This method is basically same with - * {@link #writeBytes(ByteBuf, int, int)}, except that this method - * increases the {@code readerIndex} of the source buffer by the number of - * the transferred bytes while {@link #writeBytes(ByteBuf, int, int)} - * does not. - * - * @throws IndexOutOfBoundsException - * if {@code src.readableBytes} is greater than - * {@code this.writableBytes} - */ - public abstract ByteBuf writeBytes(ByteBuf src); - - /** - * Transfers the specified source buffer's data to this buffer starting at - * the current {@code writerIndex} and increases the {@code writerIndex} - * by the number of the transferred bytes (= {@code length}). This method - * is basically same with {@link #writeBytes(ByteBuf, int, int)}, - * except that this method increases the {@code readerIndex} of the source - * buffer by the number of the transferred bytes (= {@code length}) while - * {@link #writeBytes(ByteBuf, int, int)} does not. - * - * @param length the number of bytes to transfer - * - * @throws IndexOutOfBoundsException - * if {@code length} is greater than {@code this.writableBytes} or - * if {@code length} is greater then {@code src.readableBytes} - */ - public abstract ByteBuf writeBytes(ByteBuf src, int length); - - /** - * Transfers the specified source buffer's data to this buffer starting at - * the current {@code writerIndex} and increases the {@code writerIndex} - * by the number of the transferred bytes (= {@code length}). - * - * @param srcIndex the first index of the source - * @param length the number of bytes to transfer - * - * @throws IndexOutOfBoundsException - * if the specified {@code srcIndex} is less than {@code 0}, - * if {@code srcIndex + length} is greater than - * {@code src.capacity}, or - * if {@code length} is greater than {@code this.writableBytes} - */ - public abstract ByteBuf writeBytes(ByteBuf src, int srcIndex, int length); - - /** - * Transfers the specified source array's data to this buffer starting at - * the current {@code writerIndex} and increases the {@code writerIndex} - * by the number of the transferred bytes (= {@code src.length}). - * - * @throws IndexOutOfBoundsException - * if {@code src.length} is greater than {@code this.writableBytes} - */ - public abstract ByteBuf writeBytes(byte[] src); - - /** - * Transfers the specified source array's data to this buffer starting at - * the current {@code writerIndex} and increases the {@code writerIndex} - * by the number of the transferred bytes (= {@code length}). - * - * @param srcIndex the first index of the source - * @param length the number of bytes to transfer - * - * @throws IndexOutOfBoundsException - * if the specified {@code srcIndex} is less than {@code 0}, - * if {@code srcIndex + length} is greater than - * {@code src.length}, or - * if {@code length} is greater than {@code this.writableBytes} - */ - public abstract ByteBuf writeBytes(byte[] src, int srcIndex, int length); - - /** - * Transfers the specified source buffer's data to this buffer starting at - * the current {@code writerIndex} until the source buffer's position - * reaches its limit, and increases the {@code writerIndex} by the - * number of the transferred bytes. - * - * @throws IndexOutOfBoundsException - * if {@code src.remaining()} is greater than - * {@code this.writableBytes} - */ - public abstract ByteBuf writeBytes(ByteBuffer src); - - /** - * Transfers the content of the specified stream to this buffer - * starting at the current {@code writerIndex} and increases the - * {@code writerIndex} by the number of the transferred bytes. - * - * @param length the number of bytes to transfer - * - * @return the actual number of bytes read in from the specified stream - * - * @throws IndexOutOfBoundsException - * if {@code length} is greater than {@code this.writableBytes} - * @throws IOException - * if the specified stream threw an exception during I/O - */ - public abstract int writeBytes(InputStream in, int length) throws IOException; - - /** - * Transfers the content of the specified channel to this buffer - * starting at the current {@code writerIndex} and increases the - * {@code writerIndex} by the number of the transferred bytes. - * - * @param length the maximum number of bytes to transfer - * - * @return the actual number of bytes read in from the specified channel - * - * @throws IndexOutOfBoundsException - * if {@code length} is greater than {@code this.writableBytes} - * @throws IOException - * if the specified channel threw an exception during I/O - */ - public abstract int writeBytes(ScatteringByteChannel in, int length) throws IOException; - - /** - * Fills this buffer with NUL (0x00) starting at the current - * {@code writerIndex} and increases the {@code writerIndex} by the - * specified {@code length}. - * - * @param length the number of NULs to write to the buffer - * - * @throws IndexOutOfBoundsException - * if {@code length} is greater than {@code this.writableBytes} - */ - public abstract ByteBuf writeZero(int length); - - /** - * Locates the first occurrence of the specified {@code value} in this - * buffer. The search takes place from the specified {@code fromIndex} - * (inclusive) to the specified {@code toIndex} (exclusive). - *

- * If {@code fromIndex} is greater than {@code toIndex}, the search is - * performed in a reversed order. - *

- * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @return the absolute index of the first occurrence if found. - * {@code -1} otherwise. - */ - public abstract int indexOf(int fromIndex, int toIndex, byte value); - - /** - * Locates the first occurrence of the specified {@code value} in this - * buffer. The search takes place from the current {@code readerIndex} - * (inclusive) to the current {@code writerIndex} (exclusive). - *

- * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @return the number of bytes between the current {@code readerIndex} - * and the first occurrence if found. {@code -1} otherwise. - */ - public abstract int bytesBefore(byte value); - - /** - * Locates the first occurrence of the specified {@code value} in this - * buffer. The search starts from the current {@code readerIndex} - * (inclusive) and lasts for the specified {@code length}. - *

- * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @return the number of bytes between the current {@code readerIndex} - * and the first occurrence if found. {@code -1} otherwise. - * - * @throws IndexOutOfBoundsException - * if {@code length} is greater than {@code this.readableBytes} - */ - public abstract int bytesBefore(int length, byte value); - - /** - * Locates the first occurrence of the specified {@code value} in this - * buffer. The search starts from the specified {@code index} (inclusive) - * and lasts for the specified {@code length}. - *

- * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @return the number of bytes between the specified {@code index} - * and the first occurrence if found. {@code -1} otherwise. - * - * @throws IndexOutOfBoundsException - * if {@code index + length} is greater than {@code this.capacity} - */ - public abstract int bytesBefore(int index, int length, byte value); - - /** - * Iterates over the readable bytes of this buffer with the specified {@code processor} in ascending order. - * - * @return {@code -1} if the processor iterated to or beyond the end of the readable bytes. - * The last-visited index If the {@link ByteBufProcessor#process(byte)} returned {@code false}. - */ - public abstract int forEachByte(ByteBufProcessor processor); - - /** - * Iterates over the specified area of this buffer with the specified {@code processor} in ascending order. - * (i.e. {@code index}, {@code (index + 1)}, .. {@code (index + length - 1)}) - * - * @return {@code -1} if the processor iterated to or beyond the end of the specified area. - * The last-visited index If the {@link ByteBufProcessor#process(byte)} returned {@code false}. - */ - public abstract int forEachByte(int index, int length, ByteBufProcessor processor); - - /** - * Iterates over the readable bytes of this buffer with the specified {@code processor} in descending order. - * - * @return {@code -1} if the processor iterated to or beyond the beginning of the readable bytes. - * The last-visited index If the {@link ByteBufProcessor#process(byte)} returned {@code false}. - */ - public abstract int forEachByteDesc(ByteBufProcessor processor); - - /** - * Iterates over the specified area of this buffer with the specified {@code processor} in descending order. - * (i.e. {@code (index + length - 1)}, {@code (index + length - 2)}, ... {@code index}) - * - * - * @return {@code -1} if the processor iterated to or beyond the beginning of the specified area. - * The last-visited index If the {@link ByteBufProcessor#process(byte)} returned {@code false}. - */ - public abstract int forEachByteDesc(int index, int length, ByteBufProcessor processor); - - /** - * Returns a copy of this buffer's readable bytes. Modifying the content - * of the returned buffer or this buffer does not affect each other at all. - * This method is identical to {@code buf.copy(buf.readerIndex(), buf.readableBytes())}. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - */ - public abstract ByteBuf copy(); - - /** - * Returns a copy of this buffer's sub-region. Modifying the content of - * the returned buffer or this buffer does not affect each other at all. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - */ - public abstract ByteBuf copy(int index, int length); - - /** - * Returns a slice of this buffer's readable bytes. Modifying the content - * of the returned buffer or this buffer affects each other's content - * while they maintain separate indexes and marks. This method is - * identical to {@code buf.slice(buf.readerIndex(), buf.readableBytes())}. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - *

- * Also be aware that this method will NOT call {@link #retain()} and so the - * reference count will NOT be increased. - */ - public abstract ByteBuf slice(); - - /** - * Returns a slice of this buffer's sub-region. Modifying the content of - * the returned buffer or this buffer affects each other's content while - * they maintain separate indexes and marks. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - *

- * Also be aware that this method will NOT call {@link #retain()} and so the - * reference count will NOT be increased. - */ - public abstract ByteBuf slice(int index, int length); - - /** - * Returns a buffer which shares the whole region of this buffer. - * Modifying the content of the returned buffer or this buffer affects - * each other's content while they maintain separate indexes and marks. - * This method is identical to {@code buf.slice(0, buf.capacity())}. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - *

- * The reader and writer marks will not be duplicated. Also be aware that this method will - * NOT call {@link #retain()} and so the reference count will NOT be increased. - */ - public abstract ByteBuf duplicate(); - - /** - * Returns the maximum number of NIO {@link ByteBuffer}s that consist this buffer. Note that {@link #nioBuffers()} - * or {@link #nioBuffers(int, int)} might return a less number of {@link ByteBuffer}s. - * - * @return {@code -1} if this buffer has no underlying {@link ByteBuffer}. - * the number of the underlying {@link ByteBuffer}s if this buffer has at least one underlying - * {@link ByteBuffer}. Note that this method does not return {@code 0} to avoid confusion. - * - * @see #nioBuffer() - * @see #nioBuffer(int, int) - * @see #nioBuffers() - * @see #nioBuffers(int, int) - */ - public abstract int nioBufferCount(); - - /** - * Exposes this buffer's readable bytes as an NIO {@link ByteBuffer}. The returned buffer - * shares the content with this buffer, while changing the position and limit of the returned - * NIO buffer does not affect the indexes and marks of this buffer. This method is identical - * to {@code buf.nioBuffer(buf.readerIndex(), buf.readableBytes())}. This method does not - * modify {@code readerIndex} or {@code writerIndex} of this buffer. Please note that the - * returned NIO buffer will not see the changes of this buffer if this buffer is a dynamic - * buffer and it adjusted its capacity. - * - * @throws UnsupportedOperationException - * if this buffer cannot create a {@link ByteBuffer} that shares the content with itself - * - * @see #nioBufferCount() - * @see #nioBuffers() - * @see #nioBuffers(int, int) - */ - public abstract ByteBuffer nioBuffer(); - - /** - * Exposes this buffer's sub-region as an NIO {@link ByteBuffer}. The returned buffer - * shares the content with this buffer, while changing the position and limit of the returned - * NIO buffer does not affect the indexes and marks of this buffer. This method does not - * modify {@code readerIndex} or {@code writerIndex} of this buffer. Please note that the - * returned NIO buffer will not see the changes of this buffer if this buffer is a dynamic - * buffer and it adjusted its capacity. - * - * @throws UnsupportedOperationException - * if this buffer cannot create a {@link ByteBuffer} that shares the content with itself - * - * @see #nioBufferCount() - * @see #nioBuffers() - * @see #nioBuffers(int, int) - */ - public abstract ByteBuffer nioBuffer(int index, int length); - - /** - * Internal use only: Exposes the internal NIO buffer. - */ - public abstract ByteBuffer internalNioBuffer(int index, int length); - - /** - * Exposes this buffer's readable bytes as an NIO {@link ByteBuffer}'s. The returned buffer - * shares the content with this buffer, while changing the position and limit of the returned - * NIO buffer does not affect the indexes and marks of this buffer. This method does not - * modify {@code readerIndex} or {@code writerIndex} of this buffer. Please note that the - * returned NIO buffer will not see the changes of this buffer if this buffer is a dynamic - * buffer and it adjusted its capacity. - * - * - * @throws UnsupportedOperationException - * if this buffer cannot create a {@link ByteBuffer} that shares the content with itself - * - * @see #nioBufferCount() - * @see #nioBuffer() - * @see #nioBuffer(int, int) - */ - public abstract ByteBuffer[] nioBuffers(); - - /** - * Exposes this buffer's bytes as an NIO {@link ByteBuffer}'s for the specified index and length - * The returned buffer shares the content with this buffer, while changing the position and limit - * of the returned NIO buffer does not affect the indexes and marks of this buffer. This method does - * not modify {@code readerIndex} or {@code writerIndex} of this buffer. Please note that the - * returned NIO buffer will not see the changes of this buffer if this buffer is a dynamic - * buffer and it adjusted its capacity. - * - * @throws UnsupportedOperationException - * if this buffer cannot create a {@link ByteBuffer} that shares the content with itself - * - * @see #nioBufferCount() - * @see #nioBuffer() - * @see #nioBuffer(int, int) - */ - public abstract ByteBuffer[] nioBuffers(int index, int length); - - /** - * Returns {@code true} if and only if this buffer has a backing byte array. - * If this method returns true, you can safely call {@link #array()} and - * {@link #arrayOffset()}. - */ - public abstract boolean hasArray(); - - /** - * Returns the backing byte array of this buffer. - * - * @throws UnsupportedOperationException - * if there no accessible backing byte array - */ - public abstract byte[] array(); - - /** - * Returns the offset of the first byte within the backing byte array of - * this buffer. - * - * @throws UnsupportedOperationException - * if there no accessible backing byte array - */ - public abstract int arrayOffset(); - - /** - * Returns {@code true} if and only if this buffer has a reference to the low-level memory address that points - * to the backing data. - */ - public abstract boolean hasMemoryAddress(); - - /** - * Returns the low-level memory address that point to the first byte of ths backing data. - * - * @throws UnsupportedOperationException - * if this buffer does not support accessing the low-level memory address - */ - public abstract long memoryAddress(); - - /** - * Decodes this buffer's readable bytes into a string with the specified - * character set name. This method is identical to - * {@code buf.toString(buf.readerIndex(), buf.readableBytes(), charsetName)}. - * This method does not modify {@code readerIndex} or {@code writerIndex} of - * this buffer. - * - * @throws UnsupportedCharsetException - * if the specified character set name is not supported by the - * current VM - */ - public abstract String toString(Charset charset); - - /** - * Decodes this buffer's sub-region into a string with the specified - * character set. This method does not modify {@code readerIndex} or - * {@code writerIndex} of this buffer. - */ - public abstract String toString(int index, int length, Charset charset); - - /** - * Returns a hash code which was calculated from the content of this - * buffer. If there's a byte array which is - * {@linkplain #equals(Object) equal to} this array, both arrays should - * return the same value. - */ - @Override - public abstract int hashCode(); - - /** - * Determines if the content of the specified buffer is identical to the - * content of this array. 'Identical' here means: - *

    - *
  • the size of the contents of the two buffers are same and
  • - *
  • every single byte of the content of the two buffers are same.
  • - *
- * Please note that it does not compare {@link #readerIndex()} nor - * {@link #writerIndex()}. This method also returns {@code false} for - * {@code null} and an object which is not an instance of - * {@link ByteBuf} type. - */ - @Override - public abstract boolean equals(Object obj); - - /** - * Compares the content of the specified buffer to the content of this - * buffer. Comparison is performed in the same manner with the string - * comparison functions of various languages such as {@code strcmp}, - * {@code memcmp} and {@link String#compareTo(String)}. - */ - @Override - public abstract int compareTo(ByteBuf buffer); - - /** - * Returns the string representation of this buffer. This method does not - * necessarily return the whole content of the buffer but returns - * the values of the key properties such as {@link #readerIndex()}, - * {@link #writerIndex()} and {@link #capacity()}. - */ - @Override - public abstract String toString(); - - @Override - public abstract ByteBuf retain(int increment); - - @Override - public abstract ByteBuf retain(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ByteBufAllocator.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ByteBufAllocator.java deleted file mode 100755 index f52653cafb..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ByteBufAllocator.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.buffer; - -/** - * Implementations are responsible to allocate buffers. Implementations of this interface are expected to be - * thread-safe. - */ -public interface ByteBufAllocator { - - ByteBufAllocator DEFAULT = ByteBufUtil.DEFAULT_ALLOCATOR; - - /** - * Allocate a {@link ByteBuf}. If it is a direct or heap buffer - * depends on the actual implementation. - */ - ByteBuf buffer(); - - /** - * Allocate a {@link ByteBuf} with the given initial capacity. - * If it is a direct or heap buffer depends on the actual implementation. - */ - ByteBuf buffer(int initialCapacity); - - /** - * Allocate a {@link ByteBuf} with the given initial capacity and the given - * maximal capacity. If it is a direct or heap buffer depends on the actual - * implementation. - */ - ByteBuf buffer(int initialCapacity, int maxCapacity); - - /** - * Allocate a {@link ByteBuf}, preferably a direct buffer which is suitable for I/O. - */ - ByteBuf ioBuffer(); - - /** - * Allocate a {@link ByteBuf}, preferably a direct buffer which is suitable for I/O. - */ - ByteBuf ioBuffer(int initialCapacity); - - /** - * Allocate a {@link ByteBuf}, preferably a direct buffer which is suitable for I/O. - */ - ByteBuf ioBuffer(int initialCapacity, int maxCapacity); - - /** - * Allocate a heap {@link ByteBuf}. - */ - ByteBuf heapBuffer(); - - /** - * Allocate a heap {@link ByteBuf} with the given initial capacity. - */ - ByteBuf heapBuffer(int initialCapacity); - - /** - * Allocate a heap {@link ByteBuf} with the given initial capacity and the given - * maximal capacity. - */ - ByteBuf heapBuffer(int initialCapacity, int maxCapacity); - - /** - * Allocate a direct {@link ByteBuf}. - */ - ByteBuf directBuffer(); - - /** - * Allocate a direct {@link ByteBuf} with the given initial capacity. - */ - ByteBuf directBuffer(int initialCapacity); - - /** - * Allocate a direct {@link ByteBuf} with the given initial capacity and the given - * maximal capacity. - */ - ByteBuf directBuffer(int initialCapacity, int maxCapacity); - - /** - * Allocate a {@link CompositeByteBuf}. - * If it is a direct or heap buffer depends on the actual implementation. - */ - CompositeByteBuf compositeBuffer(); - - /** - * Allocate a {@link CompositeByteBuf} with the given maximum number of components that can be stored in it. - * If it is a direct or heap buffer depends on the actual implementation. - */ - CompositeByteBuf compositeBuffer(int maxNumComponents); - - /** - * Allocate a heap {@link CompositeByteBuf}. - */ - CompositeByteBuf compositeHeapBuffer(); - - /** - * Allocate a heap {@link CompositeByteBuf} with the given maximum number of components that can be stored in it. - */ - CompositeByteBuf compositeHeapBuffer(int maxNumComponents); - - /** - * Allocate a direct {@link CompositeByteBuf}. - */ - CompositeByteBuf compositeDirectBuffer(); - - /** - * Allocate a direct {@link CompositeByteBuf} with the given maximum number of components that can be stored in it. - */ - CompositeByteBuf compositeDirectBuffer(int maxNumComponents); - - /** - * Returns {@code true} if direct {@link ByteBuf}'s are pooled - */ - boolean isDirectBufferPooled(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ByteBufHolder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ByteBufHolder.java deleted file mode 100755 index 3f5d20b0de..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ByteBufHolder.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.buffer; - -import com.ai.cloud.io.netty.util.ReferenceCounted; - -/** - * A packet which is send or receive. - */ -public interface ByteBufHolder extends ReferenceCounted { - - /** - * Return the data which is held by this {@link ByteBufHolder}. - */ - ByteBuf content(); - - /** - * Create a deep copy of this {@link ByteBufHolder}. - */ - ByteBufHolder copy(); - - /** - * Duplicate the {@link ByteBufHolder}. Be aware that this will not automatically call {@link #retain()}. - */ - ByteBufHolder duplicate(); - - @Override - ByteBufHolder retain(); - - @Override - ByteBufHolder retain(int increment); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ByteBufInputStream.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ByteBufInputStream.java deleted file mode 100755 index 065b7fc406..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ByteBufInputStream.java +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.buffer; - -import java.io.DataInput; -import java.io.DataInputStream; -import java.io.EOFException; -import java.io.IOException; -import java.io.InputStream; - -/** - * An {@link InputStream} which reads data from a {@link ByteBuf}. - *

- * A read operation against this stream will occur at the {@code readerIndex} - * of its underlying buffer and the {@code readerIndex} will increase during - * the read operation. Please note that it only reads up to the number of - * readable bytes determined at the moment of construction. Therefore, - * updating {@link ByteBuf#writerIndex()} will not affect the return - * value of {@link #available()}. - *

- * This stream implements {@link DataInput} for your convenience. - * The endianness of the stream is not always big endian but depends on - * the endianness of the underlying buffer. - * - * @see ByteBufOutputStream - */ -public class ByteBufInputStream extends InputStream implements DataInput { - - private final ByteBuf buffer; - private final int startIndex; - private final int endIndex; - - /** - * Creates a new stream which reads data from the specified {@code buffer} - * starting at the current {@code readerIndex} and ending at the current - * {@code writerIndex}. - */ - public ByteBufInputStream(ByteBuf buffer) { - this(buffer, buffer.readableBytes()); - } - - /** - * Creates a new stream which reads data from the specified {@code buffer} - * starting at the current {@code readerIndex} and ending at - * {@code readerIndex + length}. - * - * @throws IndexOutOfBoundsException - * if {@code readerIndex + length} is greater than - * {@code writerIndex} - */ - public ByteBufInputStream(ByteBuf buffer, int length) { - if (buffer == null) { - throw new NullPointerException("buffer"); - } - if (length < 0) { - throw new IllegalArgumentException("length: " + length); - } - if (length > buffer.readableBytes()) { - throw new IndexOutOfBoundsException("Too many bytes to be read - Needs " - + length + ", maximum is " + buffer.readableBytes()); - } - - this.buffer = buffer; - startIndex = buffer.readerIndex(); - endIndex = startIndex + length; - buffer.markReaderIndex(); - } - - /** - * Returns the number of read bytes by this stream so far. - */ - public int readBytes() { - return buffer.readerIndex() - startIndex; - } - - @Override - public int available() throws IOException { - return endIndex - buffer.readerIndex(); - } - - @Override - public void mark(int readlimit) { - buffer.markReaderIndex(); - } - - @Override - public boolean markSupported() { - return true; - } - - @Override - public int read() throws IOException { - if (!buffer.isReadable()) { - return -1; - } - return buffer.readByte() & 0xff; - } - - @Override - public int read(byte[] b, int off, int len) throws IOException { - int available = available(); - if (available == 0) { - return -1; - } - - len = Math.min(available, len); - buffer.readBytes(b, off, len); - return len; - } - - @Override - public void reset() throws IOException { - buffer.resetReaderIndex(); - } - - @Override - public long skip(long n) throws IOException { - if (n > Integer.MAX_VALUE) { - return skipBytes(Integer.MAX_VALUE); - } else { - return skipBytes((int) n); - } - } - - @Override - public boolean readBoolean() throws IOException { - checkAvailable(1); - return read() != 0; - } - - @Override - public byte readByte() throws IOException { - if (!buffer.isReadable()) { - throw new EOFException(); - } - return buffer.readByte(); - } - - @Override - public char readChar() throws IOException { - return (char) readShort(); - } - - @Override - public double readDouble() throws IOException { - return Double.longBitsToDouble(readLong()); - } - - @Override - public float readFloat() throws IOException { - return Float.intBitsToFloat(readInt()); - } - - @Override - public void readFully(byte[] b) throws IOException { - readFully(b, 0, b.length); - } - - @Override - public void readFully(byte[] b, int off, int len) throws IOException { - checkAvailable(len); - buffer.readBytes(b, off, len); - } - - @Override - public int readInt() throws IOException { - checkAvailable(4); - return buffer.readInt(); - } - - private final StringBuilder lineBuf = new StringBuilder(); - - @Override - public String readLine() throws IOException { - lineBuf.setLength(0); - - loop: while (true) { - if (!buffer.isReadable()) { - return lineBuf.length() > 0 ? lineBuf.toString() : null; - } - - int c = buffer.readUnsignedByte(); - switch (c) { - case '\n': - break loop; - - case '\r': - if (buffer.isReadable() && (char) buffer.getUnsignedByte(buffer.readerIndex()) == '\n') { - buffer.skipBytes(1); - } - break loop; - - default: - lineBuf.append((char) c); - } - } - - return lineBuf.toString(); - } - - @Override - public long readLong() throws IOException { - checkAvailable(8); - return buffer.readLong(); - } - - @Override - public short readShort() throws IOException { - checkAvailable(2); - return buffer.readShort(); - } - - @Override - public String readUTF() throws IOException { - return DataInputStream.readUTF(this); - } - - @Override - public int readUnsignedByte() throws IOException { - return readByte() & 0xff; - } - - @Override - public int readUnsignedShort() throws IOException { - return readShort() & 0xffff; - } - - @Override - public int skipBytes(int n) throws IOException { - int nBytes = Math.min(available(), n); - buffer.skipBytes(nBytes); - return nBytes; - } - - private void checkAvailable(int fieldSize) throws IOException { - if (fieldSize < 0) { - throw new IndexOutOfBoundsException("fieldSize cannot be a negative number"); - } - if (fieldSize > available()) { - throw new EOFException("fieldSize is too long! Length is " + fieldSize - + ", but maximum is " + available()); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ByteBufOutputStream.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ByteBufOutputStream.java deleted file mode 100755 index a4b1682174..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ByteBufOutputStream.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.buffer; - -import java.io.DataOutput; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * An {@link OutputStream} which writes data to a {@link ByteBuf}. - *

- * A write operation against this stream will occur at the {@code writerIndex} - * of its underlying buffer and the {@code writerIndex} will increase during - * the write operation. - *

- * This stream implements {@link DataOutput} for your convenience. - * The endianness of the stream is not always big endian but depends on - * the endianness of the underlying buffer. - * - * @see ByteBufInputStream - */ -public class ByteBufOutputStream extends OutputStream implements DataOutput { - - private final ByteBuf buffer; - private final int startIndex; - private final DataOutputStream utf8out = new DataOutputStream(this); - - /** - * Creates a new stream which writes data to the specified {@code buffer}. - */ - public ByteBufOutputStream(ByteBuf buffer) { - if (buffer == null) { - throw new NullPointerException("buffer"); - } - this.buffer = buffer; - startIndex = buffer.writerIndex(); - } - - /** - * Returns the number of written bytes by this stream so far. - */ - public int writtenBytes() { - return buffer.writerIndex() - startIndex; - } - - @Override - public void write(byte[] b, int off, int len) throws IOException { - if (len == 0) { - return; - } - - buffer.writeBytes(b, off, len); - } - - @Override - public void write(byte[] b) throws IOException { - buffer.writeBytes(b); - } - - @Override - public void write(int b) throws IOException { - buffer.writeByte((byte) b); - } - - @Override - public void writeBoolean(boolean v) throws IOException { - write(v? (byte) 1 : (byte) 0); - } - - @Override - public void writeByte(int v) throws IOException { - write(v); - } - - @Override - public void writeBytes(String s) throws IOException { - int len = s.length(); - for (int i = 0; i < len; i ++) { - write((byte) s.charAt(i)); - } - } - - @Override - public void writeChar(int v) throws IOException { - writeShort((short) v); - } - - @Override - public void writeChars(String s) throws IOException { - int len = s.length(); - for (int i = 0 ; i < len ; i ++) { - writeChar(s.charAt(i)); - } - } - - @Override - public void writeDouble(double v) throws IOException { - writeLong(Double.doubleToLongBits(v)); - } - - @Override - public void writeFloat(float v) throws IOException { - writeInt(Float.floatToIntBits(v)); - } - - @Override - public void writeInt(int v) throws IOException { - buffer.writeInt(v); - } - - @Override - public void writeLong(long v) throws IOException { - buffer.writeLong(v); - } - - @Override - public void writeShort(int v) throws IOException { - buffer.writeShort((short) v); - } - - @Override - public void writeUTF(String s) throws IOException { - utf8out.writeUTF(s); - } - - /** - * Returns the buffer where this stream is writing data. - */ - public ByteBuf buffer() { - return buffer; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ByteBufProcessor.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ByteBufProcessor.java deleted file mode 100755 index 7d4efdc188..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ByteBufProcessor.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.buffer; - -public interface ByteBufProcessor { - - /** - * Aborts on a {@code NUL (0x00)}. - */ - ByteBufProcessor FIND_NUL = new ByteBufProcessor() { - @Override - public boolean process(byte value) throws Exception { - return value != 0; - } - }; - - /** - * Aborts on a non-{@code NUL (0x00)}. - */ - ByteBufProcessor FIND_NON_NUL = new ByteBufProcessor() { - @Override - public boolean process(byte value) throws Exception { - return value == 0; - } - }; - - /** - * Aborts on a {@code CR ('\r')}. - */ - ByteBufProcessor FIND_CR = new ByteBufProcessor() { - @Override - public boolean process(byte value) throws Exception { - return value != '\r'; - } - }; - - /** - * Aborts on a non-{@code CR ('\r')}. - */ - ByteBufProcessor FIND_NON_CR = new ByteBufProcessor() { - @Override - public boolean process(byte value) throws Exception { - return value == '\r'; - } - }; - - /** - * Aborts on a {@code LF ('\n')}. - */ - ByteBufProcessor FIND_LF = new ByteBufProcessor() { - @Override - public boolean process(byte value) throws Exception { - return value != '\n'; - } - }; - - /** - * Aborts on a non-{@code LF ('\n')}. - */ - ByteBufProcessor FIND_NON_LF = new ByteBufProcessor() { - @Override - public boolean process(byte value) throws Exception { - return value == '\n'; - } - }; - - /** - * Aborts on a {@code CR ('\r')} or a {@code LF ('\n')}. - */ - ByteBufProcessor FIND_CRLF = new ByteBufProcessor() { - @Override - public boolean process(byte value) throws Exception { - return value != '\r' && value != '\n'; - } - }; - - /** - * Aborts on a byte which is neither a {@code CR ('\r')} nor a {@code LF ('\n')}. - */ - ByteBufProcessor FIND_NON_CRLF = new ByteBufProcessor() { - @Override - public boolean process(byte value) throws Exception { - return value == '\r' || value == '\n'; - } - }; - - /** - * Aborts on a linear whitespace (a ({@code ' '} or a {@code '\t'}). - */ - ByteBufProcessor FIND_LINEAR_WHITESPACE = new ByteBufProcessor() { - @Override - public boolean process(byte value) throws Exception { - return value != ' ' && value != '\t'; - } - }; - - /** - * Aborts on a byte which is not a linear whitespace (neither {@code ' '} nor {@code '\t'}). - */ - ByteBufProcessor FIND_NON_LINEAR_WHITESPACE = new ByteBufProcessor() { - @Override - public boolean process(byte value) throws Exception { - return value == ' ' || value == '\t'; - } - }; - - /** - * @return {@code true} if the processor wants to continue the loop and handle the next byte in the buffer. - * {@code false} if the processor wants to stop handling bytes and abort the loop. - */ - boolean process(byte value) throws Exception; -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ByteBufUtil.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ByteBufUtil.java deleted file mode 100755 index bed9d0849b..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ByteBufUtil.java +++ /dev/null @@ -1,792 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.buffer; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.CharBuffer; -import java.nio.charset.CharacterCodingException; -import java.nio.charset.Charset; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CharsetEncoder; -import java.nio.charset.CoderResult; -import java.util.Locale; - -import com.ai.cloud.io.netty.util.CharsetUtil; -import com.ai.cloud.io.netty.util.Recycler; -import com.ai.cloud.io.netty.util.Recycler.Handle; -import com.ai.cloud.io.netty.util.concurrent.FastThreadLocal; -import com.ai.cloud.io.netty.util.internal.ObjectUtil; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; -import com.ai.cloud.io.netty.util.internal.StringUtil; -import com.ai.cloud.io.netty.util.internal.SystemPropertyUtil; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * A collection of utility methods that is related with handling {@link ByteBuf}, - * such as the generation of hex dump and swapping an integer's byte order. - */ -public final class ByteBufUtil { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(ByteBufUtil.class); - private static final FastThreadLocal CHAR_BUFFERS = new FastThreadLocal() { - @Override - protected CharBuffer initialValue() throws Exception { - return CharBuffer.allocate(1024); - } - }; - - private static final int MAX_CHAR_BUFFER_SIZE; - private static final char[] HEXDUMP_TABLE = new char[256 * 4]; - private static final String NEWLINE = StringUtil.NEWLINE; - private static final String[] BYTE2HEX = new String[256]; - private static final String[] HEXPADDING = new String[16]; - private static final String[] BYTEPADDING = new String[16]; - private static final char[] BYTE2CHAR = new char[256]; - private static final String[] HEXDUMP_ROWPREFIXES = new String[65536 >>> 4]; - - static final ByteBufAllocator DEFAULT_ALLOCATOR; - - private static final int THREAD_LOCAL_BUFFER_SIZE; - - static { - final char[] DIGITS = "0123456789abcdef".toCharArray(); - for (int i = 0; i < 256; i ++) { - HEXDUMP_TABLE[ i << 1 ] = DIGITS[i >>> 4 & 0x0F]; - HEXDUMP_TABLE[(i << 1) + 1] = DIGITS[i & 0x0F]; - } - - int i; - - // Generate the lookup table for byte-to-hex-dump conversion - for (i = 0; i < BYTE2HEX.length; i ++) { - BYTE2HEX[i] = ' ' + StringUtil.byteToHexStringPadded(i); - } - - // Generate the lookup table for hex dump paddings - for (i = 0; i < HEXPADDING.length; i ++) { - int padding = HEXPADDING.length - i; - StringBuilder buf = new StringBuilder(padding * 3); - for (int j = 0; j < padding; j ++) { - buf.append(" "); - } - HEXPADDING[i] = buf.toString(); - } - - // Generate the lookup table for byte dump paddings - for (i = 0; i < BYTEPADDING.length; i ++) { - int padding = BYTEPADDING.length - i; - StringBuilder buf = new StringBuilder(padding); - for (int j = 0; j < padding; j ++) { - buf.append(' '); - } - BYTEPADDING[i] = buf.toString(); - } - - // Generate the lookup table for byte-to-char conversion - for (i = 0; i < BYTE2CHAR.length; i ++) { - if (i <= 0x1f || i >= 0x7f) { - BYTE2CHAR[i] = '.'; - } else { - BYTE2CHAR[i] = (char) i; - } - } - - // Generate the lookup table for the start-offset header in each row (up to 64KiB). - for (i = 0; i < HEXDUMP_ROWPREFIXES.length; i ++) { - StringBuilder buf = new StringBuilder(12); - buf.append(NEWLINE); - buf.append(Long.toHexString(i << 4 & 0xFFFFFFFFL | 0x100000000L)); - buf.setCharAt(buf.length() - 9, '|'); - buf.append('|'); - HEXDUMP_ROWPREFIXES[i] = buf.toString(); - } - - String allocType = SystemPropertyUtil.get("io.netty.allocator.type", "unpooled").toLowerCase(Locale.US).trim(); - ByteBufAllocator alloc; - if ("unpooled".equals(allocType)) { - alloc = UnpooledByteBufAllocator.DEFAULT; - logger.debug("-Dio.netty.allocator.type: {}", allocType); - } else if ("pooled".equals(allocType)) { - alloc = PooledByteBufAllocator.DEFAULT; - logger.debug("-Dio.netty.allocator.type: {}", allocType); - } else { - alloc = UnpooledByteBufAllocator.DEFAULT; - logger.debug("-Dio.netty.allocator.type: unpooled (unknown: {})", allocType); - } - - DEFAULT_ALLOCATOR = alloc; - - THREAD_LOCAL_BUFFER_SIZE = SystemPropertyUtil.getInt("io.netty.threadLocalDirectBufferSize", 64 * 1024); - logger.debug("-Dio.netty.threadLocalDirectBufferSize: {}", THREAD_LOCAL_BUFFER_SIZE); - - MAX_CHAR_BUFFER_SIZE = SystemPropertyUtil.getInt("io.netty.maxThreadLocalCharBufferSize", 16 * 1024); - logger.debug("-Dio.netty.maxThreadLocalCharBufferSize: {}", MAX_CHAR_BUFFER_SIZE); - } - - /** - * Returns a hex dump - * of the specified buffer's readable bytes. - */ - public static String hexDump(ByteBuf buffer) { - return hexDump(buffer, buffer.readerIndex(), buffer.readableBytes()); - } - - /** - * Returns a hex dump - * of the specified buffer's sub-region. - */ - public static String hexDump(ByteBuf buffer, int fromIndex, int length) { - if (length < 0) { - throw new IllegalArgumentException("length: " + length); - } - if (length == 0) { - return ""; - } - - int endIndex = fromIndex + length; - char[] buf = new char[length << 1]; - - int srcIdx = fromIndex; - int dstIdx = 0; - for (; srcIdx < endIndex; srcIdx ++, dstIdx += 2) { - System.arraycopy( - HEXDUMP_TABLE, buffer.getUnsignedByte(srcIdx) << 1, - buf, dstIdx, 2); - } - - return new String(buf); - } - - /** - * Calculates the hash code of the specified buffer. This method is - * useful when implementing a new buffer type. - */ - public static int hashCode(ByteBuf buffer) { - final int aLen = buffer.readableBytes(); - final int intCount = aLen >>> 2; - final int byteCount = aLen & 3; - - int hashCode = 1; - int arrayIndex = buffer.readerIndex(); - if (buffer.order() == ByteOrder.BIG_ENDIAN) { - for (int i = intCount; i > 0; i --) { - hashCode = 31 * hashCode + buffer.getInt(arrayIndex); - arrayIndex += 4; - } - } else { - for (int i = intCount; i > 0; i --) { - hashCode = 31 * hashCode + swapInt(buffer.getInt(arrayIndex)); - arrayIndex += 4; - } - } - - for (int i = byteCount; i > 0; i --) { - hashCode = 31 * hashCode + buffer.getByte(arrayIndex ++); - } - - if (hashCode == 0) { - hashCode = 1; - } - - return hashCode; - } - - /** - * Returns {@code true} if and only if the two specified buffers are - * identical to each other as described in {@code ChannelBuffer#equals(Object)}. - * This method is useful when implementing a new buffer type. - */ - public static boolean equals(ByteBuf bufferA, ByteBuf bufferB) { - final int aLen = bufferA.readableBytes(); - if (aLen != bufferB.readableBytes()) { - return false; - } - - final int longCount = aLen >>> 3; - final int byteCount = aLen & 7; - - int aIndex = bufferA.readerIndex(); - int bIndex = bufferB.readerIndex(); - - if (bufferA.order() == bufferB.order()) { - for (int i = longCount; i > 0; i --) { - if (bufferA.getLong(aIndex) != bufferB.getLong(bIndex)) { - return false; - } - aIndex += 8; - bIndex += 8; - } - } else { - for (int i = longCount; i > 0; i --) { - if (bufferA.getLong(aIndex) != swapLong(bufferB.getLong(bIndex))) { - return false; - } - aIndex += 8; - bIndex += 8; - } - } - - for (int i = byteCount; i > 0; i --) { - if (bufferA.getByte(aIndex) != bufferB.getByte(bIndex)) { - return false; - } - aIndex ++; - bIndex ++; - } - - return true; - } - - /** - * Compares the two specified buffers as described in {@link ByteBuf#compareTo(ByteBuf)}. - * This method is useful when implementing a new buffer type. - */ - public static int compare(ByteBuf bufferA, ByteBuf bufferB) { - final int aLen = bufferA.readableBytes(); - final int bLen = bufferB.readableBytes(); - final int minLength = Math.min(aLen, bLen); - final int uintCount = minLength >>> 2; - final int byteCount = minLength & 3; - - int aIndex = bufferA.readerIndex(); - int bIndex = bufferB.readerIndex(); - - if (bufferA.order() == bufferB.order()) { - for (int i = uintCount; i > 0; i --) { - long va = bufferA.getUnsignedInt(aIndex); - long vb = bufferB.getUnsignedInt(bIndex); - if (va > vb) { - return 1; - } - if (va < vb) { - return -1; - } - aIndex += 4; - bIndex += 4; - } - } else { - for (int i = uintCount; i > 0; i --) { - long va = bufferA.getUnsignedInt(aIndex); - long vb = swapInt(bufferB.getInt(bIndex)) & 0xFFFFFFFFL; - if (va > vb) { - return 1; - } - if (va < vb) { - return -1; - } - aIndex += 4; - bIndex += 4; - } - } - - for (int i = byteCount; i > 0; i --) { - short va = bufferA.getUnsignedByte(aIndex); - short vb = bufferB.getUnsignedByte(bIndex); - if (va > vb) { - return 1; - } - if (va < vb) { - return -1; - } - aIndex ++; - bIndex ++; - } - - return aLen - bLen; - } - - /** - * The default implementation of {@link ByteBuf#indexOf(int, int, byte)}. - * This method is useful when implementing a new buffer type. - */ - public static int indexOf(ByteBuf buffer, int fromIndex, int toIndex, byte value) { - if (fromIndex <= toIndex) { - return firstIndexOf(buffer, fromIndex, toIndex, value); - } else { - return lastIndexOf(buffer, fromIndex, toIndex, value); - } - } - - /** - * Toggles the endianness of the specified 16-bit short integer. - */ - public static short swapShort(short value) { - return Short.reverseBytes(value); - } - - /** - * Toggles the endianness of the specified 24-bit medium integer. - */ - public static int swapMedium(int value) { - int swapped = value << 16 & 0xff0000 | value & 0xff00 | value >>> 16 & 0xff; - if ((swapped & 0x800000) != 0) { - swapped |= 0xff000000; - } - return swapped; - } - - /** - * Toggles the endianness of the specified 32-bit integer. - */ - public static int swapInt(int value) { - return Integer.reverseBytes(value); - } - - /** - * Toggles the endianness of the specified 64-bit long integer. - */ - public static long swapLong(long value) { - return Long.reverseBytes(value); - } - - /** - * Read the given amount of bytes into a new {@link ByteBuf} that is allocated from the {@link ByteBufAllocator}. - */ - public static ByteBuf readBytes(ByteBufAllocator alloc, ByteBuf buffer, int length) { - boolean release = true; - ByteBuf dst = alloc.buffer(length); - try { - buffer.readBytes(dst); - release = false; - return dst; - } finally { - if (release) { - dst.release(); - } - } - } - - private static int firstIndexOf(ByteBuf buffer, int fromIndex, int toIndex, byte value) { - fromIndex = Math.max(fromIndex, 0); - if (fromIndex >= toIndex || buffer.capacity() == 0) { - return -1; - } - - return buffer.forEachByte(fromIndex, toIndex - fromIndex, new IndexOfProcessor(value)); - } - - private static int lastIndexOf(ByteBuf buffer, int fromIndex, int toIndex, byte value) { - fromIndex = Math.min(fromIndex, buffer.capacity()); - if (fromIndex < 0 || buffer.capacity() == 0) { - return -1; - } - - return buffer.forEachByteDesc(toIndex, fromIndex - toIndex, new IndexOfProcessor(value)); - } - - /** - * Encode a {@link CharSequence} in UTF-8 and write - * it to a {@link ByteBuf}. - * - * This method returns the actual number of bytes written. - */ - public static int writeUtf8(ByteBuf buf, CharSequence seq) { - if (buf == null) { - throw new NullPointerException("buf"); - } - if (seq == null) { - throw new NullPointerException("seq"); - } - // UTF-8 uses max. 3 bytes per char, so calculate the worst case. - final int len = seq.length(); - final int maxSize = len * 3; - buf.ensureWritable(maxSize); - - for (;;) { - if (buf instanceof AbstractByteBuf) { - return writeUtf8((AbstractByteBuf) buf, seq, len); - } else if (buf instanceof WrappedByteBuf) { - // Unwrap as the wrapped buffer may be an AbstractByteBuf and so we can use fast-path. - buf = buf.unwrap(); - } else { - byte[] bytes = seq.toString().getBytes(CharsetUtil.UTF_8); - buf.writeBytes(bytes); - return bytes.length; - } - } - } - - // Fast-Path implementation - private static int writeUtf8(AbstractByteBuf buffer, CharSequence seq, int len) { - int oldWriterIndex = buffer.writerIndex; - int writerIndex = oldWriterIndex; - - // We can use the _set methods as these not need to do any index checks and reference checks. - // This is possible as we called ensureWritable(...) before. - for (int i = 0; i < len; i++) { - char c = seq.charAt(i); - if (c < 0x80) { - buffer._setByte(writerIndex++, (byte) c); - } else if (c < 0x800) { - buffer._setByte(writerIndex++, (byte) (0xc0 | (c >> 6))); - buffer._setByte(writerIndex++, (byte) (0x80 | (c & 0x3f))); - } else { - buffer._setByte(writerIndex++, (byte) (0xe0 | (c >> 12))); - buffer._setByte(writerIndex++, (byte) (0x80 | ((c >> 6) & 0x3f))); - buffer._setByte(writerIndex++, (byte) (0x80 | (c & 0x3f))); - } - } - // update the writerIndex without any extra checks for performance reasons - buffer.writerIndex = writerIndex; - return writerIndex - oldWriterIndex; - } - - /** - * Encode a {@link CharSequence} in ASCII and write it - * to a {@link ByteBuf}. - * - * This method returns the actual number of bytes written. - */ - public static int writeAscii(ByteBuf buf, CharSequence seq) { - if (buf == null) { - throw new NullPointerException("buf"); - } - if (seq == null) { - throw new NullPointerException("seq"); - } - // ASCII uses 1 byte per char - final int len = seq.length(); - buf.ensureWritable(len); - for (;;) { - if (buf instanceof AbstractByteBuf) { - writeAscii((AbstractByteBuf) buf, seq, len); - break; - } else if (buf instanceof WrappedByteBuf) { - // Unwrap as the wrapped buffer may be an AbstractByteBuf and so we can use fast-path. - buf = buf.unwrap(); - } else { - buf.writeBytes(seq.toString().getBytes(CharsetUtil.US_ASCII)); - } - } - return len; - } - - // Fast-Path implementation - private static void writeAscii(AbstractByteBuf buffer, CharSequence seq, int len) { - int writerIndex = buffer.writerIndex; - - // We can use the _set methods as these not need to do any index checks and reference checks. - // This is possible as we called ensureWritable(...) before. - for (int i = 0; i < len; i++) { - buffer._setByte(writerIndex++, (byte) seq.charAt(i)); - } - // update the writerIndex without any extra checks for performance reasons - buffer.writerIndex = writerIndex; - } - - /** - * Encode the given {@link CharBuffer} using the given {@link Charset} into a new {@link ByteBuf} which - * is allocated via the {@link ByteBufAllocator}. - */ - public static ByteBuf encodeString(ByteBufAllocator alloc, CharBuffer src, Charset charset) { - return encodeString0(alloc, false, src, charset); - } - - static ByteBuf encodeString0(ByteBufAllocator alloc, boolean enforceHeap, CharBuffer src, Charset charset) { - final CharsetEncoder encoder = CharsetUtil.getEncoder(charset); - int length = (int) ((double) src.remaining() * encoder.maxBytesPerChar()); - boolean release = true; - final ByteBuf dst; - if (enforceHeap) { - dst = alloc.heapBuffer(length); - } else { - dst = alloc.buffer(length); - } - try { - final ByteBuffer dstBuf = dst.internalNioBuffer(0, length); - final int pos = dstBuf.position(); - CoderResult cr = encoder.encode(src, dstBuf, true); - if (!cr.isUnderflow()) { - cr.throwException(); - } - cr = encoder.flush(dstBuf); - if (!cr.isUnderflow()) { - cr.throwException(); - } - dst.writerIndex(dst.writerIndex() + dstBuf.position() - pos); - release = false; - return dst; - } catch (CharacterCodingException x) { - throw new IllegalStateException(x); - } finally { - if (release) { - dst.release(); - } - } - } - - static String decodeString(ByteBuf src, int readerIndex, int len, Charset charset) { - if (len == 0) { - return StringUtil.EMPTY_STRING; - } - final CharsetDecoder decoder = CharsetUtil.getDecoder(charset); - final int maxLength = (int) ((double) len * decoder.maxCharsPerByte()); - CharBuffer dst = CHAR_BUFFERS.get(); - if (dst.length() < maxLength) { - dst = CharBuffer.allocate(maxLength); - if (maxLength <= MAX_CHAR_BUFFER_SIZE) { - CHAR_BUFFERS.set(dst); - } - } else { - dst.clear(); - } - if (src.nioBufferCount() == 1) { - // Use internalNioBuffer(...) to reduce object creation. - decodeString(decoder, src.internalNioBuffer(readerIndex, len), dst); - } else { - // We use a heap buffer as CharsetDecoder is most likely able to use a fast-path if src and dst buffers - // are both backed by a byte array. - ByteBuf buffer = src.alloc().heapBuffer(len); - try { - buffer.writeBytes(src, readerIndex, len); - // Use internalNioBuffer(...) to reduce object creation. - decodeString(decoder, buffer.internalNioBuffer(readerIndex, len), dst); - } finally { - // Release the temporary buffer again. - buffer.release(); - } - } - return dst.flip().toString(); - } - - private static void decodeString(CharsetDecoder decoder, ByteBuffer src, CharBuffer dst) { - try { - CoderResult cr = decoder.decode(src, dst, true); - if (!cr.isUnderflow()) { - cr.throwException(); - } - cr = decoder.flush(dst); - if (!cr.isUnderflow()) { - cr.throwException(); - } - } catch (CharacterCodingException x) { - throw new IllegalStateException(x); - } - } - - /** - * Returns a multi-line hexadecimal dump of the specified {@link ByteBuf} that is easy to read by humans. - */ - public static String prettyHexDump(ByteBuf buffer) { - return prettyHexDump(buffer, buffer.readerIndex(), buffer.readableBytes()); - } - - /** - * Returns a multi-line hexadecimal dump of the specified {@link ByteBuf} that is easy to read by humans, - * starting at the given {@code offset} using the given {@code length}. - */ - public static String prettyHexDump(ByteBuf buffer, int offset, int length) { - if (length == 0) { - return StringUtil.EMPTY_STRING; - } else { - int rows = length / 16 + (length % 15 == 0? 0 : 1) + 4; - StringBuilder buf = new StringBuilder(rows * 80); - appendPrettyHexDump(buf, buffer, offset, length); - return buf.toString(); - } - } - - /** - * Appends the prettified multi-line hexadecimal dump of the specified {@link ByteBuf} to the specified - * {@link StringBuilder} that is easy to read by humans. - */ - public static void appendPrettyHexDump(StringBuilder dump, ByteBuf buf) { - appendPrettyHexDump(dump, buf, buf.readerIndex(), buf.readableBytes()); - } - - /** - * Appends the prettified multi-line hexadecimal dump of the specified {@link ByteBuf} to the specified - * {@link StringBuilder} that is easy to read by humans, starting at the given {@code offset} using - * the given {@code length}. - */ - public static void appendPrettyHexDump(StringBuilder dump, ByteBuf buf, int offset, int length) { - if (offset < 0 || length > ObjectUtil.checkNotNull(buf, "buf").capacity() - offset) { - throw new IndexOutOfBoundsException( - "expected: " + "0 <= offset(" + offset + ") <= offset + length(" + length - + ") <= " + "buf.capacity(" + buf.capacity() + ')'); - } - if (length == 0) { - return; - } - dump.append( - " +-------------------------------------------------+" + - NEWLINE + " | 0 1 2 3 4 5 6 7 8 9 a b c d e f |" + - NEWLINE + "+--------+-------------------------------------------------+----------------+"); - - final int startIndex = offset; - final int fullRows = length >>> 4; - final int remainder = length & 0xF; - - // Dump the rows which have 16 bytes. - for (int row = 0; row < fullRows; row ++) { - int rowStartIndex = (row << 4) + startIndex; - - // Per-row prefix. - appendHexDumpRowPrefix(dump, row, rowStartIndex); - - // Hex dump - int rowEndIndex = rowStartIndex + 16; - for (int j = rowStartIndex; j < rowEndIndex; j ++) { - dump.append(BYTE2HEX[buf.getUnsignedByte(j)]); - } - dump.append(" |"); - - // ASCII dump - for (int j = rowStartIndex; j < rowEndIndex; j ++) { - dump.append(BYTE2CHAR[buf.getUnsignedByte(j)]); - } - dump.append('|'); - } - - // Dump the last row which has less than 16 bytes. - if (remainder != 0) { - int rowStartIndex = (fullRows << 4) + startIndex; - appendHexDumpRowPrefix(dump, fullRows, rowStartIndex); - - // Hex dump - int rowEndIndex = rowStartIndex + remainder; - for (int j = rowStartIndex; j < rowEndIndex; j ++) { - dump.append(BYTE2HEX[buf.getUnsignedByte(j)]); - } - dump.append(HEXPADDING[remainder]); - dump.append(" |"); - - // Ascii dump - for (int j = rowStartIndex; j < rowEndIndex; j ++) { - dump.append(BYTE2CHAR[buf.getUnsignedByte(j)]); - } - dump.append(BYTEPADDING[remainder]); - dump.append('|'); - } - - dump.append(NEWLINE + "+--------+-------------------------------------------------+----------------+"); - } - - /** - * Appends the prefix of each hex dump row. Uses the look-up table for the buffer <= 64 KiB. - */ - private static void appendHexDumpRowPrefix(StringBuilder dump, int row, int rowStartIndex) { - if (row < HEXDUMP_ROWPREFIXES.length) { - dump.append(HEXDUMP_ROWPREFIXES[row]); - } else { - dump.append(NEWLINE); - dump.append(Long.toHexString(rowStartIndex & 0xFFFFFFFFL | 0x100000000L)); - dump.setCharAt(dump.length() - 9, '|'); - dump.append('|'); - } - } - - /** - * Returns a cached thread-local direct buffer, if available. - * - * @return a cached thread-local direct buffer, if available. {@code null} otherwise. - */ - public static ByteBuf threadLocalDirectBuffer() { - if (THREAD_LOCAL_BUFFER_SIZE <= 0) { - return null; - } - - if (PlatformDependent.hasUnsafe()) { - return ThreadLocalUnsafeDirectByteBuf.newInstance(); - } else { - return ThreadLocalDirectByteBuf.newInstance(); - } - } - - static final class ThreadLocalUnsafeDirectByteBuf extends UnpooledUnsafeDirectByteBuf { - - private static final Recycler RECYCLER = - new Recycler() { - @Override - protected ThreadLocalUnsafeDirectByteBuf newObject(Handle handle) { - return new ThreadLocalUnsafeDirectByteBuf(handle); - } - }; - - static ThreadLocalUnsafeDirectByteBuf newInstance() { - ThreadLocalUnsafeDirectByteBuf buf = RECYCLER.get(); - buf.setRefCnt(1); - return buf; - } - - private final Handle handle; - - private ThreadLocalUnsafeDirectByteBuf(Handle handle) { - super(UnpooledByteBufAllocator.DEFAULT, 256, Integer.MAX_VALUE); - this.handle = handle; - } - - @Override - protected void deallocate() { - if (capacity() > THREAD_LOCAL_BUFFER_SIZE) { - super.deallocate(); - } else { - clear(); - RECYCLER.recycle(this, handle); - } - } - } - - static final class ThreadLocalDirectByteBuf extends UnpooledDirectByteBuf { - - private static final Recycler RECYCLER = new Recycler() { - @Override - protected ThreadLocalDirectByteBuf newObject(Handle handle) { - return new ThreadLocalDirectByteBuf(handle); - } - }; - - static ThreadLocalDirectByteBuf newInstance() { - ThreadLocalDirectByteBuf buf = RECYCLER.get(); - buf.setRefCnt(1); - return buf; - } - - private final Handle handle; - - private ThreadLocalDirectByteBuf(Handle handle) { - super(UnpooledByteBufAllocator.DEFAULT, 256, Integer.MAX_VALUE); - this.handle = handle; - } - - @Override - protected void deallocate() { - if (capacity() > THREAD_LOCAL_BUFFER_SIZE) { - super.deallocate(); - } else { - clear(); - RECYCLER.recycle(this, handle); - } - } - } - - private static class IndexOfProcessor implements ByteBufProcessor { - private final byte byteToFind; - - public IndexOfProcessor(byte byteToFind) { - this.byteToFind = byteToFind; - } - - @Override - public boolean process(byte value) { - return value != byteToFind; - } - } - - private ByteBufUtil() { } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/CompositeByteBuf.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/CompositeByteBuf.java deleted file mode 100755 index 6d7d3838c7..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/CompositeByteBuf.java +++ /dev/null @@ -1,1667 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.ConcurrentModificationException; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; -import java.util.NoSuchElementException; - -import com.ai.cloud.io.netty.util.ResourceLeak; -import com.ai.cloud.io.netty.util.internal.EmptyArrays; - -/** - * A virtual buffer which shows multiple buffers as a single merged buffer. It is recommended to use - * {@link ByteBufAllocator#compositeBuffer()} or {@link Unpooled#wrappedBuffer(ByteBuf...)} instead of calling the - * constructor explicitly. - */ -public class CompositeByteBuf extends AbstractReferenceCountedByteBuf implements Iterable { - - private static final ByteBuffer EMPTY_NIO_BUFFER = Unpooled.EMPTY_BUFFER.nioBuffer(); - private static final Iterator EMPTY_ITERATOR = Collections.emptyList().iterator(); - - private final ResourceLeak leak; - private final ByteBufAllocator alloc; - private final boolean direct; - private final List components = new ArrayList(); - private final int maxNumComponents; - - private boolean freed; - - public CompositeByteBuf(ByteBufAllocator alloc, boolean direct, int maxNumComponents) { - super(Integer.MAX_VALUE); - if (alloc == null) { - throw new NullPointerException("alloc"); - } - this.alloc = alloc; - this.direct = direct; - this.maxNumComponents = maxNumComponents; - leak = leakDetector.open(this); - } - - public CompositeByteBuf(ByteBufAllocator alloc, boolean direct, int maxNumComponents, ByteBuf... buffers) { - super(Integer.MAX_VALUE); - if (alloc == null) { - throw new NullPointerException("alloc"); - } - if (maxNumComponents < 2) { - throw new IllegalArgumentException( - "maxNumComponents: " + maxNumComponents + " (expected: >= 2)"); - } - - this.alloc = alloc; - this.direct = direct; - this.maxNumComponents = maxNumComponents; - - addComponents0(0, buffers); - consolidateIfNeeded(); - setIndex(0, capacity()); - leak = leakDetector.open(this); - } - - public CompositeByteBuf( - ByteBufAllocator alloc, boolean direct, int maxNumComponents, Iterable buffers) { - super(Integer.MAX_VALUE); - if (alloc == null) { - throw new NullPointerException("alloc"); - } - if (maxNumComponents < 2) { - throw new IllegalArgumentException( - "maxNumComponents: " + maxNumComponents + " (expected: >= 2)"); - } - - this.alloc = alloc; - this.direct = direct; - this.maxNumComponents = maxNumComponents; - addComponents0(0, buffers); - consolidateIfNeeded(); - setIndex(0, capacity()); - leak = leakDetector.open(this); - } - - /** - * Add the given {@link ByteBuf}. - * - * Be aware that this method does not increase the {@code writerIndex} of the {@link CompositeByteBuf}. - * If you need to have it increased you need to handle it by your own. - * - * @param buffer the {@link ByteBuf} to add - */ - public CompositeByteBuf addComponent(ByteBuf buffer) { - addComponent0(components.size(), buffer); - consolidateIfNeeded(); - return this; - } - - /** - * Add the given {@link ByteBuf}s. - * - * Be aware that this method does not increase the {@code writerIndex} of the {@link CompositeByteBuf}. - * If you need to have it increased you need to handle it by your own. - * - * @param buffers the {@link ByteBuf}s to add - */ - public CompositeByteBuf addComponents(ByteBuf... buffers) { - addComponents0(components.size(), buffers); - consolidateIfNeeded(); - return this; - } - - /** - * Add the given {@link ByteBuf}s. - * - * Be aware that this method does not increase the {@code writerIndex} of the {@link CompositeByteBuf}. - * If you need to have it increased you need to handle it by your own. - * - * @param buffers the {@link ByteBuf}s to add - */ - public CompositeByteBuf addComponents(Iterable buffers) { - addComponents0(components.size(), buffers); - consolidateIfNeeded(); - return this; - } - - /** - * Add the given {@link ByteBuf} on the specific index. - * - * Be aware that this method does not increase the {@code writerIndex} of the {@link CompositeByteBuf}. - * If you need to have it increased you need to handle it by your own. - * - * @param cIndex the index on which the {@link ByteBuf} will be added - * @param buffer the {@link ByteBuf} to add - */ - public CompositeByteBuf addComponent(int cIndex, ByteBuf buffer) { - addComponent0(cIndex, buffer); - consolidateIfNeeded(); - return this; - } - - private int addComponent0(int cIndex, ByteBuf buffer) { - checkComponentIndex(cIndex); - - if (buffer == null) { - throw new NullPointerException("buffer"); - } - - int readableBytes = buffer.readableBytes(); - - // No need to consolidate - just add a component to the list. - Component c = new Component(buffer.order(ByteOrder.BIG_ENDIAN).slice()); - if (cIndex == components.size()) { - components.add(c); - if (cIndex == 0) { - c.endOffset = readableBytes; - } else { - Component prev = components.get(cIndex - 1); - c.offset = prev.endOffset; - c.endOffset = c.offset + readableBytes; - } - } else { - components.add(cIndex, c); - if (readableBytes != 0) { - updateComponentOffsets(cIndex); - } - } - return cIndex; - } - - /** - * Add the given {@link ByteBuf}s on the specific index - * - * Be aware that this method does not increase the {@code writerIndex} of the {@link CompositeByteBuf}. - * If you need to have it increased you need to handle it by your own. - * - * @param cIndex the index on which the {@link ByteBuf} will be added. - * @param buffers the {@link ByteBuf}s to add - */ - public CompositeByteBuf addComponents(int cIndex, ByteBuf... buffers) { - addComponents0(cIndex, buffers); - consolidateIfNeeded(); - return this; - } - - private int addComponents0(int cIndex, ByteBuf... buffers) { - checkComponentIndex(cIndex); - - if (buffers == null) { - throw new NullPointerException("buffers"); - } - - // No need for consolidation - for (ByteBuf b: buffers) { - if (b == null) { - break; - } - cIndex = addComponent0(cIndex, b) + 1; - int size = components.size(); - if (cIndex > size) { - cIndex = size; - } - } - return cIndex; - } - - /** - * Add the given {@link ByteBuf}s on the specific index - * - * Be aware that this method does not increase the {@code writerIndex} of the {@link CompositeByteBuf}. - * If you need to have it increased you need to handle it by your own. - * - * @param cIndex the index on which the {@link ByteBuf} will be added. - * @param buffers the {@link ByteBuf}s to add - */ - public CompositeByteBuf addComponents(int cIndex, Iterable buffers) { - addComponents0(cIndex, buffers); - consolidateIfNeeded(); - return this; - } - - private int addComponents0(int cIndex, Iterable buffers) { - if (buffers == null) { - throw new NullPointerException("buffers"); - } - - if (buffers instanceof ByteBuf) { - // If buffers also implements ByteBuf (e.g. CompositeByteBuf), it has to go to addComponent(ByteBuf). - return addComponent0(cIndex, (ByteBuf) buffers); - } - - if (!(buffers instanceof Collection)) { - List list = new ArrayList(); - for (ByteBuf b: buffers) { - list.add(b); - } - buffers = list; - } - - Collection col = (Collection) buffers; - return addComponents0(cIndex, col.toArray(new ByteBuf[col.size()])); - } - - /** - * This should only be called as last operation from a method as this may adjust the underlying - * array of components and so affect the index etc. - */ - private void consolidateIfNeeded() { - // Consolidate if the number of components will exceed the allowed maximum by the current - // operation. - final int numComponents = components.size(); - if (numComponents > maxNumComponents) { - final int capacity = components.get(numComponents - 1).endOffset; - - ByteBuf consolidated = allocBuffer(capacity); - - // We're not using foreach to avoid creating an iterator. - for (int i = 0; i < numComponents; i ++) { - Component c = components.get(i); - ByteBuf b = c.buf; - consolidated.writeBytes(b); - c.freeIfNecessary(); - } - Component c = new Component(consolidated); - c.endOffset = c.length; - components.clear(); - components.add(c); - } - } - - private void checkComponentIndex(int cIndex) { - ensureAccessible(); - if (cIndex < 0 || cIndex > components.size()) { - throw new IndexOutOfBoundsException(String.format( - "cIndex: %d (expected: >= 0 && <= numComponents(%d))", - cIndex, components.size())); - } - } - - private void checkComponentIndex(int cIndex, int numComponents) { - ensureAccessible(); - if (cIndex < 0 || cIndex + numComponents > components.size()) { - throw new IndexOutOfBoundsException(String.format( - "cIndex: %d, numComponents: %d " + - "(expected: cIndex >= 0 && cIndex + numComponents <= totalNumComponents(%d))", - cIndex, numComponents, components.size())); - } - } - - private void updateComponentOffsets(int cIndex) { - int size = components.size(); - if (size <= cIndex) { - return; - } - - Component c = components.get(cIndex); - if (cIndex == 0) { - c.offset = 0; - c.endOffset = c.length; - cIndex ++; - } - - for (int i = cIndex; i < size; i ++) { - Component prev = components.get(i - 1); - Component cur = components.get(i); - cur.offset = prev.endOffset; - cur.endOffset = cur.offset + cur.length; - } - } - - /** - * Remove the {@link ByteBuf} from the given index. - * - * @param cIndex the index on from which the {@link ByteBuf} will be remove - */ - public CompositeByteBuf removeComponent(int cIndex) { - checkComponentIndex(cIndex); - Component comp = components.remove(cIndex); - comp.freeIfNecessary(); - if (comp.length > 0) { - // Only need to call updateComponentOffsets if the length was > 0 - updateComponentOffsets(cIndex); - } - return this; - } - - /** - * Remove the number of {@link ByteBuf}s starting from the given index. - * - * @param cIndex the index on which the {@link ByteBuf}s will be started to removed - * @param numComponents the number of components to remove - */ - public CompositeByteBuf removeComponents(int cIndex, int numComponents) { - checkComponentIndex(cIndex, numComponents); - - if (numComponents == 0) { - return this; - } - List toRemove = components.subList(cIndex, cIndex + numComponents); - boolean needsUpdate = false; - for (Component c: toRemove) { - if (c.length > 0) { - needsUpdate = true; - } - c.freeIfNecessary(); - } - toRemove.clear(); - - if (needsUpdate) { - // Only need to call updateComponentOffsets if the length was > 0 - updateComponentOffsets(cIndex); - } - return this; - } - - @Override - public Iterator iterator() { - ensureAccessible(); - if (components.isEmpty()) { - return EMPTY_ITERATOR; - } - return new CompositeByteBufIterator(); - } - - /** - * Same with {@link #slice(int, int)} except that this method returns a list. - */ - public List decompose(int offset, int length) { - checkIndex(offset, length); - if (length == 0) { - return Collections.emptyList(); - } - - int componentId = toComponentIndex(offset); - List slice = new ArrayList(components.size()); - - // The first component - Component firstC = components.get(componentId); - ByteBuf first = firstC.buf.duplicate(); - first.readerIndex(offset - firstC.offset); - - ByteBuf buf = first; - int bytesToSlice = length; - do { - int readableBytes = buf.readableBytes(); - if (bytesToSlice <= readableBytes) { - // Last component - buf.writerIndex(buf.readerIndex() + bytesToSlice); - slice.add(buf); - break; - } else { - // Not the last component - slice.add(buf); - bytesToSlice -= readableBytes; - componentId ++; - - // Fetch the next component. - buf = components.get(componentId).buf.duplicate(); - } - } while (bytesToSlice > 0); - - // Slice all components because only readable bytes are interesting. - for (int i = 0; i < slice.size(); i ++) { - slice.set(i, slice.get(i).slice()); - } - - return slice; - } - - @Override - public boolean isDirect() { - int size = components.size(); - if (size == 0) { - return false; - } - for (int i = 0; i < size; i++) { - if (!components.get(i).buf.isDirect()) { - return false; - } - } - return true; - } - - @Override - public boolean hasArray() { - switch (components.size()) { - case 0: - return true; - case 1: - return components.get(0).buf.hasArray(); - default: - return false; - } - } - - @Override - public byte[] array() { - switch (components.size()) { - case 0: - return EmptyArrays.EMPTY_BYTES; - case 1: - return components.get(0).buf.array(); - default: - throw new UnsupportedOperationException(); - } - } - - @Override - public int arrayOffset() { - switch (components.size()) { - case 0: - return 0; - case 1: - return components.get(0).buf.arrayOffset(); - default: - throw new UnsupportedOperationException(); - } - } - - @Override - public boolean hasMemoryAddress() { - switch (components.size()) { - case 0: - return Unpooled.EMPTY_BUFFER.hasMemoryAddress(); - case 1: - return components.get(0).buf.hasMemoryAddress(); - default: - return false; - } - } - - @Override - public long memoryAddress() { - switch (components.size()) { - case 0: - return Unpooled.EMPTY_BUFFER.memoryAddress(); - case 1: - return components.get(0).buf.memoryAddress(); - default: - throw new UnsupportedOperationException(); - } - } - - @Override - public int capacity() { - final int numComponents = components.size(); - if (numComponents == 0) { - return 0; - } - return components.get(numComponents - 1).endOffset; - } - - @Override - public CompositeByteBuf capacity(int newCapacity) { - ensureAccessible(); - if (newCapacity < 0 || newCapacity > maxCapacity()) { - throw new IllegalArgumentException("newCapacity: " + newCapacity); - } - - int oldCapacity = capacity(); - if (newCapacity > oldCapacity) { - final int paddingLength = newCapacity - oldCapacity; - ByteBuf padding; - int nComponents = components.size(); - if (nComponents < maxNumComponents) { - padding = allocBuffer(paddingLength); - padding.setIndex(0, paddingLength); - addComponent0(components.size(), padding); - } else { - padding = allocBuffer(paddingLength); - padding.setIndex(0, paddingLength); - // FIXME: No need to create a padding buffer and consolidate. - // Just create a big single buffer and put the current content there. - addComponent0(components.size(), padding); - consolidateIfNeeded(); - } - } else if (newCapacity < oldCapacity) { - int bytesToTrim = oldCapacity - newCapacity; - for (ListIterator i = components.listIterator(components.size()); i.hasPrevious();) { - Component c = i.previous(); - if (bytesToTrim >= c.length) { - bytesToTrim -= c.length; - i.remove(); - continue; - } - - // Replace the last component with the trimmed slice. - Component newC = new Component(c.buf.slice(0, c.length - bytesToTrim)); - newC.offset = c.offset; - newC.endOffset = newC.offset + newC.length; - i.set(newC); - break; - } - - if (readerIndex() > newCapacity) { - setIndex(newCapacity, newCapacity); - } else if (writerIndex() > newCapacity) { - writerIndex(newCapacity); - } - } - return this; - } - - @Override - public ByteBufAllocator alloc() { - return alloc; - } - - @Override - public ByteOrder order() { - return ByteOrder.BIG_ENDIAN; - } - - /** - * Return the current number of {@link ByteBuf}'s that are composed in this instance - */ - public int numComponents() { - return components.size(); - } - - /** - * Return the max number of {@link ByteBuf}'s that are composed in this instance - */ - public int maxNumComponents() { - return maxNumComponents; - } - - /** - * Return the index for the given offset - */ - public int toComponentIndex(int offset) { - checkIndex(offset); - - for (int low = 0, high = components.size(); low <= high;) { - int mid = low + high >>> 1; - Component c = components.get(mid); - if (offset >= c.endOffset) { - low = mid + 1; - } else if (offset < c.offset) { - high = mid - 1; - } else { - return mid; - } - } - - throw new Error("should not reach here"); - } - - public int toByteIndex(int cIndex) { - checkComponentIndex(cIndex); - return components.get(cIndex).offset; - } - - @Override - public byte getByte(int index) { - return _getByte(index); - } - - @Override - protected byte _getByte(int index) { - Component c = findComponent(index); - return c.buf.getByte(index - c.offset); - } - - @Override - protected short _getShort(int index) { - Component c = findComponent(index); - if (index + 2 <= c.endOffset) { - return c.buf.getShort(index - c.offset); - } else if (order() == ByteOrder.BIG_ENDIAN) { - return (short) ((_getByte(index) & 0xff) << 8 | _getByte(index + 1) & 0xff); - } else { - return (short) (_getByte(index) & 0xff | (_getByte(index + 1) & 0xff) << 8); - } - } - - @Override - protected int _getUnsignedMedium(int index) { - Component c = findComponent(index); - if (index + 3 <= c.endOffset) { - return c.buf.getUnsignedMedium(index - c.offset); - } else if (order() == ByteOrder.BIG_ENDIAN) { - return (_getShort(index) & 0xffff) << 8 | _getByte(index + 2) & 0xff; - } else { - return _getShort(index) & 0xFFFF | (_getByte(index + 2) & 0xFF) << 16; - } - } - - @Override - protected int _getInt(int index) { - Component c = findComponent(index); - if (index + 4 <= c.endOffset) { - return c.buf.getInt(index - c.offset); - } else if (order() == ByteOrder.BIG_ENDIAN) { - return (_getShort(index) & 0xffff) << 16 | _getShort(index + 2) & 0xffff; - } else { - return _getShort(index) & 0xFFFF | (_getShort(index + 2) & 0xFFFF) << 16; - } - } - - @Override - protected long _getLong(int index) { - Component c = findComponent(index); - if (index + 8 <= c.endOffset) { - return c.buf.getLong(index - c.offset); - } else if (order() == ByteOrder.BIG_ENDIAN) { - return (_getInt(index) & 0xffffffffL) << 32 | _getInt(index + 4) & 0xffffffffL; - } else { - return _getInt(index) & 0xFFFFFFFFL | (_getInt(index + 4) & 0xFFFFFFFFL) << 32; - } - } - - @Override - public CompositeByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - checkDstIndex(index, length, dstIndex, dst.length); - if (length == 0) { - return this; - } - - int i = toComponentIndex(index); - while (length > 0) { - Component c = components.get(i); - ByteBuf s = c.buf; - int adjustment = c.offset; - int localLength = Math.min(length, s.capacity() - (index - adjustment)); - s.getBytes(index - adjustment, dst, dstIndex, localLength); - index += localLength; - dstIndex += localLength; - length -= localLength; - i ++; - } - return this; - } - - @Override - public CompositeByteBuf getBytes(int index, ByteBuffer dst) { - int limit = dst.limit(); - int length = dst.remaining(); - - checkIndex(index, length); - if (length == 0) { - return this; - } - - int i = toComponentIndex(index); - try { - while (length > 0) { - Component c = components.get(i); - ByteBuf s = c.buf; - int adjustment = c.offset; - int localLength = Math.min(length, s.capacity() - (index - adjustment)); - dst.limit(dst.position() + localLength); - s.getBytes(index - adjustment, dst); - index += localLength; - length -= localLength; - i ++; - } - } finally { - dst.limit(limit); - } - return this; - } - - @Override - public CompositeByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - checkDstIndex(index, length, dstIndex, dst.capacity()); - if (length == 0) { - return this; - } - - int i = toComponentIndex(index); - while (length > 0) { - Component c = components.get(i); - ByteBuf s = c.buf; - int adjustment = c.offset; - int localLength = Math.min(length, s.capacity() - (index - adjustment)); - s.getBytes(index - adjustment, dst, dstIndex, localLength); - index += localLength; - dstIndex += localLength; - length -= localLength; - i ++; - } - return this; - } - - @Override - public int getBytes(int index, GatheringByteChannel out, int length) - throws IOException { - int count = nioBufferCount(); - if (count == 1) { - return out.write(internalNioBuffer(index, length)); - } else { - long writtenBytes = out.write(nioBuffers(index, length)); - if (writtenBytes > Integer.MAX_VALUE) { - return Integer.MAX_VALUE; - } else { - return (int) writtenBytes; - } - } - } - - @Override - public CompositeByteBuf getBytes(int index, OutputStream out, int length) throws IOException { - checkIndex(index, length); - if (length == 0) { - return this; - } - - int i = toComponentIndex(index); - while (length > 0) { - Component c = components.get(i); - ByteBuf s = c.buf; - int adjustment = c.offset; - int localLength = Math.min(length, s.capacity() - (index - adjustment)); - s.getBytes(index - adjustment, out, localLength); - index += localLength; - length -= localLength; - i ++; - } - return this; - } - - @Override - public CompositeByteBuf setByte(int index, int value) { - Component c = findComponent(index); - c.buf.setByte(index - c.offset, value); - return this; - } - - @Override - protected void _setByte(int index, int value) { - setByte(index, value); - } - - @Override - public CompositeByteBuf setShort(int index, int value) { - return (CompositeByteBuf) super.setShort(index, value); - } - - @Override - protected void _setShort(int index, int value) { - Component c = findComponent(index); - if (index + 2 <= c.endOffset) { - c.buf.setShort(index - c.offset, value); - } else if (order() == ByteOrder.BIG_ENDIAN) { - _setByte(index, (byte) (value >>> 8)); - _setByte(index + 1, (byte) value); - } else { - _setByte(index, (byte) value); - _setByte(index + 1, (byte) (value >>> 8)); - } - } - - @Override - public CompositeByteBuf setMedium(int index, int value) { - return (CompositeByteBuf) super.setMedium(index, value); - } - - @Override - protected void _setMedium(int index, int value) { - Component c = findComponent(index); - if (index + 3 <= c.endOffset) { - c.buf.setMedium(index - c.offset, value); - } else if (order() == ByteOrder.BIG_ENDIAN) { - _setShort(index, (short) (value >> 8)); - _setByte(index + 2, (byte) value); - } else { - _setShort(index, (short) value); - _setByte(index + 2, (byte) (value >>> 16)); - } - } - - @Override - public CompositeByteBuf setInt(int index, int value) { - return (CompositeByteBuf) super.setInt(index, value); - } - - @Override - protected void _setInt(int index, int value) { - Component c = findComponent(index); - if (index + 4 <= c.endOffset) { - c.buf.setInt(index - c.offset, value); - } else if (order() == ByteOrder.BIG_ENDIAN) { - _setShort(index, (short) (value >>> 16)); - _setShort(index + 2, (short) value); - } else { - _setShort(index, (short) value); - _setShort(index + 2, (short) (value >>> 16)); - } - } - - @Override - public CompositeByteBuf setLong(int index, long value) { - return (CompositeByteBuf) super.setLong(index, value); - } - - @Override - protected void _setLong(int index, long value) { - Component c = findComponent(index); - if (index + 8 <= c.endOffset) { - c.buf.setLong(index - c.offset, value); - } else if (order() == ByteOrder.BIG_ENDIAN) { - _setInt(index, (int) (value >>> 32)); - _setInt(index + 4, (int) value); - } else { - _setInt(index, (int) value); - _setInt(index + 4, (int) (value >>> 32)); - } - } - - @Override - public CompositeByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { - checkSrcIndex(index, length, srcIndex, src.length); - if (length == 0) { - return this; - } - - int i = toComponentIndex(index); - while (length > 0) { - Component c = components.get(i); - ByteBuf s = c.buf; - int adjustment = c.offset; - int localLength = Math.min(length, s.capacity() - (index - adjustment)); - s.setBytes(index - adjustment, src, srcIndex, localLength); - index += localLength; - srcIndex += localLength; - length -= localLength; - i ++; - } - return this; - } - - @Override - public CompositeByteBuf setBytes(int index, ByteBuffer src) { - int limit = src.limit(); - int length = src.remaining(); - - checkIndex(index, length); - if (length == 0) { - return this; - } - - int i = toComponentIndex(index); - try { - while (length > 0) { - Component c = components.get(i); - ByteBuf s = c.buf; - int adjustment = c.offset; - int localLength = Math.min(length, s.capacity() - (index - adjustment)); - src.limit(src.position() + localLength); - s.setBytes(index - adjustment, src); - index += localLength; - length -= localLength; - i ++; - } - } finally { - src.limit(limit); - } - return this; - } - - @Override - public CompositeByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { - checkSrcIndex(index, length, srcIndex, src.capacity()); - if (length == 0) { - return this; - } - - int i = toComponentIndex(index); - while (length > 0) { - Component c = components.get(i); - ByteBuf s = c.buf; - int adjustment = c.offset; - int localLength = Math.min(length, s.capacity() - (index - adjustment)); - s.setBytes(index - adjustment, src, srcIndex, localLength); - index += localLength; - srcIndex += localLength; - length -= localLength; - i ++; - } - return this; - } - - @Override - public int setBytes(int index, InputStream in, int length) throws IOException { - checkIndex(index, length); - if (length == 0) { - return in.read(EmptyArrays.EMPTY_BYTES); - } - - int i = toComponentIndex(index); - int readBytes = 0; - - do { - Component c = components.get(i); - ByteBuf s = c.buf; - int adjustment = c.offset; - int localLength = Math.min(length, s.capacity() - (index - adjustment)); - int localReadBytes = s.setBytes(index - adjustment, in, localLength); - if (localReadBytes < 0) { - if (readBytes == 0) { - return -1; - } else { - break; - } - } - - if (localReadBytes == localLength) { - index += localLength; - length -= localLength; - readBytes += localLength; - i ++; - } else { - index += localReadBytes; - length -= localReadBytes; - readBytes += localReadBytes; - } - } while (length > 0); - - return readBytes; - } - - @Override - public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException { - checkIndex(index, length); - if (length == 0) { - return in.read(EMPTY_NIO_BUFFER); - } - - int i = toComponentIndex(index); - int readBytes = 0; - do { - Component c = components.get(i); - ByteBuf s = c.buf; - int adjustment = c.offset; - int localLength = Math.min(length, s.capacity() - (index - adjustment)); - int localReadBytes = s.setBytes(index - adjustment, in, localLength); - - if (localReadBytes == 0) { - break; - } - - if (localReadBytes < 0) { - if (readBytes == 0) { - return -1; - } else { - break; - } - } - - if (localReadBytes == localLength) { - index += localLength; - length -= localLength; - readBytes += localLength; - i ++; - } else { - index += localReadBytes; - length -= localReadBytes; - readBytes += localReadBytes; - } - } while (length > 0); - - return readBytes; - } - - @Override - public ByteBuf copy(int index, int length) { - checkIndex(index, length); - ByteBuf dst = Unpooled.buffer(length); - if (length != 0) { - copyTo(index, length, toComponentIndex(index), dst); - } - return dst; - } - - private void copyTo(int index, int length, int componentId, ByteBuf dst) { - int dstIndex = 0; - int i = componentId; - - while (length > 0) { - Component c = components.get(i); - ByteBuf s = c.buf; - int adjustment = c.offset; - int localLength = Math.min(length, s.capacity() - (index - adjustment)); - s.getBytes(index - adjustment, dst, dstIndex, localLength); - index += localLength; - dstIndex += localLength; - length -= localLength; - i ++; - } - - dst.writerIndex(dst.capacity()); - } - - /** - * Return the {@link ByteBuf} on the specified index - * - * @param cIndex the index for which the {@link ByteBuf} should be returned - * @return buf the {@link ByteBuf} on the specified index - */ - public ByteBuf component(int cIndex) { - return internalComponent(cIndex).duplicate(); - } - - /** - * Return the {@link ByteBuf} on the specified index - * - * @param offset the offset for which the {@link ByteBuf} should be returned - * @return the {@link ByteBuf} on the specified index - */ - public ByteBuf componentAtOffset(int offset) { - return internalComponentAtOffset(offset).duplicate(); - } - - /** - * Return the internal {@link ByteBuf} on the specified index. Note that updating the indexes of the returned - * buffer will lead to an undefined behavior of this buffer. - * - * @param cIndex the index for which the {@link ByteBuf} should be returned - */ - public ByteBuf internalComponent(int cIndex) { - checkComponentIndex(cIndex); - return components.get(cIndex).buf; - } - - /** - * Return the internal {@link ByteBuf} on the specified offset. Note that updating the indexes of the returned - * buffer will lead to an undefined behavior of this buffer. - * - * @param offset the offset for which the {@link ByteBuf} should be returned - */ - public ByteBuf internalComponentAtOffset(int offset) { - return findComponent(offset).buf; - } - - private Component findComponent(int offset) { - checkIndex(offset); - - for (int low = 0, high = components.size(); low <= high;) { - int mid = low + high >>> 1; - Component c = components.get(mid); - if (offset >= c.endOffset) { - low = mid + 1; - } else if (offset < c.offset) { - high = mid - 1; - } else { - assert c.length != 0; - return c; - } - } - - throw new Error("should not reach here"); - } - - @Override - public int nioBufferCount() { - switch (components.size()) { - case 0: - return 1; - case 1: - return components.get(0).buf.nioBufferCount(); - default: - int count = 0; - int componentsCount = components.size(); - for (int i = 0; i < componentsCount; i++) { - Component c = components.get(i); - count += c.buf.nioBufferCount(); - } - return count; - } - } - - @Override - public ByteBuffer internalNioBuffer(int index, int length) { - switch (components.size()) { - case 0: - return EMPTY_NIO_BUFFER; - case 1: - return components.get(0).buf.internalNioBuffer(index, length); - default: - throw new UnsupportedOperationException(); - } - } - - @Override - public ByteBuffer nioBuffer(int index, int length) { - checkIndex(index, length); - - switch (components.size()) { - case 0: - return EMPTY_NIO_BUFFER; - case 1: - ByteBuf buf = components.get(0).buf; - if (buf.nioBufferCount() == 1) { - return components.get(0).buf.nioBuffer(index, length); - } - } - - ByteBuffer merged = ByteBuffer.allocate(length).order(order()); - ByteBuffer[] buffers = nioBuffers(index, length); - - for (ByteBuffer buf: buffers) { - merged.put(buf); - } - - merged.flip(); - return merged; - } - - @Override - public ByteBuffer[] nioBuffers(int index, int length) { - checkIndex(index, length); - if (length == 0) { - return new ByteBuffer[] { EMPTY_NIO_BUFFER }; - } - - List buffers = new ArrayList(components.size()); - int i = toComponentIndex(index); - while (length > 0) { - Component c = components.get(i); - ByteBuf s = c.buf; - int adjustment = c.offset; - int localLength = Math.min(length, s.capacity() - (index - adjustment)); - switch (s.nioBufferCount()) { - case 0: - throw new UnsupportedOperationException(); - case 1: - buffers.add(s.nioBuffer(index - adjustment, localLength)); - break; - default: - Collections.addAll(buffers, s.nioBuffers(index - adjustment, localLength)); - } - - index += localLength; - length -= localLength; - i ++; - } - - return buffers.toArray(new ByteBuffer[buffers.size()]); - } - - /** - * Consolidate the composed {@link ByteBuf}s - */ - public CompositeByteBuf consolidate() { - ensureAccessible(); - final int numComponents = numComponents(); - if (numComponents <= 1) { - return this; - } - - final Component last = components.get(numComponents - 1); - final int capacity = last.endOffset; - final ByteBuf consolidated = allocBuffer(capacity); - - for (int i = 0; i < numComponents; i ++) { - Component c = components.get(i); - ByteBuf b = c.buf; - consolidated.writeBytes(b); - c.freeIfNecessary(); - } - - components.clear(); - components.add(new Component(consolidated)); - updateComponentOffsets(0); - return this; - } - - /** - * Consolidate the composed {@link ByteBuf}s - * - * @param cIndex the index on which to start to compose - * @param numComponents the number of components to compose - */ - public CompositeByteBuf consolidate(int cIndex, int numComponents) { - checkComponentIndex(cIndex, numComponents); - if (numComponents <= 1) { - return this; - } - - final int endCIndex = cIndex + numComponents; - final Component last = components.get(endCIndex - 1); - final int capacity = last.endOffset - components.get(cIndex).offset; - final ByteBuf consolidated = allocBuffer(capacity); - - for (int i = cIndex; i < endCIndex; i ++) { - Component c = components.get(i); - ByteBuf b = c.buf; - consolidated.writeBytes(b); - c.freeIfNecessary(); - } - - components.subList(cIndex + 1, endCIndex).clear(); - components.set(cIndex, new Component(consolidated)); - updateComponentOffsets(cIndex); - return this; - } - - /** - * Discard all {@link ByteBuf}s which are read. - */ - public CompositeByteBuf discardReadComponents() { - ensureAccessible(); - final int readerIndex = readerIndex(); - if (readerIndex == 0) { - return this; - } - - // Discard everything if (readerIndex = writerIndex = capacity). - int writerIndex = writerIndex(); - if (readerIndex == writerIndex && writerIndex == capacity()) { - for (Component c: components) { - c.freeIfNecessary(); - } - components.clear(); - setIndex(0, 0); - adjustMarkers(readerIndex); - return this; - } - - // Remove read components. - int firstComponentId = toComponentIndex(readerIndex); - for (int i = 0; i < firstComponentId; i ++) { - components.get(i).freeIfNecessary(); - } - components.subList(0, firstComponentId).clear(); - - // Update indexes and markers. - Component first = components.get(0); - int offset = first.offset; - updateComponentOffsets(0); - setIndex(readerIndex - offset, writerIndex - offset); - adjustMarkers(offset); - return this; - } - - @Override - public CompositeByteBuf discardReadBytes() { - ensureAccessible(); - final int readerIndex = readerIndex(); - if (readerIndex == 0) { - return this; - } - - // Discard everything if (readerIndex = writerIndex = capacity). - int writerIndex = writerIndex(); - if (readerIndex == writerIndex && writerIndex == capacity()) { - for (Component c: components) { - c.freeIfNecessary(); - } - components.clear(); - setIndex(0, 0); - adjustMarkers(readerIndex); - return this; - } - - // Remove read components. - int firstComponentId = toComponentIndex(readerIndex); - for (int i = 0; i < firstComponentId; i ++) { - components.get(i).freeIfNecessary(); - } - components.subList(0, firstComponentId).clear(); - - // Remove or replace the first readable component with a new slice. - Component c = components.get(0); - int adjustment = readerIndex - c.offset; - if (adjustment == c.length) { - // new slice would be empty, so remove instead - components.remove(0); - } else { - Component newC = new Component(c.buf.slice(adjustment, c.length - adjustment)); - components.set(0, newC); - } - - // Update indexes and markers. - updateComponentOffsets(0); - setIndex(0, writerIndex - readerIndex); - adjustMarkers(readerIndex); - return this; - } - - private ByteBuf allocBuffer(int capacity) { - if (direct) { - return alloc().directBuffer(capacity); - } - return alloc().heapBuffer(capacity); - } - - @Override - public String toString() { - String result = super.toString(); - result = result.substring(0, result.length() - 1); - return result + ", components=" + components.size() + ')'; - } - - private static final class Component { - final ByteBuf buf; - final int length; - int offset; - int endOffset; - - Component(ByteBuf buf) { - this.buf = buf; - length = buf.readableBytes(); - } - - void freeIfNecessary() { - // Unwrap so that we can free slices, too. - buf.release(); // We should not get a NPE here. If so, it must be a bug. - } - } - - @Override - public CompositeByteBuf readerIndex(int readerIndex) { - return (CompositeByteBuf) super.readerIndex(readerIndex); - } - - @Override - public CompositeByteBuf writerIndex(int writerIndex) { - return (CompositeByteBuf) super.writerIndex(writerIndex); - } - - @Override - public CompositeByteBuf setIndex(int readerIndex, int writerIndex) { - return (CompositeByteBuf) super.setIndex(readerIndex, writerIndex); - } - - @Override - public CompositeByteBuf clear() { - return (CompositeByteBuf) super.clear(); - } - - @Override - public CompositeByteBuf markReaderIndex() { - return (CompositeByteBuf) super.markReaderIndex(); - } - - @Override - public CompositeByteBuf resetReaderIndex() { - return (CompositeByteBuf) super.resetReaderIndex(); - } - - @Override - public CompositeByteBuf markWriterIndex() { - return (CompositeByteBuf) super.markWriterIndex(); - } - - @Override - public CompositeByteBuf resetWriterIndex() { - return (CompositeByteBuf) super.resetWriterIndex(); - } - - @Override - public CompositeByteBuf ensureWritable(int minWritableBytes) { - return (CompositeByteBuf) super.ensureWritable(minWritableBytes); - } - - @Override - public CompositeByteBuf getBytes(int index, ByteBuf dst) { - return (CompositeByteBuf) super.getBytes(index, dst); - } - - @Override - public CompositeByteBuf getBytes(int index, ByteBuf dst, int length) { - return (CompositeByteBuf) super.getBytes(index, dst, length); - } - - @Override - public CompositeByteBuf getBytes(int index, byte[] dst) { - return (CompositeByteBuf) super.getBytes(index, dst); - } - - @Override - public CompositeByteBuf setBoolean(int index, boolean value) { - return (CompositeByteBuf) super.setBoolean(index, value); - } - - @Override - public CompositeByteBuf setChar(int index, int value) { - return (CompositeByteBuf) super.setChar(index, value); - } - - @Override - public CompositeByteBuf setFloat(int index, float value) { - return (CompositeByteBuf) super.setFloat(index, value); - } - - @Override - public CompositeByteBuf setDouble(int index, double value) { - return (CompositeByteBuf) super.setDouble(index, value); - } - - @Override - public CompositeByteBuf setBytes(int index, ByteBuf src) { - return (CompositeByteBuf) super.setBytes(index, src); - } - - @Override - public CompositeByteBuf setBytes(int index, ByteBuf src, int length) { - return (CompositeByteBuf) super.setBytes(index, src, length); - } - - @Override - public CompositeByteBuf setBytes(int index, byte[] src) { - return (CompositeByteBuf) super.setBytes(index, src); - } - - @Override - public CompositeByteBuf setZero(int index, int length) { - return (CompositeByteBuf) super.setZero(index, length); - } - - @Override - public CompositeByteBuf readBytes(ByteBuf dst) { - return (CompositeByteBuf) super.readBytes(dst); - } - - @Override - public CompositeByteBuf readBytes(ByteBuf dst, int length) { - return (CompositeByteBuf) super.readBytes(dst, length); - } - - @Override - public CompositeByteBuf readBytes(ByteBuf dst, int dstIndex, int length) { - return (CompositeByteBuf) super.readBytes(dst, dstIndex, length); - } - - @Override - public CompositeByteBuf readBytes(byte[] dst) { - return (CompositeByteBuf) super.readBytes(dst); - } - - @Override - public CompositeByteBuf readBytes(byte[] dst, int dstIndex, int length) { - return (CompositeByteBuf) super.readBytes(dst, dstIndex, length); - } - - @Override - public CompositeByteBuf readBytes(ByteBuffer dst) { - return (CompositeByteBuf) super.readBytes(dst); - } - - @Override - public CompositeByteBuf readBytes(OutputStream out, int length) throws IOException { - return (CompositeByteBuf) super.readBytes(out, length); - } - - @Override - public CompositeByteBuf skipBytes(int length) { - return (CompositeByteBuf) super.skipBytes(length); - } - - @Override - public CompositeByteBuf writeBoolean(boolean value) { - return (CompositeByteBuf) super.writeBoolean(value); - } - - @Override - public CompositeByteBuf writeByte(int value) { - return (CompositeByteBuf) super.writeByte(value); - } - - @Override - public CompositeByteBuf writeShort(int value) { - return (CompositeByteBuf) super.writeShort(value); - } - - @Override - public CompositeByteBuf writeMedium(int value) { - return (CompositeByteBuf) super.writeMedium(value); - } - - @Override - public CompositeByteBuf writeInt(int value) { - return (CompositeByteBuf) super.writeInt(value); - } - - @Override - public CompositeByteBuf writeLong(long value) { - return (CompositeByteBuf) super.writeLong(value); - } - - @Override - public CompositeByteBuf writeChar(int value) { - return (CompositeByteBuf) super.writeChar(value); - } - - @Override - public CompositeByteBuf writeFloat(float value) { - return (CompositeByteBuf) super.writeFloat(value); - } - - @Override - public CompositeByteBuf writeDouble(double value) { - return (CompositeByteBuf) super.writeDouble(value); - } - - @Override - public CompositeByteBuf writeBytes(ByteBuf src) { - return (CompositeByteBuf) super.writeBytes(src); - } - - @Override - public CompositeByteBuf writeBytes(ByteBuf src, int length) { - return (CompositeByteBuf) super.writeBytes(src, length); - } - - @Override - public CompositeByteBuf writeBytes(ByteBuf src, int srcIndex, int length) { - return (CompositeByteBuf) super.writeBytes(src, srcIndex, length); - } - - @Override - public CompositeByteBuf writeBytes(byte[] src) { - return (CompositeByteBuf) super.writeBytes(src); - } - - @Override - public CompositeByteBuf writeBytes(byte[] src, int srcIndex, int length) { - return (CompositeByteBuf) super.writeBytes(src, srcIndex, length); - } - - @Override - public CompositeByteBuf writeBytes(ByteBuffer src) { - return (CompositeByteBuf) super.writeBytes(src); - } - - @Override - public CompositeByteBuf writeZero(int length) { - return (CompositeByteBuf) super.writeZero(length); - } - - @Override - public CompositeByteBuf retain(int increment) { - return (CompositeByteBuf) super.retain(increment); - } - - @Override - public CompositeByteBuf retain() { - return (CompositeByteBuf) super.retain(); - } - - @Override - public ByteBuffer[] nioBuffers() { - return nioBuffers(readerIndex(), readableBytes()); - } - - @Override - public CompositeByteBuf discardSomeReadBytes() { - return discardReadComponents(); - } - - @Override - protected void deallocate() { - if (freed) { - return; - } - - freed = true; - int size = components.size(); - // We're not using foreach to avoid creating an iterator. - // see https://github.com/netty/netty/issues/2642 - for (int i = 0; i < size; i++) { - components.get(i).freeIfNecessary(); - } - - if (leak != null) { - leak.close(); - } - } - - @Override - public ByteBuf unwrap() { - return null; - } - - private final class CompositeByteBufIterator implements Iterator { - private final int size = components.size(); - private int index; - - @Override - public boolean hasNext() { - return size > index; - } - - @Override - public ByteBuf next() { - if (size != components.size()) { - throw new ConcurrentModificationException(); - } - if (!hasNext()) { - throw new NoSuchElementException(); - } - try { - return components.get(index++).buf; - } catch (IndexOutOfBoundsException e) { - throw new ConcurrentModificationException(); - } - } - - @Override - public void remove() { - throw new UnsupportedOperationException("Read-Only"); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/DefaultByteBufHolder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/DefaultByteBufHolder.java deleted file mode 100755 index 4ccab6b0ad..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/DefaultByteBufHolder.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.buffer; - -import com.ai.cloud.io.netty.util.IllegalReferenceCountException; -import com.ai.cloud.io.netty.util.internal.StringUtil; - -/** - * Default implementation of a {@link ByteBufHolder} that holds it's data in a {@link ByteBuf}. - * - */ -public class DefaultByteBufHolder implements ByteBufHolder { - - private final ByteBuf data; - - public DefaultByteBufHolder(ByteBuf data) { - if (data == null) { - throw new NullPointerException("data"); - } - this.data = data; - } - - @Override - public ByteBuf content() { - if (data.refCnt() <= 0) { - throw new IllegalReferenceCountException(data.refCnt()); - } - return data; - } - - @Override - public ByteBufHolder copy() { - return new DefaultByteBufHolder(data.copy()); - } - - @Override - public ByteBufHolder duplicate() { - return new DefaultByteBufHolder(data.duplicate()); - } - - @Override - public int refCnt() { - return data.refCnt(); - } - - @Override - public ByteBufHolder retain() { - data.retain(); - return this; - } - - @Override - public ByteBufHolder retain(int increment) { - data.retain(increment); - return this; - } - - @Override - public boolean release() { - return data.release(); - } - - @Override - public boolean release(int decrement) { - return data.release(decrement); - } - - /** - * Return {@link ByteBuf#toString()} without checking the reference count first. This is useful to implemement - * {@link #toString()}. - */ - protected final String contentToString() { - return data.toString(); - } - - @Override - public String toString() { - return StringUtil.simpleClassName(this) + '(' + contentToString() + ')'; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/DuplicatedAbstractByteBuf.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/DuplicatedAbstractByteBuf.java deleted file mode 100755 index db582c29cc..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/DuplicatedAbstractByteBuf.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.buffer; - -/** - * {@link DuplicatedByteBuf} implementation that can do optimizations because it knows the duplicated buffer - * is of type {@link AbstractByteBuf}. - */ -final class DuplicatedAbstractByteBuf extends DuplicatedByteBuf { - public DuplicatedAbstractByteBuf(AbstractByteBuf buffer) { - super(buffer); - } - - @Override - protected byte _getByte(int index) { - return unwrap0()._getByte(index); - } - - @Override - protected short _getShort(int index) { - return unwrap0()._getShort(index); - } - - @Override - protected int _getUnsignedMedium(int index) { - return unwrap0()._getUnsignedMedium(index); - } - - @Override - protected int _getInt(int index) { - return unwrap0()._getInt(index); - } - - @Override - protected long _getLong(int index) { - return unwrap0()._getLong(index); - } - - @Override - protected void _setByte(int index, int value) { - unwrap0()._setByte(index, value); - } - - @Override - protected void _setShort(int index, int value) { - unwrap0()._setShort(index, value); - } - - @Override - protected void _setMedium(int index, int value) { - unwrap0()._setMedium(index, value); - } - - @Override - protected void _setInt(int index, int value) { - unwrap0()._setInt(index, value); - } - - @Override - protected void _setLong(int index, long value) { - unwrap0()._setLong(index, value); - } - - private AbstractByteBuf unwrap0() { - return (AbstractByteBuf) unwrap(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/DuplicatedByteBuf.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/DuplicatedByteBuf.java deleted file mode 100755 index 6b7e15ce34..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/DuplicatedByteBuf.java +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; - - -/** - * A derived buffer which simply forwards all data access requests to its - * parent. It is recommended to use {@link ByteBuf#duplicate()} instead - * of calling the constructor explicitly. - */ -public class DuplicatedByteBuf extends AbstractDerivedByteBuf { - - private final ByteBuf buffer; - - public DuplicatedByteBuf(ByteBuf buffer) { - super(buffer.maxCapacity()); - - if (buffer instanceof DuplicatedByteBuf) { - this.buffer = ((DuplicatedByteBuf) buffer).buffer; - } else { - this.buffer = buffer; - } - - setIndex(buffer.readerIndex(), buffer.writerIndex()); - markReaderIndex(); - markWriterIndex(); - } - - @Override - public ByteBuf unwrap() { - return buffer; - } - - @Override - public ByteBufAllocator alloc() { - return buffer.alloc(); - } - - @Override - public ByteOrder order() { - return buffer.order(); - } - - @Override - public boolean isDirect() { - return buffer.isDirect(); - } - - @Override - public int capacity() { - return buffer.capacity(); - } - - @Override - public ByteBuf capacity(int newCapacity) { - buffer.capacity(newCapacity); - return this; - } - - @Override - public boolean hasArray() { - return buffer.hasArray(); - } - - @Override - public byte[] array() { - return buffer.array(); - } - - @Override - public int arrayOffset() { - return buffer.arrayOffset(); - } - - @Override - public boolean hasMemoryAddress() { - return buffer.hasMemoryAddress(); - } - - @Override - public long memoryAddress() { - return buffer.memoryAddress(); - } - - @Override - public byte getByte(int index) { - return buffer.getByte(index); - } - - @Override - protected byte _getByte(int index) { - return buffer.getByte(index); - } - - @Override - public short getShort(int index) { - return buffer.getShort(index); - } - - @Override - protected short _getShort(int index) { - return buffer.getShort(index); - } - - @Override - public int getUnsignedMedium(int index) { - return buffer.getUnsignedMedium(index); - } - - @Override - protected int _getUnsignedMedium(int index) { - return buffer.getUnsignedMedium(index); - } - - @Override - public int getInt(int index) { - return buffer.getInt(index); - } - - @Override - protected int _getInt(int index) { - return buffer.getInt(index); - } - - @Override - public long getLong(int index) { - return buffer.getLong(index); - } - - @Override - protected long _getLong(int index) { - return buffer.getLong(index); - } - - @Override - public ByteBuf copy(int index, int length) { - return buffer.copy(index, length); - } - - @Override - public ByteBuf slice(int index, int length) { - return buffer.slice(index, length); - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - buffer.getBytes(index, dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - buffer.getBytes(index, dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuffer dst) { - buffer.getBytes(index, dst); - return this; - } - - @Override - public ByteBuf setByte(int index, int value) { - buffer.setByte(index, value); - return this; - } - - @Override - protected void _setByte(int index, int value) { - buffer.setByte(index, value); - } - - @Override - public ByteBuf setShort(int index, int value) { - buffer.setShort(index, value); - return this; - } - - @Override - protected void _setShort(int index, int value) { - buffer.setShort(index, value); - } - - @Override - public ByteBuf setMedium(int index, int value) { - buffer.setMedium(index, value); - return this; - } - - @Override - protected void _setMedium(int index, int value) { - buffer.setMedium(index, value); - } - - @Override - public ByteBuf setInt(int index, int value) { - buffer.setInt(index, value); - return this; - } - - @Override - protected void _setInt(int index, int value) { - buffer.setInt(index, value); - } - - @Override - public ByteBuf setLong(int index, long value) { - buffer.setLong(index, value); - return this; - } - - @Override - protected void _setLong(int index, long value) { - buffer.setLong(index, value); - } - - @Override - public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { - buffer.setBytes(index, src, srcIndex, length); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { - buffer.setBytes(index, src, srcIndex, length); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuffer src) { - buffer.setBytes(index, src); - return this; - } - - @Override - public ByteBuf getBytes(int index, OutputStream out, int length) - throws IOException { - buffer.getBytes(index, out, length); - return this; - } - - @Override - public int getBytes(int index, GatheringByteChannel out, int length) - throws IOException { - return buffer.getBytes(index, out, length); - } - - @Override - public int setBytes(int index, InputStream in, int length) - throws IOException { - return buffer.setBytes(index, in, length); - } - - @Override - public int setBytes(int index, ScatteringByteChannel in, int length) - throws IOException { - return buffer.setBytes(index, in, length); - } - - @Override - public int nioBufferCount() { - return buffer.nioBufferCount(); - } - - @Override - public ByteBuffer[] nioBuffers(int index, int length) { - return buffer.nioBuffers(index, length); - } - - @Override - public ByteBuffer internalNioBuffer(int index, int length) { - return nioBuffer(index, length); - } - - @Override - public int forEachByte(int index, int length, ByteBufProcessor processor) { - return buffer.forEachByte(index, length, processor); - } - - @Override - public int forEachByteDesc(int index, int length, ByteBufProcessor processor) { - return buffer.forEachByteDesc(index, length, processor); - } -} - diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/EmptyByteBuf.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/EmptyByteBuf.java deleted file mode 100755 index 20ad74b83d..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/EmptyByteBuf.java +++ /dev/null @@ -1,870 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.buffer; - -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.ReadOnlyBufferException; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; -import java.nio.charset.Charset; - -import com.ai.cloud.io.netty.util.internal.EmptyArrays; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; -import com.ai.cloud.io.netty.util.internal.StringUtil; - -/** - * An empty {@link ByteBuf} whose capacity and maximum capacity are all {@code 0}. - */ -public final class EmptyByteBuf extends ByteBuf { - - private static final ByteBuffer EMPTY_BYTE_BUFFER = ByteBuffer.allocateDirect(0); - private static final long EMPTY_BYTE_BUFFER_ADDRESS; - - static { - long emptyByteBufferAddress = 0; - try { - if (PlatformDependent.hasUnsafe()) { - emptyByteBufferAddress = PlatformDependent.directBufferAddress(EMPTY_BYTE_BUFFER); - } - } catch (Throwable t) { - // Ignore - } - EMPTY_BYTE_BUFFER_ADDRESS = emptyByteBufferAddress; - } - - private final ByteBufAllocator alloc; - private final ByteOrder order; - private final String str; - private EmptyByteBuf swapped; - - public EmptyByteBuf(ByteBufAllocator alloc) { - this(alloc, ByteOrder.BIG_ENDIAN); - } - - private EmptyByteBuf(ByteBufAllocator alloc, ByteOrder order) { - if (alloc == null) { - throw new NullPointerException("alloc"); - } - - this.alloc = alloc; - this.order = order; - str = StringUtil.simpleClassName(this) + (order == ByteOrder.BIG_ENDIAN? "BE" : "LE"); - } - - @Override - public int capacity() { - return 0; - } - - @Override - public ByteBuf capacity(int newCapacity) { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBufAllocator alloc() { - return alloc; - } - - @Override - public ByteOrder order() { - return order; - } - - @Override - public ByteBuf unwrap() { - return null; - } - - @Override - public boolean isDirect() { - return true; - } - - @Override - public int maxCapacity() { - return 0; - } - - @Override - public ByteBuf order(ByteOrder endianness) { - if (endianness == null) { - throw new NullPointerException("endianness"); - } - if (endianness == order()) { - return this; - } - - EmptyByteBuf swapped = this.swapped; - if (swapped != null) { - return swapped; - } - - this.swapped = swapped = new EmptyByteBuf(alloc(), endianness); - return swapped; - } - - @Override - public int readerIndex() { - return 0; - } - - @Override - public ByteBuf readerIndex(int readerIndex) { - return checkIndex(readerIndex); - } - - @Override - public int writerIndex() { - return 0; - } - - @Override - public ByteBuf writerIndex(int writerIndex) { - return checkIndex(writerIndex); - } - - @Override - public ByteBuf setIndex(int readerIndex, int writerIndex) { - checkIndex(readerIndex); - checkIndex(writerIndex); - return this; - } - - @Override - public int readableBytes() { - return 0; - } - - @Override - public int writableBytes() { - return 0; - } - - @Override - public int maxWritableBytes() { - return 0; - } - - @Override - public boolean isReadable() { - return false; - } - - @Override - public boolean isWritable() { - return false; - } - - @Override - public ByteBuf clear() { - return this; - } - - @Override - public ByteBuf markReaderIndex() { - return this; - } - - @Override - public ByteBuf resetReaderIndex() { - return this; - } - - @Override - public ByteBuf markWriterIndex() { - return this; - } - - @Override - public ByteBuf resetWriterIndex() { - return this; - } - - @Override - public ByteBuf discardReadBytes() { - return this; - } - - @Override - public ByteBuf discardSomeReadBytes() { - return this; - } - - @Override - public ByteBuf ensureWritable(int minWritableBytes) { - if (minWritableBytes < 0) { - throw new IllegalArgumentException("minWritableBytes: " + minWritableBytes + " (expected: >= 0)"); - } - if (minWritableBytes != 0) { - throw new IndexOutOfBoundsException(); - } - return this; - } - - @Override - public int ensureWritable(int minWritableBytes, boolean force) { - if (minWritableBytes < 0) { - throw new IllegalArgumentException("minWritableBytes: " + minWritableBytes + " (expected: >= 0)"); - } - - if (minWritableBytes == 0) { - return 0; - } - - return 1; - } - - @Override - public boolean getBoolean(int index) { - throw new IndexOutOfBoundsException(); - } - - @Override - public byte getByte(int index) { - throw new IndexOutOfBoundsException(); - } - - @Override - public short getUnsignedByte(int index) { - throw new IndexOutOfBoundsException(); - } - - @Override - public short getShort(int index) { - throw new IndexOutOfBoundsException(); - } - - @Override - public int getUnsignedShort(int index) { - throw new IndexOutOfBoundsException(); - } - - @Override - public int getMedium(int index) { - throw new IndexOutOfBoundsException(); - } - - @Override - public int getUnsignedMedium(int index) { - throw new IndexOutOfBoundsException(); - } - - @Override - public int getInt(int index) { - throw new IndexOutOfBoundsException(); - } - - @Override - public long getUnsignedInt(int index) { - throw new IndexOutOfBoundsException(); - } - - @Override - public long getLong(int index) { - throw new IndexOutOfBoundsException(); - } - - @Override - public char getChar(int index) { - throw new IndexOutOfBoundsException(); - } - - @Override - public float getFloat(int index) { - throw new IndexOutOfBoundsException(); - } - - @Override - public double getDouble(int index) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst) { - return checkIndex(index, dst.writableBytes()); - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int length) { - return checkIndex(index, length); - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - return checkIndex(index, length); - } - - @Override - public ByteBuf getBytes(int index, byte[] dst) { - return checkIndex(index, dst.length); - } - - @Override - public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - return checkIndex(index, length); - } - - @Override - public ByteBuf getBytes(int index, ByteBuffer dst) { - return checkIndex(index, dst.remaining()); - } - - @Override - public ByteBuf getBytes(int index, OutputStream out, int length) { - return checkIndex(index, length); - } - - @Override - public int getBytes(int index, GatheringByteChannel out, int length) { - checkIndex(index, length); - return 0; - } - - @Override - public ByteBuf setBoolean(int index, boolean value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf setByte(int index, int value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf setShort(int index, int value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf setMedium(int index, int value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf setInt(int index, int value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf setLong(int index, long value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf setChar(int index, int value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf setFloat(int index, float value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf setDouble(int index, double value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int length) { - return checkIndex(index, length); - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { - return checkIndex(index, length); - } - - @Override - public ByteBuf setBytes(int index, byte[] src) { - return checkIndex(index, src.length); - } - - @Override - public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { - return checkIndex(index, length); - } - - @Override - public ByteBuf setBytes(int index, ByteBuffer src) { - return checkIndex(index, src.remaining()); - } - - @Override - public int setBytes(int index, InputStream in, int length) { - checkIndex(index, length); - return 0; - } - - @Override - public int setBytes(int index, ScatteringByteChannel in, int length) { - checkIndex(index, length); - return 0; - } - - @Override - public ByteBuf setZero(int index, int length) { - return checkIndex(index, length); - } - - @Override - public boolean readBoolean() { - throw new IndexOutOfBoundsException(); - } - - @Override - public byte readByte() { - throw new IndexOutOfBoundsException(); - } - - @Override - public short readUnsignedByte() { - throw new IndexOutOfBoundsException(); - } - - @Override - public short readShort() { - throw new IndexOutOfBoundsException(); - } - - @Override - public int readUnsignedShort() { - throw new IndexOutOfBoundsException(); - } - - @Override - public int readMedium() { - throw new IndexOutOfBoundsException(); - } - - @Override - public int readUnsignedMedium() { - throw new IndexOutOfBoundsException(); - } - - @Override - public int readInt() { - throw new IndexOutOfBoundsException(); - } - - @Override - public long readUnsignedInt() { - throw new IndexOutOfBoundsException(); - } - - @Override - public long readLong() { - throw new IndexOutOfBoundsException(); - } - - @Override - public char readChar() { - throw new IndexOutOfBoundsException(); - } - - @Override - public float readFloat() { - throw new IndexOutOfBoundsException(); - } - - @Override - public double readDouble() { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf readBytes(int length) { - return checkLength(length); - } - - @Override - public ByteBuf readSlice(int length) { - return checkLength(length); - } - - @Override - public ByteBuf readBytes(ByteBuf dst) { - return checkLength(dst.writableBytes()); - } - - @Override - public ByteBuf readBytes(ByteBuf dst, int length) { - return checkLength(length); - } - - @Override - public ByteBuf readBytes(ByteBuf dst, int dstIndex, int length) { - return checkLength(length); - } - - @Override - public ByteBuf readBytes(byte[] dst) { - return checkLength(dst.length); - } - - @Override - public ByteBuf readBytes(byte[] dst, int dstIndex, int length) { - return checkLength(length); - } - - @Override - public ByteBuf readBytes(ByteBuffer dst) { - return checkLength(dst.remaining()); - } - - @Override - public ByteBuf readBytes(OutputStream out, int length) { - return checkLength(length); - } - - @Override - public int readBytes(GatheringByteChannel out, int length) { - checkLength(length); - return 0; - } - - @Override - public ByteBuf skipBytes(int length) { - return checkLength(length); - } - - @Override - public ByteBuf writeBoolean(boolean value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf writeByte(int value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf writeShort(int value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf writeMedium(int value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf writeInt(int value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf writeLong(long value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf writeChar(int value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf writeFloat(float value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf writeDouble(double value) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf writeBytes(ByteBuf src) { - throw new IndexOutOfBoundsException(); - } - - @Override - public ByteBuf writeBytes(ByteBuf src, int length) { - return checkLength(length); - } - - @Override - public ByteBuf writeBytes(ByteBuf src, int srcIndex, int length) { - return checkLength(length); - } - - @Override - public ByteBuf writeBytes(byte[] src) { - return checkLength(src.length); - } - - @Override - public ByteBuf writeBytes(byte[] src, int srcIndex, int length) { - return checkLength(length); - } - - @Override - public ByteBuf writeBytes(ByteBuffer src) { - return checkLength(src.remaining()); - } - - @Override - public int writeBytes(InputStream in, int length) { - checkLength(length); - return 0; - } - - @Override - public int writeBytes(ScatteringByteChannel in, int length) { - checkLength(length); - return 0; - } - - @Override - public ByteBuf writeZero(int length) { - return checkLength(length); - } - - @Override - public int indexOf(int fromIndex, int toIndex, byte value) { - checkIndex(fromIndex); - checkIndex(toIndex); - return -1; - } - - @Override - public int bytesBefore(byte value) { - return -1; - } - - @Override - public int bytesBefore(int length, byte value) { - checkLength(length); - return -1; - } - - @Override - public int bytesBefore(int index, int length, byte value) { - checkIndex(index, length); - return -1; - } - - @Override - public int forEachByte(ByteBufProcessor processor) { - return -1; - } - - @Override - public int forEachByte(int index, int length, ByteBufProcessor processor) { - checkIndex(index, length); - return -1; - } - - @Override - public int forEachByteDesc(ByteBufProcessor processor) { - return -1; - } - - @Override - public int forEachByteDesc(int index, int length, ByteBufProcessor processor) { - checkIndex(index, length); - return -1; - } - - @Override - public ByteBuf copy() { - return this; - } - - @Override - public ByteBuf copy(int index, int length) { - return checkIndex(index, length); - } - - @Override - public ByteBuf slice() { - return this; - } - - @Override - public ByteBuf slice(int index, int length) { - return checkIndex(index, length); - } - - @Override - public ByteBuf duplicate() { - return this; - } - - @Override - public int nioBufferCount() { - return 1; - } - - @Override - public ByteBuffer nioBuffer() { - return EMPTY_BYTE_BUFFER; - } - - @Override - public ByteBuffer nioBuffer(int index, int length) { - checkIndex(index, length); - return nioBuffer(); - } - - @Override - public ByteBuffer[] nioBuffers() { - return new ByteBuffer[] { EMPTY_BYTE_BUFFER }; - } - - @Override - public ByteBuffer[] nioBuffers(int index, int length) { - checkIndex(index, length); - return nioBuffers(); - } - - @Override - public ByteBuffer internalNioBuffer(int index, int length) { - return EMPTY_BYTE_BUFFER; - } - - @Override - public boolean hasArray() { - return true; - } - - @Override - public byte[] array() { - return EmptyArrays.EMPTY_BYTES; - } - - @Override - public int arrayOffset() { - return 0; - } - - @Override - public boolean hasMemoryAddress() { - return EMPTY_BYTE_BUFFER_ADDRESS != 0; - } - - @Override - public long memoryAddress() { - if (hasMemoryAddress()) { - return EMPTY_BYTE_BUFFER_ADDRESS; - } else { - throw new UnsupportedOperationException(); - } - } - - @Override - public String toString(Charset charset) { - return ""; - } - - @Override - public String toString(int index, int length, Charset charset) { - checkIndex(index, length); - return toString(charset); - } - - @Override - public int hashCode() { - return 0; - } - - @Override - public boolean equals(Object obj) { - return obj instanceof ByteBuf && !((ByteBuf) obj).isReadable(); - } - - @Override - public int compareTo(ByteBuf buffer) { - return buffer.isReadable()? -1 : 0; - } - - @Override - public String toString() { - return str; - } - - @Override - public boolean isReadable(int size) { - return false; - } - - @Override - public boolean isWritable(int size) { - return false; - } - - @Override - public int refCnt() { - return 1; - } - - @Override - public ByteBuf retain() { - return this; - } - - @Override - public ByteBuf retain(int increment) { - return this; - } - - @Override - public boolean release() { - return false; - } - - @Override - public boolean release(int decrement) { - return false; - } - - private ByteBuf checkIndex(int index) { - if (index != 0) { - throw new IndexOutOfBoundsException(); - } - return this; - } - - private ByteBuf checkIndex(int index, int length) { - if (length < 0) { - throw new IllegalArgumentException("length: " + length); - } - if (index != 0 || length != 0) { - throw new IndexOutOfBoundsException(); - } - return this; - } - - private ByteBuf checkLength(int length) { - if (length < 0) { - throw new IllegalArgumentException("length: " + length + " (expected: >= 0)"); - } - if (length != 0) { - throw new IndexOutOfBoundsException(); - } - return this; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/FixedCompositeByteBuf.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/FixedCompositeByteBuf.java deleted file mode 100755 index 27d996db5c..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/FixedCompositeByteBuf.java +++ /dev/null @@ -1,572 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.ReadOnlyBufferException; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; -import java.util.Collections; - -import com.ai.cloud.io.netty.util.internal.EmptyArrays; -import com.ai.cloud.io.netty.util.internal.RecyclableArrayList; - -/** - * {@link ByteBuf} implementation which allows to wrap an array of {@link ByteBuf} in a read-only mode. - * This is useful to write an array of {@link ByteBuf}s. - */ -final class FixedCompositeByteBuf extends AbstractReferenceCountedByteBuf { - private static final ByteBuf[] EMPTY = { Unpooled.EMPTY_BUFFER }; - private final int nioBufferCount; - private final int capacity; - private final ByteBufAllocator allocator; - private final ByteOrder order; - private final Object[] buffers; - private final boolean direct; - - FixedCompositeByteBuf(ByteBufAllocator allocator, ByteBuf... buffers) { - super(Integer.MAX_VALUE); - if (buffers.length == 0) { - this.buffers = EMPTY; - order = ByteOrder.BIG_ENDIAN; - nioBufferCount = 1; - capacity = 0; - direct = buffers[0].isDirect(); - } else { - ByteBuf b = buffers[0]; - this.buffers = new Object[buffers.length]; - this.buffers[0] = b; - boolean direct = true; - int nioBufferCount = b.nioBufferCount(); - int capacity = b.readableBytes(); - order = b.order(); - for (int i = 1; i < buffers.length; i++) { - b = buffers[i]; - if (buffers[i].order() != order) { - throw new IllegalArgumentException("All ByteBufs need to have same ByteOrder"); - } - nioBufferCount += b.nioBufferCount(); - capacity += b.readableBytes(); - if (!b.isDirect()) { - direct = false; - } - this.buffers[i] = b; - } - this.nioBufferCount = nioBufferCount; - this.capacity = capacity; - this.direct = direct; - } - setIndex(0, capacity()); - this.allocator = allocator; - } - - @Override - public boolean isWritable() { - return false; - } - - @Override - public boolean isWritable(int size) { - return false; - } - - @Override - public ByteBuf discardReadBytes() { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBuf setBytes(int index, ByteBuffer src) { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBuf setByte(int index, int value) { - throw new ReadOnlyBufferException(); - } - - @Override - protected void _setByte(int index, int value) { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBuf setShort(int index, int value) { - throw new ReadOnlyBufferException(); - } - - @Override - protected void _setShort(int index, int value) { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBuf setMedium(int index, int value) { - throw new ReadOnlyBufferException(); - } - - @Override - protected void _setMedium(int index, int value) { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBuf setInt(int index, int value) { - throw new ReadOnlyBufferException(); - } - - @Override - protected void _setInt(int index, int value) { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBuf setLong(int index, long value) { - throw new ReadOnlyBufferException(); - } - - @Override - protected void _setLong(int index, long value) { - throw new ReadOnlyBufferException(); - } - - @Override - public int setBytes(int index, InputStream in, int length) { - throw new ReadOnlyBufferException(); - } - - @Override - public int setBytes(int index, ScatteringByteChannel in, int length) { - throw new ReadOnlyBufferException(); - } - - @Override - public int capacity() { - return capacity; - } - - @Override - public int maxCapacity() { - return capacity; - } - - @Override - public ByteBuf capacity(int newCapacity) { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBufAllocator alloc() { - return allocator; - } - - @Override - public ByteOrder order() { - return order; - } - - @Override - public ByteBuf unwrap() { - return null; - } - - @Override - public boolean isDirect() { - return direct; - } - - private Component findComponent(int index) { - int readable = 0; - for (int i = 0 ; i < buffers.length; i++) { - Component comp = null; - ByteBuf b; - Object obj = buffers[i]; - boolean isBuffer; - if (obj instanceof ByteBuf) { - b = (ByteBuf) obj; - isBuffer = true; - } else { - comp = (Component) obj; - b = comp.buf; - isBuffer = false; - } - readable += b.readableBytes(); - if (index < readable) { - if (isBuffer) { - // Create a new component ad store ti in the array so it not create a new object - // on the next access. - comp = new Component(i, readable - b.readableBytes(), b); - buffers[i] = comp; - } - return comp; - } - } - throw new IllegalStateException(); - } - - /** - * Return the {@link ByteBuf} stored at the given index of the array. - */ - private ByteBuf buffer(int i) { - Object obj = buffers[i]; - if (obj instanceof ByteBuf) { - return (ByteBuf) obj; - } - return ((Component) obj).buf; - } - - @Override - public byte getByte(int index) { - return _getByte(index); - } - - @Override - protected byte _getByte(int index) { - Component c = findComponent(index); - return c.buf.getByte(index - c.offset); - } - - @Override - protected short _getShort(int index) { - Component c = findComponent(index); - if (index + 2 <= c.endOffset) { - return c.buf.getShort(index - c.offset); - } else if (order() == ByteOrder.BIG_ENDIAN) { - return (short) ((_getByte(index) & 0xff) << 8 | _getByte(index + 1) & 0xff); - } else { - return (short) (_getByte(index) & 0xff | (_getByte(index + 1) & 0xff) << 8); - } - } - - @Override - protected int _getUnsignedMedium(int index) { - Component c = findComponent(index); - if (index + 3 <= c.endOffset) { - return c.buf.getUnsignedMedium(index - c.offset); - } else if (order() == ByteOrder.BIG_ENDIAN) { - return (_getShort(index) & 0xffff) << 8 | _getByte(index + 2) & 0xff; - } else { - return _getShort(index) & 0xFFFF | (_getByte(index + 2) & 0xFF) << 16; - } - } - - @Override - protected int _getInt(int index) { - Component c = findComponent(index); - if (index + 4 <= c.endOffset) { - return c.buf.getInt(index - c.offset); - } else if (order() == ByteOrder.BIG_ENDIAN) { - return (_getShort(index) & 0xffff) << 16 | _getShort(index + 2) & 0xffff; - } else { - return _getShort(index) & 0xFFFF | (_getShort(index + 2) & 0xFFFF) << 16; - } - } - - @Override - protected long _getLong(int index) { - Component c = findComponent(index); - if (index + 8 <= c.endOffset) { - return c.buf.getLong(index - c.offset); - } else if (order() == ByteOrder.BIG_ENDIAN) { - return (_getInt(index) & 0xffffffffL) << 32 | _getInt(index + 4) & 0xffffffffL; - } else { - return _getInt(index) & 0xFFFFFFFFL | (_getInt(index + 4) & 0xFFFFFFFFL) << 32; - } - } - - @Override - public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - checkDstIndex(index, length, dstIndex, dst.length); - if (length == 0) { - return this; - } - - Component c = findComponent(index); - int i = c.index; - int adjustment = c.offset; - ByteBuf s = c.buf; - for (;;) { - int localLength = Math.min(length, s.readableBytes() - (index - adjustment)); - s.getBytes(index - adjustment, dst, dstIndex, localLength); - index += localLength; - dstIndex += localLength; - length -= localLength; - adjustment += s.readableBytes(); - if (length <= 0) { - break; - } - s = buffer(++i); - } - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuffer dst) { - int limit = dst.limit(); - int length = dst.remaining(); - - checkIndex(index, length); - if (length == 0) { - return this; - } - - try { - Component c = findComponent(index); - int i = c.index; - int adjustment = c.offset; - ByteBuf s = c.buf; - for (;;) { - int localLength = Math.min(length, s.readableBytes() - (index - adjustment)); - dst.limit(dst.position() + localLength); - s.getBytes(index - adjustment, dst); - index += localLength; - length -= localLength; - adjustment += s.readableBytes(); - if (length <= 0) { - break; - } - s = buffer(++i); - } - } finally { - dst.limit(limit); - } - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - checkDstIndex(index, length, dstIndex, dst.capacity()); - if (length == 0) { - return this; - } - - Component c = findComponent(index); - int i = c.index; - int adjustment = c.offset; - ByteBuf s = c.buf; - for (;;) { - int localLength = Math.min(length, s.readableBytes() - (index - adjustment)); - s.getBytes(index - adjustment, dst, dstIndex, localLength); - index += localLength; - dstIndex += localLength; - length -= localLength; - adjustment += s.readableBytes(); - if (length <= 0) { - break; - } - s = buffer(++i); - } - return this; - } - - @Override - public int getBytes(int index, GatheringByteChannel out, int length) - throws IOException { - int count = nioBufferCount(); - if (count == 1) { - return out.write(internalNioBuffer(index, length)); - } else { - long writtenBytes = out.write(nioBuffers(index, length)); - if (writtenBytes > Integer.MAX_VALUE) { - return Integer.MAX_VALUE; - } else { - return (int) writtenBytes; - } - } - } - - @Override - public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException { - checkIndex(index, length); - if (length == 0) { - return this; - } - - Component c = findComponent(index); - int i = c.index; - int adjustment = c.offset; - ByteBuf s = c.buf; - for (;;) { - int localLength = Math.min(length, s.readableBytes() - (index - adjustment)); - s.getBytes(index - adjustment, out, localLength); - index += localLength; - length -= localLength; - adjustment += s.readableBytes(); - if (length <= 0) { - break; - } - s = buffer(++i); - } - return this; - } - - @Override - public ByteBuf copy(int index, int length) { - checkIndex(index, length); - boolean release = true; - ByteBuf buf = alloc().buffer(length); - try { - buf.writeBytes(this, index, length); - release = false; - return buf; - } finally { - if (release) { - buf.release(); - } - } - } - - @Override - public int nioBufferCount() { - return nioBufferCount; - } - - @Override - public ByteBuffer nioBuffer(int index, int length) { - checkIndex(index, length); - if (buffers.length == 1) { - ByteBuf buf = buffer(0); - if (buf.nioBufferCount() == 1) { - return buf.nioBuffer(index, length); - } - } - ByteBuffer merged = ByteBuffer.allocate(length).order(order()); - ByteBuffer[] buffers = nioBuffers(index, length); - - //noinspection ForLoopReplaceableByForEach - for (int i = 0; i < buffers.length; i++) { - merged.put(buffers[i]); - } - - merged.flip(); - return merged; - } - - @Override - public ByteBuffer internalNioBuffer(int index, int length) { - if (buffers.length == 1) { - return buffer(0).internalNioBuffer(index, length); - } - throw new UnsupportedOperationException(); - } - - @Override - public ByteBuffer[] nioBuffers(int index, int length) { - checkIndex(index, length); - if (length == 0) { - return EmptyArrays.EMPTY_BYTE_BUFFERS; - } - - RecyclableArrayList array = RecyclableArrayList.newInstance(buffers.length); - try { - Component c = findComponent(index); - int i = c.index; - int adjustment = c.offset; - ByteBuf s = c.buf; - for (;;) { - int localLength = Math.min(length, s.readableBytes() - (index - adjustment)); - switch (s.nioBufferCount()) { - case 0: - throw new UnsupportedOperationException(); - case 1: - array.add(s.nioBuffer(index - adjustment, localLength)); - break; - default: - Collections.addAll(array, s.nioBuffers(index - adjustment, localLength)); - } - - index += localLength; - length -= localLength; - adjustment += s.readableBytes(); - if (length <= 0) { - break; - } - s = buffer(++i); - } - - return array.toArray(new ByteBuffer[array.size()]); - } finally { - array.recycle(); - } - } - - @Override - public boolean hasArray() { - return false; - } - - @Override - public byte[] array() { - throw new UnsupportedOperationException(); - } - - @Override - public int arrayOffset() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean hasMemoryAddress() { - return false; - } - - @Override - public long memoryAddress() { - throw new UnsupportedOperationException(); - } - - @Override - protected void deallocate() { - for (int i = 0; i < buffers.length; i++) { - buffer(i).release(); - } - } - - @Override - public String toString() { - String result = super.toString(); - result = result.substring(0, result.length() - 1); - return result + ", components=" + buffers.length + ')'; - } - - private static final class Component { - private final int index; - private final int offset; - private final ByteBuf buf; - private final int endOffset; - - Component(int index, int offset, ByteBuf buf) { - this.index = index; - this.offset = offset; - endOffset = offset + buf.readableBytes(); - this.buf = buf; - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/HeapByteBufUtil.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/HeapByteBufUtil.java deleted file mode 100755 index 19f34f54b2..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/HeapByteBufUtil.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.buffer; - -/** - * Utility class for heap buffers. - */ -final class HeapByteBufUtil { - - static byte getByte(byte[] memory, int index) { - return memory[index]; - } - - static short getShort(byte[] memory, int index) { - return (short) (memory[index] << 8 | memory[index + 1] & 0xFF); - } - - static int getUnsignedMedium(byte[] memory, int index) { - return (memory[index] & 0xff) << 16 | - (memory[index + 1] & 0xff) << 8 | - memory[index + 2] & 0xff; - } - - static int getInt(byte[] memory, int index) { - return (memory[index] & 0xff) << 24 | - (memory[index + 1] & 0xff) << 16 | - (memory[index + 2] & 0xff) << 8 | - memory[index + 3] & 0xff; - } - - static long getLong(byte[] memory, int index) { - return ((long) memory[index] & 0xff) << 56 | - ((long) memory[index + 1] & 0xff) << 48 | - ((long) memory[index + 2] & 0xff) << 40 | - ((long) memory[index + 3] & 0xff) << 32 | - ((long) memory[index + 4] & 0xff) << 24 | - ((long) memory[index + 5] & 0xff) << 16 | - ((long) memory[index + 6] & 0xff) << 8 | - (long) memory[index + 7] & 0xff; - } - - static void setByte(byte[] memory, int index, int value) { - memory[index] = (byte) value; - } - - static void setShort(byte[] memory, int index, int value) { - memory[index] = (byte) (value >>> 8); - memory[index + 1] = (byte) value; - } - - static void setMedium(byte[] memory, int index, int value) { - memory[index] = (byte) (value >>> 16); - memory[index + 1] = (byte) (value >>> 8); - memory[index + 2] = (byte) value; - } - - static void setInt(byte[] memory, int index, int value) { - memory[index] = (byte) (value >>> 24); - memory[index + 1] = (byte) (value >>> 16); - memory[index + 2] = (byte) (value >>> 8); - memory[index + 3] = (byte) value; - } - - static void setLong(byte[] memory, int index, long value) { - memory[index] = (byte) (value >>> 56); - memory[index + 1] = (byte) (value >>> 48); - memory[index + 2] = (byte) (value >>> 40); - memory[index + 3] = (byte) (value >>> 32); - memory[index + 4] = (byte) (value >>> 24); - memory[index + 5] = (byte) (value >>> 16); - memory[index + 6] = (byte) (value >>> 8); - memory[index + 7] = (byte) value; - } - - private HeapByteBufUtil() { } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolArena.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolArena.java deleted file mode 100755 index 4469612f19..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolArena.java +++ /dev/null @@ -1,688 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.buffer; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import com.ai.cloud.io.netty.util.internal.LongCounter; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; -import com.ai.cloud.io.netty.util.internal.StringUtil; - -abstract class PoolArena implements PoolArenaMetric { - static final boolean HAS_UNSAFE = PlatformDependent.hasUnsafe(); - - enum SizeClass { - Tiny, - Small, - Normal - } - - static final int numTinySubpagePools = 512 >>> 4; - - final PooledByteBufAllocator parent; - - private final int maxOrder; - final int pageSize; - final int pageShifts; - final int chunkSize; - final int subpageOverflowMask; - final int numSmallSubpagePools; - private final PoolSubpage[] tinySubpagePools; - private final PoolSubpage[] smallSubpagePools; - - private final PoolChunkList q050; - private final PoolChunkList q025; - private final PoolChunkList q000; - private final PoolChunkList qInit; - private final PoolChunkList q075; - private final PoolChunkList q100; - - private final List chunkListMetrics; - - // Metrics for allocations and deallocations - private long allocationsTiny; - private long allocationsSmall; - private long allocationsNormal; - // We need to use the LongCounter here as this is not guarded via synchronized block. - private final LongCounter allocationsHuge = PlatformDependent.newLongCounter(); - - private long deallocationsTiny; - private long deallocationsSmall; - private long deallocationsNormal; - // We need to use the LongCounter here as this is not guarded via synchronized block. - private final LongCounter deallocationsHuge = PlatformDependent.newLongCounter(); - - // TODO: Test if adding padding helps under contention - //private long pad0, pad1, pad2, pad3, pad4, pad5, pad6, pad7; - - protected PoolArena(PooledByteBufAllocator parent, int pageSize, int maxOrder, int pageShifts, int chunkSize) { - this.parent = parent; - this.pageSize = pageSize; - this.maxOrder = maxOrder; - this.pageShifts = pageShifts; - this.chunkSize = chunkSize; - subpageOverflowMask = ~(pageSize - 1); - tinySubpagePools = newSubpagePoolArray(numTinySubpagePools); - for (int i = 0; i < tinySubpagePools.length; i ++) { - tinySubpagePools[i] = newSubpagePoolHead(pageSize); - } - - numSmallSubpagePools = pageShifts - 9; - smallSubpagePools = newSubpagePoolArray(numSmallSubpagePools); - for (int i = 0; i < smallSubpagePools.length; i ++) { - smallSubpagePools[i] = newSubpagePoolHead(pageSize); - } - - q100 = new PoolChunkList(null, 100, Integer.MAX_VALUE); - q075 = new PoolChunkList(q100, 75, 100); - q050 = new PoolChunkList(q075, 50, 100); - q025 = new PoolChunkList(q050, 25, 75); - q000 = new PoolChunkList(q025, 1, 50); - qInit = new PoolChunkList(q000, Integer.MIN_VALUE, 25); - - q100.prevList(q075); - q075.prevList(q050); - q050.prevList(q025); - q025.prevList(q000); - q000.prevList(null); - qInit.prevList(qInit); - - List metrics = new ArrayList(6); - metrics.add(qInit); - metrics.add(q000); - metrics.add(q025); - metrics.add(q050); - metrics.add(q075); - metrics.add(q100); - chunkListMetrics = Collections.unmodifiableList(metrics); - } - - private PoolSubpage newSubpagePoolHead(int pageSize) { - PoolSubpage head = new PoolSubpage(pageSize); - head.prev = head; - head.next = head; - return head; - } - - @SuppressWarnings("unchecked") - private PoolSubpage[] newSubpagePoolArray(int size) { - return new PoolSubpage[size]; - } - - abstract boolean isDirect(); - - PooledByteBuf allocate(PoolThreadCache cache, int reqCapacity, int maxCapacity) { - PooledByteBuf buf = newByteBuf(maxCapacity); - allocate(cache, buf, reqCapacity); - return buf; - } - - static int tinyIdx(int normCapacity) { - return normCapacity >>> 4; - } - - static int smallIdx(int normCapacity) { - int tableIdx = 0; - int i = normCapacity >>> 10; - while (i != 0) { - i >>>= 1; - tableIdx ++; - } - return tableIdx; - } - - // capacity < pageSize - boolean isTinyOrSmall(int normCapacity) { - return (normCapacity & subpageOverflowMask) == 0; - } - - // normCapacity < 512 - static boolean isTiny(int normCapacity) { - return (normCapacity & 0xFFFFFE00) == 0; - } - - private void allocate(PoolThreadCache cache, PooledByteBuf buf, final int reqCapacity) { - final int normCapacity = normalizeCapacity(reqCapacity); - if (isTinyOrSmall(normCapacity)) { // capacity < pageSize - int tableIdx; - PoolSubpage[] table; - boolean tiny = isTiny(normCapacity); - if (tiny) { // < 512 - if (cache.allocateTiny(this, buf, reqCapacity, normCapacity)) { - // was able to allocate out of the cache so move on - return; - } - tableIdx = tinyIdx(normCapacity); - table = tinySubpagePools; - } else { - if (cache.allocateSmall(this, buf, reqCapacity, normCapacity)) { - // was able to allocate out of the cache so move on - return; - } - tableIdx = smallIdx(normCapacity); - table = smallSubpagePools; - } - - final PoolSubpage head = table[tableIdx]; - - /** - * Synchronize on the head. This is needed as {@link PoolChunk#allocateSubpage(int)} and - * {@link PoolChunk#free(long)} may modify the doubly linked list as well. - */ - synchronized (head) { - final PoolSubpage s = head.next; - if (s != head) { - assert s.doNotDestroy && s.elemSize == normCapacity; - long handle = s.allocate(); - assert handle >= 0; - s.chunk.initBufWithSubpage(buf, handle, reqCapacity); - - if (tiny) { - ++allocationsTiny; - } else { - ++allocationsSmall; - } - return; - } - } - allocateNormal(buf, reqCapacity, normCapacity); - return; - } - if (normCapacity <= chunkSize) { - if (cache.allocateNormal(this, buf, reqCapacity, normCapacity)) { - // was able to allocate out of the cache so move on - return; - } - allocateNormal(buf, reqCapacity, normCapacity); - } else { - // Huge allocations are never served via the cache so just call allocateHuge - allocateHuge(buf, reqCapacity); - } - } - - private synchronized void allocateNormal(PooledByteBuf buf, int reqCapacity, int normCapacity) { - ++allocationsNormal; - if (q050.allocate(buf, reqCapacity, normCapacity) || q025.allocate(buf, reqCapacity, normCapacity) || - q000.allocate(buf, reqCapacity, normCapacity) || qInit.allocate(buf, reqCapacity, normCapacity) || - q075.allocate(buf, reqCapacity, normCapacity) || q100.allocate(buf, reqCapacity, normCapacity)) { - return; - } - - // Add a new chunk. - PoolChunk c = newChunk(pageSize, maxOrder, pageShifts, chunkSize); - long handle = c.allocate(normCapacity); - assert handle > 0; - c.initBuf(buf, handle, reqCapacity); - qInit.add(c); - } - - private void allocateHuge(PooledByteBuf buf, int reqCapacity) { - allocationsHuge.increment(); - buf.initUnpooled(newUnpooledChunk(reqCapacity), reqCapacity); - } - - void free(PoolChunk chunk, long handle, int normCapacity, PoolThreadCache cache) { - if (chunk.unpooled) { - allocationsHuge.decrement(); - destroyChunk(chunk); - } else { - SizeClass sizeClass = sizeClass(normCapacity); - if (cache != null && cache.add(this, chunk, handle, normCapacity, sizeClass)) { - // cached so not free it. - return; - } - - freeChunk(chunk, handle, sizeClass); - } - } - - private SizeClass sizeClass(int normCapacity) { - if (!isTinyOrSmall(normCapacity)) { - return SizeClass.Normal; - } - return isTiny(normCapacity) ? SizeClass.Tiny : SizeClass.Small; - } - - void freeChunk(PoolChunk chunk, long handle, SizeClass sizeClass) { - final boolean destroyChunk; - synchronized (this) { - switch (sizeClass) { - case Normal: - ++deallocationsNormal; - break; - case Small: - ++deallocationsSmall; - break; - case Tiny: - ++deallocationsTiny; - break; - default: - throw new Error(); - } - destroyChunk = !chunk.parent.free(chunk, handle); - } - if (destroyChunk) { - // destroyChunk not need to be called while holding the synchronized lock. - destroyChunk(chunk); - } - } - - PoolSubpage findSubpagePoolHead(int elemSize) { - int tableIdx; - PoolSubpage[] table; - if (isTiny(elemSize)) { // < 512 - tableIdx = elemSize >>> 4; - table = tinySubpagePools; - } else { - tableIdx = 0; - elemSize >>>= 10; - while (elemSize != 0) { - elemSize >>>= 1; - tableIdx ++; - } - table = smallSubpagePools; - } - - return table[tableIdx]; - } - - int normalizeCapacity(int reqCapacity) { - if (reqCapacity < 0) { - throw new IllegalArgumentException("capacity: " + reqCapacity + " (expected: 0+)"); - } - if (reqCapacity >= chunkSize) { - return reqCapacity; - } - - if (!isTiny(reqCapacity)) { // >= 512 - // Doubled - - int normalizedCapacity = reqCapacity; - normalizedCapacity --; - normalizedCapacity |= normalizedCapacity >>> 1; - normalizedCapacity |= normalizedCapacity >>> 2; - normalizedCapacity |= normalizedCapacity >>> 4; - normalizedCapacity |= normalizedCapacity >>> 8; - normalizedCapacity |= normalizedCapacity >>> 16; - normalizedCapacity ++; - - if (normalizedCapacity < 0) { - normalizedCapacity >>>= 1; - } - - return normalizedCapacity; - } - - // Quantum-spaced - if ((reqCapacity & 15) == 0) { - return reqCapacity; - } - - return (reqCapacity & ~15) + 16; - } - - void reallocate(PooledByteBuf buf, int newCapacity, boolean freeOldMemory) { - if (newCapacity < 0 || newCapacity > buf.maxCapacity()) { - throw new IllegalArgumentException("newCapacity: " + newCapacity); - } - - int oldCapacity = buf.length; - if (oldCapacity == newCapacity) { - return; - } - - PoolChunk oldChunk = buf.chunk; - long oldHandle = buf.handle; - T oldMemory = buf.memory; - int oldOffset = buf.offset; - int oldMaxLength = buf.maxLength; - int readerIndex = buf.readerIndex(); - int writerIndex = buf.writerIndex(); - - allocate(parent.threadCache(), buf, newCapacity); - if (newCapacity > oldCapacity) { - memoryCopy( - oldMemory, oldOffset, - buf.memory, buf.offset, oldCapacity); - } else if (newCapacity < oldCapacity) { - if (readerIndex < newCapacity) { - if (writerIndex > newCapacity) { - writerIndex = newCapacity; - } - memoryCopy( - oldMemory, oldOffset + readerIndex, - buf.memory, buf.offset + readerIndex, writerIndex - readerIndex); - } else { - readerIndex = writerIndex = newCapacity; - } - } - - buf.setIndex(readerIndex, writerIndex); - - if (freeOldMemory) { - free(oldChunk, oldHandle, oldMaxLength, buf.cache); - } - } - - @Override - public int numTinySubpages() { - return tinySubpagePools.length; - } - - @Override - public int numSmallSubpages() { - return smallSubpagePools.length; - } - - @Override - public int numChunkLists() { - return chunkListMetrics.size(); - } - - @Override - public List tinySubpages() { - return subPageMetricList(tinySubpagePools); - } - - @Override - public List smallSubpages() { - return subPageMetricList(smallSubpagePools); - } - - @Override - public List chunkLists() { - return chunkListMetrics; - } - - private static List subPageMetricList(PoolSubpage[] pages) { - List metrics = new ArrayList(); - for (int i = 1; i < pages.length; i ++) { - PoolSubpage head = pages[i]; - if (head.next == head) { - continue; - } - PoolSubpage s = head.next; - for (;;) { - metrics.add(s); - s = s.next; - if (s == head) { - break; - } - } - } - return metrics; - } - - @Override - public long numAllocations() { - return allocationsTiny + allocationsSmall + allocationsNormal + allocationsHuge.value(); - } - - @Override - public long numTinyAllocations() { - return allocationsTiny; - } - - @Override - public long numSmallAllocations() { - return allocationsSmall; - } - - @Override - public long numNormalAllocations() { - return allocationsNormal; - } - - @Override - public long numDeallocations() { - return deallocationsTiny + deallocationsSmall + allocationsNormal + deallocationsHuge.value(); - } - - @Override - public long numTinyDeallocations() { - return deallocationsTiny; - } - - @Override - public long numSmallDeallocations() { - return deallocationsSmall; - } - - @Override - public long numNormalDeallocations() { - return deallocationsNormal; - } - - @Override - public long numHugeAllocations() { - return allocationsHuge.value(); - } - - @Override - public long numHugeDeallocations() { - return deallocationsHuge.value(); - } - - @Override - public long numActiveAllocations() { - long val = numAllocations() - numDeallocations(); - return val >= 0 ? val : 0; - } - - @Override - public long numActiveTinyAllocations() { - long val = numTinyAllocations() - numTinyDeallocations(); - return val >= 0 ? val : 0; - } - - @Override - public long numActiveSmallAllocations() { - long val = numSmallAllocations() - numSmallDeallocations(); - return val >= 0 ? val : 0; - } - - @Override - public long numActiveNormalAllocations() { - long val = numNormalAllocations() - numNormalDeallocations(); - return val >= 0 ? val : 0; - } - - @Override - public long numActiveHugeAllocations() { - long val = numHugeAllocations() - numHugeDeallocations(); - return val >= 0 ? val : 0; - } - - protected abstract PoolChunk newChunk(int pageSize, int maxOrder, int pageShifts, int chunkSize); - protected abstract PoolChunk newUnpooledChunk(int capacity); - protected abstract PooledByteBuf newByteBuf(int maxCapacity); - protected abstract void memoryCopy(T src, int srcOffset, T dst, int dstOffset, int length); - protected abstract void destroyChunk(PoolChunk chunk); - - @Override - public synchronized String toString() { - StringBuilder buf = new StringBuilder() - .append("Chunk(s) at 0~25%:") - .append(StringUtil.NEWLINE) - .append(qInit) - .append(StringUtil.NEWLINE) - .append("Chunk(s) at 0~50%:") - .append(StringUtil.NEWLINE) - .append(q000) - .append(StringUtil.NEWLINE) - .append("Chunk(s) at 25~75%:") - .append(StringUtil.NEWLINE) - .append(q025) - .append(StringUtil.NEWLINE) - .append("Chunk(s) at 50~100%:") - .append(StringUtil.NEWLINE) - .append(q050) - .append(StringUtil.NEWLINE) - .append("Chunk(s) at 75~100%:") - .append(StringUtil.NEWLINE) - .append(q075) - .append(StringUtil.NEWLINE) - .append("Chunk(s) at 100%:") - .append(StringUtil.NEWLINE) - .append(q100) - .append(StringUtil.NEWLINE) - .append("tiny subpages:"); - for (int i = 1; i < tinySubpagePools.length; i ++) { - PoolSubpage head = tinySubpagePools[i]; - if (head.next == head) { - continue; - } - - buf.append(StringUtil.NEWLINE) - .append(i) - .append(": "); - PoolSubpage s = head.next; - for (;;) { - buf.append(s); - s = s.next; - if (s == head) { - break; - } - } - } - buf.append(StringUtil.NEWLINE) - .append("small subpages:"); - for (int i = 1; i < smallSubpagePools.length; i ++) { - PoolSubpage head = smallSubpagePools[i]; - if (head.next == head) { - continue; - } - - buf.append(StringUtil.NEWLINE) - .append(i) - .append(": "); - PoolSubpage s = head.next; - for (;;) { - buf.append(s); - s = s.next; - if (s == head) { - break; - } - } - } - buf.append(StringUtil.NEWLINE); - - return buf.toString(); - } - - static final class HeapArena extends PoolArena { - - HeapArena(PooledByteBufAllocator parent, int pageSize, int maxOrder, int pageShifts, int chunkSize) { - super(parent, pageSize, maxOrder, pageShifts, chunkSize); - } - - @Override - boolean isDirect() { - return false; - } - - @Override - protected PoolChunk newChunk(int pageSize, int maxOrder, int pageShifts, int chunkSize) { - return new PoolChunk(this, new byte[chunkSize], pageSize, maxOrder, pageShifts, chunkSize); - } - - @Override - protected PoolChunk newUnpooledChunk(int capacity) { - return new PoolChunk(this, new byte[capacity], capacity); - } - - @Override - protected void destroyChunk(PoolChunk chunk) { - // Rely on GC. - } - - @Override - protected PooledByteBuf newByteBuf(int maxCapacity) { - return HAS_UNSAFE ? PooledUnsafeHeapByteBuf.newUnsafeInstance(maxCapacity) - : PooledHeapByteBuf.newInstance(maxCapacity); - } - - @Override - protected void memoryCopy(byte[] src, int srcOffset, byte[] dst, int dstOffset, int length) { - if (length == 0) { - return; - } - - System.arraycopy(src, srcOffset, dst, dstOffset, length); - } - } - - static final class DirectArena extends PoolArena { - - DirectArena(PooledByteBufAllocator parent, int pageSize, int maxOrder, int pageShifts, int chunkSize) { - super(parent, pageSize, maxOrder, pageShifts, chunkSize); - } - - @Override - boolean isDirect() { - return true; - } - - @Override - protected PoolChunk newChunk(int pageSize, int maxOrder, int pageShifts, int chunkSize) { - return new PoolChunk( - this, ByteBuffer.allocateDirect(chunkSize), pageSize, maxOrder, pageShifts, chunkSize); - } - - @Override - protected PoolChunk newUnpooledChunk(int capacity) { - return new PoolChunk(this, ByteBuffer.allocateDirect(capacity), capacity); - } - - @Override - protected void destroyChunk(PoolChunk chunk) { - PlatformDependent.freeDirectBuffer(chunk.memory); - } - - @Override - protected PooledByteBuf newByteBuf(int maxCapacity) { - if (HAS_UNSAFE) { - return PooledUnsafeDirectByteBuf.newInstance(maxCapacity); - } else { - return PooledDirectByteBuf.newInstance(maxCapacity); - } - } - - @Override - protected void memoryCopy(ByteBuffer src, int srcOffset, ByteBuffer dst, int dstOffset, int length) { - if (length == 0) { - return; - } - - if (HAS_UNSAFE) { - PlatformDependent.copyMemory( - PlatformDependent.directBufferAddress(src) + srcOffset, - PlatformDependent.directBufferAddress(dst) + dstOffset, length); - } else { - // We must duplicate the NIO buffers because they may be accessed by other Netty buffers. - src = src.duplicate(); - dst = dst.duplicate(); - src.position(srcOffset).limit(srcOffset + length); - dst.position(dstOffset); - dst.put(src); - } - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolArenaMetric.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolArenaMetric.java deleted file mode 100755 index 56c94eb3e7..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolArenaMetric.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.buffer; - -import java.util.List; - -/** - * Expose metrics for an arena. - */ -public interface PoolArenaMetric { - - /** - * Returns the number of tiny sub-pages for the arena. - */ - int numTinySubpages(); - - /** - * Returns the number of small sub-pages for the arena. - */ - int numSmallSubpages(); - - /** - * Returns the number of chunk lists for the arena. - */ - int numChunkLists(); - - /** - * Returns an unmodifiable {@link List} which holds {@link PoolSubpageMetric}s for tiny sub-pages. - */ - List tinySubpages(); - - /** - * Returns an unmodifiable {@link List} which holds {@link PoolSubpageMetric}s for small sub-pages. - */ - List smallSubpages(); - - /** - * Returns an unmodifiable {@link List} which holds {@link PoolChunkListMetric}s. - */ - List chunkLists(); - - /** - * Return the number of allocations done via the arena. This includes all sizes. - */ - long numAllocations(); - - /** - * Return the number of tiny allocations done via the arena. - */ - long numTinyAllocations(); - - /** - * Return the number of small allocations done via the arena. - */ - long numSmallAllocations(); - - /** - * Return the number of normal allocations done via the arena. - */ - long numNormalAllocations(); - - /** - * Return the number of huge allocations done via the arena. - */ - long numHugeAllocations(); - - /** - * Return the number of deallocations done via the arena. This includes all sizes. - */ - long numDeallocations(); - - /** - * Return the number of tiny deallocations done via the arena. - */ - long numTinyDeallocations(); - - /** - * Return the number of small deallocations done via the arena. - */ - long numSmallDeallocations(); - - /** - * Return the number of normal deallocations done via the arena. - */ - long numNormalDeallocations(); - - /** - * Return the number of huge deallocations done via the arena. - */ - long numHugeDeallocations(); - - /** - * Return the number of currently active allocations. - */ - long numActiveAllocations(); - - /** - * Return the number of currently active tiny allocations. - */ - long numActiveTinyAllocations(); - - /** - * Return the number of currently active small allocations. - */ - long numActiveSmallAllocations(); - - /** - * Return the number of currently active normal allocations. - */ - long numActiveNormalAllocations(); - - /** - * Return the number of currently active huge allocations. - */ - long numActiveHugeAllocations(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolChunk.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolChunk.java deleted file mode 100755 index bc4fe080aa..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolChunk.java +++ /dev/null @@ -1,454 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.buffer; - -/** - * Description of algorithm for PageRun/PoolSubpage allocation from PoolChunk - * - * Notation: The following terms are important to understand the code - * > page - a page is the smallest unit of memory chunk that can be allocated - * > chunk - a chunk is a collection of pages - * > in this code chunkSize = 2^{maxOrder} * pageSize - * - * To begin we allocate a byte array of size = chunkSize - * Whenever a ByteBuf of given size needs to be created we search for the first position - * in the byte array that has enough empty space to accommodate the requested size and - * return a (long) handle that encodes this offset information, (this memory segment is then - * marked as reserved so it is always used by exactly one ByteBuf and no more) - * - * For simplicity all sizes are normalized according to PoolArena#normalizeCapacity method - * This ensures that when we request for memory segments of size >= pageSize the normalizedCapacity - * equals the next nearest power of 2 - * - * To search for the first offset in chunk that has at least requested size available we construct a - * complete balanced binary tree and store it in an array (just like heaps) - memoryMap - * - * The tree looks like this (the size of each node being mentioned in the parenthesis) - * - * depth=0 1 node (chunkSize) - * depth=1 2 nodes (chunkSize/2) - * .. - * .. - * depth=d 2^d nodes (chunkSize/2^d) - * .. - * depth=maxOrder 2^maxOrder nodes (chunkSize/2^{maxOrder} = pageSize) - * - * depth=maxOrder is the last level and the leafs consist of pages - * - * With this tree available searching in chunkArray translates like this: - * To allocate a memory segment of size chunkSize/2^k we search for the first node (from left) at height k - * which is unused - * - * Algorithm: - * ---------- - * Encode the tree in memoryMap with the notation - * memoryMap[id] = x => in the subtree rooted at id, the first node that is free to be allocated - * is at depth x (counted from depth=0) i.e., at depths [depth_of_id, x), there is no node that is free - * - * As we allocate & free nodes, we update values stored in memoryMap so that the property is maintained - * - * Initialization - - * In the beginning we construct the memoryMap array by storing the depth of a node at each node - * i.e., memoryMap[id] = depth_of_id - * - * Observations: - * ------------- - * 1) memoryMap[id] = depth_of_id => it is free / unallocated - * 2) memoryMap[id] > depth_of_id => at least one of its child nodes is allocated, so we cannot allocate it, but - * some of its children can still be allocated based on their availability - * 3) memoryMap[id] = maxOrder + 1 => the node is fully allocated & thus none of its children can be allocated, it - * is thus marked as unusable - * - * Algorithm: [allocateNode(d) => we want to find the first node (from left) at height h that can be allocated] - * ---------- - * 1) start at root (i.e., depth = 0 or id = 1) - * 2) if memoryMap[1] > d => cannot be allocated from this chunk - * 3) if left node value <= h; we can allocate from left subtree so move to left and repeat until found - * 4) else try in right subtree - * - * Algorithm: [allocateRun(size)] - * ---------- - * 1) Compute d = log_2(chunkSize/size) - * 2) Return allocateNode(d) - * - * Algorithm: [allocateSubpage(size)] - * ---------- - * 1) use allocateNode(maxOrder) to find an empty (i.e., unused) leaf (i.e., page) - * 2) use this handle to construct the PoolSubpage object or if it already exists just call init(normCapacity) - * note that this PoolSubpage object is added to subpagesPool in the PoolArena when we init() it - * - * Note: - * ----- - * In the implementation for improving cache coherence, - * we store 2 pieces of information (i.e, 2 byte vals) as a short value in memoryMap - * - * memoryMap[id]= (depth_of_id, x) - * where as per convention defined above - * the second value (i.e, x) indicates that the first node which is free to be allocated is at depth x (from root) - */ -final class PoolChunk implements PoolChunkMetric { - - final PoolArena arena; - final T memory; - final boolean unpooled; - - private final byte[] memoryMap; - private final byte[] depthMap; - private final PoolSubpage[] subpages; - /** Used to determine if the requested capacity is equal to or greater than pageSize. */ - private final int subpageOverflowMask; - private final int pageSize; - private final int pageShifts; - private final int maxOrder; - private final int chunkSize; - private final int log2ChunkSize; - private final int maxSubpageAllocs; - /** Used to mark memory as unusable */ - private final byte unusable; - - private int freeBytes; - - PoolChunkList parent; - PoolChunk prev; - PoolChunk next; - - // TODO: Test if adding padding helps under contention - //private long pad0, pad1, pad2, pad3, pad4, pad5, pad6, pad7; - - PoolChunk(PoolArena arena, T memory, int pageSize, int maxOrder, int pageShifts, int chunkSize) { - unpooled = false; - this.arena = arena; - this.memory = memory; - this.pageSize = pageSize; - this.pageShifts = pageShifts; - this.maxOrder = maxOrder; - this.chunkSize = chunkSize; - unusable = (byte) (maxOrder + 1); - log2ChunkSize = log2(chunkSize); - subpageOverflowMask = ~(pageSize - 1); - freeBytes = chunkSize; - - assert maxOrder < 30 : "maxOrder should be < 30, but is: " + maxOrder; - maxSubpageAllocs = 1 << maxOrder; - - // Generate the memory map. - memoryMap = new byte[maxSubpageAllocs << 1]; - depthMap = new byte[memoryMap.length]; - int memoryMapIndex = 1; - for (int d = 0; d <= maxOrder; ++ d) { // move down the tree one level at a time - int depth = 1 << d; - for (int p = 0; p < depth; ++ p) { - // in each level traverse left to right and set value to the depth of subtree - memoryMap[memoryMapIndex] = (byte) d; - depthMap[memoryMapIndex] = (byte) d; - memoryMapIndex ++; - } - } - - subpages = newSubpageArray(maxSubpageAllocs); - } - - /** Creates a special chunk that is not pooled. */ - PoolChunk(PoolArena arena, T memory, int size) { - unpooled = true; - this.arena = arena; - this.memory = memory; - memoryMap = null; - depthMap = null; - subpages = null; - subpageOverflowMask = 0; - pageSize = 0; - pageShifts = 0; - maxOrder = 0; - unusable = (byte) (maxOrder + 1); - chunkSize = size; - log2ChunkSize = log2(chunkSize); - maxSubpageAllocs = 0; - } - - @SuppressWarnings("unchecked") - private PoolSubpage[] newSubpageArray(int size) { - return new PoolSubpage[size]; - } - - @Override - public int usage() { - final int freeBytes = this.freeBytes; - if (freeBytes == 0) { - return 100; - } - - int freePercentage = (int) (freeBytes * 100L / chunkSize); - if (freePercentage == 0) { - return 99; - } - return 100 - freePercentage; - } - - long allocate(int normCapacity) { - if ((normCapacity & subpageOverflowMask) != 0) { // >= pageSize - return allocateRun(normCapacity); - } else { - return allocateSubpage(normCapacity); - } - } - - /** - * Update method used by allocate - * This is triggered only when a successor is allocated and all its predecessors - * need to update their state - * The minimal depth at which subtree rooted at id has some free space - * - * @param id id - */ - private void updateParentsAlloc(int id) { - while (id > 1) { - int parentId = id >>> 1; - byte val1 = value(id); - byte val2 = value(id ^ 1); - byte val = val1 < val2 ? val1 : val2; - setValue(parentId, val); - id = parentId; - } - } - - /** - * Update method used by free - * This needs to handle the special case when both children are completely free - * in which case parent be directly allocated on request of size = child-size * 2 - * - * @param id id - */ - private void updateParentsFree(int id) { - int logChild = depth(id) + 1; - while (id > 1) { - int parentId = id >>> 1; - byte val1 = value(id); - byte val2 = value(id ^ 1); - logChild -= 1; // in first iteration equals log, subsequently reduce 1 from logChild as we traverse up - - if (val1 == logChild && val2 == logChild) { - setValue(parentId, (byte) (logChild - 1)); - } else { - byte val = val1 < val2 ? val1 : val2; - setValue(parentId, val); - } - - id = parentId; - } - } - - /** - * Algorithm to allocate an index in memoryMap when we query for a free node - * at depth d - * - * @param d depth - * @return index in memoryMap - */ - private int allocateNode(int d) { - int id = 1; - int initial = - (1 << d); // has last d bits = 0 and rest all = 1 - byte val = value(id); - if (val > d) { // unusable - return -1; - } - while (val < d || (id & initial) == 0) { // id & initial == 1 << d for all ids at depth d, for < d it is 0 - id <<= 1; - val = value(id); - if (val > d) { - id ^= 1; - val = value(id); - } - } - byte value = value(id); - assert value == d && (id & initial) == 1 << d : String.format("val = %d, id & initial = %d, d = %d", - value, id & initial, d); - setValue(id, unusable); // mark as unusable - updateParentsAlloc(id); - return id; - } - - /** - * Allocate a run of pages (>=1) - * - * @param normCapacity normalized capacity - * @return index in memoryMap - */ - private long allocateRun(int normCapacity) { - int d = maxOrder - (log2(normCapacity) - pageShifts); - int id = allocateNode(d); - if (id < 0) { - return id; - } - freeBytes -= runLength(id); - return id; - } - - /** - * Create/ initialize a new PoolSubpage of normCapacity - * Any PoolSubpage created/ initialized here is added to subpage pool in the PoolArena that owns this PoolChunk - * - * @param normCapacity normalized capacity - * @return index in memoryMap - */ - private long allocateSubpage(int normCapacity) { - // Obtain the head of the PoolSubPage pool that is owned by the PoolArena and synchronize on it. - // This is need as we may add it back and so alter the linked-list structure. - PoolSubpage head = arena.findSubpagePoolHead(normCapacity); - synchronized (head) { - int d = maxOrder; // subpages are only be allocated from pages i.e., leaves - int id = allocateNode(d); - if (id < 0) { - return id; - } - - final PoolSubpage[] subpages = this.subpages; - final int pageSize = this.pageSize; - - freeBytes -= pageSize; - - int subpageIdx = subpageIdx(id); - PoolSubpage subpage = subpages[subpageIdx]; - if (subpage == null) { - subpage = new PoolSubpage(head, this, id, runOffset(id), pageSize, normCapacity); - subpages[subpageIdx] = subpage; - } else { - subpage.init(head, normCapacity); - } - return subpage.allocate(); - } - } - - /** - * Free a subpage or a run of pages - * When a subpage is freed from PoolSubpage, it might be added back to subpage pool of the owning PoolArena - * If the subpage pool in PoolArena has at least one other PoolSubpage of given elemSize, we can - * completely free the owning Page so it is available for subsequent allocations - * - * @param handle handle to free - */ - void free(long handle) { - int memoryMapIdx = (int) handle; - int bitmapIdx = (int) (handle >>> Integer.SIZE); - - if (bitmapIdx != 0) { // free a subpage - PoolSubpage subpage = subpages[subpageIdx(memoryMapIdx)]; - assert subpage != null && subpage.doNotDestroy; - - // Obtain the head of the PoolSubPage pool that is owned by the PoolArena and synchronize on it. - // This is need as we may add it back and so alter the linked-list structure. - PoolSubpage head = arena.findSubpagePoolHead(subpage.elemSize); - synchronized (head) { - if (subpage.free(head, bitmapIdx & 0x3FFFFFFF)) { - return; - } - } - } - freeBytes += runLength(memoryMapIdx); - setValue(memoryMapIdx, depth(memoryMapIdx)); - updateParentsFree(memoryMapIdx); - } - - void initBuf(PooledByteBuf buf, long handle, int reqCapacity) { - int memoryMapIdx = (int) handle; - int bitmapIdx = (int) (handle >>> Integer.SIZE); - if (bitmapIdx == 0) { - byte val = value(memoryMapIdx); - assert val == unusable : String.valueOf(val); - buf.init(this, handle, runOffset(memoryMapIdx), reqCapacity, runLength(memoryMapIdx), - arena.parent.threadCache()); - } else { - initBufWithSubpage(buf, handle, bitmapIdx, reqCapacity); - } - } - - void initBufWithSubpage(PooledByteBuf buf, long handle, int reqCapacity) { - initBufWithSubpage(buf, handle, (int) (handle >>> Integer.SIZE), reqCapacity); - } - - private void initBufWithSubpage(PooledByteBuf buf, long handle, int bitmapIdx, int reqCapacity) { - assert bitmapIdx != 0; - - int memoryMapIdx = (int) handle; - - PoolSubpage subpage = subpages[subpageIdx(memoryMapIdx)]; - assert subpage.doNotDestroy; - assert reqCapacity <= subpage.elemSize; - - buf.init( - this, handle, - runOffset(memoryMapIdx) + (bitmapIdx & 0x3FFFFFFF) * subpage.elemSize, reqCapacity, subpage.elemSize, - arena.parent.threadCache()); - } - - private byte value(int id) { - return memoryMap[id]; - } - - private void setValue(int id, byte val) { - memoryMap[id] = val; - } - - private byte depth(int id) { - return depthMap[id]; - } - - private static int log2(int val) { - // compute the (0-based, with lsb = 0) position of highest set bit i.e, log2 - return Integer.SIZE - 1 - Integer.numberOfLeadingZeros(val); - } - - private int runLength(int id) { - // represents the size in #bytes supported by node 'id' in the tree - return 1 << log2ChunkSize - depth(id); - } - - private int runOffset(int id) { - // represents the 0-based offset in #bytes from start of the byte-array chunk - int shift = id ^ 1 << depth(id); - return shift * runLength(id); - } - - private int subpageIdx(int memoryMapIdx) { - return memoryMapIdx ^ maxSubpageAllocs; // remove highest set bit, to get offset - } - - @Override - public int chunkSize() { - return chunkSize; - } - - @Override - public int freeBytes() { - return freeBytes; - } - - @Override - public String toString() { - return new StringBuilder() - .append("Chunk(") - .append(Integer.toHexString(System.identityHashCode(this))) - .append(": ") - .append(usage()) - .append("%, ") - .append(chunkSize - freeBytes) - .append('/') - .append(chunkSize) - .append(')') - .toString(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolChunkList.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolChunkList.java deleted file mode 100755 index 5578028281..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolChunkList.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.buffer; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -import com.ai.cloud.io.netty.util.internal.StringUtil; - -final class PoolChunkList implements PoolChunkListMetric { - private static final Iterator EMPTY_METRICS = Collections.emptyList().iterator(); - private final PoolChunkList nextList; - private final int minUsage; - private final int maxUsage; - - private PoolChunk head; - - // This is only update once when create the linked like list of PoolChunkList in PoolArena constructor. - private PoolChunkList prevList; - - // TODO: Test if adding padding helps under contention - //private long pad0, pad1, pad2, pad3, pad4, pad5, pad6, pad7; - - PoolChunkList(PoolChunkList nextList, int minUsage, int maxUsage) { - this.nextList = nextList; - this.minUsage = minUsage; - this.maxUsage = maxUsage; - } - - void prevList(PoolChunkList prevList) { - assert this.prevList == null; - this.prevList = prevList; - } - - boolean allocate(PooledByteBuf buf, int reqCapacity, int normCapacity) { - if (head == null) { - return false; - } - - for (PoolChunk cur = head;;) { - long handle = cur.allocate(normCapacity); - if (handle < 0) { - cur = cur.next; - if (cur == null) { - return false; - } - } else { - cur.initBuf(buf, handle, reqCapacity); - if (cur.usage() >= maxUsage) { - remove(cur); - nextList.add(cur); - } - return true; - } - } - } - - boolean free(PoolChunk chunk, long handle) { - chunk.free(handle); - if (chunk.usage() < minUsage) { - remove(chunk); - if (prevList == null) { - assert chunk.usage() == 0; - return false; - } else { - prevList.add(chunk); - return true; - } - } - return true; - } - - void add(PoolChunk chunk) { - if (chunk.usage() >= maxUsage) { - nextList.add(chunk); - return; - } - - 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; - } - } - - private void remove(PoolChunk cur) { - if (cur == head) { - head = cur.next; - if (head != null) { - head.prev = null; - } - } else { - PoolChunk next = cur.next; - cur.prev.next = next; - if (next != null) { - next.prev = cur.prev; - } - } - } - - @Override - public int minUsage() { - return minUsage; - } - - @Override - public int maxUsage() { - return maxUsage; - } - - @Override - public Iterator iterator() { - if (head == null) { - return EMPTY_METRICS; - } - List metrics = new ArrayList(); - for (PoolChunk cur = head;;) { - metrics.add(cur); - cur = cur.next; - if (cur == null) { - break; - } - } - return metrics.iterator(); - } - - @Override - public String toString() { - if (head == null) { - return "none"; - } - - StringBuilder buf = new StringBuilder(); - for (PoolChunk cur = head;;) { - buf.append(cur); - cur = cur.next; - if (cur == null) { - break; - } - buf.append(StringUtil.NEWLINE); - } - - return buf.toString(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolChunkListMetric.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolChunkListMetric.java deleted file mode 100755 index 774002826e..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolChunkListMetric.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.buffer; - -/** - * Metrics for a list of chunks. - */ -public interface PoolChunkListMetric extends Iterable { - - /** - * Return the minum usage of the chunk list before which chunks are promoted to the previous list. - */ - int minUsage(); - - /** - * Return the minum usage of the chunk list after which chunks are promoted to the next list. - */ - int maxUsage(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolChunkMetric.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolChunkMetric.java deleted file mode 100755 index fe7930283f..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolChunkMetric.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.buffer; - -/** - * Metrics for a chunk. - */ -public interface PoolChunkMetric { - - /** - * Return the percentage of the current usage of the chunk. - */ - int usage(); - - /** - * Return the size of the chunk in bytes, this is the maximum of bytes that can be served out of the chunk. - */ - int chunkSize(); - - /** - * Return the number of free bytes in the chunk. - */ - int freeBytes(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolSubpage.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolSubpage.java deleted file mode 100755 index db1ef777ca..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolSubpage.java +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.buffer; - -final class PoolSubpage implements PoolSubpageMetric { - - final PoolChunk chunk; - private final int memoryMapIdx; - private final int runOffset; - private final int pageSize; - private final long[] bitmap; - - PoolSubpage prev; - PoolSubpage next; - - boolean doNotDestroy; - int elemSize; - private int maxNumElems; - private int bitmapLength; - private int nextAvail; - private int numAvail; - - // TODO: Test if adding padding helps under contention - //private long pad0, pad1, pad2, pad3, pad4, pad5, pad6, pad7; - - /** Special constructor that creates a linked list head */ - PoolSubpage(int pageSize) { - chunk = null; - memoryMapIdx = -1; - runOffset = -1; - elemSize = -1; - this.pageSize = pageSize; - bitmap = null; - } - - PoolSubpage(PoolSubpage head, PoolChunk chunk, int memoryMapIdx, int runOffset, int pageSize, int elemSize) { - this.chunk = chunk; - this.memoryMapIdx = memoryMapIdx; - this.runOffset = runOffset; - this.pageSize = pageSize; - bitmap = new long[pageSize >>> 10]; // pageSize / 16 / 64 - init(head, elemSize); - } - - void init(PoolSubpage head, int elemSize) { - doNotDestroy = true; - this.elemSize = elemSize; - if (elemSize != 0) { - maxNumElems = numAvail = pageSize / elemSize; - nextAvail = 0; - bitmapLength = maxNumElems >>> 6; - if ((maxNumElems & 63) != 0) { - bitmapLength ++; - } - - for (int i = 0; i < bitmapLength; i ++) { - bitmap[i] = 0; - } - } - addToPool(head); - } - - /** - * Returns the bitmap index of the subpage allocation. - */ - long allocate() { - if (elemSize == 0) { - return toHandle(0); - } - - if (numAvail == 0 || !doNotDestroy) { - return -1; - } - - final int bitmapIdx = getNextAvail(); - int q = bitmapIdx >>> 6; - int r = bitmapIdx & 63; - assert (bitmap[q] >>> r & 1) == 0; - bitmap[q] |= 1L << r; - - if (-- numAvail == 0) { - removeFromPool(); - } - - return toHandle(bitmapIdx); - } - - /** - * @return {@code true} if this subpage is in use. - * {@code false} if this subpage is not used by its chunk and thus it's OK to be released. - */ - boolean free(PoolSubpage head, int bitmapIdx) { - if (elemSize == 0) { - return true; - } - int q = bitmapIdx >>> 6; - int r = bitmapIdx & 63; - assert (bitmap[q] >>> r & 1) != 0; - bitmap[q] ^= 1L << r; - - setNextAvail(bitmapIdx); - - if (numAvail ++ == 0) { - addToPool(head); - return true; - } - - if (numAvail != maxNumElems) { - return true; - } else { - // Subpage not in use (numAvail == maxNumElems) - if (prev == next) { - // Do not remove if this subpage is the only one left in the pool. - return true; - } - - // Remove this subpage from the pool if there are other subpages left in the pool. - doNotDestroy = false; - removeFromPool(); - return false; - } - } - - private void addToPool(PoolSubpage head) { - assert prev == null && next == null; - prev = head; - next = head.next; - next.prev = this; - head.next = this; - } - - private void removeFromPool() { - assert prev != null && next != null; - prev.next = next; - next.prev = prev; - next = null; - prev = null; - } - - private void setNextAvail(int bitmapIdx) { - nextAvail = bitmapIdx; - } - - private int getNextAvail() { - int nextAvail = this.nextAvail; - if (nextAvail >= 0) { - this.nextAvail = -1; - return nextAvail; - } - return findNextAvail(); - } - - private int findNextAvail() { - final long[] bitmap = this.bitmap; - final int bitmapLength = this.bitmapLength; - for (int i = 0; i < bitmapLength; i ++) { - long bits = bitmap[i]; - if (~bits != 0) { - return findNextAvail0(i, bits); - } - } - return -1; - } - - private int findNextAvail0(int i, long bits) { - final int maxNumElems = this.maxNumElems; - final int baseVal = i << 6; - - for (int j = 0; j < 64; j ++) { - if ((bits & 1) == 0) { - int val = baseVal | j; - if (val < maxNumElems) { - return val; - } else { - break; - } - } - bits >>>= 1; - } - return -1; - } - - private long toHandle(int bitmapIdx) { - return 0x4000000000000000L | (long) bitmapIdx << 32 | memoryMapIdx; - } - - @Override - public String toString() { - if (!doNotDestroy) { - return "(" + memoryMapIdx + ": not in use)"; - } - - return String.valueOf('(') + memoryMapIdx + ": " + (maxNumElems - numAvail) + '/' + maxNumElems + - ", offset: " + runOffset + ", length: " + pageSize + ", elemSize: " + elemSize + ')'; - } - - @Override - public int maxNumElements() { - return maxNumElems; - } - - @Override - public int numAvailable() { - return numAvail; - } - - @Override - public int elementSize() { - return elemSize; - } - - @Override - public int pageSize() { - return pageSize; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolSubpageMetric.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolSubpageMetric.java deleted file mode 100755 index a7f5e7dd51..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolSubpageMetric.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.buffer; - -/** - * Metrics for a sub-page. - */ -public interface PoolSubpageMetric { - - /** - * Return the number of maximal elements that can be allocated out of the sub-page. - */ - int maxNumElements(); - - /** - * Return the number of available elements to be allocated. - */ - int numAvailable(); - - /** - * Return the size (in bytes) of the elements that will be allocated. - */ - int elementSize(); - - /** - * Return the size (in bytes) of this page. - */ - int pageSize(); -} - diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolThreadCache.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolThreadCache.java deleted file mode 100755 index b9630bebed..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PoolThreadCache.java +++ /dev/null @@ -1,479 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.buffer; - - -import java.nio.ByteBuffer; -import java.util.Queue; - -import com.ai.cloud.io.netty.buffer.PoolArena.SizeClass; -import com.ai.cloud.io.netty.util.Recycler; -import com.ai.cloud.io.netty.util.ThreadDeathWatcher; -import com.ai.cloud.io.netty.util.Recycler.Handle; -import com.ai.cloud.io.netty.util.internal.MathUtil; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * Acts a Thread cache for allocations. This implementation is moduled after - * jemalloc and the descripted - * technics of Scalable memory allocation using jemalloc. - */ -final class PoolThreadCache { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(PoolThreadCache.class); - - final PoolArena heapArena; - final PoolArena directArena; - - // Hold the caches for the different size classes, which are tiny, small and normal. - private final MemoryRegionCache[] tinySubPageHeapCaches; - private final MemoryRegionCache[] smallSubPageHeapCaches; - private final MemoryRegionCache[] tinySubPageDirectCaches; - private final MemoryRegionCache[] smallSubPageDirectCaches; - private final MemoryRegionCache[] normalHeapCaches; - private final MemoryRegionCache[] normalDirectCaches; - - // Used for bitshifting when calculate the index of normal caches later - private final int numShiftsNormalDirect; - private final int numShiftsNormalHeap; - private final int freeSweepAllocationThreshold; - - private int allocations; - - private final Thread thread = Thread.currentThread(); - private final Runnable freeTask = new Runnable() { - @Override - public void run() { - free0(); - } - }; - - // TODO: Test if adding padding helps under contention - //private long pad0, pad1, pad2, pad3, pad4, pad5, pad6, pad7; - - PoolThreadCache(PoolArena heapArena, PoolArena directArena, - int tinyCacheSize, int smallCacheSize, int normalCacheSize, - int maxCachedBufferCapacity, int freeSweepAllocationThreshold) { - if (maxCachedBufferCapacity < 0) { - throw new IllegalArgumentException("maxCachedBufferCapacity: " - + maxCachedBufferCapacity + " (expected: >= 0)"); - } - if (freeSweepAllocationThreshold < 1) { - throw new IllegalArgumentException("freeSweepAllocationThreshold: " - + maxCachedBufferCapacity + " (expected: > 0)"); - } - this.freeSweepAllocationThreshold = freeSweepAllocationThreshold; - this.heapArena = heapArena; - this.directArena = directArena; - if (directArena != null) { - tinySubPageDirectCaches = createSubPageCaches( - tinyCacheSize, PoolArena.numTinySubpagePools, SizeClass.Tiny); - smallSubPageDirectCaches = createSubPageCaches( - smallCacheSize, directArena.numSmallSubpagePools, SizeClass.Small); - - numShiftsNormalDirect = log2(directArena.pageSize); - normalDirectCaches = createNormalCaches( - normalCacheSize, maxCachedBufferCapacity, directArena); - } else { - // No directArea is configured so just null out all caches - tinySubPageDirectCaches = null; - smallSubPageDirectCaches = null; - normalDirectCaches = null; - numShiftsNormalDirect = -1; - } - if (heapArena != null) { - // Create the caches for the heap allocations - tinySubPageHeapCaches = createSubPageCaches( - tinyCacheSize, PoolArena.numTinySubpagePools, SizeClass.Tiny); - smallSubPageHeapCaches = createSubPageCaches( - smallCacheSize, heapArena.numSmallSubpagePools, SizeClass.Small); - - numShiftsNormalHeap = log2(heapArena.pageSize); - normalHeapCaches = createNormalCaches( - normalCacheSize, maxCachedBufferCapacity, heapArena); - } else { - // No heapArea is configured so just null out all caches - tinySubPageHeapCaches = null; - smallSubPageHeapCaches = null; - normalHeapCaches = null; - numShiftsNormalHeap = -1; - } - - // The thread-local cache will keep a list of pooled buffers which must be returned to - // the pool when the thread is not alive anymore. - ThreadDeathWatcher.watch(thread, freeTask); - } - - private static MemoryRegionCache[] createSubPageCaches( - int cacheSize, int numCaches, SizeClass sizeClass) { - if (cacheSize > 0) { - @SuppressWarnings("unchecked") - MemoryRegionCache[] cache = new MemoryRegionCache[numCaches]; - for (int i = 0; i < cache.length; i++) { - // TODO: maybe use cacheSize / cache.length - cache[i] = new SubPageMemoryRegionCache(cacheSize, sizeClass); - } - return cache; - } else { - return null; - } - } - - private static MemoryRegionCache[] createNormalCaches( - int cacheSize, int maxCachedBufferCapacity, PoolArena area) { - if (cacheSize > 0) { - int max = Math.min(area.chunkSize, maxCachedBufferCapacity); - int arraySize = Math.max(1, log2(max / area.pageSize) + 1); - - @SuppressWarnings("unchecked") - MemoryRegionCache[] cache = new MemoryRegionCache[arraySize]; - for (int i = 0; i < cache.length; i++) { - cache[i] = new NormalMemoryRegionCache(cacheSize); - } - return cache; - } else { - return null; - } - } - - private static int log2(int val) { - int res = 0; - while (val > 1) { - val >>= 1; - res++; - } - return res; - } - - /** - * Try to allocate a tiny buffer out of the cache. Returns {@code true} if successful {@code false} otherwise - */ - boolean allocateTiny(PoolArena area, PooledByteBuf buf, int reqCapacity, int normCapacity) { - return allocate(cacheForTiny(area, normCapacity), buf, reqCapacity); - } - - /** - * Try to allocate a small buffer out of the cache. Returns {@code true} if successful {@code false} otherwise - */ - boolean allocateSmall(PoolArena area, PooledByteBuf buf, int reqCapacity, int normCapacity) { - return allocate(cacheForSmall(area, normCapacity), buf, reqCapacity); - } - - /** - * Try to allocate a small buffer out of the cache. Returns {@code true} if successful {@code false} otherwise - */ - boolean allocateNormal(PoolArena area, PooledByteBuf buf, int reqCapacity, int normCapacity) { - return allocate(cacheForNormal(area, normCapacity), buf, reqCapacity); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - private boolean allocate(MemoryRegionCache cache, PooledByteBuf buf, int reqCapacity) { - if (cache == null) { - // no cache found so just return false here - return false; - } - boolean allocated = cache.allocate(buf, reqCapacity); - if (++ allocations >= freeSweepAllocationThreshold) { - allocations = 0; - trim(); - } - return allocated; - } - - /** - * Add {@link PoolChunk} and {@code handle} to the cache if there is enough room. - * Returns {@code true} if it fit into the cache {@code false} otherwise. - */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - boolean add(PoolArena area, PoolChunk chunk, long handle, int normCapacity, SizeClass sizeClass) { - MemoryRegionCache cache = cache(area, normCapacity, sizeClass); - if (cache == null) { - return false; - } - return cache.add(chunk, handle); - } - - private MemoryRegionCache cache(PoolArena area, int normCapacity, SizeClass sizeClass) { - switch (sizeClass) { - case Normal: - return cacheForNormal(area, normCapacity); - case Small: - return cacheForSmall(area, normCapacity); - case Tiny: - return cacheForTiny(area, normCapacity); - default: - throw new Error(); - } - } - - /** - * Should be called if the Thread that uses this cache is about to exist to release resources out of the cache - */ - void free() { - ThreadDeathWatcher.unwatch(thread, freeTask); - free0(); - } - - private void free0() { - int numFreed = free(tinySubPageDirectCaches) + - free(smallSubPageDirectCaches) + - free(normalDirectCaches) + - free(tinySubPageHeapCaches) + - free(smallSubPageHeapCaches) + - free(normalHeapCaches); - - if (numFreed > 0 && logger.isDebugEnabled()) { - logger.debug("Freed {} thread-local buffer(s) from thread: {}", numFreed, thread.getName()); - } - } - - private static int free(MemoryRegionCache[] caches) { - if (caches == null) { - return 0; - } - - int numFreed = 0; - for (MemoryRegionCache c: caches) { - numFreed += free(c); - } - return numFreed; - } - - private static int free(MemoryRegionCache cache) { - if (cache == null) { - return 0; - } - return cache.free(); - } - - void trim() { - trim(tinySubPageDirectCaches); - trim(smallSubPageDirectCaches); - trim(normalDirectCaches); - trim(tinySubPageHeapCaches); - trim(smallSubPageHeapCaches); - trim(normalHeapCaches); - } - - private static void trim(MemoryRegionCache[] caches) { - if (caches == null) { - return; - } - for (MemoryRegionCache c: caches) { - trim(c); - } - } - - private static void trim(MemoryRegionCache cache) { - if (cache == null) { - return; - } - cache.trim(); - } - - private MemoryRegionCache cacheForTiny(PoolArena area, int normCapacity) { - int idx = PoolArena.tinyIdx(normCapacity); - if (area.isDirect()) { - return cache(tinySubPageDirectCaches, idx); - } - return cache(tinySubPageHeapCaches, idx); - } - - private MemoryRegionCache cacheForSmall(PoolArena area, int normCapacity) { - int idx = PoolArena.smallIdx(normCapacity); - if (area.isDirect()) { - return cache(smallSubPageDirectCaches, idx); - } - return cache(smallSubPageHeapCaches, idx); - } - - private MemoryRegionCache cacheForNormal(PoolArena area, int normCapacity) { - if (area.isDirect()) { - int idx = log2(normCapacity >> numShiftsNormalDirect); - return cache(normalDirectCaches, idx); - } - int idx = log2(normCapacity >> numShiftsNormalHeap); - return cache(normalHeapCaches, idx); - } - - private static MemoryRegionCache cache(MemoryRegionCache[] cache, int idx) { - if (cache == null || idx > cache.length - 1) { - return null; - } - return cache[idx]; - } - - /** - * Cache used for buffers which are backed by TINY or SMALL size. - */ - private static final class SubPageMemoryRegionCache extends MemoryRegionCache { - SubPageMemoryRegionCache(int size, SizeClass sizeClass) { - super(size, sizeClass); - } - - @Override - protected void initBuf( - PoolChunk chunk, long handle, PooledByteBuf buf, int reqCapacity) { - chunk.initBufWithSubpage(buf, handle, reqCapacity); - } - } - - /** - * Cache used for buffers which are backed by NORMAL size. - */ - private static final class NormalMemoryRegionCache extends MemoryRegionCache { - NormalMemoryRegionCache(int size) { - super(size, SizeClass.Normal); - } - - @Override - protected void initBuf( - PoolChunk chunk, long handle, PooledByteBuf buf, int reqCapacity) { - chunk.initBuf(buf, handle, reqCapacity); - } - } - - private abstract static class MemoryRegionCache { - private final int size; - private final Queue> queue; - private final SizeClass sizeClass; - private int allocations; - - MemoryRegionCache(int size, SizeClass sizeClass) { - this.size = MathUtil.findNextPositivePowerOfTwo(size); - queue = PlatformDependent.newFixedMpscQueue(this.size); - this.sizeClass = sizeClass; - } - - /** - * Init the {@link PooledByteBuf} using the provided chunk and handle with the capacity restrictions. - */ - protected abstract void initBuf(PoolChunk chunk, long handle, - PooledByteBuf buf, int reqCapacity); - - /** - * Add to cache if not already full. - */ - @SuppressWarnings("unchecked") - public final boolean add(PoolChunk chunk, long handle) { - Entry entry = newEntry(chunk, handle); - boolean queued = queue.offer(entry); - if (!queued) { - // If it was not possible to cache the chunk, immediately recycle the entry - entry.recycle(); - } - - return queued; - } - - /** - * Allocate something out of the cache if possible and remove the entry from the cache. - */ - public final boolean allocate(PooledByteBuf buf, int reqCapacity) { - Entry entry = queue.poll(); - if (entry == null) { - return false; - } - initBuf(entry.chunk, entry.handle, buf, reqCapacity); - entry.recycle(); - - // allocations is not thread-safe which is fine as this is only called from the same thread all time. - ++ allocations; - return true; - } - - /** - * Clear out this cache and free up all previous cached {@link PoolChunk}s and {@code handle}s. - */ - public final int free() { - return free(Integer.MAX_VALUE); - } - - private int free(int max) { - int numFreed = 0; - for (; numFreed < max; numFreed++) { - Entry entry = queue.poll(); - if (entry != null) { - freeEntry(entry); - } else { - // all cleared - return numFreed; - } - } - return numFreed; - } - - /** - * Free up cached {@link PoolChunk}s if not allocated frequently enough. - */ - public final void trim() { - int free = size - allocations; - allocations = 0; - - // We not even allocated all the number that are - if (free > 0) { - free(free); - } - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - private void freeEntry(Entry entry) { - PoolChunk chunk = entry.chunk; - long handle = entry.handle; - - // recycle now so PoolChunk can be GC'ed. - entry.recycle(); - - chunk.arena.freeChunk(chunk, handle, sizeClass); - } - - static final class Entry { - final Handle recyclerHandle; - PoolChunk chunk; - long handle = -1; - - Entry(Handle recyclerHandle) { - this.recyclerHandle = recyclerHandle; - } - - void recycle() { - chunk = null; - handle = -1; - RECYCLER.recycle(this, recyclerHandle); - } - } - - @SuppressWarnings("rawtypes") - private static Entry newEntry(PoolChunk chunk, long handle) { - Entry entry = RECYCLER.get(); - entry.chunk = chunk; - entry.handle = handle; - return entry; - } - - @SuppressWarnings("rawtypes") - private static final Recycler RECYCLER = new Recycler() { - @Override - protected Entry newObject(Handle handle) { - return new Entry(handle); - } - }; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PooledByteBuf.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PooledByteBuf.java deleted file mode 100755 index 76581a2616..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PooledByteBuf.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.buffer; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -import com.ai.cloud.io.netty.util.Recycler; - -abstract class PooledByteBuf extends AbstractReferenceCountedByteBuf { - - private final Recycler.Handle recyclerHandle; - - protected PoolChunk chunk; - protected long handle; - protected T memory; - protected int offset; - protected int length; - int maxLength; - PoolThreadCache cache; - private ByteBuffer tmpNioBuf; - - protected PooledByteBuf(Recycler.Handle recyclerHandle, int maxCapacity) { - super(maxCapacity); - this.recyclerHandle = recyclerHandle; - } - - void init(PoolChunk chunk, long handle, int offset, int length, int maxLength, PoolThreadCache cache) { - assert handle >= 0; - assert chunk != null; - - this.chunk = chunk; - this.handle = handle; - memory = chunk.memory; - this.offset = offset; - this.length = length; - this.maxLength = maxLength; - tmpNioBuf = null; - this.cache = cache; - } - - void initUnpooled(PoolChunk chunk, int length) { - assert chunk != null; - - this.chunk = chunk; - handle = 0; - memory = chunk.memory; - offset = 0; - this.length = maxLength = length; - tmpNioBuf = null; - cache = null; - } - - /** - * Method must be called before reuse this {@link PooledByteBufAllocator} - */ - final void reuse(int maxCapacity) { - maxCapacity(maxCapacity); - setRefCnt(1); - setIndex0(0, 0); - discardMarks(); - } - - @Override - public final int capacity() { - return length; - } - - @Override - public final ByteBuf capacity(int newCapacity) { - ensureAccessible(); - - // If the request capacity does not require reallocation, just update the length of the memory. - if (chunk.unpooled) { - if (newCapacity == length) { - return this; - } - } else { - if (newCapacity > length) { - if (newCapacity <= maxLength) { - length = newCapacity; - return this; - } - } else if (newCapacity < length) { - if (newCapacity > maxLength >>> 1) { - if (maxLength <= 512) { - if (newCapacity > maxLength - 16) { - length = newCapacity; - setIndex(Math.min(readerIndex(), newCapacity), Math.min(writerIndex(), newCapacity)); - return this; - } - } else { // > 512 (i.e. >= 1024) - length = newCapacity; - setIndex(Math.min(readerIndex(), newCapacity), Math.min(writerIndex(), newCapacity)); - return this; - } - } - } else { - return this; - } - } - - // Reallocation required. - chunk.arena.reallocate(this, newCapacity, true); - return this; - } - - @Override - public final ByteBufAllocator alloc() { - return chunk.arena.parent; - } - - @Override - public final ByteOrder order() { - return ByteOrder.BIG_ENDIAN; - } - - @Override - public final ByteBuf unwrap() { - return null; - } - - protected final ByteBuffer internalNioBuffer() { - ByteBuffer tmpNioBuf = this.tmpNioBuf; - if (tmpNioBuf == null) { - this.tmpNioBuf = tmpNioBuf = newInternalNioBuffer(memory); - } - return tmpNioBuf; - } - - protected abstract ByteBuffer newInternalNioBuffer(T memory); - - @Override - protected final void deallocate() { - if (handle >= 0) { - final long handle = this.handle; - this.handle = -1; - memory = null; - chunk.arena.free(chunk, handle, maxLength, cache); - recycle(); - } - } - - private void recycle() { - Recycler.Handle recyclerHandle = this.recyclerHandle; - if (recyclerHandle != null) { - ((Recycler) recycler()).recycle(this, recyclerHandle); - } - } - - protected abstract Recycler recycler(); - - protected final int idx(int index) { - return offset + index; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PooledByteBufAllocator.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PooledByteBufAllocator.java deleted file mode 100755 index b70216e5d4..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PooledByteBufAllocator.java +++ /dev/null @@ -1,426 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.buffer; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; - -import com.ai.cloud.io.netty.util.concurrent.FastThreadLocal; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; -import com.ai.cloud.io.netty.util.internal.SystemPropertyUtil; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -public class PooledByteBufAllocator extends AbstractByteBufAllocator { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(PooledByteBufAllocator.class); - private static final int DEFAULT_NUM_HEAP_ARENA; - private static final int DEFAULT_NUM_DIRECT_ARENA; - - private static final int DEFAULT_PAGE_SIZE; - private static final int DEFAULT_MAX_ORDER; // 8192 << 11 = 16 MiB per chunk - private static final int DEFAULT_TINY_CACHE_SIZE; - private static final int DEFAULT_SMALL_CACHE_SIZE; - private static final int DEFAULT_NORMAL_CACHE_SIZE; - private static final int DEFAULT_MAX_CACHED_BUFFER_CAPACITY; - private static final int DEFAULT_CACHE_TRIM_INTERVAL; - - private static final int MIN_PAGE_SIZE = 4096; - private static final int MAX_CHUNK_SIZE = (int) (((long) Integer.MAX_VALUE + 1) / 2); - - static { - int defaultPageSize = SystemPropertyUtil.getInt("io.netty.allocator.pageSize", 8192); - Throwable pageSizeFallbackCause = null; - try { - validateAndCalculatePageShifts(defaultPageSize); - } catch (Throwable t) { - pageSizeFallbackCause = t; - defaultPageSize = 8192; - } - DEFAULT_PAGE_SIZE = defaultPageSize; - - int defaultMaxOrder = SystemPropertyUtil.getInt("io.netty.allocator.maxOrder", 11); - Throwable maxOrderFallbackCause = null; - try { - validateAndCalculateChunkSize(DEFAULT_PAGE_SIZE, defaultMaxOrder); - } catch (Throwable t) { - maxOrderFallbackCause = t; - defaultMaxOrder = 11; - } - DEFAULT_MAX_ORDER = defaultMaxOrder; - - // Determine reasonable default for nHeapArena and nDirectArena. - // Assuming each arena has 3 chunks, the pool should not consume more than 50% of max memory. - final Runtime runtime = Runtime.getRuntime(); - - // Use 2 * cores by default to reduce condition as we use 2 * cores for the number of EventLoops - // in NIO and EPOLL as well. If we choose a smaller number we will run into hotspots as allocation and - // deallocation needs to be synchronized on the PoolArena. - // See https://github.com/netty/netty/issues/3888 - final int defaultMinNumArena = runtime.availableProcessors() * 2; - final int defaultChunkSize = DEFAULT_PAGE_SIZE << DEFAULT_MAX_ORDER; - DEFAULT_NUM_HEAP_ARENA = Math.max(0, - SystemPropertyUtil.getInt( - "io.netty.allocator.numHeapArenas", - (int) Math.min( - defaultMinNumArena, - runtime.maxMemory() / defaultChunkSize / 2 / 3))); - DEFAULT_NUM_DIRECT_ARENA = Math.max(0, - SystemPropertyUtil.getInt( - "io.netty.allocator.numDirectArenas", - (int) Math.min( - defaultMinNumArena, - PlatformDependent.maxDirectMemory() / defaultChunkSize / 2 / 3))); - - // cache sizes - DEFAULT_TINY_CACHE_SIZE = SystemPropertyUtil.getInt("io.netty.allocator.tinyCacheSize", 512); - DEFAULT_SMALL_CACHE_SIZE = SystemPropertyUtil.getInt("io.netty.allocator.smallCacheSize", 256); - DEFAULT_NORMAL_CACHE_SIZE = SystemPropertyUtil.getInt("io.netty.allocator.normalCacheSize", 64); - - // 32 kb is the default maximum capacity of the cached buffer. Similar to what is explained in - // 'Scalable memory allocation using jemalloc' - DEFAULT_MAX_CACHED_BUFFER_CAPACITY = SystemPropertyUtil.getInt( - "io.netty.allocator.maxCachedBufferCapacity", 32 * 1024); - - // the number of threshold of allocations when cached entries will be freed up if not frequently used - DEFAULT_CACHE_TRIM_INTERVAL = SystemPropertyUtil.getInt( - "io.netty.allocator.cacheTrimInterval", 8192); - - if (logger.isDebugEnabled()) { - logger.debug("-Dio.netty.allocator.numHeapArenas: {}", DEFAULT_NUM_HEAP_ARENA); - logger.debug("-Dio.netty.allocator.numDirectArenas: {}", DEFAULT_NUM_DIRECT_ARENA); - if (pageSizeFallbackCause == null) { - logger.debug("-Dio.netty.allocator.pageSize: {}", DEFAULT_PAGE_SIZE); - } else { - logger.debug("-Dio.netty.allocator.pageSize: {}", DEFAULT_PAGE_SIZE, pageSizeFallbackCause); - } - if (maxOrderFallbackCause == null) { - logger.debug("-Dio.netty.allocator.maxOrder: {}", DEFAULT_MAX_ORDER); - } else { - logger.debug("-Dio.netty.allocator.maxOrder: {}", DEFAULT_MAX_ORDER, maxOrderFallbackCause); - } - logger.debug("-Dio.netty.allocator.chunkSize: {}", DEFAULT_PAGE_SIZE << DEFAULT_MAX_ORDER); - logger.debug("-Dio.netty.allocator.tinyCacheSize: {}", DEFAULT_TINY_CACHE_SIZE); - logger.debug("-Dio.netty.allocator.smallCacheSize: {}", DEFAULT_SMALL_CACHE_SIZE); - logger.debug("-Dio.netty.allocator.normalCacheSize: {}", DEFAULT_NORMAL_CACHE_SIZE); - logger.debug("-Dio.netty.allocator.maxCachedBufferCapacity: {}", DEFAULT_MAX_CACHED_BUFFER_CAPACITY); - logger.debug("-Dio.netty.allocator.cacheTrimInterval: {}", DEFAULT_CACHE_TRIM_INTERVAL); - } - } - - public static final PooledByteBufAllocator DEFAULT = - new PooledByteBufAllocator(PlatformDependent.directBufferPreferred()); - - private final PoolArena[] heapArenas; - private final PoolArena[] directArenas; - private final int tinyCacheSize; - private final int smallCacheSize; - private final int normalCacheSize; - private final List heapArenaMetrics; - private final List directArenaMetrics; - private final PoolThreadLocalCache threadCache; - - public PooledByteBufAllocator() { - this(false); - } - - public PooledByteBufAllocator(boolean preferDirect) { - this(preferDirect, DEFAULT_NUM_HEAP_ARENA, DEFAULT_NUM_DIRECT_ARENA, DEFAULT_PAGE_SIZE, DEFAULT_MAX_ORDER); - } - - public PooledByteBufAllocator(int nHeapArena, int nDirectArena, int pageSize, int maxOrder) { - this(false, nHeapArena, nDirectArena, pageSize, maxOrder); - } - - public PooledByteBufAllocator(boolean preferDirect, int nHeapArena, int nDirectArena, int pageSize, int maxOrder) { - this(preferDirect, nHeapArena, nDirectArena, pageSize, maxOrder, - DEFAULT_TINY_CACHE_SIZE, DEFAULT_SMALL_CACHE_SIZE, DEFAULT_NORMAL_CACHE_SIZE); - } - - public PooledByteBufAllocator(boolean preferDirect, int nHeapArena, int nDirectArena, int pageSize, int maxOrder, - int tinyCacheSize, int smallCacheSize, int normalCacheSize) { - super(preferDirect); - threadCache = new PoolThreadLocalCache(); - this.tinyCacheSize = tinyCacheSize; - this.smallCacheSize = smallCacheSize; - this.normalCacheSize = normalCacheSize; - final int chunkSize = validateAndCalculateChunkSize(pageSize, maxOrder); - - if (nHeapArena < 0) { - throw new IllegalArgumentException("nHeapArena: " + nHeapArena + " (expected: >= 0)"); - } - if (nDirectArena < 0) { - throw new IllegalArgumentException("nDirectArea: " + nDirectArena + " (expected: >= 0)"); - } - - int pageShifts = validateAndCalculatePageShifts(pageSize); - - if (nHeapArena > 0) { - heapArenas = newArenaArray(nHeapArena); - List metrics = new ArrayList(heapArenas.length); - for (int i = 0; i < heapArenas.length; i ++) { - PoolArena.HeapArena arena = new PoolArena.HeapArena(this, pageSize, maxOrder, pageShifts, chunkSize); - heapArenas[i] = arena; - metrics.add(arena); - } - heapArenaMetrics = Collections.unmodifiableList(metrics); - } else { - heapArenas = null; - heapArenaMetrics = Collections.emptyList(); - } - - if (nDirectArena > 0) { - directArenas = newArenaArray(nDirectArena); - List metrics = new ArrayList(directArenas.length); - for (int i = 0; i < directArenas.length; i ++) { - PoolArena.DirectArena arena = new PoolArena.DirectArena( - this, pageSize, maxOrder, pageShifts, chunkSize); - directArenas[i] = arena; - metrics.add(arena); - } - directArenaMetrics = Collections.unmodifiableList(metrics); - } else { - directArenas = null; - directArenaMetrics = Collections.emptyList(); - } - } - - @Deprecated - @SuppressWarnings("UnusedParameters") - public PooledByteBufAllocator(boolean preferDirect, int nHeapArena, int nDirectArena, int pageSize, int maxOrder, - int tinyCacheSize, int smallCacheSize, int normalCacheSize, - long cacheThreadAliveCheckInterval) { - this(preferDirect, nHeapArena, nDirectArena, pageSize, maxOrder, - tinyCacheSize, smallCacheSize, normalCacheSize); - } - - @SuppressWarnings("unchecked") - private static PoolArena[] newArenaArray(int size) { - return new PoolArena[size]; - } - - private static int validateAndCalculatePageShifts(int pageSize) { - if (pageSize < MIN_PAGE_SIZE) { - throw new IllegalArgumentException("pageSize: " + pageSize + " (expected: " + MIN_PAGE_SIZE + "+)"); - } - - if ((pageSize & pageSize - 1) != 0) { - throw new IllegalArgumentException("pageSize: " + pageSize + " (expected: power of 2)"); - } - - // Logarithm base 2. At this point we know that pageSize is a power of two. - return Integer.SIZE - 1 - Integer.numberOfLeadingZeros(pageSize); - } - - private static int validateAndCalculateChunkSize(int pageSize, int maxOrder) { - if (maxOrder > 14) { - throw new IllegalArgumentException("maxOrder: " + maxOrder + " (expected: 0-14)"); - } - - // Ensure the resulting chunkSize does not overflow. - int chunkSize = pageSize; - for (int i = maxOrder; i > 0; i --) { - if (chunkSize > MAX_CHUNK_SIZE / 2) { - throw new IllegalArgumentException(String.format( - "pageSize (%d) << maxOrder (%d) must not exceed %d", pageSize, maxOrder, MAX_CHUNK_SIZE)); - } - chunkSize <<= 1; - } - return chunkSize; - } - - @Override - protected ByteBuf newHeapBuffer(int initialCapacity, int maxCapacity) { - PoolThreadCache cache = threadCache.get(); - PoolArena heapArena = cache.heapArena; - - ByteBuf buf; - if (heapArena != null) { - buf = heapArena.allocate(cache, initialCapacity, maxCapacity); - } else { - buf = new UnpooledHeapByteBuf(this, initialCapacity, maxCapacity); - } - - return toLeakAwareBuffer(buf); - } - - @Override - protected ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity) { - PoolThreadCache cache = threadCache.get(); - PoolArena directArena = cache.directArena; - - ByteBuf buf; - if (directArena != null) { - buf = directArena.allocate(cache, initialCapacity, maxCapacity); - } else { - if (PlatformDependent.hasUnsafe()) { - buf = new UnpooledUnsafeDirectByteBuf(this, initialCapacity, maxCapacity); - } else { - buf = new UnpooledDirectByteBuf(this, initialCapacity, maxCapacity); - } - } - - return toLeakAwareBuffer(buf); - } - - @Override - public boolean isDirectBufferPooled() { - return directArenas != null; - } - - /** - * Returns {@code true} if the calling {@link Thread} has a {@link ThreadLocal} cache for the allocated - * buffers. - */ - @Deprecated - public boolean hasThreadLocalCache() { - return threadCache.isSet(); - } - - /** - * Free all cached buffers for the calling {@link Thread}. - */ - @Deprecated - public void freeThreadLocalCache() { - threadCache.remove(); - } - - final class PoolThreadLocalCache extends FastThreadLocal { - private final AtomicInteger index = new AtomicInteger(); - final AtomicInteger caches = new AtomicInteger(); - - @Override - protected PoolThreadCache initialValue() { - caches.incrementAndGet(); - final int idx = index.getAndIncrement(); - final PoolArena heapArena; - final PoolArena directArena; - - if (heapArenas != null) { - heapArena = heapArenas[Math.abs(idx % heapArenas.length)]; - } else { - heapArena = null; - } - - if (directArenas != null) { - directArena = directArenas[Math.abs(idx % directArenas.length)]; - } else { - directArena = null; - } - return new PoolThreadCache( - heapArena, directArena, tinyCacheSize, smallCacheSize, normalCacheSize, - DEFAULT_MAX_CACHED_BUFFER_CAPACITY, DEFAULT_CACHE_TRIM_INTERVAL); - } - - @Override - protected void onRemoval(PoolThreadCache value) { - value.free(); - caches.decrementAndGet(); - } - } - - /** - * Return the number of heap arenas. - */ - public int numHeapArenas() { - return heapArenaMetrics.size(); - } - - /** - * Return the number of direct arenas. - */ - public int numDirectArenas() { - return directArenaMetrics.size(); - } - - /** - * Return a {@link List} of all heap {@link PoolArenaMetric}s that are provided by this pool. - */ - public List heapArenas() { - return heapArenaMetrics; - } - - /** - * Return a {@link List} of all direct {@link PoolArenaMetric}s that are provided by this pool. - */ - public List directArenas() { - return directArenaMetrics; - } - - /** - * Return the number of thread local caches used by this {@link PooledByteBufAllocator}. - */ - public int numThreadLocalCaches() { - return threadCache.caches.get(); - } - - /** - * Return the size of the tiny cache. - */ - public int tinyCacheSize() { - return tinyCacheSize; - } - - /** - * Return the size of the small cache. - */ - public int smallCacheSize() { - return smallCacheSize; - } - - /** - * Return the size of the normal cache. - */ - public int normalCacheSize() { - return normalCacheSize; - } - - final PoolThreadCache threadCache() { - return threadCache.get(); - } - - // Too noisy at the moment. - // - //public String toString() { - // StringBuilder buf = new StringBuilder(); - // int heapArenasLen = heapArenas == null ? 0 : heapArenas.length; - // buf.append(heapArenasLen); - // buf.append(" heap arena(s):"); - // buf.append(StringUtil.NEWLINE); - // if (heapArenasLen > 0) { - // for (PoolArena a: heapArenas) { - // buf.append(a); - // } - // } - // - // int directArenasLen = directArenas == null ? 0 : directArenas.length; - // - // buf.append(directArenasLen); - // buf.append(" direct arena(s):"); - // buf.append(StringUtil.NEWLINE); - // if (directArenasLen > 0) { - // for (PoolArena a: directArenas) { - // buf.append(a); - // } - // } - // - // return buf.toString(); - //} -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PooledDirectByteBuf.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PooledDirectByteBuf.java deleted file mode 100755 index 9ac7517b17..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PooledDirectByteBuf.java +++ /dev/null @@ -1,376 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; - -import com.ai.cloud.io.netty.util.Recycler; - -final class PooledDirectByteBuf extends PooledByteBuf { - - private static final Recycler RECYCLER = new Recycler() { - @Override - protected PooledDirectByteBuf newObject(Handle handle) { - return new PooledDirectByteBuf(handle, 0); - } - }; - - static PooledDirectByteBuf newInstance(int maxCapacity) { - PooledDirectByteBuf buf = RECYCLER.get(); - buf.reuse(maxCapacity); - return buf; - } - - private PooledDirectByteBuf(Recycler.Handle recyclerHandle, int maxCapacity) { - super(recyclerHandle, maxCapacity); - } - - @Override - protected ByteBuffer newInternalNioBuffer(ByteBuffer memory) { - return memory.duplicate(); - } - - @Override - public boolean isDirect() { - return true; - } - - @Override - protected byte _getByte(int index) { - return memory.get(idx(index)); - } - - @Override - protected short _getShort(int index) { - return memory.getShort(idx(index)); - } - - @Override - protected int _getUnsignedMedium(int index) { - index = idx(index); - return (memory.get(index) & 0xff) << 16 | (memory.get(index + 1) & 0xff) << 8 | memory.get(index + 2) & 0xff; - } - - @Override - protected int _getInt(int index) { - return memory.getInt(idx(index)); - } - - @Override - protected long _getLong(int index) { - return memory.getLong(idx(index)); - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - checkDstIndex(index, length, dstIndex, dst.capacity()); - if (dst.hasArray()) { - getBytes(index, dst.array(), dst.arrayOffset() + dstIndex, length); - } else if (dst.nioBufferCount() > 0) { - for (ByteBuffer bb: dst.nioBuffers(dstIndex, length)) { - int bbLen = bb.remaining(); - getBytes(index, bb); - index += bbLen; - } - } else { - dst.setBytes(dstIndex, this, index, length); - } - return this; - } - - @Override - public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - getBytes(index, dst, dstIndex, length, false); - return this; - } - - private void getBytes(int index, byte[] dst, int dstIndex, int length, boolean internal) { - checkDstIndex(index, length, dstIndex, dst.length); - ByteBuffer tmpBuf; - if (internal) { - tmpBuf = internalNioBuffer(); - } else { - tmpBuf = memory.duplicate(); - } - index = idx(index); - tmpBuf.clear().position(index).limit(index + length); - tmpBuf.get(dst, dstIndex, length); - } - - @Override - public ByteBuf readBytes(byte[] dst, int dstIndex, int length) { - checkReadableBytes(length); - getBytes(readerIndex, dst, dstIndex, length, true); - readerIndex += length; - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuffer dst) { - getBytes(index, dst, false); - return this; - } - - private void getBytes(int index, ByteBuffer dst, boolean internal) { - checkIndex(index); - int bytesToCopy = Math.min(capacity() - index, dst.remaining()); - ByteBuffer tmpBuf; - if (internal) { - tmpBuf = internalNioBuffer(); - } else { - tmpBuf = memory.duplicate(); - } - index = idx(index); - tmpBuf.clear().position(index).limit(index + bytesToCopy); - dst.put(tmpBuf); - } - - @Override - public ByteBuf readBytes(ByteBuffer dst) { - int length = dst.remaining(); - checkReadableBytes(length); - getBytes(readerIndex, dst, true); - readerIndex += length; - return this; - } - - @Override - public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException { - getBytes(index, out, length, false); - return this; - } - - private void getBytes(int index, OutputStream out, int length, boolean internal) throws IOException { - checkIndex(index, length); - if (length == 0) { - return; - } - - byte[] tmp = new byte[length]; - ByteBuffer tmpBuf; - if (internal) { - tmpBuf = internalNioBuffer(); - } else { - tmpBuf = memory.duplicate(); - } - tmpBuf.clear().position(idx(index)); - tmpBuf.get(tmp); - out.write(tmp); - } - - @Override - public ByteBuf readBytes(OutputStream out, int length) throws IOException { - checkReadableBytes(length); - getBytes(readerIndex, out, length, true); - readerIndex += length; - return this; - } - - @Override - public int getBytes(int index, GatheringByteChannel out, int length) throws IOException { - return getBytes(index, out, length, false); - } - - private int getBytes(int index, GatheringByteChannel out, int length, boolean internal) throws IOException { - checkIndex(index, length); - if (length == 0) { - return 0; - } - - ByteBuffer tmpBuf; - if (internal) { - tmpBuf = internalNioBuffer(); - } else { - tmpBuf = memory.duplicate(); - } - index = idx(index); - tmpBuf.clear().position(index).limit(index + length); - return out.write(tmpBuf); - } - - @Override - public int readBytes(GatheringByteChannel out, int length) throws IOException { - checkReadableBytes(length); - int readBytes = getBytes(readerIndex, out, length, true); - readerIndex += readBytes; - return readBytes; - } - - @Override - protected void _setByte(int index, int value) { - memory.put(idx(index), (byte) value); - } - - @Override - protected void _setShort(int index, int value) { - memory.putShort(idx(index), (short) value); - } - - @Override - protected void _setMedium(int index, int value) { - index = idx(index); - memory.put(index, (byte) (value >>> 16)); - memory.put(index + 1, (byte) (value >>> 8)); - memory.put(index + 2, (byte) value); - } - - @Override - protected void _setInt(int index, int value) { - memory.putInt(idx(index), value); - } - - @Override - protected void _setLong(int index, long value) { - memory.putLong(idx(index), value); - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { - checkSrcIndex(index, length, srcIndex, src.capacity()); - if (src.hasArray()) { - setBytes(index, src.array(), src.arrayOffset() + srcIndex, length); - } else if (src.nioBufferCount() > 0) { - for (ByteBuffer bb: src.nioBuffers(srcIndex, length)) { - int bbLen = bb.remaining(); - setBytes(index, bb); - index += bbLen; - } - } else { - src.getBytes(srcIndex, this, index, length); - } - return this; - } - - @Override - public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { - checkSrcIndex(index, length, srcIndex, src.length); - ByteBuffer tmpBuf = internalNioBuffer(); - index = idx(index); - tmpBuf.clear().position(index).limit(index + length); - tmpBuf.put(src, srcIndex, length); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuffer src) { - checkIndex(index, src.remaining()); - ByteBuffer tmpBuf = internalNioBuffer(); - if (src == tmpBuf) { - src = src.duplicate(); - } - - index = idx(index); - tmpBuf.clear().position(index).limit(index + src.remaining()); - tmpBuf.put(src); - return this; - } - - @Override - public int setBytes(int index, InputStream in, int length) throws IOException { - checkIndex(index, length); - byte[] tmp = new byte[length]; - int readBytes = in.read(tmp); - if (readBytes <= 0) { - return readBytes; - } - ByteBuffer tmpBuf = internalNioBuffer(); - tmpBuf.clear().position(idx(index)); - tmpBuf.put(tmp, 0, readBytes); - return readBytes; - } - - @Override - public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException { - checkIndex(index, length); - ByteBuffer tmpBuf = internalNioBuffer(); - index = idx(index); - tmpBuf.clear().position(index).limit(index + length); - try { - return in.read(tmpBuf); - } catch (ClosedChannelException ignored) { - return -1; - } - } - - @Override - public ByteBuf copy(int index, int length) { - checkIndex(index, length); - ByteBuf copy = alloc().directBuffer(length, maxCapacity()); - copy.writeBytes(this, index, length); - return copy; - } - - @Override - public int nioBufferCount() { - return 1; - } - - @Override - public ByteBuffer nioBuffer(int index, int length) { - checkIndex(index, length); - index = idx(index); - return ((ByteBuffer) memory.duplicate().position(index).limit(index + length)).slice(); - } - - @Override - public ByteBuffer[] nioBuffers(int index, int length) { - return new ByteBuffer[] { nioBuffer(index, length) }; - } - - @Override - public ByteBuffer internalNioBuffer(int index, int length) { - checkIndex(index, length); - index = idx(index); - return (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length); - } - - @Override - public boolean hasArray() { - return false; - } - - @Override - public byte[] array() { - throw new UnsupportedOperationException("direct buffer"); - } - - @Override - public int arrayOffset() { - throw new UnsupportedOperationException("direct buffer"); - } - - @Override - public boolean hasMemoryAddress() { - return false; - } - - @Override - public long memoryAddress() { - throw new UnsupportedOperationException(); - } - - @Override - protected Recycler recycler() { - return RECYCLER; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PooledHeapByteBuf.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PooledHeapByteBuf.java deleted file mode 100755 index 931eff30a9..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PooledHeapByteBuf.java +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file tothe License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; - -import com.ai.cloud.io.netty.util.Recycler; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - -class PooledHeapByteBuf extends PooledByteBuf { - - private static final Recycler RECYCLER = new Recycler() { - @Override - protected PooledHeapByteBuf newObject(Handle handle) { - return new PooledHeapByteBuf(handle, 0); - } - }; - - static PooledHeapByteBuf newInstance(int maxCapacity) { - PooledHeapByteBuf buf = RECYCLER.get(); - buf.reuse(maxCapacity); - return buf; - } - - PooledHeapByteBuf(Recycler.Handle recyclerHandle, int maxCapacity) { - super(recyclerHandle, maxCapacity); - } - - @Override - public final boolean isDirect() { - return false; - } - - @Override - protected byte _getByte(int index) { - return HeapByteBufUtil.getByte(memory, idx(index)); - } - - @Override - protected short _getShort(int index) { - return HeapByteBufUtil.getShort(memory, idx(index)); - } - - @Override - protected int _getUnsignedMedium(int index) { - return HeapByteBufUtil.getUnsignedMedium(memory, idx(index)); - } - - @Override - protected int _getInt(int index) { - return HeapByteBufUtil.getInt(memory, idx(index)); - } - - @Override - protected long _getLong(int index) { - return HeapByteBufUtil.getLong(memory, idx(index)); - } - - @Override - public final ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - checkDstIndex(index, length, dstIndex, dst.capacity()); - if (dst.hasMemoryAddress()) { - PlatformDependent.copyMemory(memory, idx(index), dst.memoryAddress() + dstIndex, length); - } else if (dst.hasArray()) { - getBytes(index, dst.array(), dst.arrayOffset() + dstIndex, length); - } else { - dst.setBytes(dstIndex, memory, idx(index), length); - } - return this; - } - - @Override - public final ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - checkDstIndex(index, length, dstIndex, dst.length); - System.arraycopy(memory, idx(index), dst, dstIndex, length); - return this; - } - - @Override - public final ByteBuf getBytes(int index, ByteBuffer dst) { - checkIndex(index); - dst.put(memory, idx(index), Math.min(capacity() - index, dst.remaining())); - return this; - } - - @Override - public final ByteBuf getBytes(int index, OutputStream out, int length) throws IOException { - checkIndex(index, length); - out.write(memory, idx(index), length); - return this; - } - - @Override - public final int getBytes(int index, GatheringByteChannel out, int length) throws IOException { - return getBytes(index, out, length, false); - } - - private int getBytes(int index, GatheringByteChannel out, int length, boolean internal) throws IOException { - checkIndex(index, length); - index = idx(index); - ByteBuffer tmpBuf; - if (internal) { - tmpBuf = internalNioBuffer(); - } else { - tmpBuf = ByteBuffer.wrap(memory); - } - return out.write((ByteBuffer) tmpBuf.clear().position(index).limit(index + length)); - } - - @Override - public final int readBytes(GatheringByteChannel out, int length) throws IOException { - checkReadableBytes(length); - int readBytes = getBytes(readerIndex, out, length, true); - readerIndex += readBytes; - return readBytes; - } - - @Override - protected void _setByte(int index, int value) { - HeapByteBufUtil.setByte(memory, idx(index), value); - } - - @Override - protected void _setShort(int index, int value) { - HeapByteBufUtil.setShort(memory, idx(index), value); - } - - @Override - protected void _setMedium(int index, int value) { - HeapByteBufUtil.setMedium(memory, idx(index), value); - } - - @Override - protected void _setInt(int index, int value) { - HeapByteBufUtil.setInt(memory, idx(index), value); - } - - @Override - protected void _setLong(int index, long value) { - HeapByteBufUtil.setLong(memory, idx(index), value); - } - - @Override - public final ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { - checkSrcIndex(index, length, srcIndex, src.capacity()); - if (src.hasMemoryAddress()) { - PlatformDependent.copyMemory(src.memoryAddress() + srcIndex, memory, idx(index), length); - } else if (src.hasArray()) { - setBytes(index, src.array(), src.arrayOffset() + srcIndex, length); - } else { - src.getBytes(srcIndex, memory, idx(index), length); - } - return this; - } - - @Override - public final ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { - checkSrcIndex(index, length, srcIndex, src.length); - System.arraycopy(src, srcIndex, memory, idx(index), length); - return this; - } - - @Override - public final ByteBuf setBytes(int index, ByteBuffer src) { - int length = src.remaining(); - checkIndex(index, length); - src.get(memory, idx(index), length); - return this; - } - - @Override - public final int setBytes(int index, InputStream in, int length) throws IOException { - checkIndex(index, length); - return in.read(memory, idx(index), length); - } - - @Override - public final int setBytes(int index, ScatteringByteChannel in, int length) throws IOException { - checkIndex(index, length); - index = idx(index); - try { - return in.read((ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length)); - } catch (ClosedChannelException ignored) { - return -1; - } - } - - @Override - public final ByteBuf copy(int index, int length) { - checkIndex(index, length); - ByteBuf copy = alloc().heapBuffer(length, maxCapacity()); - copy.writeBytes(memory, idx(index), length); - return copy; - } - - @Override - public final int nioBufferCount() { - return 1; - } - - @Override - public final ByteBuffer[] nioBuffers(int index, int length) { - return new ByteBuffer[] { nioBuffer(index, length) }; - } - - @Override - public final ByteBuffer nioBuffer(int index, int length) { - checkIndex(index, length); - index = idx(index); - ByteBuffer buf = ByteBuffer.wrap(memory, index, length); - return buf.slice(); - } - - @Override - public final ByteBuffer internalNioBuffer(int index, int length) { - checkIndex(index, length); - index = idx(index); - return (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length); - } - - @Override - public final boolean hasArray() { - return true; - } - - @Override - public final byte[] array() { - ensureAccessible(); - return memory; - } - - @Override - public final int arrayOffset() { - return offset; - } - - @Override - public final boolean hasMemoryAddress() { - return false; - } - - @Override - public final long memoryAddress() { - throw new UnsupportedOperationException(); - } - - @Override - protected final ByteBuffer newInternalNioBuffer(byte[] memory) { - return ByteBuffer.wrap(memory); - } - - @Override - protected Recycler recycler() { - return RECYCLER; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PooledUnsafeDirectByteBuf.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PooledUnsafeDirectByteBuf.java deleted file mode 100755 index c083b5caa7..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PooledUnsafeDirectByteBuf.java +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; - -import com.ai.cloud.io.netty.util.Recycler; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - -final class PooledUnsafeDirectByteBuf extends PooledByteBuf { - private static final Recycler RECYCLER = new Recycler() { - @Override - protected PooledUnsafeDirectByteBuf newObject(Handle handle) { - return new PooledUnsafeDirectByteBuf(handle, 0); - } - }; - - static PooledUnsafeDirectByteBuf newInstance(int maxCapacity) { - PooledUnsafeDirectByteBuf buf = RECYCLER.get(); - buf.reuse(maxCapacity); - return buf; - } - - private long memoryAddress; - - private PooledUnsafeDirectByteBuf(Recycler.Handle recyclerHandle, int maxCapacity) { - super(recyclerHandle, maxCapacity); - } - - @Override - void init(PoolChunk chunk, long handle, int offset, int length, int maxLength, - PoolThreadCache cache) { - super.init(chunk, handle, offset, length, maxLength, cache); - initMemoryAddress(); - } - - @Override - void initUnpooled(PoolChunk chunk, int length) { - super.initUnpooled(chunk, length); - initMemoryAddress(); - } - - private void initMemoryAddress() { - memoryAddress = PlatformDependent.directBufferAddress(memory) + offset; - } - - @Override - protected ByteBuffer newInternalNioBuffer(ByteBuffer memory) { - return memory.duplicate(); - } - - @Override - public boolean isDirect() { - return true; - } - - @Override - protected byte _getByte(int index) { - return UnsafeByteBufUtil.getByte(addr(index)); - } - - @Override - protected short _getShort(int index) { - return UnsafeByteBufUtil.getShort(addr(index)); - } - - @Override - protected int _getUnsignedMedium(int index) { - return UnsafeByteBufUtil.getUnsignedMedium(addr(index)); - } - - @Override - protected int _getInt(int index) { - return UnsafeByteBufUtil.getInt(addr(index)); - } - - @Override - protected long _getLong(int index) { - return UnsafeByteBufUtil.getLong(addr(index)); - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - UnsafeByteBufUtil.getBytes(this, addr(index), index, dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - UnsafeByteBufUtil.getBytes(this, addr(index), index, dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuffer dst) { - UnsafeByteBufUtil.getBytes(this, addr(index), index, dst); - return this; - } - - @Override - public ByteBuf readBytes(ByteBuffer dst) { - int length = dst.remaining(); - checkReadableBytes(length); - getBytes(readerIndex, dst); - readerIndex += length; - return this; - } - - @Override - public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException { - UnsafeByteBufUtil.getBytes(this, addr(index), index, out, length); - return this; - } - - @Override - public int getBytes(int index, GatheringByteChannel out, int length) throws IOException { - return getBytes(index, out, length, false); - } - - private int getBytes(int index, GatheringByteChannel out, int length, boolean internal) throws IOException { - checkIndex(index, length); - if (length == 0) { - return 0; - } - - ByteBuffer tmpBuf; - if (internal) { - tmpBuf = internalNioBuffer(); - } else { - tmpBuf = memory.duplicate(); - } - index = idx(index); - tmpBuf.clear().position(index).limit(index + length); - return out.write(tmpBuf); - } - - @Override - public int readBytes(GatheringByteChannel out, int length) - throws IOException { - checkReadableBytes(length); - int readBytes = getBytes(readerIndex, out, length, true); - readerIndex += readBytes; - return readBytes; - } - - @Override - protected void _setByte(int index, int value) { - UnsafeByteBufUtil.setByte(addr(index), (byte) value); - } - - @Override - protected void _setShort(int index, int value) { - UnsafeByteBufUtil.setShort(addr(index), value); - } - - @Override - protected void _setMedium(int index, int value) { - UnsafeByteBufUtil.setMedium(addr(index), value); - } - - @Override - protected void _setInt(int index, int value) { - UnsafeByteBufUtil.setInt(addr(index), value); - } - - @Override - protected void _setLong(int index, long value) { - UnsafeByteBufUtil.setLong(addr(index), value); - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { - UnsafeByteBufUtil.setBytes(this, addr(index), index, src, srcIndex, length); - return this; - } - - @Override - public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { - UnsafeByteBufUtil.setBytes(this, addr(index), index, src, srcIndex, length); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuffer src) { - UnsafeByteBufUtil.setBytes(this, addr(index), index, src); - return this; - } - - @Override - public int setBytes(int index, InputStream in, int length) throws IOException { - return UnsafeByteBufUtil.setBytes(this, addr(index), index, in, length); - } - - @Override - public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException { - checkIndex(index, length); - ByteBuffer tmpBuf = internalNioBuffer(); - index = idx(index); - tmpBuf.clear().position(index).limit(index + length); - try { - return in.read(tmpBuf); - } catch (ClosedChannelException ignored) { - return -1; - } - } - - @Override - public ByteBuf copy(int index, int length) { - return UnsafeByteBufUtil.copy(this, addr(index), index, length); - } - - @Override - public int nioBufferCount() { - return 1; - } - - @Override - public ByteBuffer[] nioBuffers(int index, int length) { - return new ByteBuffer[] { nioBuffer(index, length) }; - } - - @Override - public ByteBuffer nioBuffer(int index, int length) { - checkIndex(index, length); - index = idx(index); - return ((ByteBuffer) memory.duplicate().position(index).limit(index + length)).slice(); - } - - @Override - public ByteBuffer internalNioBuffer(int index, int length) { - checkIndex(index, length); - index = idx(index); - return (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length); - } - - @Override - public boolean hasArray() { - return false; - } - - @Override - public byte[] array() { - throw new UnsupportedOperationException("direct buffer"); - } - - @Override - public int arrayOffset() { - throw new UnsupportedOperationException("direct buffer"); - } - - @Override - public boolean hasMemoryAddress() { - return true; - } - - @Override - public long memoryAddress() { - ensureAccessible(); - return memoryAddress; - } - - private long addr(int index) { - return memoryAddress + index; - } - - @Override - protected Recycler recycler() { - return RECYCLER; - } - - @Override - protected SwappedByteBuf newSwappedByteBuf() { - if (PlatformDependent.isUnaligned()) { - // Only use if unaligned access is supported otherwise there is no gain. - return new UnsafeDirectSwappedByteBuf(this); - } - return super.newSwappedByteBuf(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PooledUnsafeHeapByteBuf.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PooledUnsafeHeapByteBuf.java deleted file mode 100755 index e6287980f6..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/PooledUnsafeHeapByteBuf.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file tothe License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.buffer; - -import com.ai.cloud.io.netty.util.Recycler; -import com.ai.cloud.io.netty.util.Recycler.Handle; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - -final class PooledUnsafeHeapByteBuf extends PooledHeapByteBuf { - - private static final Recycler RECYCLER = new Recycler() { - @Override - protected PooledUnsafeHeapByteBuf newObject(Handle handle) { - return new PooledUnsafeHeapByteBuf(handle, 0); - } - }; - - static PooledUnsafeHeapByteBuf newUnsafeInstance(int maxCapacity) { - PooledUnsafeHeapByteBuf buf = RECYCLER.get(); - buf.reuse(maxCapacity); - return buf; - } - - private PooledUnsafeHeapByteBuf(Handle recyclerHandle, int maxCapacity) { - super(recyclerHandle, maxCapacity); - } - - @Override - protected byte _getByte(int index) { - return UnsafeByteBufUtil.getByte(memory, idx(index)); - } - - @Override - protected short _getShort(int index) { - return UnsafeByteBufUtil.getShort(memory, idx(index)); - } - - @Override - protected int _getUnsignedMedium(int index) { - return UnsafeByteBufUtil.getUnsignedMedium(memory, idx(index)); - } - - @Override - protected int _getInt(int index) { - return UnsafeByteBufUtil.getInt(memory, idx(index)); - } - - @Override - protected long _getLong(int index) { - return UnsafeByteBufUtil.getLong(memory, idx(index)); - } - - @Override - protected void _setByte(int index, int value) { - UnsafeByteBufUtil.setByte(memory, idx(index), value); - } - - @Override - protected void _setShort(int index, int value) { - UnsafeByteBufUtil.setShort(memory, idx(index), value); - } - - @Override - protected void _setMedium(int index, int value) { - UnsafeByteBufUtil.setMedium(memory, idx(index), value); - } - - @Override - protected void _setInt(int index, int value) { - UnsafeByteBufUtil.setInt(memory, idx(index), value); - } - - @Override - protected void _setLong(int index, long value) { - UnsafeByteBufUtil.setLong(memory, idx(index), value); - } - - @Override - protected Recycler recycler() { - return RECYCLER; - } - - @Override - protected SwappedByteBuf newSwappedByteBuf() { - if (PlatformDependent.isUnaligned()) { - // Only use if unaligned access is supported otherwise there is no gain. - return new UnsafeHeapSwappedByteBuf(this); - } - return super.newSwappedByteBuf(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ReadOnlyByteBuf.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ReadOnlyByteBuf.java deleted file mode 100755 index 2764c869db..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ReadOnlyByteBuf.java +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.ReadOnlyBufferException; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; - -/** - * A derived buffer which forbids any write requests to its parent. It is - * recommended to use {@link Unpooled#unmodifiableBuffer(ByteBuf)} - * instead of calling the constructor explicitly. - */ -public class ReadOnlyByteBuf extends AbstractDerivedByteBuf { - - private final ByteBuf buffer; - - public ReadOnlyByteBuf(ByteBuf buffer) { - super(buffer.maxCapacity()); - - if (buffer instanceof ReadOnlyByteBuf || buffer instanceof DuplicatedByteBuf) { - this.buffer = buffer.unwrap(); - } else { - this.buffer = buffer; - } - setIndex(buffer.readerIndex(), buffer.writerIndex()); - } - - @Override - public boolean isWritable() { - return false; - } - - @Override - public boolean isWritable(int numBytes) { - return false; - } - - @Override - public ByteBuf unwrap() { - return buffer; - } - - @Override - public ByteBufAllocator alloc() { - return buffer.alloc(); - } - - @Override - public ByteOrder order() { - return buffer.order(); - } - - @Override - public boolean isDirect() { - return buffer.isDirect(); - } - - @Override - public boolean hasArray() { - return false; - } - - @Override - public byte[] array() { - throw new ReadOnlyBufferException(); - } - - @Override - public int arrayOffset() { - throw new ReadOnlyBufferException(); - } - - @Override - public boolean hasMemoryAddress() { - return false; - } - - @Override - public long memoryAddress() { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBuf discardReadBytes() { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBuf setBytes(int index, ByteBuffer src) { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBuf setByte(int index, int value) { - throw new ReadOnlyBufferException(); - } - - @Override - protected void _setByte(int index, int value) { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBuf setShort(int index, int value) { - throw new ReadOnlyBufferException(); - } - - @Override - protected void _setShort(int index, int value) { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBuf setMedium(int index, int value) { - throw new ReadOnlyBufferException(); - } - - @Override - protected void _setMedium(int index, int value) { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBuf setInt(int index, int value) { - throw new ReadOnlyBufferException(); - } - - @Override - protected void _setInt(int index, int value) { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBuf setLong(int index, long value) { - throw new ReadOnlyBufferException(); - } - - @Override - protected void _setLong(int index, long value) { - throw new ReadOnlyBufferException(); - } - - @Override - public int setBytes(int index, InputStream in, int length) { - throw new ReadOnlyBufferException(); - } - - @Override - public int setBytes(int index, ScatteringByteChannel in, int length) { - throw new ReadOnlyBufferException(); - } - - @Override - public int getBytes(int index, GatheringByteChannel out, int length) - throws IOException { - return buffer.getBytes(index, out, length); - } - - @Override - public ByteBuf getBytes(int index, OutputStream out, int length) - throws IOException { - buffer.getBytes(index, out, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - buffer.getBytes(index, dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - buffer.getBytes(index, dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuffer dst) { - buffer.getBytes(index, dst); - return this; - } - - @Override - public ByteBuf duplicate() { - return new ReadOnlyByteBuf(this); - } - - @Override - public ByteBuf copy(int index, int length) { - return buffer.copy(index, length); - } - - @Override - public ByteBuf slice(int index, int length) { - return Unpooled.unmodifiableBuffer(buffer.slice(index, length)); - } - - @Override - public byte getByte(int index) { - return _getByte(index); - } - - @Override - protected byte _getByte(int index) { - return buffer.getByte(index); - } - - @Override - public short getShort(int index) { - return _getShort(index); - } - - @Override - protected short _getShort(int index) { - return buffer.getShort(index); - } - - @Override - public int getUnsignedMedium(int index) { - return _getUnsignedMedium(index); - } - - @Override - protected int _getUnsignedMedium(int index) { - return buffer.getUnsignedMedium(index); - } - - @Override - public int getInt(int index) { - return _getInt(index); - } - - @Override - protected int _getInt(int index) { - return buffer.getInt(index); - } - - @Override - public long getLong(int index) { - return _getLong(index); - } - - @Override - protected long _getLong(int index) { - return buffer.getLong(index); - } - - @Override - public int nioBufferCount() { - return buffer.nioBufferCount(); - } - - @Override - public ByteBuffer nioBuffer(int index, int length) { - return buffer.nioBuffer(index, length).asReadOnlyBuffer(); - } - - @Override - public ByteBuffer[] nioBuffers(int index, int length) { - return buffer.nioBuffers(index, length); - } - - @Override - public ByteBuffer internalNioBuffer(int index, int length) { - return nioBuffer(index, length); - } - - @Override - public int forEachByte(int index, int length, ByteBufProcessor processor) { - return buffer.forEachByte(index, length, processor); - } - - @Override - public int forEachByteDesc(int index, int length, ByteBufProcessor processor) { - return buffer.forEachByteDesc(index, length, processor); - } - - @Override - public int capacity() { - return buffer.capacity(); - } - - @Override - public ByteBuf capacity(int newCapacity) { - throw new ReadOnlyBufferException(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ReadOnlyByteBufferBuf.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ReadOnlyByteBufferBuf.java deleted file mode 100755 index 5bfd817d3d..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ReadOnlyByteBufferBuf.java +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.ReadOnlyBufferException; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; - -import com.ai.cloud.io.netty.util.internal.StringUtil; - - -/** - * Read-only ByteBuf which wraps a read-only ByteBuffer. - */ -class ReadOnlyByteBufferBuf extends AbstractReferenceCountedByteBuf { - - protected final ByteBuffer buffer; - private final ByteBufAllocator allocator; - private ByteBuffer tmpNioBuf; - - ReadOnlyByteBufferBuf(ByteBufAllocator allocator, ByteBuffer buffer) { - super(buffer.remaining()); - if (!buffer.isReadOnly()) { - throw new IllegalArgumentException("must be a readonly buffer: " + StringUtil.simpleClassName(buffer)); - } - - this.allocator = allocator; - this.buffer = buffer.slice().order(ByteOrder.BIG_ENDIAN); - writerIndex(this.buffer.limit()); - } - - @Override - protected void deallocate() { } - - @Override - public byte getByte(int index) { - ensureAccessible(); - return _getByte(index); - } - - @Override - protected byte _getByte(int index) { - return buffer.get(index); - } - - @Override - public short getShort(int index) { - ensureAccessible(); - return _getShort(index); - } - - @Override - protected short _getShort(int index) { - return buffer.getShort(index); - } - - @Override - public int getUnsignedMedium(int index) { - ensureAccessible(); - return _getUnsignedMedium(index); - } - - @Override - protected int _getUnsignedMedium(int index) { - return (getByte(index) & 0xff) << 16 | (getByte(index + 1) & 0xff) << 8 | getByte(index + 2) & 0xff; - } - - @Override - public int getInt(int index) { - ensureAccessible(); - return _getInt(index); - } - - @Override - protected int _getInt(int index) { - return buffer.getInt(index); - } - - @Override - public long getLong(int index) { - ensureAccessible(); - return _getLong(index); - } - - @Override - protected long _getLong(int index) { - return buffer.getLong(index); - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - checkDstIndex(index, length, dstIndex, dst.capacity()); - if (dst.hasArray()) { - getBytes(index, dst.array(), dst.arrayOffset() + dstIndex, length); - } else if (dst.nioBufferCount() > 0) { - for (ByteBuffer bb: dst.nioBuffers(dstIndex, length)) { - int bbLen = bb.remaining(); - getBytes(index, bb); - index += bbLen; - } - } else { - dst.setBytes(dstIndex, this, index, length); - } - return this; - } - - @Override - public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - checkDstIndex(index, length, dstIndex, dst.length); - - if (dstIndex < 0 || dstIndex > dst.length - length) { - throw new IndexOutOfBoundsException(String.format( - "dstIndex: %d, length: %d (expected: range(0, %d))", dstIndex, length, dst.length)); - } - - ByteBuffer tmpBuf = internalNioBuffer(); - tmpBuf.clear().position(index).limit(index + length); - tmpBuf.get(dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuffer dst) { - checkIndex(index); - if (dst == null) { - throw new NullPointerException("dst"); - } - - int bytesToCopy = Math.min(capacity() - index, dst.remaining()); - ByteBuffer tmpBuf = internalNioBuffer(); - tmpBuf.clear().position(index).limit(index + bytesToCopy); - dst.put(tmpBuf); - return this; - } - - @Override - protected void _setByte(int index, int value) { - throw new ReadOnlyBufferException(); - } - - @Override - protected void _setShort(int index, int value) { - throw new ReadOnlyBufferException(); - } - - @Override - protected void _setMedium(int index, int value) { - throw new ReadOnlyBufferException(); - } - - @Override - protected void _setInt(int index, int value) { - throw new ReadOnlyBufferException(); - } - - @Override - protected void _setLong(int index, long value) { - throw new ReadOnlyBufferException(); - } - - @Override - public int capacity() { - return maxCapacity(); - } - - @Override - public ByteBuf capacity(int newCapacity) { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBufAllocator alloc() { - return allocator; - } - - @Override - public ByteOrder order() { - return ByteOrder.BIG_ENDIAN; - } - - @Override - public ByteBuf unwrap() { - return null; - } - - @Override - public boolean isDirect() { - return buffer.isDirect(); - } - - @Override - public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException { - ensureAccessible(); - if (length == 0) { - return this; - } - - if (buffer.hasArray()) { - out.write(buffer.array(), index + buffer.arrayOffset(), length); - } else { - byte[] tmp = new byte[length]; - ByteBuffer tmpBuf = internalNioBuffer(); - tmpBuf.clear().position(index); - tmpBuf.get(tmp); - out.write(tmp); - } - return this; - } - - @Override - public int getBytes(int index, GatheringByteChannel out, int length) throws IOException { - ensureAccessible(); - if (length == 0) { - return 0; - } - - ByteBuffer tmpBuf = internalNioBuffer(); - tmpBuf.clear().position(index).limit(index + length); - return out.write(tmpBuf); - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { - throw new ReadOnlyBufferException(); - } - - @Override - public ByteBuf setBytes(int index, ByteBuffer src) { - throw new ReadOnlyBufferException(); - } - - @Override - public int setBytes(int index, InputStream in, int length) throws IOException { - throw new ReadOnlyBufferException(); - } - - @Override - public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException { - throw new ReadOnlyBufferException(); - } - - protected final ByteBuffer internalNioBuffer() { - ByteBuffer tmpNioBuf = this.tmpNioBuf; - if (tmpNioBuf == null) { - this.tmpNioBuf = tmpNioBuf = buffer.duplicate(); - } - return tmpNioBuf; - } - - @Override - public ByteBuf copy(int index, int length) { - ensureAccessible(); - ByteBuffer src; - try { - src = (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length); - } catch (IllegalArgumentException ignored) { - throw new IndexOutOfBoundsException("Too many bytes to read - Need " + (index + length)); - } - - ByteBuffer dst = ByteBuffer.allocateDirect(length); - dst.put(src); - dst.order(order()); - dst.clear(); - return new UnpooledDirectByteBuf(alloc(), dst, maxCapacity()); - } - - @Override - public int nioBufferCount() { - return 1; - } - - @Override - public ByteBuffer[] nioBuffers(int index, int length) { - return new ByteBuffer[] { nioBuffer(index, length) }; - } - - @Override - public ByteBuffer nioBuffer(int index, int length) { - return (ByteBuffer) buffer.duplicate().position(index).limit(index + length); - } - - @Override - public ByteBuffer internalNioBuffer(int index, int length) { - ensureAccessible(); - return (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length); - } - - @Override - public boolean hasArray() { - return buffer.hasArray(); - } - - @Override - public byte[] array() { - return buffer.array(); - } - - @Override - public int arrayOffset() { - return buffer.arrayOffset(); - } - - @Override - public boolean hasMemoryAddress() { - return false; - } - - @Override - public long memoryAddress() { - throw new UnsupportedOperationException(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ReadOnlyUnsafeDirectByteBuf.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ReadOnlyUnsafeDirectByteBuf.java deleted file mode 100755 index 4ed084fcb8..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/ReadOnlyUnsafeDirectByteBuf.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.buffer; - - -import java.nio.ByteBuffer; - -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - - -/** - * Read-only ByteBuf which wraps a read-only direct ByteBuffer and use unsafe for best performance. - */ -final class ReadOnlyUnsafeDirectByteBuf extends ReadOnlyByteBufferBuf { - private final long memoryAddress; - - ReadOnlyUnsafeDirectByteBuf(ByteBufAllocator allocator, ByteBuffer buffer) { - super(allocator, buffer); - memoryAddress = PlatformDependent.directBufferAddress(buffer); - } - - @Override - protected byte _getByte(int index) { - return UnsafeByteBufUtil.getByte(addr(index)); - } - - @Override - protected short _getShort(int index) { - return UnsafeByteBufUtil.getShort(addr(index)); - } - - @Override - protected int _getUnsignedMedium(int index) { - return UnsafeByteBufUtil.getUnsignedMedium(addr(index)); - } - - @Override - protected int _getInt(int index) { - return UnsafeByteBufUtil.getInt(addr(index)); - } - - @Override - protected long _getLong(int index) { - return UnsafeByteBufUtil.getLong(addr(index)); - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - checkIndex(index, length); - if (dst == null) { - throw new NullPointerException("dst"); - } - if (dstIndex < 0 || dstIndex > dst.capacity() - length) { - throw new IndexOutOfBoundsException("dstIndex: " + dstIndex); - } - - if (dst.hasMemoryAddress()) { - PlatformDependent.copyMemory(addr(index), dst.memoryAddress() + dstIndex, length); - } else if (dst.hasArray()) { - PlatformDependent.copyMemory(addr(index), dst.array(), dst.arrayOffset() + dstIndex, length); - } else { - dst.setBytes(dstIndex, this, index, length); - } - return this; - } - - @Override - public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - checkIndex(index, length); - if (dst == null) { - throw new NullPointerException("dst"); - } - if (dstIndex < 0 || dstIndex > dst.length - length) { - throw new IndexOutOfBoundsException(String.format( - "dstIndex: %d, length: %d (expected: range(0, %d))", dstIndex, length, dst.length)); - } - - if (length != 0) { - PlatformDependent.copyMemory(addr(index), dst, dstIndex, length); - } - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuffer dst) { - checkIndex(index); - if (dst == null) { - throw new NullPointerException("dst"); - } - - int bytesToCopy = Math.min(capacity() - index, dst.remaining()); - ByteBuffer tmpBuf = internalNioBuffer(); - tmpBuf.clear().position(index).limit(index + bytesToCopy); - dst.put(tmpBuf); - return this; - } - - @Override - public ByteBuf copy(int index, int length) { - checkIndex(index, length); - ByteBuf copy = alloc().directBuffer(length, maxCapacity()); - if (length != 0) { - if (copy.hasMemoryAddress()) { - PlatformDependent.copyMemory(addr(index), copy.memoryAddress(), length); - copy.setIndex(0, length); - } else { - copy.writeBytes(this, index, length); - } - } - return copy; - } - - private long addr(int index) { - return memoryAddress + index; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/SimpleLeakAwareByteBuf.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/SimpleLeakAwareByteBuf.java deleted file mode 100755 index 954f5df389..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/SimpleLeakAwareByteBuf.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.buffer; - -import java.nio.ByteOrder; - -import com.ai.cloud.io.netty.util.ResourceLeak; - -final class SimpleLeakAwareByteBuf extends WrappedByteBuf { - - private final ResourceLeak leak; - - SimpleLeakAwareByteBuf(ByteBuf buf, ResourceLeak leak) { - super(buf); - this.leak = leak; - } - - @Override - public boolean release() { - boolean deallocated = super.release(); - if (deallocated) { - leak.close(); - } - return deallocated; - } - - @Override - public boolean release(int decrement) { - boolean deallocated = super.release(decrement); - if (deallocated) { - leak.close(); - } - return deallocated; - } - - @Override - public ByteBuf order(ByteOrder endianness) { - leak.record(); - if (order() == endianness) { - return this; - } else { - return new SimpleLeakAwareByteBuf(super.order(endianness), leak); - } - } - - @Override - public ByteBuf slice() { - return new SimpleLeakAwareByteBuf(super.slice(), leak); - } - - @Override - public ByteBuf slice(int index, int length) { - return new SimpleLeakAwareByteBuf(super.slice(index, length), leak); - } - - @Override - public ByteBuf duplicate() { - return new SimpleLeakAwareByteBuf(super.duplicate(), leak); - } - - @Override - public ByteBuf readSlice(int length) { - return new SimpleLeakAwareByteBuf(super.readSlice(length), leak); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/SlicedAbstractByteBuf.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/SlicedAbstractByteBuf.java deleted file mode 100755 index f47bdb6233..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/SlicedAbstractByteBuf.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.buffer; - -/** - * A special {@link SlicedByteBuf} that can make optimizations because it knows the sliced buffer is of type - * {@link AbstractByteBuf}. - */ -final class SlicedAbstractByteBuf extends SlicedByteBuf { - - SlicedAbstractByteBuf(AbstractByteBuf buffer, int index, int length) { - super(buffer, index, length); - } - - @Override - protected byte _getByte(int index) { - return unwrap0()._getByte(idx(index)); - } - - @Override - protected short _getShort(int index) { - return unwrap0()._getShort(idx(index)); - } - - @Override - protected int _getUnsignedMedium(int index) { - return unwrap0()._getUnsignedMedium(idx(index)); - } - - @Override - protected int _getInt(int index) { - return unwrap0()._getInt(idx(index)); - } - - @Override - protected long _getLong(int index) { - return unwrap0()._getLong(idx(index)); - } - - @Override - protected void _setByte(int index, int value) { - unwrap0()._setByte(idx(index), value); - } - - @Override - protected void _setShort(int index, int value) { - unwrap0()._setShort(idx(index), value); - } - - @Override - protected void _setMedium(int index, int value) { - unwrap0()._setMedium(idx(index), value); - } - - @Override - protected void _setInt(int index, int value) { - unwrap0()._setInt(idx(index), value); - } - - @Override - protected void _setLong(int index, long value) { - unwrap0()._setLong(idx(index), value); - } - - private AbstractByteBuf unwrap0() { - return (AbstractByteBuf) unwrap(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/SlicedByteBuf.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/SlicedByteBuf.java deleted file mode 100755 index 99328d1de1..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/SlicedByteBuf.java +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; - - -/** - * A derived buffer which exposes its parent's sub-region only. It is - * recommended to use {@link ByteBuf#slice()} and - * {@link ByteBuf#slice(int, int)} instead of calling the constructor - * explicitly. - */ -public class SlicedByteBuf extends AbstractDerivedByteBuf { - - private final ByteBuf buffer; - private final int adjustment; - private final int length; - - public SlicedByteBuf(ByteBuf buffer, int index, int length) { - super(length); - if (index < 0 || index > buffer.capacity() - length) { - throw new IndexOutOfBoundsException(buffer + ".slice(" + index + ", " + length + ')'); - } - - if (buffer instanceof SlicedByteBuf) { - this.buffer = ((SlicedByteBuf) buffer).buffer; - adjustment = ((SlicedByteBuf) buffer).adjustment + index; - } else if (buffer instanceof DuplicatedByteBuf) { - this.buffer = buffer.unwrap(); - adjustment = index; - } else { - this.buffer = buffer; - adjustment = index; - } - this.length = length; - - writerIndex(length); - } - - @Override - public ByteBuf unwrap() { - return buffer; - } - - @Override - public ByteBufAllocator alloc() { - return buffer.alloc(); - } - - @Override - public ByteOrder order() { - return buffer.order(); - } - - @Override - public boolean isDirect() { - return buffer.isDirect(); - } - - @Override - public int capacity() { - return length; - } - - @Override - public ByteBuf capacity(int newCapacity) { - throw new UnsupportedOperationException("sliced buffer"); - } - - @Override - public boolean hasArray() { - return buffer.hasArray(); - } - - @Override - public byte[] array() { - return buffer.array(); - } - - @Override - public int arrayOffset() { - return idx(buffer.arrayOffset()); - } - - @Override - public boolean hasMemoryAddress() { - return buffer.hasMemoryAddress(); - } - - @Override - public long memoryAddress() { - return buffer.memoryAddress() + adjustment; - } - - @Override - protected byte _getByte(int index) { - return buffer.getByte(idx(index)); - } - - @Override - protected short _getShort(int index) { - return buffer.getShort(idx(index)); - } - - @Override - protected int _getUnsignedMedium(int index) { - return buffer.getUnsignedMedium(idx(index)); - } - - @Override - protected int _getInt(int index) { - return buffer.getInt(idx(index)); - } - - @Override - protected long _getLong(int index) { - return buffer.getLong(idx(index)); - } - - @Override - public ByteBuf duplicate() { - ByteBuf duplicate = buffer.slice(adjustment, length); - duplicate.setIndex(readerIndex(), writerIndex()); - return duplicate; - } - - @Override - public ByteBuf copy(int index, int length) { - checkIndex0(index, length); - return buffer.copy(idx(index), length); - } - - @Override - public ByteBuf slice(int index, int length) { - checkIndex0(index, length); - return buffer.slice(idx(index), length); - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - checkIndex0(index, length); - buffer.getBytes(idx(index), dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - checkIndex0(index, length); - buffer.getBytes(idx(index), dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuffer dst) { - checkIndex0(index, dst.remaining()); - buffer.getBytes(idx(index), dst); - return this; - } - - @Override - protected void _setByte(int index, int value) { - buffer.setByte(idx(index), value); - } - - @Override - protected void _setShort(int index, int value) { - buffer.setShort(idx(index), value); - } - - @Override - protected void _setMedium(int index, int value) { - buffer.setMedium(idx(index), value); - } - - @Override - protected void _setInt(int index, int value) { - buffer.setInt(idx(index), value); - } - - @Override - protected void _setLong(int index, long value) { - buffer.setLong(idx(index), value); - } - - @Override - public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { - checkIndex0(index, length); - buffer.setBytes(idx(index), src, srcIndex, length); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { - checkIndex0(index, length); - buffer.setBytes(idx(index), src, srcIndex, length); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuffer src) { - checkIndex0(index, src.remaining()); - buffer.setBytes(idx(index), src); - return this; - } - - @Override - public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException { - checkIndex0(index, length); - buffer.getBytes(idx(index), out, length); - return this; - } - - @Override - public int getBytes(int index, GatheringByteChannel out, int length) throws IOException { - checkIndex0(index, length); - return buffer.getBytes(idx(index), out, length); - } - - @Override - public int setBytes(int index, InputStream in, int length) throws IOException { - checkIndex0(index, length); - return buffer.setBytes(idx(index), in, length); - } - - @Override - public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException { - checkIndex0(index, length); - return buffer.setBytes(idx(index), in, length); - } - - @Override - public int nioBufferCount() { - return buffer.nioBufferCount(); - } - - @Override - public ByteBuffer nioBuffer(int index, int length) { - checkIndex0(index, length); - return buffer.nioBuffer(idx(index), length); - } - - @Override - public ByteBuffer[] nioBuffers(int index, int length) { - checkIndex0(index, length); - return buffer.nioBuffers(idx(index), length); - } - - @Override - public ByteBuffer internalNioBuffer(int index, int length) { - return nioBuffer(index, length); - } - - @Override - public int forEachByte(int index, int length, ByteBufProcessor processor) { - checkIndex0(index, length); - int ret = buffer.forEachByte(idx(index), length, processor); - if (ret >= adjustment) { - return ret - adjustment; - } else { - return -1; - } - } - - @Override - public int forEachByteDesc(int index, int length, ByteBufProcessor processor) { - checkIndex0(index, length); - int ret = buffer.forEachByteDesc(idx(index), length, processor); - if (ret >= adjustment) { - return ret - adjustment; - } else { - return -1; - } - } - - /** - * Returns the index with the needed adjustment. - */ - final int idx(int index) { - return index + adjustment; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/SwappedByteBuf.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/SwappedByteBuf.java deleted file mode 100755 index 3f73e58539..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/SwappedByteBuf.java +++ /dev/null @@ -1,852 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; -import java.nio.charset.Charset; - -/** - * Wrapper which swap the {@link ByteOrder} of a {@link ByteBuf}. - */ -public class SwappedByteBuf extends ByteBuf { - - private final ByteBuf buf; - private final ByteOrder order; - - public SwappedByteBuf(ByteBuf buf) { - if (buf == null) { - throw new NullPointerException("buf"); - } - this.buf = buf; - if (buf.order() == ByteOrder.BIG_ENDIAN) { - order = ByteOrder.LITTLE_ENDIAN; - } else { - order = ByteOrder.BIG_ENDIAN; - } - } - - @Override - public ByteOrder order() { - return order; - } - - @Override - public ByteBuf order(ByteOrder endianness) { - if (endianness == null) { - throw new NullPointerException("endianness"); - } - if (endianness == order) { - return this; - } - return buf; - } - - @Override - public ByteBuf unwrap() { - return buf.unwrap(); - } - - @Override - public ByteBufAllocator alloc() { - return buf.alloc(); - } - - @Override - public int capacity() { - return buf.capacity(); - } - - @Override - public ByteBuf capacity(int newCapacity) { - buf.capacity(newCapacity); - return this; - } - - @Override - public int maxCapacity() { - return buf.maxCapacity(); - } - - @Override - public boolean isDirect() { - return buf.isDirect(); - } - - @Override - public int readerIndex() { - return buf.readerIndex(); - } - - @Override - public ByteBuf readerIndex(int readerIndex) { - buf.readerIndex(readerIndex); - return this; - } - - @Override - public int writerIndex() { - return buf.writerIndex(); - } - - @Override - public ByteBuf writerIndex(int writerIndex) { - buf.writerIndex(writerIndex); - return this; - } - - @Override - public ByteBuf setIndex(int readerIndex, int writerIndex) { - buf.setIndex(readerIndex, writerIndex); - return this; - } - - @Override - public int readableBytes() { - return buf.readableBytes(); - } - - @Override - public int writableBytes() { - return buf.writableBytes(); - } - - @Override - public int maxWritableBytes() { - return buf.maxWritableBytes(); - } - - @Override - public boolean isReadable() { - return buf.isReadable(); - } - - @Override - public boolean isReadable(int size) { - return buf.isReadable(size); - } - - @Override - public boolean isWritable() { - return buf.isWritable(); - } - - @Override - public boolean isWritable(int size) { - return buf.isWritable(size); - } - - @Override - public ByteBuf clear() { - buf.clear(); - return this; - } - - @Override - public ByteBuf markReaderIndex() { - buf.markReaderIndex(); - return this; - } - - @Override - public ByteBuf resetReaderIndex() { - buf.resetReaderIndex(); - return this; - } - - @Override - public ByteBuf markWriterIndex() { - buf.markWriterIndex(); - return this; - } - - @Override - public ByteBuf resetWriterIndex() { - buf.resetWriterIndex(); - return this; - } - - @Override - public ByteBuf discardReadBytes() { - buf.discardReadBytes(); - return this; - } - - @Override - public ByteBuf discardSomeReadBytes() { - buf.discardSomeReadBytes(); - return this; - } - - @Override - public ByteBuf ensureWritable(int writableBytes) { - buf.ensureWritable(writableBytes); - return this; - } - - @Override - public int ensureWritable(int minWritableBytes, boolean force) { - return buf.ensureWritable(minWritableBytes, force); - } - - @Override - public boolean getBoolean(int index) { - return buf.getBoolean(index); - } - - @Override - public byte getByte(int index) { - return buf.getByte(index); - } - - @Override - public short getUnsignedByte(int index) { - return buf.getUnsignedByte(index); - } - - @Override - public short getShort(int index) { - return ByteBufUtil.swapShort(buf.getShort(index)); - } - - @Override - public int getUnsignedShort(int index) { - return getShort(index) & 0xFFFF; - } - - @Override - public int getMedium(int index) { - return ByteBufUtil.swapMedium(buf.getMedium(index)); - } - - @Override - public int getUnsignedMedium(int index) { - return getMedium(index) & 0xFFFFFF; - } - - @Override - public int getInt(int index) { - return ByteBufUtil.swapInt(buf.getInt(index)); - } - - @Override - public long getUnsignedInt(int index) { - return getInt(index) & 0xFFFFFFFFL; - } - - @Override - public long getLong(int index) { - return ByteBufUtil.swapLong(buf.getLong(index)); - } - - @Override - public char getChar(int index) { - return (char) getShort(index); - } - - @Override - public float getFloat(int index) { - return Float.intBitsToFloat(getInt(index)); - } - - @Override - public double getDouble(int index) { - return Double.longBitsToDouble(getLong(index)); - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst) { - buf.getBytes(index, dst); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int length) { - buf.getBytes(index, dst, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - buf.getBytes(index, dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, byte[] dst) { - buf.getBytes(index, dst); - return this; - } - - @Override - public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - buf.getBytes(index, dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuffer dst) { - buf.getBytes(index, dst); - return this; - } - - @Override - public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException { - buf.getBytes(index, out, length); - return this; - } - - @Override - public int getBytes(int index, GatheringByteChannel out, int length) throws IOException { - return buf.getBytes(index, out, length); - } - - @Override - public ByteBuf setBoolean(int index, boolean value) { - buf.setBoolean(index, value); - return this; - } - - @Override - public ByteBuf setByte(int index, int value) { - buf.setByte(index, value); - return this; - } - - @Override - public ByteBuf setShort(int index, int value) { - buf.setShort(index, ByteBufUtil.swapShort((short) value)); - return this; - } - - @Override - public ByteBuf setMedium(int index, int value) { - buf.setMedium(index, ByteBufUtil.swapMedium(value)); - return this; - } - - @Override - public ByteBuf setInt(int index, int value) { - buf.setInt(index, ByteBufUtil.swapInt(value)); - return this; - } - - @Override - public ByteBuf setLong(int index, long value) { - buf.setLong(index, ByteBufUtil.swapLong(value)); - return this; - } - - @Override - public ByteBuf setChar(int index, int value) { - setShort(index, value); - return this; - } - - @Override - public ByteBuf setFloat(int index, float value) { - setInt(index, Float.floatToRawIntBits(value)); - return this; - } - - @Override - public ByteBuf setDouble(int index, double value) { - setLong(index, Double.doubleToRawLongBits(value)); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src) { - buf.setBytes(index, src); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int length) { - buf.setBytes(index, src, length); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { - buf.setBytes(index, src, srcIndex, length); - return this; - } - - @Override - public ByteBuf setBytes(int index, byte[] src) { - buf.setBytes(index, src); - return this; - } - - @Override - public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { - buf.setBytes(index, src, srcIndex, length); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuffer src) { - buf.setBytes(index, src); - return this; - } - - @Override - public int setBytes(int index, InputStream in, int length) throws IOException { - return buf.setBytes(index, in, length); - } - - @Override - public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException { - return buf.setBytes(index, in, length); - } - - @Override - public ByteBuf setZero(int index, int length) { - buf.setZero(index, length); - return this; - } - - @Override - public boolean readBoolean() { - return buf.readBoolean(); - } - - @Override - public byte readByte() { - return buf.readByte(); - } - - @Override - public short readUnsignedByte() { - return buf.readUnsignedByte(); - } - - @Override - public short readShort() { - return ByteBufUtil.swapShort(buf.readShort()); - } - - @Override - public int readUnsignedShort() { - return readShort() & 0xFFFF; - } - - @Override - public int readMedium() { - return ByteBufUtil.swapMedium(buf.readMedium()); - } - - @Override - public int readUnsignedMedium() { - return readMedium() & 0xFFFFFF; - } - - @Override - public int readInt() { - return ByteBufUtil.swapInt(buf.readInt()); - } - - @Override - public long readUnsignedInt() { - return readInt() & 0xFFFFFFFFL; - } - - @Override - public long readLong() { - return ByteBufUtil.swapLong(buf.readLong()); - } - - @Override - public char readChar() { - return (char) readShort(); - } - - @Override - public float readFloat() { - return Float.intBitsToFloat(readInt()); - } - - @Override - public double readDouble() { - return Double.longBitsToDouble(readLong()); - } - - @Override - public ByteBuf readBytes(int length) { - return buf.readBytes(length).order(order()); - } - - @Override - public ByteBuf readSlice(int length) { - return buf.readSlice(length).order(order); - } - - @Override - public ByteBuf readBytes(ByteBuf dst) { - buf.readBytes(dst); - return this; - } - - @Override - public ByteBuf readBytes(ByteBuf dst, int length) { - buf.readBytes(dst, length); - return this; - } - - @Override - public ByteBuf readBytes(ByteBuf dst, int dstIndex, int length) { - buf.readBytes(dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf readBytes(byte[] dst) { - buf.readBytes(dst); - return this; - } - - @Override - public ByteBuf readBytes(byte[] dst, int dstIndex, int length) { - buf.readBytes(dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf readBytes(ByteBuffer dst) { - buf.readBytes(dst); - return this; - } - - @Override - public ByteBuf readBytes(OutputStream out, int length) throws IOException { - buf.readBytes(out, length); - return this; - } - - @Override - public int readBytes(GatheringByteChannel out, int length) throws IOException { - return buf.readBytes(out, length); - } - - @Override - public ByteBuf skipBytes(int length) { - buf.skipBytes(length); - return this; - } - - @Override - public ByteBuf writeBoolean(boolean value) { - buf.writeBoolean(value); - return this; - } - - @Override - public ByteBuf writeByte(int value) { - buf.writeByte(value); - return this; - } - - @Override - public ByteBuf writeShort(int value) { - buf.writeShort(ByteBufUtil.swapShort((short) value)); - return this; - } - - @Override - public ByteBuf writeMedium(int value) { - buf.writeMedium(ByteBufUtil.swapMedium(value)); - return this; - } - - @Override - public ByteBuf writeInt(int value) { - buf.writeInt(ByteBufUtil.swapInt(value)); - return this; - } - - @Override - public ByteBuf writeLong(long value) { - buf.writeLong(ByteBufUtil.swapLong(value)); - return this; - } - - @Override - public ByteBuf writeChar(int value) { - writeShort(value); - return this; - } - - @Override - public ByteBuf writeFloat(float value) { - writeInt(Float.floatToRawIntBits(value)); - return this; - } - - @Override - public ByteBuf writeDouble(double value) { - writeLong(Double.doubleToRawLongBits(value)); - return this; - } - - @Override - public ByteBuf writeBytes(ByteBuf src) { - buf.writeBytes(src); - return this; - } - - @Override - public ByteBuf writeBytes(ByteBuf src, int length) { - buf.writeBytes(src, length); - return this; - } - - @Override - public ByteBuf writeBytes(ByteBuf src, int srcIndex, int length) { - buf.writeBytes(src, srcIndex, length); - return this; - } - - @Override - public ByteBuf writeBytes(byte[] src) { - buf.writeBytes(src); - return this; - } - - @Override - public ByteBuf writeBytes(byte[] src, int srcIndex, int length) { - buf.writeBytes(src, srcIndex, length); - return this; - } - - @Override - public ByteBuf writeBytes(ByteBuffer src) { - buf.writeBytes(src); - return this; - } - - @Override - public int writeBytes(InputStream in, int length) throws IOException { - return buf.writeBytes(in, length); - } - - @Override - public int writeBytes(ScatteringByteChannel in, int length) throws IOException { - return buf.writeBytes(in, length); - } - - @Override - public ByteBuf writeZero(int length) { - buf.writeZero(length); - return this; - } - - @Override - public int indexOf(int fromIndex, int toIndex, byte value) { - return buf.indexOf(fromIndex, toIndex, value); - } - - @Override - public int bytesBefore(byte value) { - return buf.bytesBefore(value); - } - - @Override - public int bytesBefore(int length, byte value) { - return buf.bytesBefore(length, value); - } - - @Override - public int bytesBefore(int index, int length, byte value) { - return buf.bytesBefore(index, length, value); - } - - @Override - public int forEachByte(ByteBufProcessor processor) { - return buf.forEachByte(processor); - } - - @Override - public int forEachByte(int index, int length, ByteBufProcessor processor) { - return buf.forEachByte(index, length, processor); - } - - @Override - public int forEachByteDesc(ByteBufProcessor processor) { - return buf.forEachByteDesc(processor); - } - - @Override - public int forEachByteDesc(int index, int length, ByteBufProcessor processor) { - return buf.forEachByteDesc(index, length, processor); - } - - @Override - public ByteBuf copy() { - return buf.copy().order(order); - } - - @Override - public ByteBuf copy(int index, int length) { - return buf.copy(index, length).order(order); - } - - @Override - public ByteBuf slice() { - return buf.slice().order(order); - } - - @Override - public ByteBuf slice(int index, int length) { - return buf.slice(index, length).order(order); - } - - @Override - public ByteBuf duplicate() { - return buf.duplicate().order(order); - } - - @Override - public int nioBufferCount() { - return buf.nioBufferCount(); - } - - @Override - public ByteBuffer nioBuffer() { - return buf.nioBuffer().order(order); - } - - @Override - public ByteBuffer nioBuffer(int index, int length) { - return buf.nioBuffer(index, length).order(order); - } - - @Override - public ByteBuffer internalNioBuffer(int index, int length) { - return nioBuffer(index, length); - } - - @Override - public ByteBuffer[] nioBuffers() { - ByteBuffer[] nioBuffers = buf.nioBuffers(); - for (int i = 0; i < nioBuffers.length; i++) { - nioBuffers[i] = nioBuffers[i].order(order); - } - return nioBuffers; - } - - @Override - public ByteBuffer[] nioBuffers(int index, int length) { - ByteBuffer[] nioBuffers = buf.nioBuffers(index, length); - for (int i = 0; i < nioBuffers.length; i++) { - nioBuffers[i] = nioBuffers[i].order(order); - } - return nioBuffers; - } - - @Override - public boolean hasArray() { - return buf.hasArray(); - } - - @Override - public byte[] array() { - return buf.array(); - } - - @Override - public int arrayOffset() { - return buf.arrayOffset(); - } - - @Override - public boolean hasMemoryAddress() { - return buf.hasMemoryAddress(); - } - - @Override - public long memoryAddress() { - return buf.memoryAddress(); - } - - @Override - public String toString(Charset charset) { - return buf.toString(charset); - } - - @Override - public String toString(int index, int length, Charset charset) { - return buf.toString(index, length, charset); - } - - @Override - public int refCnt() { - return buf.refCnt(); - } - - @Override - public ByteBuf retain() { - buf.retain(); - return this; - } - - @Override - public ByteBuf retain(int increment) { - buf.retain(increment); - return this; - } - - @Override - public boolean release() { - return buf.release(); - } - - @Override - public boolean release(int decrement) { - return buf.release(decrement); - } - - @Override - public int hashCode() { - return buf.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof ByteBuf) { - return ByteBufUtil.equals(this, (ByteBuf) obj); - } - return false; - } - - @Override - public int compareTo(ByteBuf buffer) { - return ByteBufUtil.compare(this, buffer); - } - - @Override - public String toString() { - return "Swapped(" + buf.toString() + ')'; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/Unpooled.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/Unpooled.java deleted file mode 100755 index f92f716b4a..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/Unpooled.java +++ /dev/null @@ -1,865 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.buffer; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.CharBuffer; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.List; - -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - - -/** - * Creates a new {@link ByteBuf} by allocating new space or by wrapping - * or copying existing byte arrays, byte buffers and a string. - * - *

Use static import

- * This classes is intended to be used with Java 5 static import statement: - * - *
- * import static io.netty.buffer.{@link Unpooled}.*;
- *
- * {@link ByteBuf} heapBuffer    = buffer(128);
- * {@link ByteBuf} directBuffer  = directBuffer(256);
- * {@link ByteBuf} wrappedBuffer = wrappedBuffer(new byte[128], new byte[256]);
- * {@link ByteBuf} copiedBuffe r = copiedBuffer({@link ByteBuffer}.allocate(128));
- * 
- * - *

Allocating a new buffer

- * - * Three buffer types are provided out of the box. - * - *
    - *
  • {@link #buffer(int)} allocates a new fixed-capacity heap buffer.
  • - *
  • {@link #directBuffer(int)} allocates a new fixed-capacity direct buffer.
  • - *
- * - *

Creating a wrapped buffer

- * - * Wrapped buffer is a buffer which is a view of one or more existing - * byte arrays and byte buffers. Any changes in the content of the original - * array or buffer will be visible in the wrapped buffer. Various wrapper - * methods are provided and their name is all {@code wrappedBuffer()}. - * You might want to take a look at the methods that accept varargs closely if - * you want to create a buffer which is composed of more than one array to - * reduce the number of memory copy. - * - *

Creating a copied buffer

- * - * Copied buffer is a deep copy of one or more existing byte arrays, byte - * buffers or a string. Unlike a wrapped buffer, there's no shared data - * between the original data and the copied buffer. Various copy methods are - * provided and their name is all {@code copiedBuffer()}. It is also convenient - * to use this operation to merge multiple buffers into one buffer. - */ -public final class Unpooled { - - private static final ByteBufAllocator ALLOC = UnpooledByteBufAllocator.DEFAULT; - - /** - * Big endian byte order. - */ - public static final ByteOrder BIG_ENDIAN = ByteOrder.BIG_ENDIAN; - - /** - * Little endian byte order. - */ - public static final ByteOrder LITTLE_ENDIAN = ByteOrder.LITTLE_ENDIAN; - - /** - * A buffer whose capacity is {@code 0}. - */ - public static final ByteBuf EMPTY_BUFFER = ALLOC.buffer(0, 0); - - static { - assert EMPTY_BUFFER instanceof EmptyByteBuf: "EMPTY_BUFFER must be an EmptyByteBuf."; - } - - /** - * Creates a new big-endian Java heap buffer with reasonably small initial capacity, which - * expands its capacity boundlessly on demand. - */ - public static ByteBuf buffer() { - return ALLOC.heapBuffer(); - } - - /** - * Creates a new big-endian direct buffer with reasonably small initial capacity, which - * expands its capacity boundlessly on demand. - */ - public static ByteBuf directBuffer() { - return ALLOC.directBuffer(); - } - - /** - * Creates a new big-endian Java heap buffer with the specified {@code capacity}, which - * expands its capacity boundlessly on demand. The new buffer's {@code readerIndex} and - * {@code writerIndex} are {@code 0}. - */ - public static ByteBuf buffer(int initialCapacity) { - return ALLOC.heapBuffer(initialCapacity); - } - - /** - * Creates a new big-endian direct buffer with the specified {@code capacity}, which - * expands its capacity boundlessly on demand. The new buffer's {@code readerIndex} and - * {@code writerIndex} are {@code 0}. - */ - public static ByteBuf directBuffer(int initialCapacity) { - return ALLOC.directBuffer(initialCapacity); - } - - /** - * Creates a new big-endian Java heap buffer with the specified - * {@code initialCapacity}, that may grow up to {@code maxCapacity} - * The new buffer's {@code readerIndex} and {@code writerIndex} are - * {@code 0}. - */ - public static ByteBuf buffer(int initialCapacity, int maxCapacity) { - return ALLOC.heapBuffer(initialCapacity, maxCapacity); - } - - /** - * Creates a new big-endian direct buffer with the specified - * {@code initialCapacity}, that may grow up to {@code maxCapacity}. - * The new buffer's {@code readerIndex} and {@code writerIndex} are - * {@code 0}. - */ - public static ByteBuf directBuffer(int initialCapacity, int maxCapacity) { - return ALLOC.directBuffer(initialCapacity, maxCapacity); - } - - /** - * Creates a new big-endian buffer which wraps the specified {@code array}. - * A modification on the specified array's content will be visible to the - * returned buffer. - */ - public static ByteBuf wrappedBuffer(byte[] array) { - if (array.length == 0) { - return EMPTY_BUFFER; - } - return new UnpooledHeapByteBuf(ALLOC, array, array.length); - } - - /** - * Creates a new big-endian buffer which wraps the sub-region of the - * specified {@code array}. A modification on the specified array's - * content will be visible to the returned buffer. - */ - public static ByteBuf wrappedBuffer(byte[] array, int offset, int length) { - if (length == 0) { - return EMPTY_BUFFER; - } - - if (offset == 0 && length == array.length) { - return wrappedBuffer(array); - } - - return wrappedBuffer(array).slice(offset, length); - } - - /** - * Creates a new buffer which wraps the specified NIO buffer's current - * slice. A modification on the specified buffer's content will be - * visible to the returned buffer. - */ - public static ByteBuf wrappedBuffer(ByteBuffer buffer) { - if (!buffer.hasRemaining()) { - return EMPTY_BUFFER; - } - if (buffer.hasArray()) { - return wrappedBuffer( - buffer.array(), - buffer.arrayOffset() + buffer.position(), - buffer.remaining()).order(buffer.order()); - } else if (PlatformDependent.hasUnsafe()) { - if (buffer.isReadOnly()) { - if (buffer.isDirect()) { - return new ReadOnlyUnsafeDirectByteBuf(ALLOC, buffer); - } else { - return new ReadOnlyByteBufferBuf(ALLOC, buffer); - } - } else { - return new UnpooledUnsafeDirectByteBuf(ALLOC, buffer, buffer.remaining()); - } - } else { - if (buffer.isReadOnly()) { - return new ReadOnlyByteBufferBuf(ALLOC, buffer); - } else { - return new UnpooledDirectByteBuf(ALLOC, buffer, buffer.remaining()); - } - } - } - - /** - * Creates a new buffer which wraps the specified buffer's readable bytes. - * A modification on the specified buffer's content will be visible to the - * returned buffer. - */ - public static ByteBuf wrappedBuffer(ByteBuf buffer) { - if (buffer.isReadable()) { - return buffer.slice(); - } else { - return EMPTY_BUFFER; - } - } - - /** - * Creates a new big-endian composite buffer which wraps the specified - * arrays without copying them. A modification on the specified arrays' - * content will be visible to the returned buffer. - */ - public static ByteBuf wrappedBuffer(byte[]... arrays) { - return wrappedBuffer(16, arrays); - } - - /** - * Creates a new big-endian composite buffer which wraps the readable bytes of the - * specified buffers without copying them. A modification on the content - * of the specified buffers will be visible to the returned buffer. - */ - public static ByteBuf wrappedBuffer(ByteBuf... buffers) { - return wrappedBuffer(16, buffers); - } - - /** - * Creates a new big-endian composite buffer which wraps the slices of the specified - * NIO buffers without copying them. A modification on the content of the - * specified buffers will be visible to the returned buffer. - */ - public static ByteBuf wrappedBuffer(ByteBuffer... buffers) { - return wrappedBuffer(16, buffers); - } - - /** - * Creates a new big-endian composite buffer which wraps the specified - * arrays without copying them. A modification on the specified arrays' - * content will be visible to the returned buffer. - */ - public static ByteBuf wrappedBuffer(int maxNumComponents, byte[]... arrays) { - switch (arrays.length) { - case 0: - break; - case 1: - if (arrays[0].length != 0) { - return wrappedBuffer(arrays[0]); - } - break; - default: - // Get the list of the component, while guessing the byte order. - final List components = new ArrayList(arrays.length); - for (byte[] a: arrays) { - if (a == null) { - break; - } - if (a.length > 0) { - components.add(wrappedBuffer(a)); - } - } - - if (!components.isEmpty()) { - return new CompositeByteBuf(ALLOC, false, maxNumComponents, components); - } - } - - return EMPTY_BUFFER; - } - - /** - * Creates a new big-endian composite buffer which wraps the readable bytes of the - * specified buffers without copying them. A modification on the content - * of the specified buffers will be visible to the returned buffer. - */ - public static ByteBuf wrappedBuffer(int maxNumComponents, ByteBuf... buffers) { - switch (buffers.length) { - case 0: - break; - case 1: - if (buffers[0].isReadable()) { - return wrappedBuffer(buffers[0].order(BIG_ENDIAN)); - } - break; - default: - for (ByteBuf b: buffers) { - if (b.isReadable()) { - return new CompositeByteBuf(ALLOC, false, maxNumComponents, buffers); - } - } - } - return EMPTY_BUFFER; - } - - /** - * Creates a new big-endian composite buffer which wraps the slices of the specified - * NIO buffers without copying them. A modification on the content of the - * specified buffers will be visible to the returned buffer. - */ - public static ByteBuf wrappedBuffer(int maxNumComponents, ByteBuffer... buffers) { - switch (buffers.length) { - case 0: - break; - case 1: - if (buffers[0].hasRemaining()) { - return wrappedBuffer(buffers[0].order(BIG_ENDIAN)); - } - break; - default: - // Get the list of the component, while guessing the byte order. - final List components = new ArrayList(buffers.length); - for (ByteBuffer b: buffers) { - if (b == null) { - break; - } - if (b.remaining() > 0) { - components.add(wrappedBuffer(b.order(BIG_ENDIAN))); - } - } - - if (!components.isEmpty()) { - return new CompositeByteBuf(ALLOC, false, maxNumComponents, components); - } - } - - return EMPTY_BUFFER; - } - - /** - * Returns a new big-endian composite buffer with no components. - */ - public static CompositeByteBuf compositeBuffer() { - return compositeBuffer(16); - } - - /** - * Returns a new big-endian composite buffer with no components. - */ - public static CompositeByteBuf compositeBuffer(int maxNumComponents) { - return new CompositeByteBuf(ALLOC, false, maxNumComponents); - } - - /** - * Creates a new big-endian buffer whose content is a copy of the - * specified {@code array}. The new buffer's {@code readerIndex} and - * {@code writerIndex} are {@code 0} and {@code array.length} respectively. - */ - public static ByteBuf copiedBuffer(byte[] array) { - if (array.length == 0) { - return EMPTY_BUFFER; - } - return wrappedBuffer(array.clone()); - } - - /** - * Creates a new big-endian buffer whose content is a copy of the - * specified {@code array}'s sub-region. The new buffer's - * {@code readerIndex} and {@code writerIndex} are {@code 0} and - * the specified {@code length} respectively. - */ - public static ByteBuf copiedBuffer(byte[] array, int offset, int length) { - if (length == 0) { - return EMPTY_BUFFER; - } - byte[] copy = new byte[length]; - System.arraycopy(array, offset, copy, 0, length); - return wrappedBuffer(copy); - } - - /** - * Creates a new buffer whose content is a copy of the specified - * {@code buffer}'s current slice. The new buffer's {@code readerIndex} - * and {@code writerIndex} are {@code 0} and {@code buffer.remaining} - * respectively. - */ - public static ByteBuf copiedBuffer(ByteBuffer buffer) { - int length = buffer.remaining(); - if (length == 0) { - return EMPTY_BUFFER; - } - byte[] copy = new byte[length]; - // Duplicate the buffer so we not adjust the position during our get operation. - // See https://github.com/netty/netty/issues/3896 - ByteBuffer duplicate = buffer.duplicate(); - duplicate.get(copy); - return wrappedBuffer(copy).order(duplicate.order()); - } - - /** - * Creates a new buffer whose content is a copy of the specified - * {@code buffer}'s readable bytes. The new buffer's {@code readerIndex} - * and {@code writerIndex} are {@code 0} and {@code buffer.readableBytes} - * respectively. - */ - public static ByteBuf copiedBuffer(ByteBuf buffer) { - int readable = buffer.readableBytes(); - if (readable > 0) { - ByteBuf copy = buffer(readable); - copy.writeBytes(buffer, buffer.readerIndex(), readable); - return copy; - } else { - return EMPTY_BUFFER; - } - } - - /** - * Creates a new big-endian buffer whose content is a merged copy of - * the specified {@code arrays}. The new buffer's {@code readerIndex} - * and {@code writerIndex} are {@code 0} and the sum of all arrays' - * {@code length} respectively. - */ - public static ByteBuf copiedBuffer(byte[]... arrays) { - switch (arrays.length) { - case 0: - return EMPTY_BUFFER; - case 1: - if (arrays[0].length == 0) { - return EMPTY_BUFFER; - } else { - return copiedBuffer(arrays[0]); - } - } - - // Merge the specified arrays into one array. - int length = 0; - for (byte[] a: arrays) { - if (Integer.MAX_VALUE - length < a.length) { - throw new IllegalArgumentException( - "The total length of the specified arrays is too big."); - } - length += a.length; - } - - if (length == 0) { - return EMPTY_BUFFER; - } - - byte[] mergedArray = new byte[length]; - for (int i = 0, j = 0; i < arrays.length; i ++) { - byte[] a = arrays[i]; - System.arraycopy(a, 0, mergedArray, j, a.length); - j += a.length; - } - - return wrappedBuffer(mergedArray); - } - - /** - * Creates a new buffer whose content is a merged copy of the specified - * {@code buffers}' readable bytes. The new buffer's {@code readerIndex} - * and {@code writerIndex} are {@code 0} and the sum of all buffers' - * {@code readableBytes} respectively. - * - * @throws IllegalArgumentException - * if the specified buffers' endianness are different from each - * other - */ - public static ByteBuf copiedBuffer(ByteBuf... buffers) { - switch (buffers.length) { - case 0: - return EMPTY_BUFFER; - case 1: - return copiedBuffer(buffers[0]); - } - - // Merge the specified buffers into one buffer. - ByteOrder order = null; - int length = 0; - for (ByteBuf b: buffers) { - int bLen = b.readableBytes(); - if (bLen <= 0) { - continue; - } - if (Integer.MAX_VALUE - length < bLen) { - throw new IllegalArgumentException( - "The total length of the specified buffers is too big."); - } - length += bLen; - if (order != null) { - if (!order.equals(b.order())) { - throw new IllegalArgumentException("inconsistent byte order"); - } - } else { - order = b.order(); - } - } - - if (length == 0) { - return EMPTY_BUFFER; - } - - byte[] mergedArray = new byte[length]; - for (int i = 0, j = 0; i < buffers.length; i ++) { - ByteBuf b = buffers[i]; - int bLen = b.readableBytes(); - b.getBytes(b.readerIndex(), mergedArray, j, bLen); - j += bLen; - } - - return wrappedBuffer(mergedArray).order(order); - } - - /** - * Creates a new buffer whose content is a merged copy of the specified - * {@code buffers}' slices. The new buffer's {@code readerIndex} and - * {@code writerIndex} are {@code 0} and the sum of all buffers' - * {@code remaining} respectively. - * - * @throws IllegalArgumentException - * if the specified buffers' endianness are different from each - * other - */ - public static ByteBuf copiedBuffer(ByteBuffer... buffers) { - switch (buffers.length) { - case 0: - return EMPTY_BUFFER; - case 1: - return copiedBuffer(buffers[0]); - } - - // Merge the specified buffers into one buffer. - ByteOrder order = null; - int length = 0; - for (ByteBuffer b: buffers) { - int bLen = b.remaining(); - if (bLen <= 0) { - continue; - } - if (Integer.MAX_VALUE - length < bLen) { - throw new IllegalArgumentException( - "The total length of the specified buffers is too big."); - } - length += bLen; - if (order != null) { - if (!order.equals(b.order())) { - throw new IllegalArgumentException("inconsistent byte order"); - } - } else { - order = b.order(); - } - } - - if (length == 0) { - return EMPTY_BUFFER; - } - - byte[] mergedArray = new byte[length]; - for (int i = 0, j = 0; i < buffers.length; i ++) { - // Duplicate the buffer so we not adjust the position during our get operation. - // See https://github.com/netty/netty/issues/3896 - ByteBuffer b = buffers[i].duplicate(); - int bLen = b.remaining(); - b.get(mergedArray, j, bLen); - j += bLen; - } - - return wrappedBuffer(mergedArray).order(order); - } - - /** - * Creates a new big-endian buffer whose content is the specified - * {@code string} encoded in the specified {@code charset}. - * The new buffer's {@code readerIndex} and {@code writerIndex} are - * {@code 0} and the length of the encoded string respectively. - */ - public static ByteBuf copiedBuffer(CharSequence string, Charset charset) { - if (string == null) { - throw new NullPointerException("string"); - } - - if (string instanceof CharBuffer) { - return copiedBuffer((CharBuffer) string, charset); - } - - return copiedBuffer(CharBuffer.wrap(string), charset); - } - - /** - * Creates a new big-endian buffer whose content is a subregion of - * the specified {@code string} encoded in the specified {@code charset}. - * The new buffer's {@code readerIndex} and {@code writerIndex} are - * {@code 0} and the length of the encoded string respectively. - */ - public static ByteBuf copiedBuffer( - CharSequence string, int offset, int length, Charset charset) { - if (string == null) { - throw new NullPointerException("string"); - } - if (length == 0) { - return EMPTY_BUFFER; - } - - if (string instanceof CharBuffer) { - CharBuffer buf = (CharBuffer) string; - if (buf.hasArray()) { - return copiedBuffer( - buf.array(), - buf.arrayOffset() + buf.position() + offset, - length, charset); - } - - buf = buf.slice(); - buf.limit(length); - buf.position(offset); - return copiedBuffer(buf, charset); - } - - return copiedBuffer(CharBuffer.wrap(string, offset, offset + length), charset); - } - - /** - * Creates a new big-endian buffer whose content is the specified - * {@code array} encoded in the specified {@code charset}. - * The new buffer's {@code readerIndex} and {@code writerIndex} are - * {@code 0} and the length of the encoded string respectively. - */ - public static ByteBuf copiedBuffer(char[] array, Charset charset) { - if (array == null) { - throw new NullPointerException("array"); - } - return copiedBuffer(array, 0, array.length, charset); - } - - /** - * Creates a new big-endian buffer whose content is a subregion of - * the specified {@code array} encoded in the specified {@code charset}. - * The new buffer's {@code readerIndex} and {@code writerIndex} are - * {@code 0} and the length of the encoded string respectively. - */ - public static ByteBuf copiedBuffer(char[] array, int offset, int length, Charset charset) { - if (array == null) { - throw new NullPointerException("array"); - } - if (length == 0) { - return EMPTY_BUFFER; - } - return copiedBuffer(CharBuffer.wrap(array, offset, length), charset); - } - - private static ByteBuf copiedBuffer(CharBuffer buffer, Charset charset) { - return ByteBufUtil.encodeString0(ALLOC, true, buffer, charset); - } - - /** - * Creates a read-only buffer which disallows any modification operations - * on the specified {@code buffer}. The new buffer has the same - * {@code readerIndex} and {@code writerIndex} with the specified - * {@code buffer}. - */ - public static ByteBuf unmodifiableBuffer(ByteBuf buffer) { - ByteOrder endianness = buffer.order(); - if (endianness == BIG_ENDIAN) { - return new ReadOnlyByteBuf(buffer); - } - - return new ReadOnlyByteBuf(buffer.order(BIG_ENDIAN)).order(LITTLE_ENDIAN); - } - - /** - * Creates a new 4-byte big-endian buffer that holds the specified 32-bit integer. - */ - public static ByteBuf copyInt(int value) { - ByteBuf buf = buffer(4); - buf.writeInt(value); - return buf; - } - - /** - * Create a big-endian buffer that holds a sequence of the specified 32-bit integers. - */ - public static ByteBuf copyInt(int... values) { - if (values == null || values.length == 0) { - return EMPTY_BUFFER; - } - ByteBuf buffer = buffer(values.length * 4); - for (int v: values) { - buffer.writeInt(v); - } - return buffer; - } - - /** - * Creates a new 2-byte big-endian buffer that holds the specified 16-bit integer. - */ - public static ByteBuf copyShort(int value) { - ByteBuf buf = buffer(2); - buf.writeShort(value); - return buf; - } - - /** - * Create a new big-endian buffer that holds a sequence of the specified 16-bit integers. - */ - public static ByteBuf copyShort(short... values) { - if (values == null || values.length == 0) { - return EMPTY_BUFFER; - } - ByteBuf buffer = buffer(values.length * 2); - for (int v: values) { - buffer.writeShort(v); - } - return buffer; - } - - /** - * Create a new big-endian buffer that holds a sequence of the specified 16-bit integers. - */ - public static ByteBuf copyShort(int... values) { - if (values == null || values.length == 0) { - return EMPTY_BUFFER; - } - ByteBuf buffer = buffer(values.length * 2); - for (int v: values) { - buffer.writeShort(v); - } - return buffer; - } - - /** - * Creates a new 3-byte big-endian buffer that holds the specified 24-bit integer. - */ - public static ByteBuf copyMedium(int value) { - ByteBuf buf = buffer(3); - buf.writeMedium(value); - return buf; - } - - /** - * Create a new big-endian buffer that holds a sequence of the specified 24-bit integers. - */ - public static ByteBuf copyMedium(int... values) { - if (values == null || values.length == 0) { - return EMPTY_BUFFER; - } - ByteBuf buffer = buffer(values.length * 3); - for (int v: values) { - buffer.writeMedium(v); - } - return buffer; - } - - /** - * Creates a new 8-byte big-endian buffer that holds the specified 64-bit integer. - */ - public static ByteBuf copyLong(long value) { - ByteBuf buf = buffer(8); - buf.writeLong(value); - return buf; - } - - /** - * Create a new big-endian buffer that holds a sequence of the specified 64-bit integers. - */ - public static ByteBuf copyLong(long... values) { - if (values == null || values.length == 0) { - return EMPTY_BUFFER; - } - ByteBuf buffer = buffer(values.length * 8); - for (long v: values) { - buffer.writeLong(v); - } - return buffer; - } - - /** - * Creates a new single-byte big-endian buffer that holds the specified boolean value. - */ - public static ByteBuf copyBoolean(boolean value) { - ByteBuf buf = buffer(1); - buf.writeBoolean(value); - return buf; - } - - /** - * Create a new big-endian buffer that holds a sequence of the specified boolean values. - */ - public static ByteBuf copyBoolean(boolean... values) { - if (values == null || values.length == 0) { - return EMPTY_BUFFER; - } - ByteBuf buffer = buffer(values.length); - for (boolean v: values) { - buffer.writeBoolean(v); - } - return buffer; - } - - /** - * Creates a new 4-byte big-endian buffer that holds the specified 32-bit floating point number. - */ - public static ByteBuf copyFloat(float value) { - ByteBuf buf = buffer(4); - buf.writeFloat(value); - return buf; - } - - /** - * Create a new big-endian buffer that holds a sequence of the specified 32-bit floating point numbers. - */ - public static ByteBuf copyFloat(float... values) { - if (values == null || values.length == 0) { - return EMPTY_BUFFER; - } - ByteBuf buffer = buffer(values.length * 4); - for (float v: values) { - buffer.writeFloat(v); - } - return buffer; - } - - /** - * Creates a new 8-byte big-endian buffer that holds the specified 64-bit floating point number. - */ - public static ByteBuf copyDouble(double value) { - ByteBuf buf = buffer(8); - buf.writeDouble(value); - return buf; - } - - /** - * Create a new big-endian buffer that holds a sequence of the specified 64-bit floating point numbers. - */ - public static ByteBuf copyDouble(double... values) { - if (values == null || values.length == 0) { - return EMPTY_BUFFER; - } - ByteBuf buffer = buffer(values.length * 8); - for (double v: values) { - buffer.writeDouble(v); - } - return buffer; - } - - /** - * Return a unreleasable view on the given {@link ByteBuf} which will just ignore release and retain calls. - */ - public static ByteBuf unreleasableBuffer(ByteBuf buf) { - return new UnreleasableByteBuf(buf); - } - - /** - * Wrap the given {@link ByteBuf}s in an unmodifiable {@link ByteBuf}. Be aware the returned {@link ByteBuf} will - * not try to slice the given {@link ByteBuf}s to reduce GC-Pressure. - */ - public static ByteBuf unmodifiableBuffer(ByteBuf... buffers) { - return new FixedCompositeByteBuf(ALLOC, buffers); - } - - private Unpooled() { - // Unused - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnpooledByteBufAllocator.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnpooledByteBufAllocator.java deleted file mode 100755 index 43ac4d3da9..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnpooledByteBufAllocator.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.buffer; - -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - -/** - * Simplistic {@link ByteBufAllocator} implementation that does not pool anything. - */ -public final class UnpooledByteBufAllocator extends AbstractByteBufAllocator { - - /** - * Default instance - */ - public static final UnpooledByteBufAllocator DEFAULT = - new UnpooledByteBufAllocator(PlatformDependent.directBufferPreferred()); - - /** - * Create a new instance - * - * @param preferDirect {@code true} if {@link #buffer(int)} should try to allocate a direct buffer rather than - * a heap buffer - */ - public UnpooledByteBufAllocator(boolean preferDirect) { - super(preferDirect); - } - - @Override - protected ByteBuf newHeapBuffer(int initialCapacity, int maxCapacity) { - return PlatformDependent.hasUnsafe() ? new UnpooledUnsafeHeapByteBuf(this, initialCapacity, maxCapacity) - : new UnpooledHeapByteBuf(this, initialCapacity, maxCapacity); - } - - @Override - protected ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity) { - ByteBuf buf; - if (PlatformDependent.hasUnsafe()) { - buf = new UnpooledUnsafeDirectByteBuf(this, initialCapacity, maxCapacity); - } else { - buf = new UnpooledDirectByteBuf(this, initialCapacity, maxCapacity); - } - - return toLeakAwareBuffer(buf); - } - - @Override - public boolean isDirectBufferPooled() { - return false; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnpooledDirectByteBuf.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnpooledDirectByteBuf.java deleted file mode 100755 index ceadb0a457..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnpooledDirectByteBuf.java +++ /dev/null @@ -1,599 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; - -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - -/** - * A NIO {@link ByteBuffer} based buffer. It is recommended to use {@link Unpooled#directBuffer(int)} - * and {@link Unpooled#wrappedBuffer(ByteBuffer)} instead of calling the - * constructor explicitly. - */ -public class UnpooledDirectByteBuf extends AbstractReferenceCountedByteBuf { - - private final ByteBufAllocator alloc; - - private ByteBuffer buffer; - private ByteBuffer tmpNioBuf; - private int capacity; - private boolean doNotFree; - - /** - * Creates a new direct buffer. - * - * @param initialCapacity the initial capacity of the underlying direct buffer - * @param maxCapacity the maximum capacity of the underlying direct buffer - */ - protected UnpooledDirectByteBuf(ByteBufAllocator alloc, int initialCapacity, int maxCapacity) { - super(maxCapacity); - if (alloc == null) { - throw new NullPointerException("alloc"); - } - if (initialCapacity < 0) { - throw new IllegalArgumentException("initialCapacity: " + initialCapacity); - } - if (maxCapacity < 0) { - throw new IllegalArgumentException("maxCapacity: " + maxCapacity); - } - if (initialCapacity > maxCapacity) { - throw new IllegalArgumentException(String.format( - "initialCapacity(%d) > maxCapacity(%d)", initialCapacity, maxCapacity)); - } - - this.alloc = alloc; - setByteBuffer(ByteBuffer.allocateDirect(initialCapacity)); - } - - /** - * Creates a new direct buffer by wrapping the specified initial buffer. - * - * @param maxCapacity the maximum capacity of the underlying direct buffer - */ - protected UnpooledDirectByteBuf(ByteBufAllocator alloc, ByteBuffer initialBuffer, int maxCapacity) { - super(maxCapacity); - if (alloc == null) { - throw new NullPointerException("alloc"); - } - if (initialBuffer == null) { - throw new NullPointerException("initialBuffer"); - } - if (!initialBuffer.isDirect()) { - throw new IllegalArgumentException("initialBuffer is not a direct buffer."); - } - if (initialBuffer.isReadOnly()) { - throw new IllegalArgumentException("initialBuffer is a read-only buffer."); - } - - int initialCapacity = initialBuffer.remaining(); - if (initialCapacity > maxCapacity) { - throw new IllegalArgumentException(String.format( - "initialCapacity(%d) > maxCapacity(%d)", initialCapacity, maxCapacity)); - } - - this.alloc = alloc; - doNotFree = true; - setByteBuffer(initialBuffer.slice().order(ByteOrder.BIG_ENDIAN)); - writerIndex(initialCapacity); - } - - /** - * Allocate a new direct {@link ByteBuffer} with the given initialCapacity. - */ - protected ByteBuffer allocateDirect(int initialCapacity) { - return ByteBuffer.allocateDirect(initialCapacity); - } - - /** - * Free a direct {@link ByteBuffer} - */ - protected void freeDirect(ByteBuffer buffer) { - PlatformDependent.freeDirectBuffer(buffer); - } - - private void setByteBuffer(ByteBuffer buffer) { - ByteBuffer oldBuffer = this.buffer; - if (oldBuffer != null) { - if (doNotFree) { - doNotFree = false; - } else { - freeDirect(oldBuffer); - } - } - - this.buffer = buffer; - tmpNioBuf = null; - capacity = buffer.remaining(); - } - - @Override - public boolean isDirect() { - return true; - } - - @Override - public int capacity() { - return capacity; - } - - @Override - public ByteBuf capacity(int newCapacity) { - ensureAccessible(); - if (newCapacity < 0 || newCapacity > maxCapacity()) { - throw new IllegalArgumentException("newCapacity: " + newCapacity); - } - - int readerIndex = readerIndex(); - int writerIndex = writerIndex(); - - int oldCapacity = capacity; - if (newCapacity > oldCapacity) { - ByteBuffer oldBuffer = buffer; - ByteBuffer newBuffer = allocateDirect(newCapacity); - oldBuffer.position(0).limit(oldBuffer.capacity()); - newBuffer.position(0).limit(oldBuffer.capacity()); - newBuffer.put(oldBuffer); - newBuffer.clear(); - setByteBuffer(newBuffer); - } else if (newCapacity < oldCapacity) { - ByteBuffer oldBuffer = buffer; - ByteBuffer newBuffer = allocateDirect(newCapacity); - if (readerIndex < newCapacity) { - if (writerIndex > newCapacity) { - writerIndex(writerIndex = newCapacity); - } - oldBuffer.position(readerIndex).limit(writerIndex); - newBuffer.position(readerIndex).limit(writerIndex); - newBuffer.put(oldBuffer); - newBuffer.clear(); - } else { - setIndex(newCapacity, newCapacity); - } - setByteBuffer(newBuffer); - } - return this; - } - - @Override - public ByteBufAllocator alloc() { - return alloc; - } - - @Override - public ByteOrder order() { - return ByteOrder.BIG_ENDIAN; - } - - @Override - public boolean hasArray() { - return false; - } - - @Override - public byte[] array() { - throw new UnsupportedOperationException("direct buffer"); - } - - @Override - public int arrayOffset() { - throw new UnsupportedOperationException("direct buffer"); - } - - @Override - public boolean hasMemoryAddress() { - return false; - } - - @Override - public long memoryAddress() { - throw new UnsupportedOperationException(); - } - - @Override - public byte getByte(int index) { - ensureAccessible(); - return _getByte(index); - } - - @Override - protected byte _getByte(int index) { - return buffer.get(index); - } - - @Override - public short getShort(int index) { - ensureAccessible(); - return _getShort(index); - } - - @Override - protected short _getShort(int index) { - return buffer.getShort(index); - } - - @Override - public int getUnsignedMedium(int index) { - ensureAccessible(); - return _getUnsignedMedium(index); - } - - @Override - protected int _getUnsignedMedium(int index) { - return (getByte(index) & 0xff) << 16 | (getByte(index + 1) & 0xff) << 8 | getByte(index + 2) & 0xff; - } - - @Override - public int getInt(int index) { - ensureAccessible(); - return _getInt(index); - } - - @Override - protected int _getInt(int index) { - return buffer.getInt(index); - } - - @Override - public long getLong(int index) { - ensureAccessible(); - return _getLong(index); - } - - @Override - protected long _getLong(int index) { - return buffer.getLong(index); - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - checkDstIndex(index, length, dstIndex, dst.capacity()); - if (dst.hasArray()) { - getBytes(index, dst.array(), dst.arrayOffset() + dstIndex, length); - } else if (dst.nioBufferCount() > 0) { - for (ByteBuffer bb: dst.nioBuffers(dstIndex, length)) { - int bbLen = bb.remaining(); - getBytes(index, bb); - index += bbLen; - } - } else { - dst.setBytes(dstIndex, this, index, length); - } - return this; - } - - @Override - public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - getBytes(index, dst, dstIndex, length, false); - return this; - } - - private void getBytes(int index, byte[] dst, int dstIndex, int length, boolean internal) { - checkDstIndex(index, length, dstIndex, dst.length); - - ByteBuffer tmpBuf; - if (internal) { - tmpBuf = internalNioBuffer(); - } else { - tmpBuf = buffer.duplicate(); - } - tmpBuf.clear().position(index).limit(index + length); - tmpBuf.get(dst, dstIndex, length); - } - - @Override - public ByteBuf readBytes(byte[] dst, int dstIndex, int length) { - checkReadableBytes(length); - getBytes(readerIndex, dst, dstIndex, length, true); - readerIndex += length; - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuffer dst) { - getBytes(index, dst, false); - return this; - } - - private void getBytes(int index, ByteBuffer dst, boolean internal) { - checkIndex(index); - if (dst == null) { - throw new NullPointerException("dst"); - } - - int bytesToCopy = Math.min(capacity() - index, dst.remaining()); - ByteBuffer tmpBuf; - if (internal) { - tmpBuf = internalNioBuffer(); - } else { - tmpBuf = buffer.duplicate(); - } - tmpBuf.clear().position(index).limit(index + bytesToCopy); - dst.put(tmpBuf); - } - - @Override - public ByteBuf readBytes(ByteBuffer dst) { - int length = dst.remaining(); - checkReadableBytes(length); - getBytes(readerIndex, dst, true); - readerIndex += length; - return this; - } - - @Override - public ByteBuf setByte(int index, int value) { - ensureAccessible(); - _setByte(index, value); - return this; - } - - @Override - protected void _setByte(int index, int value) { - buffer.put(index, (byte) value); - } - - @Override - public ByteBuf setShort(int index, int value) { - ensureAccessible(); - _setShort(index, value); - return this; - } - - @Override - protected void _setShort(int index, int value) { - buffer.putShort(index, (short) value); - } - - @Override - public ByteBuf setMedium(int index, int value) { - ensureAccessible(); - _setMedium(index, value); - return this; - } - - @Override - protected void _setMedium(int index, int value) { - setByte(index, (byte) (value >>> 16)); - setByte(index + 1, (byte) (value >>> 8)); - setByte(index + 2, (byte) value); - } - - @Override - public ByteBuf setInt(int index, int value) { - ensureAccessible(); - _setInt(index, value); - return this; - } - - @Override - protected void _setInt(int index, int value) { - buffer.putInt(index, value); - } - - @Override - public ByteBuf setLong(int index, long value) { - ensureAccessible(); - _setLong(index, value); - return this; - } - - @Override - protected void _setLong(int index, long value) { - buffer.putLong(index, value); - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { - checkSrcIndex(index, length, srcIndex, src.capacity()); - if (src.nioBufferCount() > 0) { - for (ByteBuffer bb: src.nioBuffers(srcIndex, length)) { - int bbLen = bb.remaining(); - setBytes(index, bb); - index += bbLen; - } - } else { - src.getBytes(srcIndex, this, index, length); - } - return this; - } - - @Override - public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { - checkSrcIndex(index, length, srcIndex, src.length); - ByteBuffer tmpBuf = internalNioBuffer(); - tmpBuf.clear().position(index).limit(index + length); - tmpBuf.put(src, srcIndex, length); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuffer src) { - ensureAccessible(); - ByteBuffer tmpBuf = internalNioBuffer(); - if (src == tmpBuf) { - src = src.duplicate(); - } - - tmpBuf.clear().position(index).limit(index + src.remaining()); - tmpBuf.put(src); - return this; - } - - @Override - public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException { - getBytes(index, out, length, false); - return this; - } - - private void getBytes(int index, OutputStream out, int length, boolean internal) throws IOException { - ensureAccessible(); - if (length == 0) { - return; - } - - if (buffer.hasArray()) { - out.write(buffer.array(), index + buffer.arrayOffset(), length); - } else { - byte[] tmp = new byte[length]; - ByteBuffer tmpBuf; - if (internal) { - tmpBuf = internalNioBuffer(); - } else { - tmpBuf = buffer.duplicate(); - } - tmpBuf.clear().position(index); - tmpBuf.get(tmp); - out.write(tmp); - } - } - - @Override - public ByteBuf readBytes(OutputStream out, int length) throws IOException { - checkReadableBytes(length); - getBytes(readerIndex, out, length, true); - readerIndex += length; - return this; - } - - @Override - public int getBytes(int index, GatheringByteChannel out, int length) throws IOException { - return getBytes(index, out, length, false); - } - - private int getBytes(int index, GatheringByteChannel out, int length, boolean internal) throws IOException { - ensureAccessible(); - if (length == 0) { - return 0; - } - - ByteBuffer tmpBuf; - if (internal) { - tmpBuf = internalNioBuffer(); - } else { - tmpBuf = buffer.duplicate(); - } - tmpBuf.clear().position(index).limit(index + length); - return out.write(tmpBuf); - } - - @Override - public int readBytes(GatheringByteChannel out, int length) throws IOException { - checkReadableBytes(length); - int readBytes = getBytes(readerIndex, out, length, true); - readerIndex += readBytes; - return readBytes; - } - - @Override - public int setBytes(int index, InputStream in, int length) throws IOException { - ensureAccessible(); - if (buffer.hasArray()) { - return in.read(buffer.array(), buffer.arrayOffset() + index, length); - } else { - byte[] tmp = new byte[length]; - int readBytes = in.read(tmp); - if (readBytes <= 0) { - return readBytes; - } - ByteBuffer tmpBuf = internalNioBuffer(); - tmpBuf.clear().position(index); - tmpBuf.put(tmp, 0, readBytes); - return readBytes; - } - } - - @Override - public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException { - ensureAccessible(); - ByteBuffer tmpBuf = internalNioBuffer(); - tmpBuf.clear().position(index).limit(index + length); - try { - return in.read(tmpNioBuf); - } catch (ClosedChannelException ignored) { - return -1; - } - } - - @Override - public int nioBufferCount() { - return 1; - } - - @Override - public ByteBuffer[] nioBuffers(int index, int length) { - return new ByteBuffer[] { nioBuffer(index, length) }; - } - - @Override - public ByteBuf copy(int index, int length) { - ensureAccessible(); - ByteBuffer src; - try { - src = (ByteBuffer) buffer.duplicate().clear().position(index).limit(index + length); - } catch (IllegalArgumentException ignored) { - throw new IndexOutOfBoundsException("Too many bytes to read - Need " + (index + length)); - } - - return alloc().directBuffer(length, maxCapacity()).writeBytes(src); - } - - @Override - public ByteBuffer internalNioBuffer(int index, int length) { - checkIndex(index, length); - return (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length); - } - - private ByteBuffer internalNioBuffer() { - ByteBuffer tmpNioBuf = this.tmpNioBuf; - if (tmpNioBuf == null) { - this.tmpNioBuf = tmpNioBuf = buffer.duplicate(); - } - return tmpNioBuf; - } - - @Override - public ByteBuffer nioBuffer(int index, int length) { - checkIndex(index, length); - return ((ByteBuffer) buffer.duplicate().position(index).limit(index + length)).slice(); - } - - @Override - protected void deallocate() { - ByteBuffer buffer = this.buffer; - if (buffer == null) { - return; - } - - this.buffer = null; - - if (!doNotFree) { - freeDirect(buffer); - } - } - - @Override - public ByteBuf unwrap() { - return null; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnpooledHeapByteBuf.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnpooledHeapByteBuf.java deleted file mode 100755 index 433d7e640a..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnpooledHeapByteBuf.java +++ /dev/null @@ -1,424 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; - -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - -/** - * Big endian Java heap buffer implementation. - */ -public class UnpooledHeapByteBuf extends AbstractReferenceCountedByteBuf { - - private final ByteBufAllocator alloc; - byte[] array; - private ByteBuffer tmpNioBuf; - - /** - * Creates a new heap buffer with a newly allocated byte array. - * - * @param initialCapacity the initial capacity of the underlying byte array - * @param maxCapacity the max capacity of the underlying byte array - */ - protected UnpooledHeapByteBuf(ByteBufAllocator alloc, int initialCapacity, int maxCapacity) { - this(alloc, new byte[initialCapacity], 0, 0, maxCapacity); - } - - /** - * Creates a new heap buffer with an existing byte array. - * - * @param initialArray the initial underlying byte array - * @param maxCapacity the max capacity of the underlying byte array - */ - protected UnpooledHeapByteBuf(ByteBufAllocator alloc, byte[] initialArray, int maxCapacity) { - this(alloc, initialArray, 0, initialArray.length, maxCapacity); - } - - private UnpooledHeapByteBuf( - ByteBufAllocator alloc, byte[] initialArray, int readerIndex, int writerIndex, int maxCapacity) { - - super(maxCapacity); - - if (alloc == null) { - throw new NullPointerException("alloc"); - } - if (initialArray == null) { - throw new NullPointerException("initialArray"); - } - if (initialArray.length > maxCapacity) { - throw new IllegalArgumentException(String.format( - "initialCapacity(%d) > maxCapacity(%d)", initialArray.length, maxCapacity)); - } - - this.alloc = alloc; - setArray(initialArray); - setIndex(readerIndex, writerIndex); - } - - private void setArray(byte[] initialArray) { - array = initialArray; - tmpNioBuf = null; - } - - @Override - public ByteBufAllocator alloc() { - return alloc; - } - - @Override - public ByteOrder order() { - return ByteOrder.BIG_ENDIAN; - } - - @Override - public boolean isDirect() { - return false; - } - - @Override - public int capacity() { - ensureAccessible(); - return array.length; - } - - @Override - public ByteBuf capacity(int newCapacity) { - ensureAccessible(); - if (newCapacity < 0 || newCapacity > maxCapacity()) { - throw new IllegalArgumentException("newCapacity: " + newCapacity); - } - - int oldCapacity = array.length; - if (newCapacity > oldCapacity) { - byte[] newArray = new byte[newCapacity]; - System.arraycopy(array, 0, newArray, 0, array.length); - setArray(newArray); - } else if (newCapacity < oldCapacity) { - byte[] newArray = new byte[newCapacity]; - int readerIndex = readerIndex(); - if (readerIndex < newCapacity) { - int writerIndex = writerIndex(); - if (writerIndex > newCapacity) { - writerIndex(writerIndex = newCapacity); - } - System.arraycopy(array, readerIndex, newArray, readerIndex, writerIndex - readerIndex); - } else { - setIndex(newCapacity, newCapacity); - } - setArray(newArray); - } - return this; - } - - @Override - public boolean hasArray() { - return true; - } - - @Override - public byte[] array() { - ensureAccessible(); - return array; - } - - @Override - public int arrayOffset() { - return 0; - } - - @Override - public boolean hasMemoryAddress() { - return false; - } - - @Override - public long memoryAddress() { - throw new UnsupportedOperationException(); - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - checkDstIndex(index, length, dstIndex, dst.capacity()); - if (dst.hasMemoryAddress()) { - PlatformDependent.copyMemory(array, index, dst.memoryAddress() + dstIndex, length); - } else if (dst.hasArray()) { - getBytes(index, dst.array(), dst.arrayOffset() + dstIndex, length); - } else { - dst.setBytes(dstIndex, array, index, length); - } - return this; - } - - @Override - public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - checkDstIndex(index, length, dstIndex, dst.length); - System.arraycopy(array, index, dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuffer dst) { - ensureAccessible(); - dst.put(array, index, Math.min(capacity() - index, dst.remaining())); - return this; - } - - @Override - public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException { - ensureAccessible(); - out.write(array, index, length); - return this; - } - - @Override - public int getBytes(int index, GatheringByteChannel out, int length) throws IOException { - ensureAccessible(); - return getBytes(index, out, length, false); - } - - private int getBytes(int index, GatheringByteChannel out, int length, boolean internal) throws IOException { - ensureAccessible(); - ByteBuffer tmpBuf; - if (internal) { - tmpBuf = internalNioBuffer(); - } else { - tmpBuf = ByteBuffer.wrap(array); - } - return out.write((ByteBuffer) tmpBuf.clear().position(index).limit(index + length)); - } - - @Override - public int readBytes(GatheringByteChannel out, int length) throws IOException { - checkReadableBytes(length); - int readBytes = getBytes(readerIndex, out, length, true); - readerIndex += readBytes; - return readBytes; - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { - checkSrcIndex(index, length, srcIndex, src.capacity()); - if (src.hasMemoryAddress()) { - PlatformDependent.copyMemory(src.memoryAddress() + srcIndex, array, index, length); - } else if (src.hasArray()) { - setBytes(index, src.array(), src.arrayOffset() + srcIndex, length); - } else { - src.getBytes(srcIndex, array, index, length); - } - return this; - } - - @Override - public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { - checkSrcIndex(index, length, srcIndex, src.length); - System.arraycopy(src, srcIndex, array, index, length); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuffer src) { - ensureAccessible(); - src.get(array, index, src.remaining()); - return this; - } - - @Override - public int setBytes(int index, InputStream in, int length) throws IOException { - ensureAccessible(); - return in.read(array, index, length); - } - - @Override - public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException { - ensureAccessible(); - try { - return in.read((ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length)); - } catch (ClosedChannelException ignored) { - return -1; - } - } - - @Override - public int nioBufferCount() { - return 1; - } - - @Override - public ByteBuffer nioBuffer(int index, int length) { - ensureAccessible(); - return ByteBuffer.wrap(array, index, length).slice(); - } - - @Override - public ByteBuffer[] nioBuffers(int index, int length) { - return new ByteBuffer[] { nioBuffer(index, length) }; - } - - @Override - public ByteBuffer internalNioBuffer(int index, int length) { - checkIndex(index, length); - return (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length); - } - - @Override - public byte getByte(int index) { - ensureAccessible(); - return _getByte(index); - } - - @Override - protected byte _getByte(int index) { - return HeapByteBufUtil.getByte(array, index); - } - - @Override - public short getShort(int index) { - ensureAccessible(); - return _getShort(index); - } - - @Override - protected short _getShort(int index) { - return HeapByteBufUtil.getShort(array, index); - } - - @Override - public int getUnsignedMedium(int index) { - ensureAccessible(); - return _getUnsignedMedium(index); - } - - @Override - protected int _getUnsignedMedium(int index) { - return HeapByteBufUtil.getUnsignedMedium(array, index); - } - - @Override - public int getInt(int index) { - ensureAccessible(); - return _getInt(index); - } - - @Override - protected int _getInt(int index) { - return HeapByteBufUtil.getInt(array, index); - } - - @Override - public long getLong(int index) { - ensureAccessible(); - return _getLong(index); - } - - @Override - protected long _getLong(int index) { - return HeapByteBufUtil.getLong(array, index); - } - - @Override - public ByteBuf setByte(int index, int value) { - ensureAccessible(); - _setByte(index, value); - return this; - } - - @Override - protected void _setByte(int index, int value) { - HeapByteBufUtil.setByte(array, index, value); - } - - @Override - public ByteBuf setShort(int index, int value) { - ensureAccessible(); - _setShort(index, value); - return this; - } - - @Override - protected void _setShort(int index, int value) { - HeapByteBufUtil.setShort(array, index, value); - } - - @Override - public ByteBuf setMedium(int index, int value) { - ensureAccessible(); - _setMedium(index, value); - return this; - } - - @Override - protected void _setMedium(int index, int value) { - HeapByteBufUtil.setMedium(array, index, value); - } - - @Override - public ByteBuf setInt(int index, int value) { - ensureAccessible(); - _setInt(index, value); - return this; - } - - @Override - protected void _setInt(int index, int value) { - HeapByteBufUtil.setInt(array, index, value); - } - - @Override - public ByteBuf setLong(int index, long value) { - ensureAccessible(); - _setLong(index, value); - return this; - } - - @Override - protected void _setLong(int index, long value) { - HeapByteBufUtil.setLong(array, index, value); - } - - @Override - public ByteBuf copy(int index, int length) { - checkIndex(index, length); - byte[] copiedArray = new byte[length]; - System.arraycopy(array, index, copiedArray, 0, length); - return new UnpooledHeapByteBuf(alloc(), copiedArray, maxCapacity()); - } - - private ByteBuffer internalNioBuffer() { - ByteBuffer tmpNioBuf = this.tmpNioBuf; - if (tmpNioBuf == null) { - this.tmpNioBuf = tmpNioBuf = ByteBuffer.wrap(array); - } - return tmpNioBuf; - } - - @Override - protected void deallocate() { - array = null; - } - - @Override - public ByteBuf unwrap() { - return null; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnpooledUnsafeDirectByteBuf.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnpooledUnsafeDirectByteBuf.java deleted file mode 100755 index 510072b561..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnpooledUnsafeDirectByteBuf.java +++ /dev/null @@ -1,429 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; - -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - -/** - * A NIO {@link ByteBuffer} based buffer. It is recommended to use {@link Unpooled#directBuffer(int)} - * and {@link Unpooled#wrappedBuffer(ByteBuffer)} instead of calling the - * constructor explicitly. - */ -public class UnpooledUnsafeDirectByteBuf extends AbstractReferenceCountedByteBuf { - - private final ByteBufAllocator alloc; - - private long memoryAddress; - private ByteBuffer buffer; - private ByteBuffer tmpNioBuf; - private int capacity; - private boolean doNotFree; - - /** - * Creates a new direct buffer. - * - * @param initialCapacity the initial capacity of the underlying direct buffer - * @param maxCapacity the maximum capacity of the underlying direct buffer - */ - protected UnpooledUnsafeDirectByteBuf(ByteBufAllocator alloc, int initialCapacity, int maxCapacity) { - super(maxCapacity); - if (alloc == null) { - throw new NullPointerException("alloc"); - } - if (initialCapacity < 0) { - throw new IllegalArgumentException("initialCapacity: " + initialCapacity); - } - if (maxCapacity < 0) { - throw new IllegalArgumentException("maxCapacity: " + maxCapacity); - } - if (initialCapacity > maxCapacity) { - throw new IllegalArgumentException(String.format( - "initialCapacity(%d) > maxCapacity(%d)", initialCapacity, maxCapacity)); - } - - this.alloc = alloc; - setByteBuffer(allocateDirect(initialCapacity)); - } - - /** - * Creates a new direct buffer by wrapping the specified initial buffer. - * - * @param maxCapacity the maximum capacity of the underlying direct buffer - */ - protected UnpooledUnsafeDirectByteBuf(ByteBufAllocator alloc, ByteBuffer initialBuffer, int maxCapacity) { - super(maxCapacity); - if (alloc == null) { - throw new NullPointerException("alloc"); - } - if (initialBuffer == null) { - throw new NullPointerException("initialBuffer"); - } - if (!initialBuffer.isDirect()) { - throw new IllegalArgumentException("initialBuffer is not a direct buffer."); - } - if (initialBuffer.isReadOnly()) { - throw new IllegalArgumentException("initialBuffer is a read-only buffer."); - } - - int initialCapacity = initialBuffer.remaining(); - if (initialCapacity > maxCapacity) { - throw new IllegalArgumentException(String.format( - "initialCapacity(%d) > maxCapacity(%d)", initialCapacity, maxCapacity)); - } - - this.alloc = alloc; - doNotFree = true; - setByteBuffer(initialBuffer.slice().order(ByteOrder.BIG_ENDIAN)); - writerIndex(initialCapacity); - } - - /** - * Allocate a new direct {@link ByteBuffer} with the given initialCapacity. - */ - protected ByteBuffer allocateDirect(int initialCapacity) { - return ByteBuffer.allocateDirect(initialCapacity); - } - - /** - * Free a direct {@link ByteBuffer} - */ - protected void freeDirect(ByteBuffer buffer) { - PlatformDependent.freeDirectBuffer(buffer); - } - - private void setByteBuffer(ByteBuffer buffer) { - ByteBuffer oldBuffer = this.buffer; - if (oldBuffer != null) { - if (doNotFree) { - doNotFree = false; - } else { - freeDirect(oldBuffer); - } - } - - this.buffer = buffer; - memoryAddress = PlatformDependent.directBufferAddress(buffer); - tmpNioBuf = null; - capacity = buffer.remaining(); - } - - @Override - public boolean isDirect() { - return true; - } - - @Override - public int capacity() { - return capacity; - } - - @Override - public ByteBuf capacity(int newCapacity) { - ensureAccessible(); - if (newCapacity < 0 || newCapacity > maxCapacity()) { - throw new IllegalArgumentException("newCapacity: " + newCapacity); - } - - int readerIndex = readerIndex(); - int writerIndex = writerIndex(); - - int oldCapacity = capacity; - if (newCapacity > oldCapacity) { - ByteBuffer oldBuffer = buffer; - ByteBuffer newBuffer = allocateDirect(newCapacity); - oldBuffer.position(0).limit(oldBuffer.capacity()); - newBuffer.position(0).limit(oldBuffer.capacity()); - newBuffer.put(oldBuffer); - newBuffer.clear(); - setByteBuffer(newBuffer); - } else if (newCapacity < oldCapacity) { - ByteBuffer oldBuffer = buffer; - ByteBuffer newBuffer = allocateDirect(newCapacity); - if (readerIndex < newCapacity) { - if (writerIndex > newCapacity) { - writerIndex(writerIndex = newCapacity); - } - oldBuffer.position(readerIndex).limit(writerIndex); - newBuffer.position(readerIndex).limit(writerIndex); - newBuffer.put(oldBuffer); - newBuffer.clear(); - } else { - setIndex(newCapacity, newCapacity); - } - setByteBuffer(newBuffer); - } - return this; - } - - @Override - public ByteBufAllocator alloc() { - return alloc; - } - - @Override - public ByteOrder order() { - return ByteOrder.BIG_ENDIAN; - } - - @Override - public boolean hasArray() { - return false; - } - - @Override - public byte[] array() { - throw new UnsupportedOperationException("direct buffer"); - } - - @Override - public int arrayOffset() { - throw new UnsupportedOperationException("direct buffer"); - } - - @Override - public boolean hasMemoryAddress() { - return true; - } - - @Override - public long memoryAddress() { - ensureAccessible(); - return memoryAddress; - } - - @Override - protected byte _getByte(int index) { - return UnsafeByteBufUtil.getByte(addr(index)); - } - - @Override - protected short _getShort(int index) { - return UnsafeByteBufUtil.getShort(addr(index)); - } - - @Override - protected int _getUnsignedMedium(int index) { - return UnsafeByteBufUtil.getUnsignedMedium(addr(index)); - } - - @Override - protected int _getInt(int index) { - return UnsafeByteBufUtil.getInt(addr(index)); - } - - @Override - protected long _getLong(int index) { - return UnsafeByteBufUtil.getLong(addr(index)); - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - UnsafeByteBufUtil.getBytes(this, addr(index), index, dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - UnsafeByteBufUtil.getBytes(this, addr(index), index, dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuffer dst) { - UnsafeByteBufUtil.getBytes(this, addr(index), index, dst); - return this; - } - - @Override - public ByteBuf readBytes(ByteBuffer dst) { - int length = dst.remaining(); - checkReadableBytes(length); - getBytes(readerIndex, dst); - readerIndex += length; - return this; - } - - @Override - protected void _setByte(int index, int value) { - UnsafeByteBufUtil.setByte(addr(index), value); - } - - @Override - protected void _setShort(int index, int value) { - UnsafeByteBufUtil.setShort(addr(index), value); - } - - @Override - protected void _setMedium(int index, int value) { - UnsafeByteBufUtil.setMedium(addr(index), value); - } - - @Override - protected void _setInt(int index, int value) { - UnsafeByteBufUtil.setInt(addr(index), value); - } - - @Override - protected void _setLong(int index, long value) { - UnsafeByteBufUtil.setLong(addr(index), value); - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { - UnsafeByteBufUtil.setBytes(this, addr(index), index, src, srcIndex, length); - return this; - } - - @Override - public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { - UnsafeByteBufUtil.setBytes(this, addr(index), index, src, srcIndex, length); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuffer src) { - UnsafeByteBufUtil.setBytes(this, addr(index), index, src); - return this; - } - - @Override - public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException { - UnsafeByteBufUtil.getBytes(this, addr(index), index, out, length); - return this; - } - - @Override - public int getBytes(int index, GatheringByteChannel out, int length) throws IOException { - return getBytes(index, out, length, false); - } - - private int getBytes(int index, GatheringByteChannel out, int length, boolean internal) throws IOException { - ensureAccessible(); - if (length == 0) { - return 0; - } - - ByteBuffer tmpBuf; - if (internal) { - tmpBuf = internalNioBuffer(); - } else { - tmpBuf = buffer.duplicate(); - } - tmpBuf.clear().position(index).limit(index + length); - return out.write(tmpBuf); - } - - @Override - public int readBytes(GatheringByteChannel out, int length) throws IOException { - checkReadableBytes(length); - int readBytes = getBytes(readerIndex, out, length, true); - readerIndex += readBytes; - return readBytes; - } - - @Override - public int setBytes(int index, InputStream in, int length) throws IOException { - return UnsafeByteBufUtil.setBytes(this, addr(index), index, in, length); - } - - @Override - public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException { - ensureAccessible(); - ByteBuffer tmpBuf = internalNioBuffer(); - tmpBuf.clear().position(index).limit(index + length); - try { - return in.read(tmpBuf); - } catch (ClosedChannelException ignored) { - return -1; - } - } - - @Override - public int nioBufferCount() { - return 1; - } - - @Override - public ByteBuffer[] nioBuffers(int index, int length) { - return new ByteBuffer[] { nioBuffer(index, length) }; - } - - @Override - public ByteBuf copy(int index, int length) { - return UnsafeByteBufUtil.copy(this, addr(index), index, length); - } - - @Override - public ByteBuffer internalNioBuffer(int index, int length) { - checkIndex(index, length); - return (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length); - } - - private ByteBuffer internalNioBuffer() { - ByteBuffer tmpNioBuf = this.tmpNioBuf; - if (tmpNioBuf == null) { - this.tmpNioBuf = tmpNioBuf = buffer.duplicate(); - } - return tmpNioBuf; - } - - @Override - public ByteBuffer nioBuffer(int index, int length) { - checkIndex(index, length); - return ((ByteBuffer) buffer.duplicate().position(index).limit(index + length)).slice(); - } - - @Override - protected void deallocate() { - ByteBuffer buffer = this.buffer; - if (buffer == null) { - return; - } - - this.buffer = null; - - if (!doNotFree) { - freeDirect(buffer); - } - } - - @Override - public ByteBuf unwrap() { - return null; - } - - long addr(int index) { - return memoryAddress + index; - } - - @Override - protected SwappedByteBuf newSwappedByteBuf() { - if (PlatformDependent.isUnaligned()) { - // Only use if unaligned access is supported otherwise there is no gain. - return new UnsafeDirectSwappedByteBuf(this); - } - return super.newSwappedByteBuf(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnpooledUnsafeHeapByteBuf.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnpooledUnsafeHeapByteBuf.java deleted file mode 100755 index d2477e4254..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnpooledUnsafeHeapByteBuf.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.buffer; - - -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - -final class UnpooledUnsafeHeapByteBuf extends UnpooledHeapByteBuf { - - /** - * Creates a new heap buffer with a newly allocated byte array. - * - * @param initialCapacity the initial capacity of the underlying byte array - * @param maxCapacity the max capacity of the underlying byte array - */ - UnpooledUnsafeHeapByteBuf(ByteBufAllocator alloc, int initialCapacity, int maxCapacity) { - super(alloc, initialCapacity, maxCapacity); - } - - @Override - public byte getByte(int index) { - checkIndex(index); - return _getByte(index); - } - - @Override - protected byte _getByte(int index) { - return UnsafeByteBufUtil.getByte(array, index); - } - - @Override - public short getShort(int index) { - checkIndex(index, 2); - return _getShort(index); - } - - @Override - protected short _getShort(int index) { - return UnsafeByteBufUtil.getShort(array, index); - } - - @Override - public int getUnsignedMedium(int index) { - checkIndex(index, 3); - return _getUnsignedMedium(index); - } - - @Override - protected int _getUnsignedMedium(int index) { - return UnsafeByteBufUtil.getUnsignedMedium(array, index); - } - - @Override - public int getInt(int index) { - checkIndex(index, 4); - return _getInt(index); - } - - @Override - protected int _getInt(int index) { - return UnsafeByteBufUtil.getInt(array, index); - } - - @Override - public long getLong(int index) { - checkIndex(index, 8); - return _getLong(index); - } - - @Override - protected long _getLong(int index) { - return UnsafeByteBufUtil.getLong(array, index); - } - - @Override - public ByteBuf setByte(int index, int value) { - checkIndex(index); - _setByte(index, value); - return this; - } - - @Override - protected void _setByte(int index, int value) { - UnsafeByteBufUtil.setByte(array, index, value); - } - - @Override - public ByteBuf setShort(int index, int value) { - checkIndex(index, 2); - _setShort(index, value); - return this; - } - - @Override - protected void _setShort(int index, int value) { - UnsafeByteBufUtil.setShort(array, index, value); - } - - @Override - public ByteBuf setMedium(int index, int value) { - checkIndex(index, 3); - _setMedium(index, value); - return this; - } - - @Override - protected void _setMedium(int index, int value) { - UnsafeByteBufUtil.setMedium(array, index, value); - } - - @Override - public ByteBuf setInt(int index, int value) { - checkIndex(index, 4); - _setInt(index, value); - return this; - } - - @Override - protected void _setInt(int index, int value) { - UnsafeByteBufUtil.setInt(array, index, value); - } - - @Override - public ByteBuf setLong(int index, long value) { - checkIndex(index, 8); - _setLong(index, value); - return this; - } - - @Override - protected void _setLong(int index, long value) { - UnsafeByteBufUtil.setLong(array, index, value); - } - - @Override - protected SwappedByteBuf newSwappedByteBuf() { - if (PlatformDependent.isUnaligned()) { - // Only use if unaligned access is supported otherwise there is no gain. - return new UnsafeHeapSwappedByteBuf(this); - } - return super.newSwappedByteBuf(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnreleasableByteBuf.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnreleasableByteBuf.java deleted file mode 100755 index af85fabc10..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnreleasableByteBuf.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.buffer; - -import java.nio.ByteOrder; - -/** - * A {@link ByteBuf} implementation that wraps another buffer to prevent a user from increasing or decreasing the - * wrapped buffer's reference count. - */ -final class UnreleasableByteBuf extends WrappedByteBuf { - - private SwappedByteBuf swappedBuf; - - UnreleasableByteBuf(ByteBuf buf) { - super(buf); - } - - @Override - public ByteBuf order(ByteOrder endianness) { - if (endianness == null) { - throw new NullPointerException("endianness"); - } - if (endianness == order()) { - return this; - } - - SwappedByteBuf swappedBuf = this.swappedBuf; - if (swappedBuf == null) { - this.swappedBuf = swappedBuf = new SwappedByteBuf(this); - } - return swappedBuf; - } - - @Override - public ByteBuf readSlice(int length) { - return new UnreleasableByteBuf(buf.readSlice(length)); - } - - @Override - public ByteBuf slice() { - return new UnreleasableByteBuf(buf.slice()); - } - - @Override - public ByteBuf slice(int index, int length) { - return new UnreleasableByteBuf(buf.slice(index, length)); - } - - @Override - public ByteBuf duplicate() { - return new UnreleasableByteBuf(buf.duplicate()); - } - - @Override - public ByteBuf retain(int increment) { - return this; - } - - @Override - public ByteBuf retain() { - return this; - } - - @Override - public boolean release() { - return false; - } - - @Override - public boolean release(int decrement) { - return false; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnsafeByteBufUtil.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnsafeByteBufUtil.java deleted file mode 100755 index 87eeb3f50b..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnsafeByteBufUtil.java +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - -import static com.ai.cloud.io.netty.util.internal.MathUtil.isOutOfBounds; -import static com.ai.cloud.io.netty.util.internal.ObjectUtil.checkNotNull; - -/** - * All operations get and set as {@link ByteOrder#BIG_ENDIAN}. - */ -final class UnsafeByteBufUtil { - - static final boolean BIG_ENDIAN_NATIVE_ORDER = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN; - private static final boolean UNALIGNED = PlatformDependent.isUnaligned(); - - static byte getByte(long address) { - return PlatformDependent.getByte(address); - } - - static short getShort(long address) { - if (UNALIGNED) { - short v = PlatformDependent.getShort(address); - return BIG_ENDIAN_NATIVE_ORDER ? v : Short.reverseBytes(v); - } - return (short) (PlatformDependent.getByte(address) << 8 | PlatformDependent.getByte(address + 1) & 0xff); - } - - static int getUnsignedMedium(long address) { - if (UNALIGNED) { - if (BIG_ENDIAN_NATIVE_ORDER) { - return (PlatformDependent.getByte(address) & 0xff) | - (PlatformDependent.getShort(address + 1) & 0xffff) << 8; - } - return (Short.reverseBytes(PlatformDependent.getShort(address)) & 0xffff) << 8 | - PlatformDependent.getByte(address + 2) & 0xff; - } - return (PlatformDependent.getByte(address) & 0xff) << 16 | - (PlatformDependent.getByte(address + 1) & 0xff) << 8 | - PlatformDependent.getByte(address + 2) & 0xff; - } - - static int getInt(long address) { - if (UNALIGNED) { - int v = PlatformDependent.getInt(address); - return BIG_ENDIAN_NATIVE_ORDER ? v : Integer.reverseBytes(v); - } - return PlatformDependent.getByte(address) << 24 | - (PlatformDependent.getByte(address + 1) & 0xff) << 16 | - (PlatformDependent.getByte(address + 2) & 0xff) << 8 | - PlatformDependent.getByte(address + 3) & 0xff; - } - - static long getLong(long address) { - if (UNALIGNED) { - long v = PlatformDependent.getLong(address); - return BIG_ENDIAN_NATIVE_ORDER ? v : Long.reverseBytes(v); - } - return (long) PlatformDependent.getByte(address) << 56 | - ((long) PlatformDependent.getByte(address + 1) & 0xff) << 48 | - ((long) PlatformDependent.getByte(address + 2) & 0xff) << 40 | - ((long) PlatformDependent.getByte(address + 3) & 0xff) << 32 | - ((long) PlatformDependent.getByte(address + 4) & 0xff) << 24 | - ((long) PlatformDependent.getByte(address + 5) & 0xff) << 16 | - ((long) PlatformDependent.getByte(address + 6) & 0xff) << 8 | - (long) PlatformDependent.getByte(address + 7) & 0xff; - } - - static void setByte(long address, int value) { - PlatformDependent.putByte(address, (byte) value); - } - - static void setShort(long address, int value) { - if (UNALIGNED) { - PlatformDependent.putShort( - address, BIG_ENDIAN_NATIVE_ORDER ? (short) value : Short.reverseBytes((short) value)); - } else { - PlatformDependent.putByte(address, (byte) (value >>> 8)); - PlatformDependent.putByte(address + 1, (byte) value); - } - } - - static void setMedium(long address, int value) { - if (UNALIGNED) { - if (BIG_ENDIAN_NATIVE_ORDER) { - PlatformDependent.putByte(address, (byte) value); - PlatformDependent.putShort(address + 1, (short) (value >>> 8)); - } else { - PlatformDependent.putShort(address, Short.reverseBytes((short) (value >>> 8))); - PlatformDependent.putByte(address + 2, (byte) value); - } - } else { - PlatformDependent.putByte(address, (byte) (value >>> 16)); - PlatformDependent.putByte(address + 1, (byte) (value >>> 8)); - PlatformDependent.putByte(address + 2, (byte) value); - } - } - - static void setInt(long address, int value) { - if (UNALIGNED) { - PlatformDependent.putInt(address, BIG_ENDIAN_NATIVE_ORDER ? value : Integer.reverseBytes(value)); - } else { - PlatformDependent.putByte(address, (byte) (value >>> 24)); - PlatformDependent.putByte(address + 1, (byte) (value >>> 16)); - PlatformDependent.putByte(address + 2, (byte) (value >>> 8)); - PlatformDependent.putByte(address + 3, (byte) value); - } - } - - static void setLong(long address, long value) { - if (UNALIGNED) { - PlatformDependent.putLong(address, BIG_ENDIAN_NATIVE_ORDER ? value : Long.reverseBytes(value)); - } else { - PlatformDependent.putByte(address, (byte) (value >>> 56)); - PlatformDependent.putByte(address + 1, (byte) (value >>> 48)); - PlatformDependent.putByte(address + 2, (byte) (value >>> 40)); - PlatformDependent.putByte(address + 3, (byte) (value >>> 32)); - PlatformDependent.putByte(address + 4, (byte) (value >>> 24)); - PlatformDependent.putByte(address + 5, (byte) (value >>> 16)); - PlatformDependent.putByte(address + 6, (byte) (value >>> 8)); - PlatformDependent.putByte(address + 7, (byte) value); - } - } - - static byte getByte(byte[] array, int index) { - return PlatformDependent.getByte(array, index); - } - - static short getShort(byte[] array, int index) { - if (UNALIGNED) { - short v = PlatformDependent.getShort(array, index); - return BIG_ENDIAN_NATIVE_ORDER ? v : Short.reverseBytes(v); - } - return (short) (PlatformDependent.getByte(index) << 8 | PlatformDependent.getByte(index + 1) & 0xff); - } - - static int getUnsignedMedium(byte[] array, int index) { - if (UNALIGNED) { - if (BIG_ENDIAN_NATIVE_ORDER) { - return (PlatformDependent.getByte(array, index) & 0xff) | - (PlatformDependent.getShort(array, index + 1) & 0xffff) << 8; - } - return (Short.reverseBytes(PlatformDependent.getShort(array, index)) & 0xffff) << 8 | - PlatformDependent.getByte(array, index + 2) & 0xff; - } - return (PlatformDependent.getByte(array, index) & 0xff) << 16 | - (PlatformDependent.getByte(array, index + 1) & 0xff) << 8 | - PlatformDependent.getByte(array, index + 2) & 0xff; - } - - static int getInt(byte[] array, int index) { - if (UNALIGNED) { - int v = PlatformDependent.getInt(array, index); - return BIG_ENDIAN_NATIVE_ORDER ? v : Integer.reverseBytes(v); - } - return PlatformDependent.getByte(array, index) << 24 | - (PlatformDependent.getByte(array, index + 1) & 0xff) << 16 | - (PlatformDependent.getByte(array, index + 2) & 0xff) << 8 | - PlatformDependent.getByte(array, index + 3) & 0xff; - } - - static long getLong(byte[] array, int index) { - if (UNALIGNED) { - long v = PlatformDependent.getLong(array, index); - return BIG_ENDIAN_NATIVE_ORDER ? v : Long.reverseBytes(v); - } - return (long) PlatformDependent.getByte(array, index) << 56 | - ((long) PlatformDependent.getByte(array, index + 1) & 0xff) << 48 | - ((long) PlatformDependent.getByte(array, index + 2) & 0xff) << 40 | - ((long) PlatformDependent.getByte(array, index + 3) & 0xff) << 32 | - ((long) PlatformDependent.getByte(array, index + 4) & 0xff) << 24 | - ((long) PlatformDependent.getByte(array, index + 5) & 0xff) << 16 | - ((long) PlatformDependent.getByte(array, index + 6) & 0xff) << 8 | - (long) PlatformDependent.getByte(array, index + 7) & 0xff; - } - - static void setByte(byte[] array, int index, int value) { - PlatformDependent.putByte(array, index, (byte) value); - } - - static void setShort(byte[] array, int index, int value) { - if (UNALIGNED) { - PlatformDependent.putShort( - array, index, BIG_ENDIAN_NATIVE_ORDER ? (short) value : Short.reverseBytes((short) value)); - } else { - PlatformDependent.putByte(array, index, (byte) (value >>> 8)); - PlatformDependent.putByte(array, index + 1, (byte) value); - } - } - - static void setMedium(byte[] array, int index, int value) { - if (UNALIGNED) { - if (BIG_ENDIAN_NATIVE_ORDER) { - PlatformDependent.putByte(array, index, (byte) value); - PlatformDependent.putShort(array, index + 1, (short) (value >>> 8)); - } else { - PlatformDependent.putShort(array, index, Short.reverseBytes((short) (value >>> 8))); - PlatformDependent.putByte(array, index + 2, (byte) value); - } - } else { - PlatformDependent.putByte(array, index, (byte) (value >>> 16)); - PlatformDependent.putByte(array, index + 1, (byte) (value >>> 8)); - PlatformDependent.putByte(array, index + 2, (byte) value); - } - } - - static void setInt(byte[] array, int index, int value) { - if (UNALIGNED) { - PlatformDependent.putInt(array, index, BIG_ENDIAN_NATIVE_ORDER ? value : Integer.reverseBytes(value)); - } else { - PlatformDependent.putByte(array, index, (byte) (value >>> 24)); - PlatformDependent.putByte(array, index + 1, (byte) (value >>> 16)); - PlatformDependent.putByte(array, index + 2, (byte) (value >>> 8)); - PlatformDependent.putByte(array, index + 3, (byte) value); - } - } - - static void setLong(byte[] array, int index, long value) { - if (UNALIGNED) { - PlatformDependent.putLong(array, index, BIG_ENDIAN_NATIVE_ORDER ? value : Long.reverseBytes(value)); - } else { - PlatformDependent.putByte(array, index, (byte) (value >>> 56)); - PlatformDependent.putByte(array, index + 1, (byte) (value >>> 48)); - PlatformDependent.putByte(array, index + 2, (byte) (value >>> 40)); - PlatformDependent.putByte(array, index + 3, (byte) (value >>> 32)); - PlatformDependent.putByte(array, index + 4, (byte) (value >>> 24)); - PlatformDependent.putByte(array, index + 5, (byte) (value >>> 16)); - PlatformDependent.putByte(array, index + 6, (byte) (value >>> 8)); - PlatformDependent.putByte(array, index + 7, (byte) value); - } - } - - static ByteBuf copy(AbstractByteBuf buf, long addr, int index, int length) { - buf.checkIndex(index, length); - ByteBuf copy = buf.alloc().directBuffer(length, buf.maxCapacity()); - if (length != 0) { - if (copy.hasMemoryAddress()) { - PlatformDependent.copyMemory(addr, copy.memoryAddress(), length); - copy.setIndex(0, length); - } else { - copy.writeBytes(buf, index, length); - } - } - return copy; - } - - static int setBytes(AbstractByteBuf buf, long addr, int index, InputStream in, int length) throws IOException { - buf.checkIndex(index, length); - ByteBuf tmpBuf = buf.alloc().heapBuffer(length); - try { - byte[] tmp = tmpBuf.array(); - int offset = tmpBuf.arrayOffset(); - int readBytes = in.read(tmp, offset, length); - if (readBytes > 0) { - PlatformDependent.copyMemory(tmp, offset, addr, readBytes); - } - return readBytes; - } finally { - tmpBuf.release(); - } - } - - static void getBytes(AbstractByteBuf buf, long addr, int index, ByteBuf dst, int dstIndex, int length) { - buf.checkIndex(index, length); - checkNotNull(dst, "dst"); - if (isOutOfBounds(dstIndex, length, dst.capacity())) { - throw new IndexOutOfBoundsException("dstIndex: " + dstIndex); - } - - if (dst.hasMemoryAddress()) { - PlatformDependent.copyMemory(addr, dst.memoryAddress() + dstIndex, length); - } else if (dst.hasArray()) { - PlatformDependent.copyMemory(addr, dst.array(), dst.arrayOffset() + dstIndex, length); - } else { - dst.setBytes(dstIndex, buf, index, length); - } - } - - static void getBytes(AbstractByteBuf buf, long addr, int index, byte[] dst, int dstIndex, int length) { - buf.checkIndex(index, length); - checkNotNull(dst, "dst"); - if (isOutOfBounds(dstIndex, length, dst.length)) { - throw new IndexOutOfBoundsException("dstIndex: " + dstIndex); - } - if (length != 0) { - PlatformDependent.copyMemory(addr, dst, dstIndex, length); - } - } - - static void getBytes(AbstractByteBuf buf, long addr, int index, ByteBuffer dst) { - buf.checkIndex(index); - int bytesToCopy = Math.min(buf.capacity() - index, dst.remaining()); - if (bytesToCopy == 0) { - return; - } - - if (dst.isDirect()) { - // Copy to direct memory - long dstAddress = PlatformDependent.directBufferAddress(dst); - PlatformDependent.copyMemory(addr, dstAddress + dst.position(), bytesToCopy); - } else { - // Copy to array - PlatformDependent.copyMemory(addr, dst.array(), dst.arrayOffset() + dst.position(), bytesToCopy); - } - - dst.position(dst.position() + bytesToCopy); - } - - static void setBytes(AbstractByteBuf buf, long addr, int index, ByteBuf src, int srcIndex, int length) { - buf.checkIndex(index, length); - checkNotNull(src, "src"); - if (isOutOfBounds(srcIndex, length, src.capacity())) { - throw new IndexOutOfBoundsException("srcIndex: " + srcIndex); - } - - if (length != 0) { - if (src.hasMemoryAddress()) { - PlatformDependent.copyMemory(src.memoryAddress() + srcIndex, addr, length); - } else if (src.hasArray()) { - PlatformDependent.copyMemory(src.array(), src.arrayOffset() + srcIndex, addr, length); - } else { - src.getBytes(srcIndex, buf, index, length); - } - } - } - - static void setBytes(AbstractByteBuf buf, long addr, int index, byte[] src, int srcIndex, int length) { - buf.checkIndex(index, length); - if (length != 0) { - PlatformDependent.copyMemory(src, srcIndex, addr, length); - } - } - - static void setBytes(AbstractByteBuf buf, long addr, int index, ByteBuffer src) { - buf.checkIndex(index, src.remaining()); - - int length = src.remaining(); - if (length == 0) { - return; - } - - if (src.isDirect()) { - // Copy from direct memory - long srcAddress = PlatformDependent.directBufferAddress(src); - PlatformDependent.copyMemory(srcAddress + src.position(), addr, src.remaining()); - } else { - // Copy from array - PlatformDependent.copyMemory(src.array(), src.arrayOffset() + src.position(), addr, length); - } - src.position(src.position() + length); - } - - static void getBytes(AbstractByteBuf buf, long addr, int index, OutputStream out, int length) throws IOException { - buf.checkIndex(index, length); - if (length != 0) { - ByteBuf tmpBuf = buf.alloc().heapBuffer(length); - try { - byte[] tmp = tmpBuf.array(); - int offset = tmpBuf.arrayOffset(); - PlatformDependent.copyMemory(addr, tmp, offset, length); - out.write(tmp, offset, length); - } finally { - tmpBuf.release(); - } - } - } - - private UnsafeByteBufUtil() { } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnsafeDirectSwappedByteBuf.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnsafeDirectSwappedByteBuf.java deleted file mode 100755 index ccc28a2ffc..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnsafeDirectSwappedByteBuf.java +++ /dev/null @@ -1,67 +0,0 @@ -/* -* Copyright 2014 The Netty Project -* -* The Netty Project licenses this file to you under the Apache License, -* version 2.0 (the "License"); you may not use this file except in compliance -* with the License. You may obtain a copy of the License at: -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -* License for the specific language governing permissions and limitations -* under the License. -*/ - -package com.ai.cloud.io.netty.buffer; - -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - -/** - * Special {@link SwappedByteBuf} for {@link ByteBuf}s that are backed by a {@code memoryAddress}. - */ -final class UnsafeDirectSwappedByteBuf extends AbstractUnsafeSwappedByteBuf { - - UnsafeDirectSwappedByteBuf(AbstractByteBuf buf) { - super(buf); - } - - private static long addr(AbstractByteBuf wrapped, int index) { - // We need to call wrapped.memoryAddress() everytime and NOT cache it as it may change if the buffer expand. - // See: - // - https://github.com/netty/netty/issues/2587 - // - https://github.com/netty/netty/issues/2580 - return wrapped.memoryAddress() + index; - } - - @Override - protected long _getLong(AbstractByteBuf wrapped, int index) { - return PlatformDependent.getLong(addr(wrapped, index)); - } - - @Override - protected int _getInt(AbstractByteBuf wrapped, int index) { - return PlatformDependent.getInt(addr(wrapped, index)); - } - - @Override - protected short _getShort(AbstractByteBuf wrapped, int index) { - return PlatformDependent.getShort(addr(wrapped, index)); - } - - @Override - protected void _setShort(AbstractByteBuf wrapped, int index, short value) { - PlatformDependent.putShort(addr(wrapped, index), value); - } - - @Override - protected void _setInt(AbstractByteBuf wrapped, int index, int value) { - PlatformDependent.putInt(addr(wrapped, index), value); - } - - @Override - protected void _setLong(AbstractByteBuf wrapped, int index, long value) { - PlatformDependent.putLong(addr(wrapped, index), value); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnsafeHeapSwappedByteBuf.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnsafeHeapSwappedByteBuf.java deleted file mode 100755 index 45dba627b1..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/UnsafeHeapSwappedByteBuf.java +++ /dev/null @@ -1,63 +0,0 @@ -/* -* Copyright 2014 The Netty Project -* -* The Netty Project licenses this file to you under the Apache License, -* version 2.0 (the "License"); you may not use this file except in compliance -* with the License. You may obtain a copy of the License at: -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -* License for the specific language governing permissions and limitations -* under the License. -*/ - -package com.ai.cloud.io.netty.buffer; - -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - -/** - * Special {@link SwappedByteBuf} for {@link ByteBuf}s that use unsafe to access the byte array. - */ -final class UnsafeHeapSwappedByteBuf extends AbstractUnsafeSwappedByteBuf { - - UnsafeHeapSwappedByteBuf(AbstractByteBuf buf) { - super(buf); - } - - private static int idx(ByteBuf wrapped, int index) { - return wrapped.arrayOffset() + index; - } - - @Override - protected long _getLong(AbstractByteBuf wrapped, int index) { - return PlatformDependent.getLong(wrapped.array(), idx(wrapped, index)); - } - - @Override - protected int _getInt(AbstractByteBuf wrapped, int index) { - return PlatformDependent.getInt(wrapped.array(), idx(wrapped, index)); - } - - @Override - protected short _getShort(AbstractByteBuf wrapped, int index) { - return PlatformDependent.getShort(wrapped.array(), idx(wrapped, index)); - } - - @Override - protected void _setShort(AbstractByteBuf wrapped, int index, short value) { - PlatformDependent.putShort(wrapped.array(), idx(wrapped, index), value); - } - - @Override - protected void _setInt(AbstractByteBuf wrapped, int index, int value) { - PlatformDependent.putInt(wrapped.array(), idx(wrapped, index), value); - } - - @Override - protected void _setLong(AbstractByteBuf wrapped, int index, long value) { - PlatformDependent.putLong(wrapped.array(), idx(wrapped, index), value); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/WrappedByteBuf.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/WrappedByteBuf.java deleted file mode 100755 index e768d91793..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/WrappedByteBuf.java +++ /dev/null @@ -1,834 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; -import java.nio.charset.Charset; - -import com.ai.cloud.io.netty.util.internal.StringUtil; - -/** - * Wraps another {@link ByteBuf}. - * - * It's important that the {@link #readerIndex()} and {@link #writerIndex()} will not do any adjustments on the - * indices on the fly because of internal optimizations made by {@link ByteBufUtil#writeAscii(ByteBuf, CharSequence)} - * and {@link ByteBufUtil#writeUtf8(ByteBuf, CharSequence)}. - */ -class WrappedByteBuf extends ByteBuf { - - protected final ByteBuf buf; - - protected WrappedByteBuf(ByteBuf buf) { - if (buf == null) { - throw new NullPointerException("buf"); - } - this.buf = buf; - } - - @Override - public final boolean hasMemoryAddress() { - return buf.hasMemoryAddress(); - } - - @Override - public final long memoryAddress() { - return buf.memoryAddress(); - } - - @Override - public final int capacity() { - return buf.capacity(); - } - - @Override - public ByteBuf capacity(int newCapacity) { - buf.capacity(newCapacity); - return this; - } - - @Override - public final int maxCapacity() { - return buf.maxCapacity(); - } - - @Override - public final ByteBufAllocator alloc() { - return buf.alloc(); - } - - @Override - public final ByteOrder order() { - return buf.order(); - } - - @Override - public ByteBuf order(ByteOrder endianness) { - return buf.order(endianness); - } - - @Override - public final ByteBuf unwrap() { - return buf; - } - - @Override - public final boolean isDirect() { - return buf.isDirect(); - } - - @Override - public final int readerIndex() { - return buf.readerIndex(); - } - - @Override - public final ByteBuf readerIndex(int readerIndex) { - buf.readerIndex(readerIndex); - return this; - } - - @Override - public final int writerIndex() { - return buf.writerIndex(); - } - - @Override - public final ByteBuf writerIndex(int writerIndex) { - buf.writerIndex(writerIndex); - return this; - } - - @Override - public ByteBuf setIndex(int readerIndex, int writerIndex) { - buf.setIndex(readerIndex, writerIndex); - return this; - } - - @Override - public final int readableBytes() { - return buf.readableBytes(); - } - - @Override - public final int writableBytes() { - return buf.writableBytes(); - } - - @Override - public final int maxWritableBytes() { - return buf.maxWritableBytes(); - } - - @Override - public final boolean isReadable() { - return buf.isReadable(); - } - - @Override - public final boolean isWritable() { - return buf.isWritable(); - } - - @Override - public final ByteBuf clear() { - buf.clear(); - return this; - } - - @Override - public final ByteBuf markReaderIndex() { - buf.markReaderIndex(); - return this; - } - - @Override - public final ByteBuf resetReaderIndex() { - buf.resetReaderIndex(); - return this; - } - - @Override - public final ByteBuf markWriterIndex() { - buf.markWriterIndex(); - return this; - } - - @Override - public final ByteBuf resetWriterIndex() { - buf.resetWriterIndex(); - return this; - } - - @Override - public ByteBuf discardReadBytes() { - buf.discardReadBytes(); - return this; - } - - @Override - public ByteBuf discardSomeReadBytes() { - buf.discardSomeReadBytes(); - return this; - } - - @Override - public ByteBuf ensureWritable(int minWritableBytes) { - buf.ensureWritable(minWritableBytes); - return this; - } - - @Override - public int ensureWritable(int minWritableBytes, boolean force) { - return buf.ensureWritable(minWritableBytes, force); - } - - @Override - public boolean getBoolean(int index) { - return buf.getBoolean(index); - } - - @Override - public byte getByte(int index) { - return buf.getByte(index); - } - - @Override - public short getUnsignedByte(int index) { - return buf.getUnsignedByte(index); - } - - @Override - public short getShort(int index) { - return buf.getShort(index); - } - - @Override - public int getUnsignedShort(int index) { - return buf.getUnsignedShort(index); - } - - @Override - public int getMedium(int index) { - return buf.getMedium(index); - } - - @Override - public int getUnsignedMedium(int index) { - return buf.getUnsignedMedium(index); - } - - @Override - public int getInt(int index) { - return buf.getInt(index); - } - - @Override - public long getUnsignedInt(int index) { - return buf.getUnsignedInt(index); - } - - @Override - public long getLong(int index) { - return buf.getLong(index); - } - - @Override - public char getChar(int index) { - return buf.getChar(index); - } - - @Override - public float getFloat(int index) { - return buf.getFloat(index); - } - - @Override - public double getDouble(int index) { - return buf.getDouble(index); - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst) { - buf.getBytes(index, dst); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int length) { - buf.getBytes(index, dst, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - buf.getBytes(index, dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, byte[] dst) { - buf.getBytes(index, dst); - return this; - } - - @Override - public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - buf.getBytes(index, dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuffer dst) { - buf.getBytes(index, dst); - return this; - } - - @Override - public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException { - buf.getBytes(index, out, length); - return this; - } - - @Override - public int getBytes(int index, GatheringByteChannel out, int length) throws IOException { - return buf.getBytes(index, out, length); - } - - @Override - public ByteBuf setBoolean(int index, boolean value) { - buf.setBoolean(index, value); - return this; - } - - @Override - public ByteBuf setByte(int index, int value) { - buf.setByte(index, value); - return this; - } - - @Override - public ByteBuf setShort(int index, int value) { - buf.setShort(index, value); - return this; - } - - @Override - public ByteBuf setMedium(int index, int value) { - buf.setMedium(index, value); - return this; - } - - @Override - public ByteBuf setInt(int index, int value) { - buf.setInt(index, value); - return this; - } - - @Override - public ByteBuf setLong(int index, long value) { - buf.setLong(index, value); - return this; - } - - @Override - public ByteBuf setChar(int index, int value) { - buf.setChar(index, value); - return this; - } - - @Override - public ByteBuf setFloat(int index, float value) { - buf.setFloat(index, value); - return this; - } - - @Override - public ByteBuf setDouble(int index, double value) { - buf.setDouble(index, value); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src) { - buf.setBytes(index, src); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int length) { - buf.setBytes(index, src, length); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { - buf.setBytes(index, src, srcIndex, length); - return this; - } - - @Override - public ByteBuf setBytes(int index, byte[] src) { - buf.setBytes(index, src); - return this; - } - - @Override - public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { - buf.setBytes(index, src, srcIndex, length); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuffer src) { - buf.setBytes(index, src); - return this; - } - - @Override - public int setBytes(int index, InputStream in, int length) throws IOException { - return buf.setBytes(index, in, length); - } - - @Override - public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException { - return buf.setBytes(index, in, length); - } - - @Override - public ByteBuf setZero(int index, int length) { - buf.setZero(index, length); - return this; - } - - @Override - public boolean readBoolean() { - return buf.readBoolean(); - } - - @Override - public byte readByte() { - return buf.readByte(); - } - - @Override - public short readUnsignedByte() { - return buf.readUnsignedByte(); - } - - @Override - public short readShort() { - return buf.readShort(); - } - - @Override - public int readUnsignedShort() { - return buf.readUnsignedShort(); - } - - @Override - public int readMedium() { - return buf.readMedium(); - } - - @Override - public int readUnsignedMedium() { - return buf.readUnsignedMedium(); - } - - @Override - public int readInt() { - return buf.readInt(); - } - - @Override - public long readUnsignedInt() { - return buf.readUnsignedInt(); - } - - @Override - public long readLong() { - return buf.readLong(); - } - - @Override - public char readChar() { - return buf.readChar(); - } - - @Override - public float readFloat() { - return buf.readFloat(); - } - - @Override - public double readDouble() { - return buf.readDouble(); - } - - @Override - public ByteBuf readBytes(int length) { - return buf.readBytes(length); - } - - @Override - public ByteBuf readSlice(int length) { - return buf.readSlice(length); - } - - @Override - public ByteBuf readBytes(ByteBuf dst) { - buf.readBytes(dst); - return this; - } - - @Override - public ByteBuf readBytes(ByteBuf dst, int length) { - buf.readBytes(dst, length); - return this; - } - - @Override - public ByteBuf readBytes(ByteBuf dst, int dstIndex, int length) { - buf.readBytes(dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf readBytes(byte[] dst) { - buf.readBytes(dst); - return this; - } - - @Override - public ByteBuf readBytes(byte[] dst, int dstIndex, int length) { - buf.readBytes(dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf readBytes(ByteBuffer dst) { - buf.readBytes(dst); - return this; - } - - @Override - public ByteBuf readBytes(OutputStream out, int length) throws IOException { - buf.readBytes(out, length); - return this; - } - - @Override - public int readBytes(GatheringByteChannel out, int length) throws IOException { - return buf.readBytes(out, length); - } - - @Override - public ByteBuf skipBytes(int length) { - buf.skipBytes(length); - return this; - } - - @Override - public ByteBuf writeBoolean(boolean value) { - buf.writeBoolean(value); - return this; - } - - @Override - public ByteBuf writeByte(int value) { - buf.writeByte(value); - return this; - } - - @Override - public ByteBuf writeShort(int value) { - buf.writeShort(value); - return this; - } - - @Override - public ByteBuf writeMedium(int value) { - buf.writeMedium(value); - return this; - } - - @Override - public ByteBuf writeInt(int value) { - buf.writeInt(value); - return this; - } - - @Override - public ByteBuf writeLong(long value) { - buf.writeLong(value); - return this; - } - - @Override - public ByteBuf writeChar(int value) { - buf.writeChar(value); - return this; - } - - @Override - public ByteBuf writeFloat(float value) { - buf.writeFloat(value); - return this; - } - - @Override - public ByteBuf writeDouble(double value) { - buf.writeDouble(value); - return this; - } - - @Override - public ByteBuf writeBytes(ByteBuf src) { - buf.writeBytes(src); - return this; - } - - @Override - public ByteBuf writeBytes(ByteBuf src, int length) { - buf.writeBytes(src, length); - return this; - } - - @Override - public ByteBuf writeBytes(ByteBuf src, int srcIndex, int length) { - buf.writeBytes(src, srcIndex, length); - return this; - } - - @Override - public ByteBuf writeBytes(byte[] src) { - buf.writeBytes(src); - return this; - } - - @Override - public ByteBuf writeBytes(byte[] src, int srcIndex, int length) { - buf.writeBytes(src, srcIndex, length); - return this; - } - - @Override - public ByteBuf writeBytes(ByteBuffer src) { - buf.writeBytes(src); - return this; - } - - @Override - public int writeBytes(InputStream in, int length) throws IOException { - return buf.writeBytes(in, length); - } - - @Override - public int writeBytes(ScatteringByteChannel in, int length) throws IOException { - return buf.writeBytes(in, length); - } - - @Override - public ByteBuf writeZero(int length) { - buf.writeZero(length); - return this; - } - - @Override - public int indexOf(int fromIndex, int toIndex, byte value) { - return buf.indexOf(fromIndex, toIndex, value); - } - - @Override - public int bytesBefore(byte value) { - return buf.bytesBefore(value); - } - - @Override - public int bytesBefore(int length, byte value) { - return buf.bytesBefore(length, value); - } - - @Override - public int bytesBefore(int index, int length, byte value) { - return buf.bytesBefore(index, length, value); - } - - @Override - public int forEachByte(ByteBufProcessor processor) { - return buf.forEachByte(processor); - } - - @Override - public int forEachByte(int index, int length, ByteBufProcessor processor) { - return buf.forEachByte(index, length, processor); - } - - @Override - public int forEachByteDesc(ByteBufProcessor processor) { - return buf.forEachByteDesc(processor); - } - - @Override - public int forEachByteDesc(int index, int length, ByteBufProcessor processor) { - return buf.forEachByteDesc(index, length, processor); - } - - @Override - public ByteBuf copy() { - return buf.copy(); - } - - @Override - public ByteBuf copy(int index, int length) { - return buf.copy(index, length); - } - - @Override - public ByteBuf slice() { - return buf.slice(); - } - - @Override - public ByteBuf slice(int index, int length) { - return buf.slice(index, length); - } - - @Override - public ByteBuf duplicate() { - return buf.duplicate(); - } - - @Override - public int nioBufferCount() { - return buf.nioBufferCount(); - } - - @Override - public ByteBuffer nioBuffer() { - return buf.nioBuffer(); - } - - @Override - public ByteBuffer nioBuffer(int index, int length) { - return buf.nioBuffer(index, length); - } - - @Override - public ByteBuffer[] nioBuffers() { - return buf.nioBuffers(); - } - - @Override - public ByteBuffer[] nioBuffers(int index, int length) { - return buf.nioBuffers(index, length); - } - - @Override - public ByteBuffer internalNioBuffer(int index, int length) { - return buf.internalNioBuffer(index, length); - } - - @Override - public boolean hasArray() { - return buf.hasArray(); - } - - @Override - public byte[] array() { - return buf.array(); - } - - @Override - public int arrayOffset() { - return buf.arrayOffset(); - } - - @Override - public String toString(Charset charset) { - return buf.toString(charset); - } - - @Override - public String toString(int index, int length, Charset charset) { - return buf.toString(index, length, charset); - } - - @Override - public int hashCode() { - return buf.hashCode(); - } - - @Override - @SuppressWarnings("EqualsWhichDoesntCheckParameterClass") - public boolean equals(Object obj) { - return buf.equals(obj); - } - - @Override - public int compareTo(ByteBuf buffer) { - return buf.compareTo(buffer); - } - - @Override - public String toString() { - return StringUtil.simpleClassName(this) + '(' + buf.toString() + ')'; - } - - @Override - public ByteBuf retain(int increment) { - buf.retain(increment); - return this; - } - - @Override - public ByteBuf retain() { - buf.retain(); - return this; - } - - @Override - public final boolean isReadable(int size) { - return buf.isReadable(size); - } - - @Override - public final boolean isWritable(int size) { - return buf.isWritable(size); - } - - @Override - public final int refCnt() { - return buf.refCnt(); - } - - @Override - public boolean release() { - return buf.release(); - } - - @Override - public boolean release(int decrement) { - return buf.release(decrement); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/package-info.java deleted file mode 100755 index 3d61cebbd9..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/buffer/package-info.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * Abstraction of a byte buffer - the fundamental data structure - * to represent a low-level binary and text message. - * - * Netty uses its own buffer API instead of NIO {@link java.nio.ByteBuffer} to - * represent a sequence of bytes. This approach has significant advantage over - * using {@link java.nio.ByteBuffer}. Netty's new buffer type, - * {@link com.ai.cloud.io.netty.buffer.ByteBuf}, has been designed from ground - * up to address the problems of {@link java.nio.ByteBuffer} and to meet the - * daily needs of network application developers. To list a few cool features: - *
    - *
  • You can define your buffer type if necessary.
  • - *
  • Transparent zero copy is achieved by built-in composite buffer type.
  • - *
  • A dynamic buffer type is provided out-of-the-box, whose capacity is - * expanded on demand, just like {@link java.lang.StringBuffer}.
  • - *
  • There's no need to call the {@code flip()} method anymore.
  • - *
  • It is often faster than {@link java.nio.ByteBuffer}.
  • - *
- * - *

Extensibility

- * - * {@link com.ai.cloud.io.netty.buffer.ByteBuf} has rich set of operations - * optimized for rapid protocol implementation. For example, - * {@link com.ai.cloud.io.netty.buffer.ByteBuf} provides various operations - * for accessing unsigned values and strings and searching for certain byte - * sequence in a buffer. You can also extend or wrap existing buffer type - * to add convenient accessors. The custom buffer type still implements - * {@link com.ai.cloud.io.netty.buffer.ByteBuf} interface rather than - * introducing an incompatible type. - * - *

Transparent Zero Copy

- * - * To lift up the performance of a network application to the extreme, you need - * to reduce the number of memory copy operation. You might have a set of - * buffers that could be sliced and combined to compose a whole message. Netty - * provides a composite buffer which allows you to create a new buffer from the - * arbitrary number of existing buffers with no memory copy. For example, a - * message could be composed of two parts; header and body. In a modularized - * application, the two parts could be produced by different modules and - * assembled later when the message is sent out. - *
- * +--------+----------+
- * | header |   body   |
- * +--------+----------+
- * 
- * If {@link java.nio.ByteBuffer} were used, you would have to create a new big - * buffer and copy the two parts into the new buffer. Alternatively, you can - * perform a gathering write operation in NIO, but it restricts you to represent - * the composite of buffers as an array of {@link java.nio.ByteBuffer}s rather - * than a single buffer, breaking the abstraction and introducing complicated - * state management. Moreover, it's of no use if you are not going to read or - * write from an NIO channel. - *
- * // The composite type is incompatible with the component type.
- * ByteBuffer[] message = new ByteBuffer[] { header, body };
- * 
- * By contrast, {@link com.ai.cloud.io.netty.buffer.ByteBuf} does not have such - * caveats because it is fully extensible and has a built-in composite buffer - * type. - *
- * // The composite type is compatible with the component type.
- * {@link ByteBuf} message = {@link Unpooled}.wrappedBuffer(header, body);
- *
- * // Therefore, you can even create a composite by mixing a composite and an
- * // ordinary buffer.
- * {@link ByteBuf} messageWithFooter = {@link Unpooled}.wrappedBuffer(message, footer);
- *
- * // Because the composite is still a {@link ByteBuf}, you can access its content
- * // easily, and the accessor method will behave just like it's a single buffer
- * // even if the region you want to access spans over multiple components.  The
- * // unsigned integer being read here is located across body and footer.
- * messageWithFooter.getUnsignedInt(
- *     messageWithFooter.readableBytes() - footer.readableBytes() - 1);
- * 
- * - *

Automatic Capacity Extension

- * - * Many protocols define variable length messages, which means there's no way to - * determine the length of a message until you construct the message or it is - * difficult and inconvenient to calculate the length precisely. It is just - * like when you build a {@link java.lang.String}. You often estimate the length - * of the resulting string and let {@link java.lang.StringBuffer} expand itself - * on demand. - *
- * // A new dynamic buffer is created.  Internally, the actual buffer is created
- * // lazily to avoid potentially wasted memory space.
- * {@link ByteBuf} b = {@link Unpooled}.buffer(4);
- *
- * // When the first write attempt is made, the internal buffer is created with
- * // the specified initial capacity (4).
- * b.writeByte('1');
- *
- * b.writeByte('2');
- * b.writeByte('3');
- * b.writeByte('4');
- *
- * // When the number of written bytes exceeds the initial capacity (4), the
- * // internal buffer is reallocated automatically with a larger capacity.
- * b.writeByte('5');
- * 
- * - *

Better Performance

- * - * Most frequently used buffer implementation of - * {@link com.ai.cloud.io.netty.buffer.ByteBuf} is a very thin wrapper of a - * byte array (i.e. {@code byte[]}). Unlike {@link java.nio.ByteBuffer}, it has - * no complicated boundary check and index compensation, and therefore it is - * easier for a JVM to optimize the buffer access. More complicated buffer - * implementation is used only for sliced or composite buffers, and it performs - * as well as {@link java.nio.ByteBuffer}. - */ -package com.ai.cloud.io.netty.buffer; diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/AbstractChannel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/AbstractChannel.java deleted file mode 100755 index 8bbb36fbf8..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/AbstractChannel.java +++ /dev/null @@ -1,970 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import java.io.IOException; -import java.net.ConnectException; -import java.net.InetSocketAddress; -import java.net.NoRouteToHostException; -import java.net.SocketAddress; -import java.net.SocketException; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.NotYetConnectedException; -import java.util.concurrent.Executor; -import java.util.concurrent.RejectedExecutionException; - -import com.ai.cloud.io.netty.buffer.ByteBufAllocator; -import com.ai.cloud.io.netty.util.DefaultAttributeMap; -import com.ai.cloud.io.netty.util.ReferenceCountUtil; -import com.ai.cloud.io.netty.util.internal.EmptyArrays; -import com.ai.cloud.io.netty.util.internal.OneTimeTask; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; -import com.ai.cloud.io.netty.util.internal.ThreadLocalRandom; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * A skeletal {@link Channel} implementation. - */ -public abstract class AbstractChannel extends DefaultAttributeMap implements Channel { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(AbstractChannel.class); - - static final ClosedChannelException CLOSED_CHANNEL_EXCEPTION = new ClosedChannelException(); - static final NotYetConnectedException NOT_YET_CONNECTED_EXCEPTION = new NotYetConnectedException(); - - static { - CLOSED_CHANNEL_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); - NOT_YET_CONNECTED_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); - } - - private MessageSizeEstimator.Handle estimatorHandle; - - private final Channel parent; - private final long hashCode = ThreadLocalRandom.current().nextLong(); - private final Unsafe unsafe; - private final ChannelPipeline pipeline; - private final ChannelFuture succeededFuture = new SucceededChannelFuture(this, null); - private final VoidChannelPromise voidPromise = new VoidChannelPromise(this, true); - private final VoidChannelPromise unsafeVoidPromise = new VoidChannelPromise(this, false); - private final CloseFuture closeFuture = new CloseFuture(this); - - private volatile SocketAddress localAddress; - private volatile SocketAddress remoteAddress; - private volatile EventLoop eventLoop; - private volatile boolean registered; - - /** Cache for the string representation of this channel */ - private boolean strValActive; - private String strVal; - - /** - * Creates a new instance. - * - * @param parent - * the parent of this channel. {@code null} if there's no parent. - */ - protected AbstractChannel(Channel parent) { - this.parent = parent; - unsafe = newUnsafe(); - pipeline = new DefaultChannelPipeline(this); - } - - @Override - public boolean isWritable() { - ChannelOutboundBuffer buf = unsafe.outboundBuffer(); - return buf != null && buf.isWritable(); - } - - @Override - public Channel parent() { - return parent; - } - - @Override - public ChannelPipeline pipeline() { - return pipeline; - } - - @Override - public ByteBufAllocator alloc() { - return config().getAllocator(); - } - - @Override - public EventLoop eventLoop() { - EventLoop eventLoop = this.eventLoop; - if (eventLoop == null) { - throw new IllegalStateException("channel not registered to an event loop"); - } - return eventLoop; - } - - @Override - public SocketAddress localAddress() { - SocketAddress localAddress = this.localAddress; - if (localAddress == null) { - try { - this.localAddress = localAddress = unsafe().localAddress(); - } catch (Throwable t) { - // Sometimes fails on a closed socket in Windows. - return null; - } - } - return localAddress; - } - - protected void invalidateLocalAddress() { - localAddress = null; - } - - @Override - public SocketAddress remoteAddress() { - SocketAddress remoteAddress = this.remoteAddress; - if (remoteAddress == null) { - try { - this.remoteAddress = remoteAddress = unsafe().remoteAddress(); - } catch (Throwable t) { - // Sometimes fails on a closed socket in Windows. - return null; - } - } - return remoteAddress; - } - - /** - * Reset the stored remoteAddress - */ - protected void invalidateRemoteAddress() { - remoteAddress = null; - } - - @Override - public boolean isRegistered() { - return registered; - } - - @Override - public ChannelFuture bind(SocketAddress localAddress) { - return pipeline.bind(localAddress); - } - - @Override - public ChannelFuture connect(SocketAddress remoteAddress) { - return pipeline.connect(remoteAddress); - } - - @Override - public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress) { - return pipeline.connect(remoteAddress, localAddress); - } - - @Override - public ChannelFuture disconnect() { - return pipeline.disconnect(); - } - - @Override - public ChannelFuture close() { - return pipeline.close(); - } - - @Override - public ChannelFuture deregister() { - return pipeline.deregister(); - } - - @Override - public Channel flush() { - pipeline.flush(); - return this; - } - - @Override - public ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise) { - return pipeline.bind(localAddress, promise); - } - - @Override - public ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise) { - return pipeline.connect(remoteAddress, promise); - } - - @Override - public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) { - return pipeline.connect(remoteAddress, localAddress, promise); - } - - @Override - public ChannelFuture disconnect(ChannelPromise promise) { - return pipeline.disconnect(promise); - } - - @Override - public ChannelFuture close(ChannelPromise promise) { - return pipeline.close(promise); - } - - @Override - public ChannelFuture deregister(ChannelPromise promise) { - return pipeline.deregister(promise); - } - - @Override - public Channel read() { - pipeline.read(); - return this; - } - - @Override - public ChannelFuture write(Object msg) { - return pipeline.write(msg); - } - - @Override - public ChannelFuture write(Object msg, ChannelPromise promise) { - return pipeline.write(msg, promise); - } - - @Override - public ChannelFuture writeAndFlush(Object msg) { - return pipeline.writeAndFlush(msg); - } - - @Override - public ChannelFuture writeAndFlush(Object msg, ChannelPromise promise) { - return pipeline.writeAndFlush(msg, promise); - } - - @Override - public ChannelPromise newPromise() { - return new DefaultChannelPromise(this); - } - - @Override - public ChannelProgressivePromise newProgressivePromise() { - return new DefaultChannelProgressivePromise(this); - } - - @Override - public ChannelFuture newSucceededFuture() { - return succeededFuture; - } - - @Override - public ChannelFuture newFailedFuture(Throwable cause) { - return new FailedChannelFuture(this, null, cause); - } - - @Override - public ChannelFuture closeFuture() { - return closeFuture; - } - - @Override - public Unsafe unsafe() { - return unsafe; - } - - /** - * Create a new {@link AbstractUnsafe} instance which will be used for the life-time of the {@link Channel} - */ - protected abstract AbstractUnsafe newUnsafe(); - - /** - * Returns the ID of this channel. - */ - @Override - public final int hashCode() { - return (int) hashCode; - } - - /** - * Returns {@code true} if and only if the specified object is identical - * with this channel (i.e: {@code this == o}). - */ - @Override - public final boolean equals(Object o) { - return this == o; - } - - @Override - public final int compareTo(Channel o) { - if (this == o) { - return 0; - } - - long ret = hashCode - o.hashCode(); - if (ret > 0) { - return 1; - } - if (ret < 0) { - return -1; - } - - ret = System.identityHashCode(this) - System.identityHashCode(o); - if (ret != 0) { - return (int) ret; - } - - // Jackpot! - different objects with same hashes - throw new Error(); - } - - /** - * Returns the {@link String} representation of this channel. The returned - * string contains the {@linkplain #hashCode()} ID}, {@linkplain #localAddress() local address}, - * and {@linkplain #remoteAddress() remote address} of this channel for - * easier identification. - */ - @Override - public String toString() { - boolean active = isActive(); - if (strValActive == active && strVal != null) { - return strVal; - } - - SocketAddress remoteAddr = remoteAddress(); - SocketAddress localAddr = localAddress(); - if (remoteAddr != null) { - SocketAddress srcAddr; - SocketAddress dstAddr; - if (parent == null) { - srcAddr = localAddr; - dstAddr = remoteAddr; - } else { - srcAddr = remoteAddr; - dstAddr = localAddr; - } - strVal = String.format("[id: 0x%08x, %s %s %s]", (int) hashCode, srcAddr, active? "=>" : ":>", dstAddr); - } else if (localAddr != null) { - strVal = String.format("[id: 0x%08x, %s]", (int) hashCode, localAddr); - } else { - strVal = String.format("[id: 0x%08x]", (int) hashCode); - } - - strValActive = active; - return strVal; - } - - @Override - public final ChannelPromise voidPromise() { - return voidPromise; - } - - final MessageSizeEstimator.Handle estimatorHandle() { - if (estimatorHandle == null) { - estimatorHandle = config().getMessageSizeEstimator().newHandle(); - } - return estimatorHandle; - } - - /** - * {@link Unsafe} implementation which sub-classes must extend and use. - */ - protected abstract class AbstractUnsafe implements Unsafe { - - private ChannelOutboundBuffer outboundBuffer = new ChannelOutboundBuffer(AbstractChannel.this); - private boolean inFlush0; - /** true if the channel has never been registered, false otherwise */ - private boolean neverRegistered = true; - - @Override - public final ChannelOutboundBuffer outboundBuffer() { - return outboundBuffer; - } - - @Override - public final SocketAddress localAddress() { - return localAddress0(); - } - - @Override - public final SocketAddress remoteAddress() { - return remoteAddress0(); - } - - @Override - public final void register(EventLoop eventLoop, final ChannelPromise promise) { - if (eventLoop == null) { - throw new NullPointerException("eventLoop"); - } - if (isRegistered()) { - promise.setFailure(new IllegalStateException("registered to an event loop already")); - return; - } - if (!isCompatible(eventLoop)) { - promise.setFailure( - new IllegalStateException("incompatible event loop type: " + eventLoop.getClass().getName())); - return; - } - - AbstractChannel.this.eventLoop = eventLoop; - - if (eventLoop.inEventLoop()) { - register0(promise); - } else { - try { - eventLoop.execute(new OneTimeTask() { - @Override - public void run() { - register0(promise); - } - }); - } catch (Throwable t) { - logger.warn( - "Force-closing a channel whose registration task was not accepted by an event loop: {}", - AbstractChannel.this, t); - closeForcibly(); - closeFuture.setClosed(); - safeSetFailure(promise, t); - } - } - } - - private void register0(ChannelPromise promise) { - try { - // check if the channel is still open as it could be closed in the mean time when the register - // call was outside of the eventLoop - if (!promise.setUncancellable() || !ensureOpen(promise)) { - return; - } - boolean firstRegistration = neverRegistered; - doRegister(); - neverRegistered = false; - registered = true; - safeSetSuccess(promise); - pipeline.fireChannelRegistered(); - // Only fire a channelActive if the channel has never been registered. This prevents firing - // multiple channel actives if the channel is deregistered and re-registered. - if (firstRegistration && isActive()) { - pipeline.fireChannelActive(); - } - } catch (Throwable t) { - // Close the channel directly to avoid FD leak. - closeForcibly(); - closeFuture.setClosed(); - safeSetFailure(promise, t); - } - } - - @Override - public final void bind(final SocketAddress localAddress, final ChannelPromise promise) { - if (!promise.setUncancellable() || !ensureOpen(promise)) { - return; - } - - // See: https://github.com/netty/netty/issues/576 - if (Boolean.TRUE.equals(config().getOption(ChannelOption.SO_BROADCAST)) && - localAddress instanceof InetSocketAddress && - !((InetSocketAddress) localAddress).getAddress().isAnyLocalAddress() && - !PlatformDependent.isWindows() && !PlatformDependent.isRoot()) { - // Warn a user about the fact that a non-root user can't receive a - // broadcast packet on *nix if the socket is bound on non-wildcard address. - logger.warn( - "A non-root user can't receive a broadcast packet if the socket " + - "is not bound to a wildcard address; binding to a non-wildcard " + - "address (" + localAddress + ") anyway as requested."); - } - - boolean wasActive = isActive(); - try { - doBind(localAddress); - } catch (Throwable t) { - safeSetFailure(promise, t); - closeIfClosed(); - return; - } - - if (!wasActive && isActive()) { - invokeLater(new OneTimeTask() { - @Override - public void run() { - pipeline.fireChannelActive(); - } - }); - } - - safeSetSuccess(promise); - } - - @Override - public final void disconnect(final ChannelPromise promise) { - if (!promise.setUncancellable()) { - return; - } - - boolean wasActive = isActive(); - try { - doDisconnect(); - } catch (Throwable t) { - safeSetFailure(promise, t); - closeIfClosed(); - return; - } - - if (wasActive && !isActive()) { - invokeLater(new OneTimeTask() { - @Override - public void run() { - pipeline.fireChannelInactive(); - } - }); - } - - safeSetSuccess(promise); - closeIfClosed(); // doDisconnect() might have closed the channel - } - - @Override - public final void close(final ChannelPromise promise) { - close(promise, CLOSED_CHANNEL_EXCEPTION, false); - } - - private void close(final ChannelPromise promise, final Throwable cause, final boolean notify) { - if (!promise.setUncancellable()) { - return; - } - - final ChannelOutboundBuffer outboundBuffer = this.outboundBuffer; - if (outboundBuffer == null) { - // Only needed if no VoidChannelPromise. - if (!(promise instanceof VoidChannelPromise)) { - // This means close() was called before so we just register a listener and return - closeFuture.addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - promise.setSuccess(); - } - }); - } - return; - } - - if (closeFuture.isDone()) { - // Closed already. - safeSetSuccess(promise); - return; - } - - final boolean wasActive = isActive(); - this.outboundBuffer = null; // Disallow adding any messages and flushes to outboundBuffer. - Executor closeExecutor = closeExecutor(); - if (closeExecutor != null) { - closeExecutor.execute(new OneTimeTask() { - @Override - public void run() { - try { - // Execute the close. - doClose0(promise); - } finally { - // Call invokeLater so closeAndDeregister is executed in the EventLoop again! - invokeLater(new OneTimeTask() { - @Override - public void run() { - // Fail all the queued messages - outboundBuffer.failFlushed(cause, notify); - outboundBuffer.close(CLOSED_CHANNEL_EXCEPTION); - fireChannelInactiveAndDeregister(wasActive); - } - }); - } - } - }); - } else { - try { - // Close the channel and fail the queued messages in all cases. - doClose0(promise); - } finally { - // Fail all the queued messages. - outboundBuffer.failFlushed(cause, notify); - outboundBuffer.close(CLOSED_CHANNEL_EXCEPTION); - } - if (inFlush0) { - invokeLater(new OneTimeTask() { - @Override - public void run() { - fireChannelInactiveAndDeregister(wasActive); - } - }); - } else { - fireChannelInactiveAndDeregister(wasActive); - } - } - } - - private void doClose0(ChannelPromise promise) { - try { - doClose(); - closeFuture.setClosed(); - safeSetSuccess(promise); - } catch (Throwable t) { - closeFuture.setClosed(); - safeSetFailure(promise, t); - } - } - - private void fireChannelInactiveAndDeregister(final boolean wasActive) { - if (wasActive && !isActive()) { - invokeLater(new OneTimeTask() { - @Override - public void run() { - pipeline.fireChannelInactive(); - } - }); - } - - deregister(voidPromise()); - } - - @Override - public final void closeForcibly() { - try { - doClose(); - } catch (Exception e) { - logger.warn("Failed to close a channel.", e); - } - } - - @Override - public final void deregister(final ChannelPromise promise) { - if (!promise.setUncancellable()) { - return; - } - - if (!registered) { - safeSetSuccess(promise); - return; - } - - try { - doDeregister(); - } catch (Throwable t) { - logger.warn("Unexpected exception occurred while deregistering a channel.", t); - } finally { - if (registered) { - registered = false; - invokeLater(new OneTimeTask() { - @Override - public void run() { - pipeline.fireChannelUnregistered(); - } - }); - safeSetSuccess(promise); - } else { - // Some transports like local and AIO does not allow the deregistration of - // an open channel. Their doDeregister() calls close(). Consequently, - // close() calls deregister() again - no need to fire channelUnregistered. - safeSetSuccess(promise); - } - } - } - - @Override - public final void beginRead() { - if (!isActive()) { - return; - } - - try { - doBeginRead(); - } catch (final Exception e) { - invokeLater(new OneTimeTask() { - @Override - public void run() { - pipeline.fireExceptionCaught(e); - } - }); - close(voidPromise()); - } - } - - @Override - public final void write(Object msg, ChannelPromise promise) { - ChannelOutboundBuffer outboundBuffer = this.outboundBuffer; - if (outboundBuffer == null) { - // If the outboundBuffer is null we know the channel was closed and so - // need to fail the future right away. If it is not null the handling of the rest - // will be done in flush0() - // See https://github.com/netty/netty/issues/2362 - safeSetFailure(promise, CLOSED_CHANNEL_EXCEPTION); - // release message now to prevent resource-leak - ReferenceCountUtil.release(msg); - return; - } - - int size; - try { - msg = filterOutboundMessage(msg); - size = estimatorHandle().size(msg); - if (size < 0) { - size = 0; - } - } catch (Throwable t) { - safeSetFailure(promise, t); - ReferenceCountUtil.release(msg); - return; - } - - outboundBuffer.addMessage(msg, size, promise); - } - - @Override - public final void flush() { - ChannelOutboundBuffer outboundBuffer = this.outboundBuffer; - if (outboundBuffer == null) { - return; - } - - outboundBuffer.addFlush(); - flush0(); - } - - protected void flush0() { - if (inFlush0) { - // Avoid re-entrance - return; - } - - final ChannelOutboundBuffer outboundBuffer = this.outboundBuffer; - if (outboundBuffer == null || outboundBuffer.isEmpty()) { - return; - } - - inFlush0 = true; - - // Mark all pending write requests as failure if the channel is inactive. - if (!isActive()) { - try { - if (isOpen()) { - outboundBuffer.failFlushed(NOT_YET_CONNECTED_EXCEPTION, true); - } else { - // Do not trigger channelWritabilityChanged because the channel is closed already. - outboundBuffer.failFlushed(CLOSED_CHANNEL_EXCEPTION, false); - } - } finally { - inFlush0 = false; - } - return; - } - - try { - doWrite(outboundBuffer); - } catch (Throwable t) { - if (t instanceof IOException && config().isAutoClose()) { - /** - * Just call {@link #close(ChannelPromise, Throwable, boolean)} here which will take care of - * failing all flushed messages and also ensure the actual close of the underlying transport - * will happen before the promises are notified. - * - * This is needed as otherwise {@link #isActive()} , {@link #isOpen()} and {@link #isWritable()} - * may still return {@code true} even if the channel should be closed as result of the exception. - */ - close(voidPromise(), t, false); - } else { - outboundBuffer.failFlushed(t, true); - } - } finally { - inFlush0 = false; - } - } - - @Override - public final ChannelPromise voidPromise() { - return unsafeVoidPromise; - } - - protected final boolean ensureOpen(ChannelPromise promise) { - if (isOpen()) { - return true; - } - - safeSetFailure(promise, CLOSED_CHANNEL_EXCEPTION); - return false; - } - - /** - * Marks the specified {@code promise} as success. If the {@code promise} is done already, log a message. - */ - protected final void safeSetSuccess(ChannelPromise promise) { - if (!(promise instanceof VoidChannelPromise) && !promise.trySuccess()) { - logger.warn("Failed to mark a promise as success because it is done already: {}", promise); - } - } - - /** - * Marks the specified {@code promise} as failure. If the {@code promise} is done already, log a message. - */ - protected final void safeSetFailure(ChannelPromise promise, Throwable cause) { - if (!(promise instanceof VoidChannelPromise) && !promise.tryFailure(cause)) { - logger.warn("Failed to mark a promise as failure because it's done already: {}", promise, cause); - } - } - - protected final void closeIfClosed() { - if (isOpen()) { - return; - } - close(voidPromise()); - } - - private void invokeLater(Runnable task) { - try { - // This method is used by outbound operation implementations to trigger an inbound event later. - // They do not trigger an inbound event immediately because an outbound operation might have been - // triggered by another inbound event handler method. If fired immediately, the call stack - // will look like this for example: - // - // handlerA.inboundBufferUpdated() - (1) an inbound handler method closes a connection. - // -> handlerA.ctx.close() - // -> channel.unsafe.close() - // -> handlerA.channelInactive() - (2) another inbound handler method called while in (1) yet - // - // which means the execution of two inbound handler methods of the same handler overlap undesirably. - eventLoop().execute(task); - } catch (RejectedExecutionException e) { - logger.warn("Can't invoke task later as EventLoop rejected it", e); - } - } - - /** - * Appends the remote address to the message of the exceptions caused by connection attempt failure. - */ - protected final Throwable annotateConnectException(Throwable cause, SocketAddress remoteAddress) { - if (cause instanceof ConnectException) { - Throwable newT = new ConnectException(cause.getMessage() + ": " + remoteAddress); - newT.setStackTrace(cause.getStackTrace()); - cause = newT; - } else if (cause instanceof NoRouteToHostException) { - Throwable newT = new NoRouteToHostException(cause.getMessage() + ": " + remoteAddress); - newT.setStackTrace(cause.getStackTrace()); - cause = newT; - } else if (cause instanceof SocketException) { - Throwable newT = new SocketException(cause.getMessage() + ": " + remoteAddress); - newT.setStackTrace(cause.getStackTrace()); - cause = newT; - } - - return cause; - } - - /** - * @return {@link Executor} to execute {@link #doClose()} or {@code null} if it should be done in the - * {@link EventLoop}. - + - */ - protected Executor closeExecutor() { - return null; - } - } - - /** - * Return {@code true} if the given {@link EventLoop} is compatible with this instance. - */ - protected abstract boolean isCompatible(EventLoop loop); - - /** - * Returns the {@link SocketAddress} which is bound locally. - */ - protected abstract SocketAddress localAddress0(); - - /** - * Return the {@link SocketAddress} which the {@link Channel} is connected to. - */ - protected abstract SocketAddress remoteAddress0(); - - /** - * Is called after the {@link Channel} is registered with its {@link EventLoop} as part of the register process. - * - * Sub-classes may override this method - */ - protected void doRegister() throws Exception { - // NOOP - } - - /** - * Bind the {@link Channel} to the {@link SocketAddress} - */ - protected abstract void doBind(SocketAddress localAddress) throws Exception; - - /** - * Disconnect this {@link Channel} from its remote peer - */ - protected abstract void doDisconnect() throws Exception; - - /** - * Close the {@link Channel} - */ - protected abstract void doClose() throws Exception; - - /** - * Deregister the {@link Channel} from its {@link EventLoop}. - * - * Sub-classes may override this method - */ - protected void doDeregister() throws Exception { - // NOOP - } - - /** - * Schedule a read operation. - */ - protected abstract void doBeginRead() throws Exception; - - /** - * Flush the content of the given buffer to the remote peer. - */ - protected abstract void doWrite(ChannelOutboundBuffer in) throws Exception; - - /** - * Invoked when a new message is added to a {@link ChannelOutboundBuffer} of this {@link AbstractChannel}, so that - * the {@link Channel} implementation converts the message to another. (e.g. heap buffer -> direct buffer) - */ - protected Object filterOutboundMessage(Object msg) throws Exception { - return msg; - } - - static final class CloseFuture extends DefaultChannelPromise { - - CloseFuture(AbstractChannel ch) { - super(ch); - } - - @Override - public ChannelPromise setSuccess() { - throw new IllegalStateException(); - } - - @Override - public ChannelPromise setFailure(Throwable cause) { - throw new IllegalStateException(); - } - - @Override - public boolean trySuccess() { - throw new IllegalStateException(); - } - - @Override - public boolean tryFailure(Throwable cause) { - throw new IllegalStateException(); - } - - boolean setClosed() { - return super.trySuccess(); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/AbstractChannelHandlerContext.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/AbstractChannelHandlerContext.java deleted file mode 100755 index b868d6b37d..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/AbstractChannelHandlerContext.java +++ /dev/null @@ -1,1063 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.net.SocketAddress; -import java.nio.ByteBuffer; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.WeakHashMap; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.ByteBufAllocator; -import com.ai.cloud.io.netty.buffer.ByteBufHolder; -import com.ai.cloud.io.netty.util.DefaultAttributeMap; -import com.ai.cloud.io.netty.util.Recycler; -import com.ai.cloud.io.netty.util.ReferenceCountUtil; -import com.ai.cloud.io.netty.util.concurrent.EventExecutor; -import com.ai.cloud.io.netty.util.concurrent.EventExecutorGroup; -import com.ai.cloud.io.netty.util.concurrent.FastThreadLocal; -import com.ai.cloud.io.netty.util.internal.OneTimeTask; -import com.ai.cloud.io.netty.util.internal.RecyclableMpscLinkedQueueNode; -import com.ai.cloud.io.netty.util.internal.StringUtil; - -import static com.ai.cloud.io.netty.channel.DefaultChannelPipeline.*; - -abstract class AbstractChannelHandlerContext extends DefaultAttributeMap implements ChannelHandlerContext { - - volatile AbstractChannelHandlerContext next; - volatile AbstractChannelHandlerContext prev; - - private final boolean inbound; - private final boolean outbound; - private final AbstractChannel channel; - private final DefaultChannelPipeline pipeline; - private final String name; - private boolean removed; - - // Will be set to null if no child executor should be used, otherwise it will be set to the - // child executor. - final EventExecutor executor; - private ChannelFuture succeededFuture; - - // Lazily instantiated tasks used to trigger events to a handler with different executor. - // These needs to be volatile as otherwise an other Thread may see an half initialized instance. - // See the JMM for more details - private volatile Runnable invokeChannelReadCompleteTask; - private volatile Runnable invokeReadTask; - private volatile Runnable invokeChannelWritableStateChangedTask; - private volatile Runnable invokeFlushTask; - - AbstractChannelHandlerContext(DefaultChannelPipeline pipeline, EventExecutorGroup group, String name, - boolean inbound, boolean outbound) { - - if (name == null) { - throw new NullPointerException("name"); - } - - channel = pipeline.channel; - this.pipeline = pipeline; - this.name = name; - - if (group != null) { - // Pin one of the child executors once and remember it so that the same child executor - // is used to fire events for the same channel. - EventExecutor childExecutor = pipeline.childExecutors.get(group); - if (childExecutor == null) { - childExecutor = group.next(); - pipeline.childExecutors.put(group, childExecutor); - } - executor = childExecutor; - } else { - executor = null; - } - - this.inbound = inbound; - this.outbound = outbound; - } - - @Override - public Channel channel() { - return channel; - } - - @Override - public ChannelPipeline pipeline() { - return pipeline; - } - - @Override - public ByteBufAllocator alloc() { - return channel().config().getAllocator(); - } - - @Override - public EventExecutor executor() { - if (executor == null) { - return channel().eventLoop(); - } else { - return executor; - } - } - - @Override - public String name() { - return name; - } - - @Override - public ChannelHandlerContext fireChannelRegistered() { - final AbstractChannelHandlerContext next = findContextInbound(); - EventExecutor executor = next.executor(); - if (executor.inEventLoop()) { - next.invokeChannelRegistered(); - } else { - executor.execute(new OneTimeTask() { - @Override - public void run() { - next.invokeChannelRegistered(); - } - }); - } - return this; - } - - private void invokeChannelRegistered() { - try { - ((ChannelInboundHandler) handler()).channelRegistered(this); - } catch (Throwable t) { - notifyHandlerException(t); - } - } - - @Override - public ChannelHandlerContext fireChannelUnregistered() { - final AbstractChannelHandlerContext next = findContextInbound(); - EventExecutor executor = next.executor(); - if (executor.inEventLoop()) { - next.invokeChannelUnregistered(); - } else { - executor.execute(new OneTimeTask() { - @Override - public void run() { - next.invokeChannelUnregistered(); - } - }); - } - return this; - } - - private void invokeChannelUnregistered() { - try { - ((ChannelInboundHandler) handler()).channelUnregistered(this); - } catch (Throwable t) { - notifyHandlerException(t); - } - } - - @Override - public ChannelHandlerContext fireChannelActive() { - final AbstractChannelHandlerContext next = findContextInbound(); - EventExecutor executor = next.executor(); - if (executor.inEventLoop()) { - next.invokeChannelActive(); - } else { - executor.execute(new OneTimeTask() { - @Override - public void run() { - next.invokeChannelActive(); - } - }); - } - return this; - } - - private void invokeChannelActive() { - try { - ((ChannelInboundHandler) handler()).channelActive(this); - } catch (Throwable t) { - notifyHandlerException(t); - } - } - - @Override - public ChannelHandlerContext fireChannelInactive() { - final AbstractChannelHandlerContext next = findContextInbound(); - EventExecutor executor = next.executor(); - if (executor.inEventLoop()) { - next.invokeChannelInactive(); - } else { - executor.execute(new OneTimeTask() { - @Override - public void run() { - next.invokeChannelInactive(); - } - }); - } - return this; - } - - private void invokeChannelInactive() { - try { - ((ChannelInboundHandler) handler()).channelInactive(this); - } catch (Throwable t) { - notifyHandlerException(t); - } - } - - @Override - public ChannelHandlerContext fireExceptionCaught(final Throwable cause) { - if (cause == null) { - throw new NullPointerException("cause"); - } - - final AbstractChannelHandlerContext next = this.next; - - EventExecutor executor = next.executor(); - if (executor.inEventLoop()) { - next.invokeExceptionCaught(cause); - } else { - try { - executor.execute(new OneTimeTask() { - @Override - public void run() { - next.invokeExceptionCaught(cause); - } - }); - } catch (Throwable t) { - if (logger.isWarnEnabled()) { - logger.warn("Failed to submit an exceptionCaught() event.", t); - logger.warn("The exceptionCaught() event that was failed to submit was:", cause); - } - } - } - - return this; - } - - private void invokeExceptionCaught(final Throwable cause) { - try { - handler().exceptionCaught(this, cause); - } catch (Throwable t) { - if (logger.isWarnEnabled()) { - logger.warn( - "An exception was thrown by a user handler's " + - "exceptionCaught() method while handling the following exception:", cause); - } - } - } - - @Override - public ChannelHandlerContext fireUserEventTriggered(final Object event) { - if (event == null) { - throw new NullPointerException("event"); - } - - final AbstractChannelHandlerContext next = findContextInbound(); - EventExecutor executor = next.executor(); - if (executor.inEventLoop()) { - next.invokeUserEventTriggered(event); - } else { - executor.execute(new OneTimeTask() { - @Override - public void run() { - next.invokeUserEventTriggered(event); - } - }); - } - return this; - } - - private void invokeUserEventTriggered(Object event) { - try { - ((ChannelInboundHandler) handler()).userEventTriggered(this, event); - } catch (Throwable t) { - notifyHandlerException(t); - } - } - - @Override - public ChannelHandlerContext fireChannelRead(final Object msg) { - if (msg == null) { - throw new NullPointerException("msg"); - } - - final AbstractChannelHandlerContext next = findContextInbound(); - EventExecutor executor = next.executor(); - if (executor.inEventLoop()) { - next.invokeChannelRead(msg); - } else { - executor.execute(new OneTimeTask() { - @Override - public void run() { - next.invokeChannelRead(msg); - } - }); - } - return this; - } - - private void invokeChannelRead(Object msg) { - try { - ((ChannelInboundHandler) handler()).channelRead(this, msg); - } catch (Throwable t) { - notifyHandlerException(t); - } - } - - @Override - public ChannelHandlerContext fireChannelReadComplete() { - final AbstractChannelHandlerContext next = findContextInbound(); - EventExecutor executor = next.executor(); - if (executor.inEventLoop()) { - next.invokeChannelReadComplete(); - } else { - Runnable task = next.invokeChannelReadCompleteTask; - if (task == null) { - next.invokeChannelReadCompleteTask = task = new Runnable() { - @Override - public void run() { - next.invokeChannelReadComplete(); - } - }; - } - executor.execute(task); - } - return this; - } - - private void invokeChannelReadComplete() { - try { - ((ChannelInboundHandler) handler()).channelReadComplete(this); - } catch (Throwable t) { - notifyHandlerException(t); - } - } - - @Override - public ChannelHandlerContext fireChannelWritabilityChanged() { - final AbstractChannelHandlerContext next = findContextInbound(); - EventExecutor executor = next.executor(); - if (executor.inEventLoop()) { - next.invokeChannelWritabilityChanged(); - } else { - Runnable task = next.invokeChannelWritableStateChangedTask; - if (task == null) { - next.invokeChannelWritableStateChangedTask = task = new Runnable() { - @Override - public void run() { - next.invokeChannelWritabilityChanged(); - } - }; - } - executor.execute(task); - } - return this; - } - - private void invokeChannelWritabilityChanged() { - try { - ((ChannelInboundHandler) handler()).channelWritabilityChanged(this); - } catch (Throwable t) { - notifyHandlerException(t); - } - } - - @Override - public ChannelFuture bind(SocketAddress localAddress) { - return bind(localAddress, newPromise()); - } - - @Override - public ChannelFuture connect(SocketAddress remoteAddress) { - return connect(remoteAddress, newPromise()); - } - - @Override - public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress) { - return connect(remoteAddress, localAddress, newPromise()); - } - - @Override - public ChannelFuture disconnect() { - return disconnect(newPromise()); - } - - @Override - public ChannelFuture close() { - return close(newPromise()); - } - - @Override - public ChannelFuture deregister() { - return deregister(newPromise()); - } - - @Override - public ChannelFuture bind(final SocketAddress localAddress, final ChannelPromise promise) { - if (localAddress == null) { - throw new NullPointerException("localAddress"); - } - if (!validatePromise(promise, false)) { - // cancelled - return promise; - } - - final AbstractChannelHandlerContext next = findContextOutbound(); - EventExecutor executor = next.executor(); - if (executor.inEventLoop()) { - next.invokeBind(localAddress, promise); - } else { - safeExecute(executor, new OneTimeTask() { - @Override - public void run() { - next.invokeBind(localAddress, promise); - } - }, promise, null); - } - - return promise; - } - - private void invokeBind(SocketAddress localAddress, ChannelPromise promise) { - try { - ((ChannelOutboundHandler) handler()).bind(this, localAddress, promise); - } catch (Throwable t) { - notifyOutboundHandlerException(t, promise); - } - } - - @Override - public ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise) { - return connect(remoteAddress, null, promise); - } - - @Override - public ChannelFuture connect( - final SocketAddress remoteAddress, final SocketAddress localAddress, final ChannelPromise promise) { - - if (remoteAddress == null) { - throw new NullPointerException("remoteAddress"); - } - if (!validatePromise(promise, false)) { - // cancelled - return promise; - } - - final AbstractChannelHandlerContext next = findContextOutbound(); - EventExecutor executor = next.executor(); - if (executor.inEventLoop()) { - next.invokeConnect(remoteAddress, localAddress, promise); - } else { - safeExecute(executor, new OneTimeTask() { - @Override - public void run() { - next.invokeConnect(remoteAddress, localAddress, promise); - } - }, promise, null); - } - - return promise; - } - - private void invokeConnect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) { - try { - ((ChannelOutboundHandler) handler()).connect(this, remoteAddress, localAddress, promise); - } catch (Throwable t) { - notifyOutboundHandlerException(t, promise); - } - } - - @Override - public ChannelFuture disconnect(final ChannelPromise promise) { - if (!validatePromise(promise, false)) { - // cancelled - return promise; - } - - final AbstractChannelHandlerContext next = findContextOutbound(); - EventExecutor executor = next.executor(); - if (executor.inEventLoop()) { - // Translate disconnect to close if the channel has no notion of disconnect-reconnect. - // So far, UDP/IP is the only transport that has such behavior. - if (!channel().metadata().hasDisconnect()) { - next.invokeClose(promise); - } else { - next.invokeDisconnect(promise); - } - } else { - safeExecute(executor, new OneTimeTask() { - @Override - public void run() { - if (!channel().metadata().hasDisconnect()) { - next.invokeClose(promise); - } else { - next.invokeDisconnect(promise); - } - } - }, promise, null); - } - - return promise; - } - - private void invokeDisconnect(ChannelPromise promise) { - try { - ((ChannelOutboundHandler) handler()).disconnect(this, promise); - } catch (Throwable t) { - notifyOutboundHandlerException(t, promise); - } - } - - @Override - public ChannelFuture close(final ChannelPromise promise) { - if (!validatePromise(promise, false)) { - // cancelled - return promise; - } - - final AbstractChannelHandlerContext next = findContextOutbound(); - EventExecutor executor = next.executor(); - if (executor.inEventLoop()) { - next.invokeClose(promise); - } else { - safeExecute(executor, new OneTimeTask() { - @Override - public void run() { - next.invokeClose(promise); - } - }, promise, null); - } - - return promise; - } - - private void invokeClose(ChannelPromise promise) { - try { - ((ChannelOutboundHandler) handler()).close(this, promise); - } catch (Throwable t) { - notifyOutboundHandlerException(t, promise); - } - } - - @Override - public ChannelFuture deregister(final ChannelPromise promise) { - if (!validatePromise(promise, false)) { - // cancelled - return promise; - } - - final AbstractChannelHandlerContext next = findContextOutbound(); - EventExecutor executor = next.executor(); - if (executor.inEventLoop()) { - next.invokeDeregister(promise); - } else { - safeExecute(executor, new OneTimeTask() { - @Override - public void run() { - next.invokeDeregister(promise); - } - }, promise, null); - } - - return promise; - } - - private void invokeDeregister(ChannelPromise promise) { - try { - ((ChannelOutboundHandler) handler()).deregister(this, promise); - } catch (Throwable t) { - notifyOutboundHandlerException(t, promise); - } - } - - @Override - public ChannelHandlerContext read() { - final AbstractChannelHandlerContext next = findContextOutbound(); - EventExecutor executor = next.executor(); - if (executor.inEventLoop()) { - next.invokeRead(); - } else { - Runnable task = next.invokeReadTask; - if (task == null) { - next.invokeReadTask = task = new Runnable() { - @Override - public void run() { - next.invokeRead(); - } - }; - } - executor.execute(task); - } - - return this; - } - - private void invokeRead() { - try { - ((ChannelOutboundHandler) handler()).read(this); - } catch (Throwable t) { - notifyHandlerException(t); - } - } - - @Override - public ChannelFuture write(Object msg) { - return write(msg, newPromise()); - } - - @Override - public ChannelFuture write(final Object msg, final ChannelPromise promise) { - if (msg == null) { - throw new NullPointerException("msg"); - } - - if (!validatePromise(promise, true)) { - ReferenceCountUtil.release(msg); - // cancelled - return promise; - } - write(msg, false, promise); - - return promise; - } - - private void invokeWrite(Object msg, ChannelPromise promise) { - try { - ((ChannelOutboundHandler) handler()).write(this, msg, promise); - } catch (Throwable t) { - notifyOutboundHandlerException(t, promise); - } - } - - @Override - public ChannelHandlerContext flush() { - final AbstractChannelHandlerContext next = findContextOutbound(); - EventExecutor executor = next.executor(); - if (executor.inEventLoop()) { - next.invokeFlush(); - } else { - Runnable task = next.invokeFlushTask; - if (task == null) { - next.invokeFlushTask = task = new Runnable() { - @Override - public void run() { - next.invokeFlush(); - } - }; - } - safeExecute(executor, task, channel.voidPromise(), null); - } - - return this; - } - - private void invokeFlush() { - try { - ((ChannelOutboundHandler) handler()).flush(this); - } catch (Throwable t) { - notifyHandlerException(t); - } - } - - @Override - public ChannelFuture writeAndFlush(Object msg, ChannelPromise promise) { - if (msg == null) { - throw new NullPointerException("msg"); - } - - if (!validatePromise(promise, true)) { - ReferenceCountUtil.release(msg); - // cancelled - return promise; - } - - write(msg, true, promise); - - return promise; - } - - private void write(Object msg, boolean flush, ChannelPromise promise) { - AbstractChannelHandlerContext next = findContextOutbound(); - EventExecutor executor = next.executor(); - if (executor.inEventLoop()) { - next.invokeWrite(msg, promise); - if (flush) { - next.invokeFlush(); - } - } else { - AbstractWriteTask task; - if (flush) { - task = WriteAndFlushTask.newInstance(next, msg, promise); - } else { - task = WriteTask.newInstance(next, msg, promise); - } - safeExecute(executor, task, promise, msg); - } - } - - @Override - public ChannelFuture writeAndFlush(Object msg) { - return writeAndFlush(msg, newPromise()); - } - - private static void notifyOutboundHandlerException(Throwable cause, ChannelPromise promise) { - if (!promise.tryFailure(cause) && !(promise instanceof VoidChannelPromise)) { - if (logger.isWarnEnabled()) { - logger.warn("Failed to fail the promise because it's done already: {}", promise, cause); - } - } - } - - private void notifyHandlerException(Throwable cause) { - if (inExceptionCaught(cause)) { - if (logger.isWarnEnabled()) { - logger.warn( - "An exception was thrown by a user handler " + - "while handling an exceptionCaught event", cause); - } - return; - } - - invokeExceptionCaught(cause); - } - - private static boolean inExceptionCaught(Throwable cause) { - do { - StackTraceElement[] trace = cause.getStackTrace(); - if (trace != null) { - for (StackTraceElement t : trace) { - if (t == null) { - break; - } - if ("exceptionCaught".equals(t.getMethodName())) { - return true; - } - } - } - - cause = cause.getCause(); - } while (cause != null); - - return false; - } - - @Override - public ChannelPromise newPromise() { - return new DefaultChannelPromise(channel(), executor()); - } - - @Override - public ChannelProgressivePromise newProgressivePromise() { - return new DefaultChannelProgressivePromise(channel(), executor()); - } - - @Override - public ChannelFuture newSucceededFuture() { - ChannelFuture succeededFuture = this.succeededFuture; - if (succeededFuture == null) { - this.succeededFuture = succeededFuture = new SucceededChannelFuture(channel(), executor()); - } - return succeededFuture; - } - - @Override - public ChannelFuture newFailedFuture(Throwable cause) { - return new FailedChannelFuture(channel(), executor(), cause); - } - - private boolean validatePromise(ChannelPromise promise, boolean allowVoidPromise) { - if (promise == null) { - throw new NullPointerException("promise"); - } - - if (promise.isDone()) { - // Check if the promise was cancelled and if so signal that the processing of the operation - // should not be performed. - // - // See https://github.com/netty/netty/issues/2349 - if (promise.isCancelled()) { - return false; - } - throw new IllegalArgumentException("promise already done: " + promise); - } - - if (promise.channel() != channel()) { - throw new IllegalArgumentException(String.format( - "promise.channel does not match: %s (expected: %s)", promise.channel(), channel())); - } - - if (promise.getClass() == DefaultChannelPromise.class) { - return true; - } - - if (!allowVoidPromise && promise instanceof VoidChannelPromise) { - throw new IllegalArgumentException( - StringUtil.simpleClassName(VoidChannelPromise.class) + " not allowed for this operation"); - } - - if (promise instanceof AbstractChannel.CloseFuture) { - throw new IllegalArgumentException( - StringUtil.simpleClassName(AbstractChannel.CloseFuture.class) + " not allowed in a pipeline"); - } - return true; - } - - private AbstractChannelHandlerContext findContextInbound() { - AbstractChannelHandlerContext ctx = this; - do { - ctx = ctx.next; - } while (!ctx.inbound); - return ctx; - } - - private AbstractChannelHandlerContext findContextOutbound() { - AbstractChannelHandlerContext ctx = this; - do { - ctx = ctx.prev; - } while (!ctx.outbound); - return ctx; - } - - @Override - public ChannelPromise voidPromise() { - return channel.voidPromise(); - } - - void setRemoved() { - removed = true; - } - - @Override - public boolean isRemoved() { - return removed; - } - - private static void safeExecute(EventExecutor executor, Runnable runnable, ChannelPromise promise, Object msg) { - try { - executor.execute(runnable); - } catch (Throwable cause) { - try { - promise.setFailure(cause); - } finally { - if (msg != null) { - ReferenceCountUtil.release(msg); - } - } - } - } - - abstract static class AbstractWriteTask extends RecyclableMpscLinkedQueueNode implements Runnable { - - private static final FastThreadLocal, Integer>> CLASS_SIZES = - new FastThreadLocal, Integer>>() { - @Override - protected Map, Integer> initialValue() throws Exception { - Map, Integer> map = new WeakHashMap, Integer>(); - map.put(void.class, 0); - map.put(byte.class, 1); - map.put(char.class, 2); - map.put(short.class, 2); - map.put(boolean.class, 4); // Probably an integer. - map.put(int.class, 4); - map.put(float.class, 4); - map.put(long.class, 8); - map.put(double.class, 8); - return map; - } - }; - - private AbstractChannelHandlerContext ctx; - private Object msg; - private ChannelPromise promise; - private int size; - - private AbstractWriteTask(Recycler.Handle handle) { - super(handle); - } - - private static int estimateSize(Object o, Map, Integer> classSizes) { - int answer = 8 + estimateSize(o.getClass(), classSizes, null); - - if (o instanceof ByteBuf) { - answer += ((ByteBuf) o).readableBytes(); - } else if (o instanceof ByteBufHolder) { - answer += ((ByteBufHolder) o).content().readableBytes(); - } else if (o instanceof FileRegion) { - // nothing to add. - } else if (o instanceof byte[]) { - answer += ((byte[]) o).length; - } else if (o instanceof ByteBuffer) { - answer += ((ByteBuffer) o).remaining(); - } else if (o instanceof CharSequence) { - answer += ((CharSequence) o).length() << 1; - } else if (o instanceof Iterable) { - for (Object m : (Iterable) o) { - answer += estimateSize(m, classSizes); - } - } - - return align(answer); - } - - private static int estimateSize(Class clazz, Map, Integer> classSizes, - Set> visitedClasses) { - Integer objectSize = classSizes.get(clazz); - if (objectSize != null) { - return objectSize; - } - - if (visitedClasses != null) { - if (visitedClasses.contains(clazz)) { - return 0; - } - } else { - visitedClasses = new HashSet>(); - } - - visitedClasses.add(clazz); - - int answer = 8; // Basic overhead. - for (Class c = clazz; c != null; c = c.getSuperclass()) { - Field[] fields = c.getDeclaredFields(); - for (Field f : fields) { - if ((f.getModifiers() & Modifier.STATIC) != 0) { - // Ignore static fields. - continue; - } - - answer += estimateSize(f.getType(), classSizes, visitedClasses); - } - } - - visitedClasses.remove(clazz); - - // Some alignment. - answer = align(answer); - - // Put the final answer. - classSizes.put(clazz, answer); - return answer; - } - - private static int align(int size) { - return size + 8 - (size & 7); - } - - protected static void init(AbstractWriteTask task, AbstractChannelHandlerContext ctx, - Object msg, ChannelPromise promise) { - task.ctx = ctx; - task.msg = msg; - task.promise = promise; - task.size = ctx.channel.estimatorHandle().size(msg) + estimateSize(task, CLASS_SIZES.get()); - - ChannelOutboundBuffer buffer = ctx.channel.unsafe().outboundBuffer(); - // Check for null as it may be set to null if the channel is closed already - if (buffer != null) { - buffer.incrementPendingOutboundBytes(task.size); - } - } - - @Override - public final void run() { - try { - if (size > 0) { - ChannelOutboundBuffer buffer = ctx.channel.unsafe().outboundBuffer(); - // Check for null as it may be set to null if the channel is closed already - if (buffer != null) { - buffer.decrementPendingOutboundBytes(size); - } - } - write(ctx, msg, promise); - } finally { - // Set to null so the GC can collect them directly - ctx = null; - msg = null; - promise = null; - } - } - - @Override - public Runnable value() { - return this; - } - - protected void write(AbstractChannelHandlerContext ctx, Object msg, ChannelPromise promise) { - ctx.invokeWrite(msg, promise); - } - } - - static final class WriteTask extends AbstractWriteTask implements SingleThreadEventLoop.NonWakeupRunnable { - - private static final Recycler RECYCLER = new Recycler() { - @Override - protected WriteTask newObject(Handle handle) { - return new WriteTask(handle); - } - }; - - private static WriteTask newInstance( - AbstractChannelHandlerContext ctx, Object msg, ChannelPromise promise) { - WriteTask task = RECYCLER.get(); - init(task, ctx, msg, promise); - return task; - } - - private WriteTask(Recycler.Handle handle) { - super(handle); - } - - @Override - protected void recycle(Recycler.Handle handle) { - RECYCLER.recycle(this, handle); - } - } - - static final class WriteAndFlushTask extends AbstractWriteTask { - - private static final Recycler RECYCLER = new Recycler() { - @Override - protected WriteAndFlushTask newObject(Handle handle) { - return new WriteAndFlushTask(handle); - } - }; - - private static WriteAndFlushTask newInstance( - AbstractChannelHandlerContext ctx, Object msg, ChannelPromise promise) { - WriteAndFlushTask task = RECYCLER.get(); - init(task, ctx, msg, promise); - return task; - } - - private WriteAndFlushTask(Recycler.Handle handle) { - super(handle); - } - - @Override - public void write(AbstractChannelHandlerContext ctx, Object msg, ChannelPromise promise) { - super.write(ctx, msg, promise); - ctx.invokeFlush(); - } - - @Override - protected void recycle(Recycler.Handle handle) { - RECYCLER.recycle(this, handle); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/AbstractServerChannel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/AbstractServerChannel.java deleted file mode 100755 index 01285c8f8c..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/AbstractServerChannel.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import java.net.SocketAddress; - -import com.ai.cloud.io.netty.util.internal.EmptyArrays; - -/** - * A skeletal server-side {@link Channel} implementation. A server-side - * {@link Channel} does not allow the following operations: - *
    - *
  • {@link #connect(SocketAddress, ChannelPromise)}
  • - *
  • {@link #disconnect(ChannelPromise)}
  • - *
  • {@link #write(Object, ChannelPromise)}
  • - *
  • {@link #flush()}
  • - *
  • and the shortcut methods which calls the methods mentioned above - *
- */ -public abstract class AbstractServerChannel extends AbstractChannel implements ServerChannel { - - private static final ChannelMetadata METADATA = new ChannelMetadata(false); - - /** - * Creates a new instance. - */ - protected AbstractServerChannel() { - super(null); - } - - @Override - public ChannelMetadata metadata() { - return METADATA; - } - - @Override - public SocketAddress remoteAddress() { - return null; - } - - @Override - protected SocketAddress remoteAddress0() { - return null; - } - - @Override - protected void doDisconnect() throws Exception { - throw new UnsupportedOperationException(); - } - - @Override - protected AbstractUnsafe newUnsafe() { - return new DefaultServerUnsafe(); - } - - @Override - protected void doWrite(ChannelOutboundBuffer in) throws Exception { - throw new UnsupportedOperationException(); - } - - @Override - protected final Object filterOutboundMessage(Object msg) { - throw new UnsupportedOperationException(); - } - - private final class DefaultServerUnsafe extends AbstractUnsafe { - @Override - public void connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) { - safeSetFailure(promise, new UnsupportedOperationException()); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/AdaptiveRecvByteBufAllocator.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/AdaptiveRecvByteBufAllocator.java deleted file mode 100755 index c762d404cc..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/AdaptiveRecvByteBufAllocator.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import java.util.ArrayList; -import java.util.List; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.ByteBufAllocator; - -/** - * The {@link RecvByteBufAllocator} that automatically increases and - * decreases the predicted buffer size on feed back. - *

- * It gradually increases the expected number of readable bytes if the previous - * read fully filled the allocated buffer. It gradually decreases the expected - * number of readable bytes if the read operation was not able to fill a certain - * amount of the allocated buffer two times consecutively. Otherwise, it keeps - * returning the same prediction. - */ -public class AdaptiveRecvByteBufAllocator implements RecvByteBufAllocator { - - static final int DEFAULT_MINIMUM = 64; - static final int DEFAULT_INITIAL = 1024; - static final int DEFAULT_MAXIMUM = 65536; - - private static final int INDEX_INCREMENT = 4; - private static final int INDEX_DECREMENT = 1; - - private static final int[] SIZE_TABLE; - - static { - List sizeTable = new ArrayList(); - for (int i = 16; i < 512; i += 16) { - sizeTable.add(i); - } - - for (int i = 512; i > 0; i <<= 1) { - sizeTable.add(i); - } - - SIZE_TABLE = new int[sizeTable.size()]; - for (int i = 0; i < SIZE_TABLE.length; i ++) { - SIZE_TABLE[i] = sizeTable.get(i); - } - } - - public static final AdaptiveRecvByteBufAllocator DEFAULT = new AdaptiveRecvByteBufAllocator(); - - private static int getSizeTableIndex(final int size) { - for (int low = 0, high = SIZE_TABLE.length - 1;;) { - if (high < low) { - return low; - } - if (high == low) { - return high; - } - - int mid = low + high >>> 1; - int a = SIZE_TABLE[mid]; - int b = SIZE_TABLE[mid + 1]; - if (size > b) { - low = mid + 1; - } else if (size < a) { - high = mid - 1; - } else if (size == a) { - return mid; - } else { - return mid + 1; - } - } - } - - private static final class HandleImpl implements Handle { - private final int minIndex; - private final int maxIndex; - private int index; - private int nextReceiveBufferSize; - private boolean decreaseNow; - - HandleImpl(int minIndex, int maxIndex, int initial) { - this.minIndex = minIndex; - this.maxIndex = maxIndex; - - index = getSizeTableIndex(initial); - nextReceiveBufferSize = SIZE_TABLE[index]; - } - - @Override - public ByteBuf allocate(ByteBufAllocator alloc) { - return alloc.ioBuffer(nextReceiveBufferSize); - } - - @Override - public int guess() { - return nextReceiveBufferSize; - } - - @Override - public void record(int actualReadBytes) { - if (actualReadBytes <= SIZE_TABLE[Math.max(0, index - INDEX_DECREMENT - 1)]) { - if (decreaseNow) { - index = Math.max(index - INDEX_DECREMENT, minIndex); - nextReceiveBufferSize = SIZE_TABLE[index]; - decreaseNow = false; - } else { - decreaseNow = true; - } - } else if (actualReadBytes >= nextReceiveBufferSize) { - index = Math.min(index + INDEX_INCREMENT, maxIndex); - nextReceiveBufferSize = SIZE_TABLE[index]; - decreaseNow = false; - } - } - } - - private final int minIndex; - private final int maxIndex; - private final int initial; - - /** - * Creates a new predictor with the default parameters. With the default - * parameters, the expected buffer size starts from {@code 1024}, does not - * go down below {@code 64}, and does not go up above {@code 65536}. - */ - private AdaptiveRecvByteBufAllocator() { - this(DEFAULT_MINIMUM, DEFAULT_INITIAL, DEFAULT_MAXIMUM); - } - - /** - * Creates a new predictor with the specified parameters. - * - * @param minimum the inclusive lower bound of the expected buffer size - * @param initial the initial buffer size when no feed back was received - * @param maximum the inclusive upper bound of the expected buffer size - */ - public AdaptiveRecvByteBufAllocator(int minimum, int initial, int maximum) { - if (minimum <= 0) { - throw new IllegalArgumentException("minimum: " + minimum); - } - if (initial < minimum) { - throw new IllegalArgumentException("initial: " + initial); - } - if (maximum < initial) { - throw new IllegalArgumentException("maximum: " + maximum); - } - - int minIndex = getSizeTableIndex(minimum); - if (SIZE_TABLE[minIndex] < minimum) { - this.minIndex = minIndex + 1; - } else { - this.minIndex = minIndex; - } - - int maxIndex = getSizeTableIndex(maximum); - if (SIZE_TABLE[maxIndex] > maximum) { - this.maxIndex = maxIndex - 1; - } else { - this.maxIndex = maxIndex; - } - - this.initial = initial; - } - - @Override - public Handle newHandle() { - return new HandleImpl(minIndex, maxIndex, initial); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/AddressedEnvelope.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/AddressedEnvelope.java deleted file mode 100755 index 31ddb3bf60..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/AddressedEnvelope.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.channel; - -import java.net.SocketAddress; - -import com.ai.cloud.io.netty.util.ReferenceCounted; - -/** - * A message that wraps another message with a sender address and a recipient address. - * - * @param the type of the wrapped message - * @param the type of the address - */ -public interface AddressedEnvelope extends ReferenceCounted { - /** - * Returns the message wrapped by this envelope message. - */ - M content(); - - /** - * Returns the address of the sender of this message. - */ - A sender(); - - /** - * Returns the address of the recipient of this message. - */ - A recipient(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/Channel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/Channel.java deleted file mode 100755 index 3549dd0b4f..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/Channel.java +++ /dev/null @@ -1,520 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import java.net.ConnectException; -import java.net.InetSocketAddress; -import java.net.SocketAddress; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.ByteBufAllocator; -import com.ai.cloud.io.netty.channel.socket.DatagramChannel; -import com.ai.cloud.io.netty.channel.socket.DatagramPacket; -import com.ai.cloud.io.netty.channel.socket.ServerSocketChannel; -import com.ai.cloud.io.netty.channel.socket.SocketChannel; -import com.ai.cloud.io.netty.util.AttributeMap; -import com.ai.cloud.io.netty.util.concurrent.EventExecutor; -import com.ai.cloud.io.netty.util.concurrent.FutureListener; - - -/** - * A nexus to a network socket or a component which is capable of I/O - * operations such as read, write, connect, and bind. - *

- * A channel provides a user: - *

- * - *

All I/O operations are asynchronous.

- *

- * All I/O operations in Netty are asynchronous. It means any I/O calls will - * return immediately with no guarantee that the requested I/O operation has - * been completed at the end of the call. Instead, you will be returned with - * a {@link ChannelFuture} instance which will notify you when the requested I/O - * operation has succeeded, failed, or canceled. - * - *

Channels are hierarchical

- *

- * A {@link Channel} can have a {@linkplain #parent() parent} depending on - * how it was created. For instance, a {@link SocketChannel}, that was accepted - * by {@link ServerSocketChannel}, will return the {@link ServerSocketChannel} - * as its parent on {@link #parent()}. - *

- * The semantics of the hierarchical structure depends on the transport - * implementation where the {@link Channel} belongs to. For example, you could - * write a new {@link Channel} implementation that creates the sub-channels that - * share one socket connection, as BEEP and - * SSH do. - * - *

Downcast to access transport-specific operations

- *

- * Some transports exposes additional operations that is specific to the - * transport. Down-cast the {@link Channel} to sub-type to invoke such - * operations. For example, with the old I/O datagram transport, multicast - * join / leave operations are provided by {@link DatagramChannel}. - * - *

Release resources

- *

- * It is important to call {@link #close()} or {@link #close(ChannelPromise)} to release all - * resources once you are done with the {@link Channel}. This ensures all resources are - * released in a proper way, i.e. filehandles. - */ -public interface Channel extends AttributeMap, Comparable { - - /** - * Return the {@link EventLoop} this {@link Channel} was registered to. - */ - EventLoop eventLoop(); - - /** - * Returns the parent of this channel. - * - * @return the parent channel. - * {@code null} if this channel does not have a parent channel. - */ - Channel parent(); - - /** - * Returns the configuration of this channel. - */ - ChannelConfig config(); - - /** - * Returns {@code true} if the {@link Channel} is open and may get active later - */ - boolean isOpen(); - - /** - * Returns {@code true} if the {@link Channel} is registered with an {@link EventLoop}. - */ - boolean isRegistered(); - - /** - * Return {@code true} if the {@link Channel} is active and so connected. - */ - boolean isActive(); - - /** - * Return the {@link ChannelMetadata} of the {@link Channel} which describe the nature of the {@link Channel}. - */ - ChannelMetadata metadata(); - - /** - * Returns the local address where this channel is bound to. The returned - * {@link SocketAddress} is supposed to be down-cast into more concrete - * type such as {@link InetSocketAddress} to retrieve the detailed - * information. - * - * @return the local address of this channel. - * {@code null} if this channel is not bound. - */ - SocketAddress localAddress(); - - /** - * Returns the remote address where this channel is connected to. The - * returned {@link SocketAddress} is supposed to be down-cast into more - * concrete type such as {@link InetSocketAddress} to retrieve the detailed - * information. - * - * @return the remote address of this channel. - * {@code null} if this channel is not connected. - * If this channel is not connected but it can receive messages - * from arbitrary remote addresses (e.g. {@link DatagramChannel}, - * use {@link DatagramPacket#recipient()} to determine - * the origination of the received message as this method will - * return {@code null}. - */ - SocketAddress remoteAddress(); - - /** - * Returns the {@link ChannelFuture} which will be notified when this - * channel is closed. This method always returns the same future instance. - */ - ChannelFuture closeFuture(); - - /** - * Returns {@code true} if and only if the I/O thread will perform the - * requested write operation immediately. Any write requests made when - * this method returns {@code false} are queued until the I/O thread is - * ready to process the queued write requests. - */ - boolean isWritable(); - - /** - * Returns an internal-use-only object that provides unsafe operations. - */ - Unsafe unsafe(); - - /** - * Return the assigned {@link ChannelPipeline}. - */ - ChannelPipeline pipeline(); - - /** - * Return the assigned {@link ByteBufAllocator} which will be used to allocate {@link ByteBuf}s. - */ - ByteBufAllocator alloc(); - - /** - * Return a new {@link ChannelPromise}. - */ - ChannelPromise newPromise(); - - /** - * Return an new {@link ChannelProgressivePromise}. - */ - ChannelProgressivePromise newProgressivePromise(); - - /** - * Create a new {@link ChannelFuture} which is marked as succeeded already. So {@link ChannelFuture#isSuccess()} - * will return {@code true}. All {@link FutureListener} added to it will be notified directly. Also - * every call of blocking methods will just return without blocking. - */ - ChannelFuture newSucceededFuture(); - - /** - * Create a new {@link ChannelFuture} which is marked as failed already. So {@link ChannelFuture#isSuccess()} - * will return {@code false}. All {@link FutureListener} added to it will be notified directly. Also - * every call of blocking methods will just return without blocking. - */ - ChannelFuture newFailedFuture(Throwable cause); - - /** - * Return a special ChannelPromise which can be reused for different operations. - *

- * It's only supported to use - * it for {@link Channel#write(Object, ChannelPromise)}. - *

- *

- * Be aware that the returned {@link ChannelPromise} will not support most operations and should only be used - * if you want to save an object allocation for every write operation. You will not be able to detect if the - * operation was complete, only if it failed as the implementation will call - * {@link ChannelPipeline#fireExceptionCaught(Throwable)} in this case. - *

- * Be aware this is an expert feature and should be used with care! - */ - ChannelPromise voidPromise(); - - /** - * Request to bind to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation - * completes, either because the operation was successful or because of an error. - *

- * This will result in having the - * {@link ChannelOutboundHandler#bind(ChannelHandlerContext, SocketAddress, ChannelPromise)} method - * called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture bind(SocketAddress localAddress); - - /** - * Request to connect to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation - * completes, either because the operation was successful or because of an error. - *

- * If the connection fails because of a connection timeout, the {@link ChannelFuture} will get failed with - * a {@link ConnectTimeoutException}. If it fails because of connection refused a {@link ConnectException} - * will be used. - *

- * This will result in having the - * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture connect(SocketAddress remoteAddress); - - /** - * Request to connect to the given {@link SocketAddress} while bind to the localAddress and notify the - * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of - * an error. - *

- * This will result in having the - * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress); - - /** - * Request to disconnect from the remote peer and notify the {@link ChannelFuture} once the operation completes, - * either because the operation was successful or because of an error. - *

- * This will result in having the - * {@link ChannelOutboundHandler#disconnect(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture disconnect(); - - /** - * Request to close this {@link Channel} and notify the {@link ChannelFuture} once the operation completes, - * either because the operation was successful or because of - * an error. - * - * After it is closed it is not possible to reuse it again. - *

- * This will result in having the - * {@link ChannelOutboundHandler#close(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture close(); - - /** - * Request to deregister this {@link Channel} from the previous assigned {@link EventExecutor} and notify the - * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of - * an error. - *

- * This will result in having the - * {@link ChannelOutboundHandler#deregister(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - * - */ - ChannelFuture deregister(); - - /** - * Request to bind to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation - * completes, either because the operation was successful or because of an error. - * - * The given {@link ChannelPromise} will be notified. - *

- * This will result in having the - * {@link ChannelOutboundHandler#bind(ChannelHandlerContext, SocketAddress, ChannelPromise)} method - * called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise); - - /** - * Request to connect to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation - * completes, either because the operation was successful or because of an error. - * - * The given {@link ChannelFuture} will be notified. - * - *

- * If the connection fails because of a connection timeout, the {@link ChannelFuture} will get failed with - * a {@link ConnectTimeoutException}. If it fails because of connection refused a {@link ConnectException} - * will be used. - *

- * This will result in having the - * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise); - - /** - * Request to connect to the given {@link SocketAddress} while bind to the localAddress and notify the - * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of - * an error. - * - * The given {@link ChannelPromise} will be notified and also returned. - *

- * This will result in having the - * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise); - - /** - * Request to disconnect from the remote peer and notify the {@link ChannelFuture} once the operation completes, - * either because the operation was successful or because of an error. - * - * The given {@link ChannelPromise} will be notified. - *

- * This will result in having the - * {@link ChannelOutboundHandler#disconnect(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture disconnect(ChannelPromise promise); - - /** - * Request to close this {@link Channel} and notify the {@link ChannelFuture} once the operation completes, - * either because the operation was successful or because of - * an error. - * - * After it is closed it is not possible to reuse it again. - * The given {@link ChannelPromise} will be notified. - *

- * This will result in having the - * {@link ChannelOutboundHandler#close(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture close(ChannelPromise promise); - - /** - * Request to deregister this {@link Channel} from the previous assigned {@link EventExecutor} and notify the - * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of - * an error. - * - * The given {@link ChannelPromise} will be notified. - *

- * This will result in having the - * {@link ChannelOutboundHandler#deregister(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture deregister(ChannelPromise promise); - - /** - * Request to Read data from the {@link Channel} into the first inbound buffer, triggers an - * {@link ChannelInboundHandler#channelRead(ChannelHandlerContext, Object)} event if data was - * read, and triggers a - * {@link ChannelInboundHandler#channelReadComplete(ChannelHandlerContext) channelReadComplete} event so the - * handler can decide to continue reading. If there's a pending read operation already, this method does nothing. - *

- * This will result in having the - * {@link ChannelOutboundHandler#read(ChannelHandlerContext)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - Channel read(); - - /** - * Request to write a message via this {@link Channel} through the {@link ChannelPipeline}. - * This method will not request to actual flush, so be sure to call {@link #flush()} - * once you want to request to flush all pending data to the actual transport. - */ - ChannelFuture write(Object msg); - - /** - * Request to write a message via this {@link Channel} through the {@link ChannelPipeline}. - * This method will not request to actual flush, so be sure to call {@link #flush()} - * once you want to request to flush all pending data to the actual transport. - */ - ChannelFuture write(Object msg, ChannelPromise promise); - - /** - * Request to flush all pending messages. - */ - Channel flush(); - - /** - * Shortcut for call {@link #write(Object, ChannelPromise)} and {@link #flush()}. - */ - ChannelFuture writeAndFlush(Object msg, ChannelPromise promise); - - /** - * Shortcut for call {@link #write(Object)} and {@link #flush()}. - */ - ChannelFuture writeAndFlush(Object msg); - - /** - * Unsafe operations that should never be called from user-code. These methods - * are only provided to implement the actual transport, and must be invoked from an I/O thread except for the - * following methods: - *

    - *
  • {@link #localAddress()}
  • - *
  • {@link #remoteAddress()}
  • - *
  • {@link #closeForcibly()}
  • - *
  • {@link #register(EventLoop, ChannelPromise)}
  • - *
  • {@link #voidPromise()}
  • - *
- */ - interface Unsafe { - /** - * Return the {@link SocketAddress} to which is bound local or - * {@code null} if none. - */ - SocketAddress localAddress(); - - /** - * Return the {@link SocketAddress} to which is bound remote or - * {@code null} if none is bound yet. - */ - SocketAddress remoteAddress(); - - /** - * Register the {@link Channel} of the {@link ChannelPromise} with the {@link EventLoop} and notify - * the {@link ChannelFuture} once the registration was complete. - */ - void register(EventLoop eventLoop, ChannelPromise promise); - - /** - * Bind the {@link SocketAddress} to the {@link Channel} of the {@link ChannelPromise} and notify - * it once its done. - */ - void bind(SocketAddress localAddress, ChannelPromise promise); - - /** - * Connect the {@link Channel} of the given {@link ChannelFuture} with the given remote {@link SocketAddress}. - * If a specific local {@link SocketAddress} should be used it need to be given as argument. Otherwise just - * pass {@code null} to it. - * - * The {@link ChannelPromise} will get notified once the connect operation was complete. - */ - void connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise); - - /** - * Disconnect the {@link Channel} of the {@link ChannelFuture} and notify the {@link ChannelPromise} once the - * operation was complete. - */ - void disconnect(ChannelPromise promise); - - /** - * Close the {@link Channel} of the {@link ChannelPromise} and notify the {@link ChannelPromise} once the - * operation was complete. - */ - void close(ChannelPromise promise); - - /** - * Closes the {@link Channel} immediately without firing any events. Probably only useful - * when registration attempt failed. - */ - void closeForcibly(); - - /** - * Deregister the {@link Channel} of the {@link ChannelPromise} from {@link EventLoop} and notify the - * {@link ChannelPromise} once the operation was complete. - */ - void deregister(ChannelPromise promise); - - /** - * Schedules a read operation that fills the inbound buffer of the first {@link ChannelInboundHandler} in the - * {@link ChannelPipeline}. If there's already a pending read operation, this method does nothing. - */ - void beginRead(); - - /** - * Schedules a write operation. - */ - void write(Object msg, ChannelPromise promise); - - /** - * Flush out all write operations scheduled via {@link #write(Object, ChannelPromise)}. - */ - void flush(); - - /** - * Return a special ChannelPromise which can be reused and passed to the operations in {@link Unsafe}. - * It will never be notified of a success or error and so is only a placeholder for operations - * that take a {@link ChannelPromise} as argument but for which you not want to get notified. - */ - ChannelPromise voidPromise(); - - /** - * Returns the {@link ChannelOutboundBuffer} of the {@link Channel} where the pending write requests are stored. - */ - ChannelOutboundBuffer outboundBuffer(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelConfig.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelConfig.java deleted file mode 100755 index 8ed6e1e982..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelConfig.java +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import java.nio.ByteBuffer; -import java.nio.channels.WritableByteChannel; -import java.util.Map; - -import com.ai.cloud.io.netty.buffer.ByteBufAllocator; -import com.ai.cloud.io.netty.channel.socket.SocketChannelConfig; - -/** - * A set of configuration properties of a {@link Channel}. - *

- * Please down-cast to more specific configuration type such as - * {@link SocketChannelConfig} or use {@link #setOptions(Map)} to set the - * transport-specific properties: - *

- * {@link Channel} ch = ...;
- * {@link SocketChannelConfig} cfg = ({@link SocketChannelConfig}) ch.getConfig();
- * cfg.setTcpNoDelay(false);
- * 
- * - *

Option map

- * - * An option map property is a dynamic write-only property which allows - * the configuration of a {@link Channel} without down-casting its associated - * {@link ChannelConfig}. To update an option map, please call {@link #setOptions(Map)}. - *

- * All {@link ChannelConfig} has the following options: - * - * - * - * - * - * - * - * - * - * - * - * - * - *
NameAssociated setter method
{@link ChannelOption#CONNECT_TIMEOUT_MILLIS}{@link #setConnectTimeoutMillis(int)}
{@link ChannelOption#WRITE_SPIN_COUNT}{@link #setWriteSpinCount(int)}
{@link ChannelOption#ALLOCATOR}{@link #setAllocator(ByteBufAllocator)}
{@link ChannelOption#AUTO_READ}{@link #setAutoRead(boolean)}
- *

- * More options are available in the sub-types of {@link ChannelConfig}. For - * example, you can configure the parameters which are specific to a TCP/IP - * socket as explained in {@link SocketChannelConfig}. - */ -public interface ChannelConfig { - - /** - * Return all set {@link ChannelOption}'s. - */ - Map, Object> getOptions(); - - /** - * Sets the configuration properties from the specified {@link Map}. - */ - boolean setOptions(Map, ?> options); - - /** - * Return the value of the given {@link ChannelOption} - */ - T getOption(ChannelOption option); - - /** - * Sets a configuration property with the specified name and value. - * To override this method properly, you must call the super class: - *

-     * public boolean setOption(ChannelOption<T> option, T value) {
-     *     if (super.setOption(option, value)) {
-     *         return true;
-     *     }
-     *
-     *     if (option.equals(additionalOption)) {
-     *         ....
-     *         return true;
-     *     }
-     *
-     *     return false;
-     * }
-     * 
- * - * @return {@code true} if and only if the property has been set - */ - boolean setOption(ChannelOption option, T value); - - /** - * Returns the connect timeout of the channel in milliseconds. If the - * {@link Channel} does not support connect operation, this property is not - * used at all, and therefore will be ignored. - * - * @return the connect timeout in milliseconds. {@code 0} if disabled. - */ - int getConnectTimeoutMillis(); - - /** - * Sets the connect timeout of the channel in milliseconds. If the - * {@link Channel} does not support connect operation, this property is not - * used at all, and therefore will be ignored. - * - * @param connectTimeoutMillis the connect timeout in milliseconds. - * {@code 0} to disable. - */ - ChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis); - - /** - * Returns the maximum number of messages to read per read loop. - * a {@link ChannelInboundHandler#channelRead(ChannelHandlerContext, Object) channelRead()} event. - * If this value is greater than 1, an event loop might attempt to read multiple times to procure multiple messages. - */ - int getMaxMessagesPerRead(); - - /** - * Sets the maximum number of messages to read per read loop. - * If this value is greater than 1, an event loop might attempt to read multiple times to procure multiple messages. - */ - ChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead); - - /** - * Returns the maximum loop count for a write operation until - * {@link WritableByteChannel#write(ByteBuffer)} returns a non-zero value. - * It is similar to what a spin lock is used for in concurrency programming. - * It improves memory utilization and write throughput depending on - * the platform that JVM runs on. The default value is {@code 16}. - */ - int getWriteSpinCount(); - - /** - * Sets the maximum loop count for a write operation until - * {@link WritableByteChannel#write(ByteBuffer)} returns a non-zero value. - * It is similar to what a spin lock is used for in concurrency programming. - * It improves memory utilization and write throughput depending on - * the platform that JVM runs on. The default value is {@code 16}. - * - * @throws IllegalArgumentException - * if the specified value is {@code 0} or less than {@code 0} - */ - ChannelConfig setWriteSpinCount(int writeSpinCount); - - /** - * Returns {@link ByteBufAllocator} which is used for the channel - * to allocate buffers. - */ - ByteBufAllocator getAllocator(); - - /** - * Set the {@link ByteBufAllocator} which is used for the channel - * to allocate buffers. - */ - ChannelConfig setAllocator(ByteBufAllocator allocator); - - /** - * Returns {@link RecvByteBufAllocator} which is used for the channel - * to allocate receive buffers. - */ - RecvByteBufAllocator getRecvByteBufAllocator(); - - /** - * Set the {@link ByteBufAllocator} which is used for the channel - * to allocate receive buffers. - */ - ChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator); - - /** - * Returns {@code true} if and only if {@link ChannelHandlerContext#read()} will be invoked automatically so that - * a user application doesn't need to call it at all. The default value is {@code true}. - */ - boolean isAutoRead(); - - /** - * Sets if {@link ChannelHandlerContext#read()} will be invoked automatically so that a user application doesn't - * need to call it at all. The default value is {@code true}. - */ - ChannelConfig setAutoRead(boolean autoRead); - - /** - * @deprecated From version 5.0, {@link Channel} will not be closed on write failure. - * - * Returns {@code true} if and only if the {@link Channel} will be closed automatically and immediately on - * write failure. The default is {@code false}. - */ - @Deprecated - boolean isAutoClose(); - - /** - * @deprecated From version 5.0, {@link Channel} will not be closed on write failure. - * - * Sets whether the {@link Channel} should be closed automatically and immediately on write faillure. - * The default is {@code false}. - */ - @Deprecated - ChannelConfig setAutoClose(boolean autoClose); - - /** - * Returns the high water mark of the write buffer. If the number of bytes - * queued in the write buffer exceeds this value, {@link Channel#isWritable()} - * will start to return {@code false}. - */ - int getWriteBufferHighWaterMark(); - - /** - * Sets the high water mark of the write buffer. If the number of bytes - * queued in the write buffer exceeds this value, {@link Channel#isWritable()} - * will start to return {@code false}. - */ - ChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark); - - /** - * Returns the low water mark of the write buffer. Once the number of bytes - * queued in the write buffer exceeded the - * {@linkplain #setWriteBufferHighWaterMark(int) high water mark} and then - * dropped down below this value, {@link Channel#isWritable()} will start to return - * {@code true} again. - */ - int getWriteBufferLowWaterMark(); - - /** - * Sets the low water mark of the write buffer. Once the number of bytes - * queued in the write buffer exceeded the - * {@linkplain #setWriteBufferHighWaterMark(int) high water mark} and then - * dropped down below this value, {@link Channel#isWritable()} will start to return - * {@code true} again. - */ - ChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark); - - /** - * Returns {@link MessageSizeEstimator} which is used for the channel - * to detect the size of a message. - */ - MessageSizeEstimator getMessageSizeEstimator(); - - /** - * Set the {@link MessageSizeEstimator} which is used for the channel - * to detect the size of a message. - */ - ChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelDuplexHandler.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelDuplexHandler.java deleted file mode 100755 index ed7fdcef99..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelDuplexHandler.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import java.net.SocketAddress; - -/** - * {@link ChannelHandler} implementation which represents a combination out of a {@link ChannelInboundHandler} and - * the {@link ChannelOutboundHandler}. - * - * It is a good starting point if your {@link ChannelHandler} implementation needs to intercept operations and also - * state updates. - */ -public class ChannelDuplexHandler extends ChannelInboundHandlerAdapter implements ChannelOutboundHandler { - - /** - * Calls {@link ChannelHandlerContext#bind(SocketAddress, ChannelPromise)} to forward - * to the next {@link ChannelOutboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void bind(ChannelHandlerContext ctx, SocketAddress localAddress, - ChannelPromise future) throws Exception { - ctx.bind(localAddress, future); - } - - /** - * Calls {@link ChannelHandlerContext#connect(SocketAddress, SocketAddress, ChannelPromise)} to forward - * to the next {@link ChannelOutboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress, - SocketAddress localAddress, ChannelPromise future) throws Exception { - ctx.connect(remoteAddress, localAddress, future); - } - - /** - * Calls {@link ChannelHandlerContext#disconnect(ChannelPromise)} to forward - * to the next {@link ChannelOutboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void disconnect(ChannelHandlerContext ctx, ChannelPromise future) - throws Exception { - ctx.disconnect(future); - } - - /** - * Calls {@link ChannelHandlerContext#close(ChannelPromise)} to forward - * to the next {@link ChannelOutboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void close(ChannelHandlerContext ctx, ChannelPromise future) throws Exception { - ctx.close(future); - } - - /** - * Calls {@link ChannelHandlerContext#close(ChannelPromise)} to forward - * to the next {@link ChannelOutboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void deregister(ChannelHandlerContext ctx, ChannelPromise future) throws Exception { - ctx.deregister(future); - } - - /** - * Calls {@link ChannelHandlerContext#read()} to forward - * to the next {@link ChannelOutboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void read(ChannelHandlerContext ctx) throws Exception { - ctx.read(); - } - - /** - * Calls {@link ChannelHandlerContext#write(Object, ChannelPromise)} to forward - * to the next {@link ChannelOutboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - ctx.write(msg, promise); - } - - /** - * Calls {@link ChannelHandlerContext#flush()} to forward - * to the next {@link ChannelOutboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void flush(ChannelHandlerContext ctx) throws Exception { - ctx.flush(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelException.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelException.java deleted file mode 100755 index 6471a64a8f..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelException.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -/** - * A {@link RuntimeException} which is thrown when an I/O operation fails. - */ -public class ChannelException extends RuntimeException { - - private static final long serialVersionUID = 2908618315971075004L; - - /** - * Creates a new exception. - */ - public ChannelException() { - } - - /** - * Creates a new exception. - */ - public ChannelException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Creates a new exception. - */ - public ChannelException(String message) { - super(message); - } - - /** - * Creates a new exception. - */ - public ChannelException(Throwable cause) { - super(cause); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelFlushPromiseNotifier.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelFlushPromiseNotifier.java deleted file mode 100755 index 3701cd2ef4..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelFlushPromiseNotifier.java +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import java.util.ArrayDeque; -import java.util.Queue; - -/** - * This implementation allows to register {@link ChannelFuture} instances which will get notified once some amount of - * data was written and so a checkpoint was reached. - */ -public final class ChannelFlushPromiseNotifier { - - private long writeCounter; - private final Queue flushCheckpoints = new ArrayDeque(); - private final boolean tryNotify; - - /** - * Create a new instance - * - * @param tryNotify if {@code true} the {@link ChannelPromise}s will get notified with - * {@link ChannelPromise#trySuccess()} and {@link ChannelPromise#tryFailure(Throwable)}. - * Otherwise {@link ChannelPromise#setSuccess()} and {@link ChannelPromise#setFailure(Throwable)} - * is used - */ - public ChannelFlushPromiseNotifier(boolean tryNotify) { - this.tryNotify = tryNotify; - } - - /** - * Create a new instance which will use {@link ChannelPromise#setSuccess()} and - * {@link ChannelPromise#setFailure(Throwable)} to notify the {@link ChannelPromise}s. - */ - public ChannelFlushPromiseNotifier() { - this(false); - } - - /** - * @deprecated use {@link #add(ChannelPromise, long)} - */ - @Deprecated - public ChannelFlushPromiseNotifier add(ChannelPromise promise, int pendingDataSize) { - return add(promise, (long) pendingDataSize); - } - - /** - * Add a {@link ChannelPromise} to this {@link ChannelFlushPromiseNotifier} which will be notified after the given - * {@code pendingDataSize} was reached. - */ - public ChannelFlushPromiseNotifier add(ChannelPromise promise, long pendingDataSize) { - if (promise == null) { - throw new NullPointerException("promise"); - } - if (pendingDataSize < 0) { - throw new IllegalArgumentException("pendingDataSize must be >= 0 but was " + pendingDataSize); - } - long checkpoint = writeCounter + pendingDataSize; - if (promise instanceof FlushCheckpoint) { - FlushCheckpoint cp = (FlushCheckpoint) promise; - cp.flushCheckpoint(checkpoint); - flushCheckpoints.add(cp); - } else { - flushCheckpoints.add(new DefaultFlushCheckpoint(checkpoint, promise)); - } - return this; - } - /** - * Increase the current write counter by the given delta - */ - public ChannelFlushPromiseNotifier increaseWriteCounter(long delta) { - if (delta < 0) { - throw new IllegalArgumentException("delta must be >= 0 but was " + delta); - } - writeCounter += delta; - return this; - } - - /** - * Return the current write counter of this {@link ChannelFlushPromiseNotifier} - */ - public long writeCounter() { - return writeCounter; - } - - /** - * Notify all {@link ChannelFuture}s that were registered with {@link #add(ChannelPromise, int)} and - * their pendingDatasize is smaller after the the current writeCounter returned by {@link #writeCounter()}. - * - * After a {@link ChannelFuture} was notified it will be removed from this {@link ChannelFlushPromiseNotifier} and - * so not receive anymore notification. - */ - public ChannelFlushPromiseNotifier notifyPromises() { - notifyPromises0(null); - return this; - } - - /** - * @deprecated use {@link #notifyPromises()} - */ - @Deprecated - public ChannelFlushPromiseNotifier notifyFlushFutures() { - return notifyPromises(); - } - - /** - * Notify all {@link ChannelFuture}s that were registered with {@link #add(ChannelPromise, int)} and - * their pendingDatasize isis smaller then the current writeCounter returned by {@link #writeCounter()}. - * - * After a {@link ChannelFuture} was notified it will be removed from this {@link ChannelFlushPromiseNotifier} and - * so not receive anymore notification. - * - * The rest of the remaining {@link ChannelFuture}s will be failed with the given {@link Throwable}. - * - * So after this operation this {@link ChannelFutureListener} is empty. - */ - public ChannelFlushPromiseNotifier notifyPromises(Throwable cause) { - notifyPromises(); - for (;;) { - FlushCheckpoint cp = flushCheckpoints.poll(); - if (cp == null) { - break; - } - if (tryNotify) { - cp.promise().tryFailure(cause); - } else { - cp.promise().setFailure(cause); - } - } - return this; - } - - /** - * @deprecated use {@link #notifyPromises(Throwable)} - */ - @Deprecated - public ChannelFlushPromiseNotifier notifyFlushFutures(Throwable cause) { - return notifyPromises(cause); - } - - /** - * Notify all {@link ChannelFuture}s that were registered with {@link #add(ChannelPromise, int)} and - * their pendingDatasize is smaller then the current writeCounter returned by {@link #writeCounter()} using - * the given cause1. - * - * After a {@link ChannelFuture} was notified it will be removed from this {@link ChannelFlushPromiseNotifier} and - * so not receive anymore notification. - * - * The rest of the remaining {@link ChannelFuture}s will be failed with the given {@link Throwable}. - * - * So after this operation this {@link ChannelFutureListener} is empty. - * - * @param cause1 the {@link Throwable} which will be used to fail all of the {@link ChannelFuture}s whichs - * pendingDataSize is smaller then the current writeCounter returned by {@link #writeCounter()} - * @param cause2 the {@link Throwable} which will be used to fail the remaining {@link ChannelFuture}s - */ - public ChannelFlushPromiseNotifier notifyPromises(Throwable cause1, Throwable cause2) { - notifyPromises0(cause1); - for (;;) { - FlushCheckpoint cp = flushCheckpoints.poll(); - if (cp == null) { - break; - } - if (tryNotify) { - cp.promise().tryFailure(cause2); - } else { - cp.promise().setFailure(cause2); - } - } - return this; - } - - /** - * @deprecated use {@link #notifyPromises(Throwable, Throwable)} - */ - @Deprecated - public ChannelFlushPromiseNotifier notifyFlushFutures(Throwable cause1, Throwable cause2) { - return notifyPromises(cause1, cause2); - } - - private void notifyPromises0(Throwable cause) { - if (flushCheckpoints.isEmpty()) { - writeCounter = 0; - return; - } - - final long writeCounter = this.writeCounter; - for (;;) { - FlushCheckpoint cp = flushCheckpoints.peek(); - if (cp == null) { - // Reset the counter if there's nothing in the notification list. - this.writeCounter = 0; - break; - } - - if (cp.flushCheckpoint() > writeCounter) { - if (writeCounter > 0 && flushCheckpoints.size() == 1) { - this.writeCounter = 0; - cp.flushCheckpoint(cp.flushCheckpoint() - writeCounter); - } - break; - } - - flushCheckpoints.remove(); - ChannelPromise promise = cp.promise(); - if (cause == null) { - if (tryNotify) { - promise.trySuccess(); - } else { - promise.setSuccess(); - } - } else { - if (tryNotify) { - promise.tryFailure(cause); - } else { - promise.setFailure(cause); - } - } - } - - // Avoid overflow - final long newWriteCounter = this.writeCounter; - if (newWriteCounter >= 0x8000000000L) { - // Reset the counter only when the counter grew pretty large - // so that we can reduce the cost of updating all entries in the notification list. - this.writeCounter = 0; - for (FlushCheckpoint cp: flushCheckpoints) { - cp.flushCheckpoint(cp.flushCheckpoint() - newWriteCounter); - } - } - } - - interface FlushCheckpoint { - long flushCheckpoint(); - void flushCheckpoint(long checkpoint); - ChannelPromise promise(); - } - - private static class DefaultFlushCheckpoint implements FlushCheckpoint { - private long checkpoint; - private final ChannelPromise future; - - DefaultFlushCheckpoint(long checkpoint, ChannelPromise future) { - this.checkpoint = checkpoint; - this.future = future; - } - - @Override - public long flushCheckpoint() { - return checkpoint; - } - - @Override - public void flushCheckpoint(long checkpoint) { - this.checkpoint = checkpoint; - } - - @Override - public ChannelPromise promise() { - return future; - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelFuture.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelFuture.java deleted file mode 100755 index f54d83a990..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelFuture.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import java.util.concurrent.TimeUnit; - -import com.ai.cloud.io.netty.bootstrap.Bootstrap; -import com.ai.cloud.io.netty.util.concurrent.BlockingOperationException; -import com.ai.cloud.io.netty.util.concurrent.Future; -import com.ai.cloud.io.netty.util.concurrent.GenericFutureListener; - - -/** - * The result of an asynchronous {@link Channel} I/O operation. - *

- * All I/O operations in Netty are asynchronous. It means any I/O calls will - * return immediately with no guarantee that the requested I/O operation has - * been completed at the end of the call. Instead, you will be returned with - * a {@link ChannelFuture} instance which gives you the information about the - * result or status of the I/O operation. - *

- * A {@link ChannelFuture} is either uncompleted or completed. - * When an I/O operation begins, a new future object is created. The new future - * is uncompleted initially - it is neither succeeded, failed, nor cancelled - * because the I/O operation is not finished yet. If the I/O operation is - * finished either successfully, with failure, or by cancellation, the future is - * marked as completed with more specific information, such as the cause of the - * failure. Please note that even failure and cancellation belong to the - * completed state. - *

- *                                      +---------------------------+
- *                                      | Completed successfully    |
- *                                      +---------------------------+
- *                                 +---->      isDone() = true      |
- * +--------------------------+    |    |   isSuccess() = true      |
- * |        Uncompleted       |    |    +===========================+
- * +--------------------------+    |    | Completed with failure    |
- * |      isDone() = false    |    |    +---------------------------+
- * |   isSuccess() = false    |----+---->   isDone() = true         |
- * | isCancelled() = false    |    |    | cause() = non-null     |
- * |    cause() = null     |    |    +===========================+
- * +--------------------------+    |    | Completed by cancellation |
- *                                 |    +---------------------------+
- *                                 +---->      isDone() = true      |
- *                                      | isCancelled() = true      |
- *                                      +---------------------------+
- * 
- * - * Various methods are provided to let you check if the I/O operation has been - * completed, wait for the completion, and retrieve the result of the I/O - * operation. It also allows you to add {@link ChannelFutureListener}s so you - * can get notified when the I/O operation is completed. - * - *

Prefer {@link #addListener(GenericFutureListener)} to {@link #await()}

- * - * It is recommended to prefer {@link #addListener(GenericFutureListener)} to - * {@link #await()} wherever possible to get notified when an I/O operation is - * done and to do any follow-up tasks. - *

- * {@link #addListener(GenericFutureListener)} is non-blocking. It simply adds - * the specified {@link ChannelFutureListener} to the {@link ChannelFuture}, and - * I/O thread will notify the listeners when the I/O operation associated with - * the future is done. {@link ChannelFutureListener} yields the best - * performance and resource utilization because it does not block at all, but - * it could be tricky to implement a sequential logic if you are not used to - * event-driven programming. - *

- * By contrast, {@link #await()} is a blocking operation. Once called, the - * caller thread blocks until the operation is done. It is easier to implement - * a sequential logic with {@link #await()}, but the caller thread blocks - * unnecessarily until the I/O operation is done and there's relatively - * expensive cost of inter-thread notification. Moreover, there's a chance of - * dead lock in a particular circumstance, which is described below. - * - *

Do not call {@link #await()} inside {@link ChannelHandler}

- *

- * The event handler methods in {@link ChannelHandler} is usually called by - * an I/O thread. If {@link #await()} is called by an event handler - * method, which is called by the I/O thread, the I/O operation it is waiting - * for might never be complete because {@link #await()} can block the I/O - * operation it is waiting for, which is a dead lock. - *

- * // BAD - NEVER DO THIS
- * {@code @Override}
- * public void channelRead({@link ChannelHandlerContext} ctx, GoodByeMessage msg) {
- *     {@link ChannelFuture} future = ctx.channel().close();
- *     future.awaitUninterruptibly();
- *     // Perform post-closure operation
- *     // ...
- * }
- *
- * // GOOD
- * {@code @Override}
- * public void channelRead({@link ChannelHandlerContext} ctx,  GoodByeMessage msg) {
- *     {@link ChannelFuture} future = ctx.channel().close();
- *     future.addListener(new {@link ChannelFutureListener}() {
- *         public void operationComplete({@link ChannelFuture} future) {
- *             // Perform post-closure operation
- *             // ...
- *         }
- *     });
- * }
- * 
- *

- * In spite of the disadvantages mentioned above, there are certainly the cases - * where it is more convenient to call {@link #await()}. In such a case, please - * make sure you do not call {@link #await()} in an I/O thread. Otherwise, - * {@link BlockingOperationException} will be raised to prevent a dead lock. - * - *

Do not confuse I/O timeout and await timeout

- * - * The timeout value you specify with {@link #await(long)}, - * {@link #await(long, TimeUnit)}, {@link #awaitUninterruptibly(long)}, or - * {@link #awaitUninterruptibly(long, TimeUnit)} are not related with I/O - * timeout at all. If an I/O operation times out, the future will be marked as - * 'completed with failure,' as depicted in the diagram above. For example, - * connect timeout should be configured via a transport-specific option: - *
- * // BAD - NEVER DO THIS
- * {@link Bootstrap} b = ...;
- * {@link ChannelFuture} f = b.connect(...);
- * f.awaitUninterruptibly(10, TimeUnit.SECONDS);
- * if (f.isCancelled()) {
- *     // Connection attempt cancelled by user
- * } else if (!f.isSuccess()) {
- *     // You might get a NullPointerException here because the future
- *     // might not be completed yet.
- *     f.cause().printStackTrace();
- * } else {
- *     // Connection established successfully
- * }
- *
- * // GOOD
- * {@link Bootstrap} b = ...;
- * // Configure the connect timeout option.
- * b.option({@link ChannelOption}.CONNECT_TIMEOUT_MILLIS, 10000);
- * {@link ChannelFuture} f = b.connect(...);
- * f.awaitUninterruptibly();
- *
- * // Now we are sure the future is completed.
- * assert f.isDone();
- *
- * if (f.isCancelled()) {
- *     // Connection attempt cancelled by user
- * } else if (!f.isSuccess()) {
- *     f.cause().printStackTrace();
- * } else {
- *     // Connection established successfully
- * }
- * 
- */ -public interface ChannelFuture extends Future { - - /** - * Returns a channel where the I/O operation associated with this - * future takes place. - */ - Channel channel(); - - @Override - ChannelFuture addListener(GenericFutureListener> listener); - - @Override - ChannelFuture addListeners(GenericFutureListener>... listeners); - - @Override - ChannelFuture removeListener(GenericFutureListener> listener); - - @Override - ChannelFuture removeListeners(GenericFutureListener>... listeners); - - @Override - ChannelFuture sync() throws InterruptedException; - - @Override - ChannelFuture syncUninterruptibly(); - - @Override - ChannelFuture await() throws InterruptedException; - - @Override - ChannelFuture awaitUninterruptibly(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelFutureListener.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelFutureListener.java deleted file mode 100755 index 1ff9a59078..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelFutureListener.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import com.ai.cloud.io.netty.util.concurrent.Future; -import com.ai.cloud.io.netty.util.concurrent.GenericFutureListener; - - -/** - * Listens to the result of a {@link ChannelFuture}. The result of the - * asynchronous {@link Channel} I/O operation is notified once this listener - * is added by calling {@link ChannelFuture#addListener(GenericFutureListener)}. - * - *

Return the control to the caller quickly

- * - * {@link #operationComplete(Future)} is directly called by an I/O - * thread. Therefore, performing a time consuming task or a blocking operation - * in the handler method can cause an unexpected pause during I/O. If you need - * to perform a blocking operation on I/O completion, try to execute the - * operation in a different thread using a thread pool. - */ -public interface ChannelFutureListener extends GenericFutureListener { - - /** - * A {@link ChannelFutureListener} that closes the {@link Channel} which is - * associated with the specified {@link ChannelFuture}. - */ - ChannelFutureListener CLOSE = new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) { - future.channel().close(); - } - }; - - /** - * A {@link ChannelFutureListener} that closes the {@link Channel} when the - * operation ended up with a failure or cancellation rather than a success. - */ - ChannelFutureListener CLOSE_ON_FAILURE = new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) { - if (!future.isSuccess()) { - future.channel().close(); - } - } - }; - - /** - * A {@link ChannelFutureListener} that forwards the {@link Throwable} of the {@link ChannelFuture} into the - * {@link ChannelPipeline}. This mimics the old behavior of Netty 3. - */ - ChannelFutureListener FIRE_EXCEPTION_ON_FAILURE = new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) { - if (!future.isSuccess()) { - future.channel().pipeline().fireExceptionCaught(future.cause()); - } - } - }; - - // Just a type alias -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelHandler.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelHandler.java deleted file mode 100755 index e734eb28ad..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelHandler.java +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import com.ai.cloud.io.netty.util.Attribute; -import com.ai.cloud.io.netty.util.AttributeKey; - -/** - * Handles or intercepts a {@link ChannelInboundInvoker} or {@link ChannelOutboundInvoker} operation, and forwards it - * to the next handler in a {@link ChannelPipeline}. - * - *

Sub-types

- *

- * {@link ChannelHandler} itself does not provide many methods. To handle a - * a {@link ChannelInboundInvoker} or {@link ChannelOutboundInvoker} operation - * you need to implement its sub-interfaces. There are many different sub-interfaces - * which handles inbound and outbound operations. - * - * But the most useful for developers may be: - *

    - *
  • {@link ChannelInboundHandlerAdapter} handles and intercepts inbound operations
  • - *
  • {@link ChannelOutboundHandlerAdapter} handles and intercepts outbound operations
  • - *
- * - * You will also find more detailed explanation from the documentation of - * each sub-interface on how an event is interpreted when it goes upstream and - * downstream respectively. - * - *

The context object

- *

- * A {@link ChannelHandler} is provided with a {@link ChannelHandlerContext} - * object. A {@link ChannelHandler} is supposed to interact with the - * {@link ChannelPipeline} it belongs to via a context object. Using the - * context object, the {@link ChannelHandler} can pass events upstream or - * downstream, modify the pipeline dynamically, or store the information - * (using {@link AttributeKey}s) which is specific to the handler. - * - *

State management

- * - * A {@link ChannelHandler} often needs to store some stateful information. - * The simplest and recommended approach is to use member variables: - *
- * public interface Message {
- *     // your methods here
- * }
- *
- * public class DataServerHandler extends {@link SimpleChannelInboundHandler}<Message> {
- *
- *     private boolean loggedIn;
- *
- *     {@code @Override}
- *     public void channelRead0({@link ChannelHandlerContext} ctx, Message message) {
- *         {@link Channel} ch = e.getChannel();
- *         if (message instanceof LoginMessage) {
- *             authenticate((LoginMessage) message);
- *             loggedIn = true;
- *         } else (message instanceof GetDataMessage) {
- *             if (loggedIn) {
- *                 ch.write(fetchSecret((GetDataMessage) message));
- *             } else {
- *                 fail();
- *             }
- *         }
- *     }
- *     ...
- * }
- * 
- * Because the handler instance has a state variable which is dedicated to - * one connection, you have to create a new handler instance for each new - * channel to avoid a race condition where a unauthenticated client can get - * the confidential information: - *
- * // Create a new handler instance per channel.
- * // See {@link ChannelInitializer#initChannel(Channel)}.
- * public class DataServerInitializer extends {@link ChannelInitializer}<{@link Channel}> {
- *     {@code @Override}
- *     public void initChannel({@link Channel} channel) {
- *         channel.pipeline().addLast("handler", new DataServerHandler());
- *     }
- * }
- *
- * 
- * - *

Using {@link AttributeKey}

- * - * Although it's recommended to use member variables to store the state of a - * handler, for some reason you might not want to create many handler instances. - * In such a case, you can use {@link AttributeKey}s which is provided by - * {@link ChannelHandlerContext}: - *
- * public interface Message {
- *     // your methods here
- * }
- *
- * {@code @Sharable}
- * public class DataServerHandler extends {@link SimpleChannelInboundHandler}<Message> {
- *     private final {@link AttributeKey}<{@link Boolean}> auth =
- *           {@link AttributeKey#valueOf(String) AttributeKey.valueOf("auth")};
- *
- *     {@code @Override}
- *     public void channelRead({@link ChannelHandlerContext} ctx, Message message) {
- *         {@link Attribute}<{@link Boolean}> attr = ctx.attr(auth);
- *         {@link Channel} ch = ctx.channel();
- *         if (message instanceof LoginMessage) {
- *             authenticate((LoginMessage) o);
- *             attr.set(true);
- *         } else (message instanceof GetDataMessage) {
- *             if (Boolean.TRUE.equals(attr.get())) {
- *                 ch.write(fetchSecret((GetDataMessage) o));
- *             } else {
- *                 fail();
- *             }
- *         }
- *     }
- *     ...
- * }
- * 
- * Now that the state of the handler isattached to the {@link ChannelHandlerContext}, you can add the - * same handler instance to different pipelines: - *
- * public class DataServerInitializer extends {@link ChannelInitializer}<{@link Channel}> {
- *
- *     private static final DataServerHandler SHARED = new DataServerHandler();
- *
- *     {@code @Override}
- *     public void initChannel({@link Channel} channel) {
- *         channel.pipeline().addLast("handler", SHARED);
- *     }
- * }
- * 
- * - * - *

The {@code @Sharable} annotation

- *

- * In the example above which used an {@link AttributeKey}, - * you might have noticed the {@code @Sharable} annotation. - *

- * If a {@link ChannelHandler} is annotated with the {@code @Sharable} - * annotation, it means you can create an instance of the handler just once and - * add it to one or more {@link ChannelPipeline}s multiple times without - * a race condition. - *

- * If this annotation is not specified, you have to create a new handler - * instance every time you add it to a pipeline because it has unshared state - * such as member variables. - *

- * This annotation is provided for documentation purpose, just like - * the JCIP annotations. - * - *

Additional resources worth reading

- *

- * Please refer to the {@link ChannelHandler}, and - * {@link ChannelPipeline} to find out more about inbound and outbound operations, - * what fundamental differences they have, how they flow in a pipeline, and how to handle - * the operation in your application. - */ -public interface ChannelHandler { - - /** - * Gets called after the {@link ChannelHandler} was added to the actual context and it's ready to handle events. - */ - void handlerAdded(ChannelHandlerContext ctx) throws Exception; - - /** - * Gets called after the {@link ChannelHandler} was removed from the actual context and it doesn't handle events - * anymore. - */ - void handlerRemoved(ChannelHandlerContext ctx) throws Exception; - - /** - * Gets called if a {@link Throwable} was thrown. - */ - void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception; - - /** - * Indicates that the same instance of the annotated {@link ChannelHandler} - * can be added to one or more {@link ChannelPipeline}s multiple times - * without a race condition. - *

- * If this annotation is not specified, you have to create a new handler - * instance every time you add it to a pipeline because it has unshared - * state such as member variables. - *

- * This annotation is provided for documentation purpose, just like - * the JCIP annotations. - */ - @Inherited - @Documented - @Target(ElementType.TYPE) - @Retention(RetentionPolicy.RUNTIME) - @interface Sharable { - // no value - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelHandlerAdapter.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelHandlerAdapter.java deleted file mode 100755 index 7817772fdf..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelHandlerAdapter.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.channel; - -import java.util.Map; -import java.util.WeakHashMap; - -import com.ai.cloud.io.netty.util.internal.InternalThreadLocalMap; - -/** - * Skelton implementation of a {@link ChannelHandler}. - */ -public abstract class ChannelHandlerAdapter implements ChannelHandler { - - // Not using volatile because it's used only for a sanity check. - boolean added; - - /** - * Return {@code true} if the implementation is {@link Sharable} and so can be added - * to different {@link ChannelPipeline}s. - */ - public boolean isSharable() { - /** - * Cache the result of {@link Sharable} annotation detection to workaround a condition. We use a - * {@link ThreadLocal} and {@link WeakHashMap} to eliminate the volatile write/reads. Using different - * {@link WeakHashMap} instances per {@link Thread} is good enough for us and the number of - * {@link Thread}s are quite limited anyway. - * - * See #2289. - */ - Class clazz = getClass(); - Map, Boolean> cache = InternalThreadLocalMap.get().handlerSharableCache(); - Boolean sharable = cache.get(clazz); - if (sharable == null) { - sharable = clazz.isAnnotationPresent(Sharable.class); - cache.put(clazz, sharable); - } - return sharable; - } - - /** - * Do nothing by default, sub-classes may override this method. - */ - @Override - public void handlerAdded(ChannelHandlerContext ctx) throws Exception { - // NOOP - } - - /** - * Do nothing by default, sub-classes may override this method. - */ - @Override - public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { - // NOOP - } - - /** - * Calls {@link ChannelHandlerContext#fireExceptionCaught(Throwable)} to forward - * to the next {@link ChannelHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - ctx.fireExceptionCaught(cause); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelHandlerContext.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelHandlerContext.java deleted file mode 100755 index e674de3262..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelHandlerContext.java +++ /dev/null @@ -1,495 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - - -import java.net.ConnectException; -import java.net.SocketAddress; -import java.nio.channels.Channels; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.ByteBufAllocator; -import com.ai.cloud.io.netty.util.Attribute; -import com.ai.cloud.io.netty.util.AttributeKey; -import com.ai.cloud.io.netty.util.AttributeMap; -import com.ai.cloud.io.netty.util.concurrent.EventExecutor; -import com.ai.cloud.io.netty.util.concurrent.FutureListener; - -/** - * Enables a {@link ChannelHandler} to interact with its {@link ChannelPipeline} - * and other handlers. A handler can notify the next {@link ChannelHandler} in the {@link ChannelPipeline}, - * modify the {@link ChannelPipeline} it belongs to dynamically. - * - *

Notify

- * - * You can notify the closest handler in the - * same {@link ChannelPipeline} by calling one of the various methods provided here. - * Please refer to {@link ChannelPipeline} to understand how an event flows. - * - *

Modifying a pipeline

- * - * You can get the {@link ChannelPipeline} your handler belongs to by calling - * {@link #pipeline()}. A non-trivial application could insert, remove, or - * replace handlers in the pipeline dynamically at runtime. - * - *

Retrieving for later use

- * - * You can keep the {@link ChannelHandlerContext} for later use, such as - * triggering an event outside the handler methods, even from a different thread. - *
- * public class MyHandler extends {@link ChannelDuplexHandler} {
- *
- *     private {@link ChannelHandlerContext} ctx;
- *
- *     public void beforeAdd({@link ChannelHandlerContext} ctx) {
- *         this.ctx = ctx;
- *     }
- *
- *     public void login(String username, password) {
- *         ctx.write(new LoginMessage(username, password));
- *     }
- *     ...
- * }
- * 
- * - *

Storing stateful information

- * - * {@link #attr(AttributeKey)} allow you to - * store and access stateful information that is related with a handler and its - * context. Please refer to {@link ChannelHandler} to learn various recommended - * ways to manage stateful information. - * - *

A handler can have more than one context

- * - * Please note that a {@link ChannelHandler} instance can be added to more than - * one {@link ChannelPipeline}. It means a single {@link ChannelHandler} - * instance can have more than one {@link ChannelHandlerContext} and therefore - * the single instance can be invoked with different - * {@link ChannelHandlerContext}s if it is added to one or more - * {@link ChannelPipeline}s more than once. - *

- * For example, the following handler will have as many independent {@link AttributeKey}s - * as how many times it is added to pipelines, regardless if it is added to the - * same pipeline multiple times or added to different pipelines multiple times: - *

- * public class FactorialHandler extends {@link ChannelInboundHandlerAdapter}<{@link Integer}> {
- *
- *   private final {@link AttributeKey}<{@link Integer}> counter =
- *           new {@link AttributeKey}<{@link Integer}>("counter");
- *
- *   // This handler will receive a sequence of increasing integers starting
- *   // from 1.
- *   {@code @Override}
- *   public void channelRead({@link ChannelHandlerContext} ctx, {@link Integer} integer) {
- *     {@link Attribute}<{@link Integer}> attr = ctx.getAttr(counter);
- *     Integer a = ctx.getAttr(counter).get();
- *
- *     if (a == null) {
- *       a = 1;
- *     }
- *
- *     attr.set(a * integer));
- *   }
- * }
- *
- * // Different context objects are given to "f1", "f2", "f3", and "f4" even if
- * // they refer to the same handler instance.  Because the FactorialHandler
- * // stores its state in a context object (as an (using an {@link AttributeKey}), the factorial is
- * // calculated correctly 4 times once the two pipelines (p1 and p2) are active.
- * FactorialHandler fh = new FactorialHandler();
- *
- * {@link ChannelPipeline} p1 = {@link Channels}.pipeline();
- * p1.addLast("f1", fh);
- * p1.addLast("f2", fh);
- *
- * {@link ChannelPipeline} p2 = {@link Channels}.pipeline();
- * p2.addLast("f3", fh);
- * p2.addLast("f4", fh);
- * 
- * - *

Additional resources worth reading

- *

- * Please refer to the {@link ChannelHandler}, and - * {@link ChannelPipeline} to find out more about inbound and outbound operations, - * what fundamental differences they have, how they flow in a pipeline, and how to handle - * the operation in your application. - */ -public interface ChannelHandlerContext - extends AttributeMap { - - /** - * Return the {@link Channel} which is bound to the {@link ChannelHandlerContext}. - */ - Channel channel(); - - /** - * The {@link EventExecutor} that is used to dispatch the events. This can also be used to directly - * submit tasks that get executed in the event loop. For more information please refer to the - * {@link EventExecutor} javadoc. - */ - EventExecutor executor(); - - /** - * The unique name of the {@link ChannelHandlerContext}.The name was used when then {@link ChannelHandler} - * was added to the {@link ChannelPipeline}. This name can also be used to access the registered - * {@link ChannelHandler} from the {@link ChannelPipeline}. - */ - String name(); - - /** - * The {@link ChannelHandler} that is bound this {@link ChannelHandlerContext}. - */ - ChannelHandler handler(); - - /** - * Return {@code true} if the {@link ChannelHandler} which belongs to this {@link ChannelHandler} was removed - * from the {@link ChannelPipeline}. Note that this method is only meant to be called from with in the - * {@link EventLoop}. - */ - boolean isRemoved(); - - /** - * A {@link Channel} was registered to its {@link EventLoop}. - * - * This will result in having the {@link ChannelInboundHandler#channelRegistered(ChannelHandlerContext)} method - * called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelHandlerContext fireChannelRegistered(); - - /** - * A {@link Channel} was unregistered from its {@link EventLoop}. - * - * This will result in having the {@link ChannelInboundHandler#channelUnregistered(ChannelHandlerContext)} method - * called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelHandlerContext fireChannelUnregistered(); - - /** - * A {@link Channel} is active now, which means it is connected. - * - * This will result in having the {@link ChannelInboundHandler#channelActive(ChannelHandlerContext)} method - * called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelHandlerContext fireChannelActive(); - - /** - * A {@link Channel} is inactive now, which means it is closed. - * - * This will result in having the {@link ChannelInboundHandler#channelInactive(ChannelHandlerContext)} method - * called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelHandlerContext fireChannelInactive(); - - /** - * A {@link Channel} received an {@link Throwable} in one of its inbound operations. - * - * This will result in having the {@link ChannelInboundHandler#exceptionCaught(ChannelHandlerContext, Throwable)} - * method called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelHandlerContext fireExceptionCaught(Throwable cause); - - /** - * A {@link Channel} received an user defined event. - * - * This will result in having the {@link ChannelInboundHandler#userEventTriggered(ChannelHandlerContext, Object)} - * method called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelHandlerContext fireUserEventTriggered(Object event); - - /** - * A {@link Channel} received a message. - * - * This will result in having the {@link ChannelInboundHandler#channelRead(ChannelHandlerContext, Object)} - * method called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelHandlerContext fireChannelRead(Object msg); - - /** - * Triggers an {@link ChannelInboundHandler#channelReadComplete(ChannelHandlerContext)} - * event to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}. - */ - ChannelHandlerContext fireChannelReadComplete(); - - /** - * Triggers an {@link ChannelInboundHandler#channelWritabilityChanged(ChannelHandlerContext)} - * event to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}. - */ - ChannelHandlerContext fireChannelWritabilityChanged(); - - /** - * Request to bind to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation - * completes, either because the operation was successful or because of an error. - *

- * This will result in having the - * {@link ChannelOutboundHandler#bind(ChannelHandlerContext, SocketAddress, ChannelPromise)} method - * called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture bind(SocketAddress localAddress); - - /** - * Request to connect to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation - * completes, either because the operation was successful or because of an error. - *

- * If the connection fails because of a connection timeout, the {@link ChannelFuture} will get failed with - * a {@link ConnectTimeoutException}. If it fails because of connection refused a {@link ConnectException} - * will be used. - *

- * This will result in having the - * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture connect(SocketAddress remoteAddress); - - /** - * Request to connect to the given {@link SocketAddress} while bind to the localAddress and notify the - * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of - * an error. - *

- * This will result in having the - * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress); - - /** - * Request to disconnect from the remote peer and notify the {@link ChannelFuture} once the operation completes, - * either because the operation was successful or because of an error. - *

- * This will result in having the - * {@link ChannelOutboundHandler#disconnect(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture disconnect(); - - /** - * Request to close the {@link Channel} and notify the {@link ChannelFuture} once the operation completes, - * either because the operation was successful or because of - * an error. - * - * After it is closed it is not possible to reuse it again. - *

- * This will result in having the - * {@link ChannelOutboundHandler#close(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture close(); - - /** - * Request to deregister from the previous assigned {@link EventExecutor} and notify the - * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of - * an error. - *

- * This will result in having the - * {@link ChannelOutboundHandler#deregister(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - * - */ - ChannelFuture deregister(); - - /** - * Request to bind to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation - * completes, either because the operation was successful or because of an error. - * - * The given {@link ChannelPromise} will be notified. - *

- * This will result in having the - * {@link ChannelOutboundHandler#bind(ChannelHandlerContext, SocketAddress, ChannelPromise)} method - * called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise); - - /** - * Request to connect to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation - * completes, either because the operation was successful or because of an error. - * - * The given {@link ChannelFuture} will be notified. - * - *

- * If the connection fails because of a connection timeout, the {@link ChannelFuture} will get failed with - * a {@link ConnectTimeoutException}. If it fails because of connection refused a {@link ConnectException} - * will be used. - *

- * This will result in having the - * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise); - - /** - * Request to connect to the given {@link SocketAddress} while bind to the localAddress and notify the - * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of - * an error. - * - * The given {@link ChannelPromise} will be notified and also returned. - *

- * This will result in having the - * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise); - - /** - * Request to disconnect from the remote peer and notify the {@link ChannelFuture} once the operation completes, - * either because the operation was successful or because of an error. - * - * The given {@link ChannelPromise} will be notified. - *

- * This will result in having the - * {@link ChannelOutboundHandler#disconnect(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture disconnect(ChannelPromise promise); - - /** - * Request to close the {@link Channel} and notify the {@link ChannelFuture} once the operation completes, - * either because the operation was successful or because of - * an error. - * - * After it is closed it is not possible to reuse it again. - * The given {@link ChannelPromise} will be notified. - *

- * This will result in having the - * {@link ChannelOutboundHandler#close(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture close(ChannelPromise promise); - - /** - * Request to deregister from the previous assigned {@link EventExecutor} and notify the - * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of - * an error. - * - * The given {@link ChannelPromise} will be notified. - *

- * This will result in having the - * {@link ChannelOutboundHandler#deregister(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture deregister(ChannelPromise promise); - - /** - * Request to Read data from the {@link Channel} into the first inbound buffer, triggers an - * {@link ChannelInboundHandler#channelRead(ChannelHandlerContext, Object)} event if data was - * read, and triggers a - * {@link ChannelInboundHandler#channelReadComplete(ChannelHandlerContext) channelReadComplete} event so the - * handler can decide to continue reading. If there's a pending read operation already, this method does nothing. - *

- * This will result in having the - * {@link ChannelOutboundHandler#read(ChannelHandlerContext)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelHandlerContext read(); - - /** - * Request to write a message via this {@link ChannelHandlerContext} through the {@link ChannelPipeline}. - * This method will not request to actual flush, so be sure to call {@link #flush()} - * once you want to request to flush all pending data to the actual transport. - */ - ChannelFuture write(Object msg); - - /** - * Request to write a message via this {@link ChannelHandlerContext} through the {@link ChannelPipeline}. - * This method will not request to actual flush, so be sure to call {@link #flush()} - * once you want to request to flush all pending data to the actual transport. - */ - ChannelFuture write(Object msg, ChannelPromise promise); - - /** - * Request to flush all pending messages via this ChannelOutboundInvoker. - */ - ChannelHandlerContext flush(); - - /** - * Shortcut for call {@link #write(Object, ChannelPromise)} and {@link #flush()}. - */ - ChannelFuture writeAndFlush(Object msg, ChannelPromise promise); - - /** - * Shortcut for call {@link #write(Object)} and {@link #flush()}. - */ - ChannelFuture writeAndFlush(Object msg); - - /** - * Return the assigned {@link ChannelPipeline} - */ - ChannelPipeline pipeline(); - - /** - * Return the assigned {@link ByteBufAllocator} which will be used to allocate {@link ByteBuf}s. - */ - ByteBufAllocator alloc(); - - /** - * Return a new {@link ChannelPromise}. - */ - ChannelPromise newPromise(); - - /** - * Return an new {@link ChannelProgressivePromise} - */ - ChannelProgressivePromise newProgressivePromise(); - - /** - * Create a new {@link ChannelFuture} which is marked as succeeded already. So {@link ChannelFuture#isSuccess()} - * will return {@code true}. All {@link FutureListener} added to it will be notified directly. Also - * every call of blocking methods will just return without blocking. - */ - ChannelFuture newSucceededFuture(); - - /** - * Create a new {@link ChannelFuture} which is marked as failed already. So {@link ChannelFuture#isSuccess()} - * will return {@code false}. All {@link FutureListener} added to it will be notified directly. Also - * every call of blocking methods will just return without blocking. - */ - ChannelFuture newFailedFuture(Throwable cause); - - /** - * Return a special ChannelPromise which can be reused for different operations. - *

- * It's only supported to use - * it for {@link ChannelHandlerContext#write(Object, ChannelPromise)}. - *

- *

- * Be aware that the returned {@link ChannelPromise} will not support most operations and should only be used - * if you want to save an object allocation for every write operation. You will not be able to detect if the - * operation was complete, only if it failed as the implementation will call - * {@link ChannelPipeline#fireExceptionCaught(Throwable)} in this case. - *

- * Be aware this is an expert feature and should be used with care! - */ - ChannelPromise voidPromise(); - -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelInboundHandler.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelInboundHandler.java deleted file mode 100755 index 801b74a94f..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelInboundHandler.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -/** - * {@link ChannelHandler} which adds callbacks for state changes. This allows the user - * to hook in to state changes easily. - */ -public interface ChannelInboundHandler extends ChannelHandler { - - /** - * The {@link Channel} of the {@link ChannelHandlerContext} was registered with its {@link EventLoop} - */ - void channelRegistered(ChannelHandlerContext ctx) throws Exception; - - /** - * The {@link Channel} of the {@link ChannelHandlerContext} was unregistered from its {@link EventLoop} - */ - void channelUnregistered(ChannelHandlerContext ctx) throws Exception; - - /** - * The {@link Channel} of the {@link ChannelHandlerContext} is now active - */ - void channelActive(ChannelHandlerContext ctx) throws Exception; - - /** - * The {@link Channel} of the {@link ChannelHandlerContext} was registered is now inactive and reached its - * end of lifetime. - */ - void channelInactive(ChannelHandlerContext ctx) throws Exception; - - /** - * Invoked when the current {@link Channel} has read a message from the peer. - */ - void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception; - - /** - * Invoked when the last message read by the current read operation has been consumed by - * {@link #channelRead(ChannelHandlerContext, Object)}. If {@link ChannelOption#AUTO_READ} is off, no further - * attempt to read an inbound data from the current {@link Channel} will be made until - * {@link ChannelHandlerContext#read()} is called. - */ - void channelReadComplete(ChannelHandlerContext ctx) throws Exception; - - /** - * Gets called if an user event was triggered. - */ - void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception; - - /** - * Gets called once the writable state of a {@link Channel} changed. You can check the state with - * {@link Channel#isWritable()}. - */ - void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception; - - /** - * Gets called if a {@link Throwable} was thrown. - */ - @Override - void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception; -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelInboundHandlerAdapter.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelInboundHandlerAdapter.java deleted file mode 100755 index cb36ee9d2a..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelInboundHandlerAdapter.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -/** - * Abstract base class for {@link ChannelInboundHandler} implementations which provide - * implementations of all of their methods. - * - *

- * This implementation just forward the operation to the next {@link ChannelHandler} in the - * {@link ChannelPipeline}. Sub-classes may override a method implementation to change this. - *

- *

- * Be aware that messages are not released after the {@link #channelRead(ChannelHandlerContext, Object)} - * method returns automatically. If you are looking for a {@link ChannelInboundHandler} implementation that - * releases the received messages automatically, please see {@link SimpleChannelInboundHandler}. - *

- */ -public class ChannelInboundHandlerAdapter extends ChannelHandlerAdapter implements ChannelInboundHandler { - - /** - * Calls {@link ChannelHandlerContext#fireChannelRegistered()} to forward - * to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void channelRegistered(ChannelHandlerContext ctx) throws Exception { - ctx.fireChannelRegistered(); - } - - /** - * Calls {@link ChannelHandlerContext#fireChannelUnregistered()} to forward - * to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { - ctx.fireChannelUnregistered(); - } - - /** - * Calls {@link ChannelHandlerContext#fireChannelActive()} to forward - * to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { - ctx.fireChannelActive(); - } - - /** - * Calls {@link ChannelHandlerContext#fireChannelInactive()} to forward - * to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { - ctx.fireChannelInactive(); - } - - /** - * Calls {@link ChannelHandlerContext#fireChannelRead(Object)} to forward - * to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - ctx.fireChannelRead(msg); - } - - /** - * Calls {@link ChannelHandlerContext#fireChannelReadComplete()} to forward - * to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { - ctx.fireChannelReadComplete(); - } - - /** - * Calls {@link ChannelHandlerContext#fireUserEventTriggered(Object)} to forward - * to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { - ctx.fireUserEventTriggered(evt); - } - - /** - * Calls {@link ChannelHandlerContext#fireChannelWritabilityChanged()} to forward - * to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception { - ctx.fireChannelWritabilityChanged(); - } - - /** - * Calls {@link ChannelHandlerContext#fireExceptionCaught(Throwable)} to forward - * to the next {@link ChannelHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) - throws Exception { - ctx.fireExceptionCaught(cause); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelInitializer.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelInitializer.java deleted file mode 100755 index 3eac4f757a..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelInitializer.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import com.ai.cloud.io.netty.bootstrap.Bootstrap; -import com.ai.cloud.io.netty.bootstrap.ServerBootstrap; -import com.ai.cloud.io.netty.channel.ChannelHandler.Sharable; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * A special {@link ChannelInboundHandler} which offers an easy way to initialize a {@link Channel} once it was - * registered to its {@link EventLoop}. - * - * Implementations are most often used in the context of {@link Bootstrap#handler(ChannelHandler)} , - * {@link ServerBootstrap#handler(ChannelHandler)} and {@link ServerBootstrap#childHandler(ChannelHandler)} to - * setup the {@link ChannelPipeline} of a {@link Channel}. - * - *
- *
- * public class MyChannelInitializer extends {@link ChannelInitializer} {
- *     public void initChannel({@link Channel} channel) {
- *         channel.pipeline().addLast("myHandler", new MyHandler());
- *     }
- * }
- *
- * {@link ServerBootstrap} bootstrap = ...;
- * ...
- * bootstrap.childHandler(new MyChannelInitializer());
- * ...
- * 
- * Be aware that this class is marked as {@link Sharable} and so the implementation must be safe to be re-used. - * - * @param A sub-type of {@link Channel} - */ -@Sharable -public abstract class ChannelInitializer extends ChannelInboundHandlerAdapter { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(ChannelInitializer.class); - - /** - * This method will be called once the {@link Channel} was registered. After the method returns this instance - * will be removed from the {@link ChannelPipeline} of the {@link Channel}. - * - * @param ch the {@link Channel} which was registered. - * @throws Exception is thrown if an error occurs. In that case it will be handled by - * {@link #exceptionCaught(ChannelHandlerContext, Throwable)} which will by default close - * the {@link Channel}. - */ - protected abstract void initChannel(C ch) throws Exception; - - @Override - @SuppressWarnings("unchecked") - public final void channelRegistered(ChannelHandlerContext ctx) throws Exception { - initChannel((C) ctx.channel()); - ctx.pipeline().remove(this); - ctx.fireChannelRegistered(); - } - - /** - * Handle the {@link Throwable} by logging and closing the {@link Channel}. Sub-classes may override this. - */ - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - logger.warn("Failed to initialize a channel. Closing: " + ctx.channel(), cause); - try { - ChannelPipeline pipeline = ctx.pipeline(); - if (pipeline.context(this) != null) { - pipeline.remove(this); - } - } finally { - ctx.close(); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelMetadata.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelMetadata.java deleted file mode 100755 index 2b51236557..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelMetadata.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import java.net.SocketAddress; - -/** - * Represents the properties of a {@link Channel} implementation. - */ -public final class ChannelMetadata { - - private final boolean hasDisconnect; - - /** - * Create a new instance - * - * @param hasDisconnect {@code true} if and only if the channel has the {@code disconnect()} operation - * that allows a user to disconnect and then call {@link Channel#connect(SocketAddress)} - * again, such as UDP/IP. - */ - public ChannelMetadata(boolean hasDisconnect) { - this.hasDisconnect = hasDisconnect; - } - - /** - * Returns {@code true} if and only if the channel has the {@code disconnect()} operation - * that allows a user to disconnect and then call {@link Channel#connect(SocketAddress)} again, - * such as UDP/IP. - */ - public boolean hasDisconnect() { - return hasDisconnect; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelOption.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelOption.java deleted file mode 100755 index ba4d71cfb0..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelOption.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.util.concurrent.ConcurrentMap; - -import com.ai.cloud.io.netty.buffer.ByteBufAllocator; -import com.ai.cloud.io.netty.util.UniqueName; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - -import static com.ai.cloud.io.netty.util.internal.ObjectUtil.checkNotNull; - -/** - * A {@link ChannelOption} allows to configure a {@link ChannelConfig} in a type-safe - * way. Which {@link ChannelOption} is supported depends on the actual implementation - * of {@link ChannelConfig} and may depend on the nature of the transport it belongs - * to. - * - * @param the type of the value which is valid for the {@link ChannelOption} - */ -@SuppressWarnings("deprecation") -public class ChannelOption extends UniqueName { - - @SuppressWarnings("rawtypes") - private static final ConcurrentMap names = PlatformDependent.newConcurrentHashMap(); - - public static final ChannelOption ALLOCATOR = valueOf("ALLOCATOR"); - public static final ChannelOption RCVBUF_ALLOCATOR = valueOf("RCVBUF_ALLOCATOR"); - public static final ChannelOption MESSAGE_SIZE_ESTIMATOR = valueOf("MESSAGE_SIZE_ESTIMATOR"); - - public static final ChannelOption CONNECT_TIMEOUT_MILLIS = valueOf("CONNECT_TIMEOUT_MILLIS"); - public static final ChannelOption MAX_MESSAGES_PER_READ = valueOf("MAX_MESSAGES_PER_READ"); - public static final ChannelOption WRITE_SPIN_COUNT = valueOf("WRITE_SPIN_COUNT"); - public static final ChannelOption WRITE_BUFFER_HIGH_WATER_MARK = valueOf("WRITE_BUFFER_HIGH_WATER_MARK"); - public static final ChannelOption WRITE_BUFFER_LOW_WATER_MARK = valueOf("WRITE_BUFFER_LOW_WATER_MARK"); - - public static final ChannelOption ALLOW_HALF_CLOSURE = valueOf("ALLOW_HALF_CLOSURE"); - public static final ChannelOption AUTO_READ = valueOf("AUTO_READ"); - - /** - * @deprecated From version 5.0, {@link Channel} will not be closed on write failure. - * - * {@code true} if and only if the {@link Channel} is closed automatically and immediately on write failure. - * The default is {@code false}. - */ - @Deprecated - public static final ChannelOption AUTO_CLOSE = valueOf("AUTO_CLOSE"); - - public static final ChannelOption SO_BROADCAST = valueOf("SO_BROADCAST"); - public static final ChannelOption SO_KEEPALIVE = valueOf("SO_KEEPALIVE"); - public static final ChannelOption SO_SNDBUF = valueOf("SO_SNDBUF"); - public static final ChannelOption SO_RCVBUF = valueOf("SO_RCVBUF"); - public static final ChannelOption SO_REUSEADDR = valueOf("SO_REUSEADDR"); - public static final ChannelOption SO_LINGER = valueOf("SO_LINGER"); - public static final ChannelOption SO_BACKLOG = valueOf("SO_BACKLOG"); - public static final ChannelOption SO_TIMEOUT = valueOf("SO_TIMEOUT"); - - public static final ChannelOption IP_TOS = valueOf("IP_TOS"); - public static final ChannelOption IP_MULTICAST_ADDR = valueOf("IP_MULTICAST_ADDR"); - public static final ChannelOption IP_MULTICAST_IF = valueOf("IP_MULTICAST_IF"); - public static final ChannelOption IP_MULTICAST_TTL = valueOf("IP_MULTICAST_TTL"); - public static final ChannelOption IP_MULTICAST_LOOP_DISABLED = valueOf("IP_MULTICAST_LOOP_DISABLED"); - - public static final ChannelOption TCP_NODELAY = valueOf("TCP_NODELAY"); - - @Deprecated - public static final ChannelOption AIO_READ_TIMEOUT = valueOf("AIO_READ_TIMEOUT"); - @Deprecated - public static final ChannelOption AIO_WRITE_TIMEOUT = valueOf("AIO_WRITE_TIMEOUT"); - - @Deprecated - public static final ChannelOption DATAGRAM_CHANNEL_ACTIVE_ON_REGISTRATION = - valueOf("DATAGRAM_CHANNEL_ACTIVE_ON_REGISTRATION"); - - /** - * Creates a new {@link ChannelOption} with the specified {@param name} or return the already existing - * {@link ChannelOption} for the given name. - */ - @SuppressWarnings("unchecked") - public static ChannelOption valueOf(String name) { - checkNotNull(name, "name"); - ChannelOption option = names.get(name); - if (option == null) { - option = new ChannelOption(name); - ChannelOption old = names.putIfAbsent(name, option); - if (old != null) { - option = old; - } - } - return option; - } - - /** - * Returns {@code true} if a {@link ChannelOption} exists for the given {@code name}. - */ - public static boolean exists(String name) { - checkNotNull(name, "name"); - return names.containsKey(name); - } - - /** - * Creates a new {@link ChannelOption} for the given {@param name} or fail with an - * {@link IllegalArgumentException} if a {@link ChannelOption} for the given {@param name} exists. - */ - @SuppressWarnings("unchecked") - public static ChannelOption newInstance(String name) { - checkNotNull(name, "name"); - ChannelOption option = new ChannelOption(name); - ChannelOption old = names.putIfAbsent(name, option); - if (old != null) { - throw new IllegalArgumentException(String.format("'%s' is already in use", name)); - } - return option; - } - - /** - * @deprecated Use {@link #valueOf(String)} instead. - */ - @Deprecated - protected ChannelOption(String name) { - super(name); - } - - /** - * Validate the value which is set for the {@link ChannelOption}. Sub-classes - * may override this for special checks. - */ - public void validate(T value) { - if (value == null) { - throw new NullPointerException("value"); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelOutboundBuffer.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelOutboundBuffer.java deleted file mode 100755 index dcfce453d1..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelOutboundBuffer.java +++ /dev/null @@ -1,831 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import java.nio.ByteBuffer; -import java.nio.channels.ClosedChannelException; -import java.util.Arrays; -import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; -import java.util.concurrent.atomic.AtomicLongFieldUpdater; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.ByteBufHolder; -import com.ai.cloud.io.netty.buffer.Unpooled; -import com.ai.cloud.io.netty.channel.socket.nio.NioSocketChannel; -import com.ai.cloud.io.netty.util.Recycler; -import com.ai.cloud.io.netty.util.ReferenceCountUtil; -import com.ai.cloud.io.netty.util.Recycler.Handle; -import com.ai.cloud.io.netty.util.concurrent.FastThreadLocal; -import com.ai.cloud.io.netty.util.internal.InternalThreadLocalMap; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * (Transport implementors only) an internal data structure used by {@link AbstractChannel} to store its pending - * outbound write requests. - *

- * All methods must be called by a transport implementation from an I/O thread, except the following ones: - *

    - *
  • {@link #size()} and {@link #isEmpty()}
  • - *
  • {@link #isWritable()}
  • - *
  • {@link #getUserDefinedWritability(int)} and {@link #setUserDefinedWritability(int, boolean)}
  • - *
- *

- */ -public final class ChannelOutboundBuffer { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(ChannelOutboundBuffer.class); - - private static final FastThreadLocal NIO_BUFFERS = new FastThreadLocal() { - @Override - protected ByteBuffer[] initialValue() throws Exception { - return new ByteBuffer[1024]; - } - }; - - private final Channel channel; - - // Entry(flushedEntry) --> ... Entry(unflushedEntry) --> ... Entry(tailEntry) - // - // The Entry that is the first in the linked-list structure that was flushed - private Entry flushedEntry; - // The Entry which is the first unflushed in the linked-list structure - private Entry unflushedEntry; - // The Entry which represents the tail of the buffer - private Entry tailEntry; - // The number of flushed entries that are not written yet - private int flushed; - - private int nioBufferCount; - private long nioBufferSize; - - private boolean inFail; - - private static final AtomicLongFieldUpdater TOTAL_PENDING_SIZE_UPDATER; - - @SuppressWarnings("UnusedDeclaration") - private volatile long totalPendingSize; - - private static final AtomicIntegerFieldUpdater UNWRITABLE_UPDATER; - - @SuppressWarnings("UnusedDeclaration") - private volatile int unwritable; - - private volatile Runnable fireChannelWritabilityChangedTask; - - static { - AtomicIntegerFieldUpdater unwritableUpdater = - PlatformDependent.newAtomicIntegerFieldUpdater(ChannelOutboundBuffer.class, "unwritable"); - if (unwritableUpdater == null) { - unwritableUpdater = AtomicIntegerFieldUpdater.newUpdater(ChannelOutboundBuffer.class, "unwritable"); - } - UNWRITABLE_UPDATER = unwritableUpdater; - - AtomicLongFieldUpdater pendingSizeUpdater = - PlatformDependent.newAtomicLongFieldUpdater(ChannelOutboundBuffer.class, "totalPendingSize"); - if (pendingSizeUpdater == null) { - pendingSizeUpdater = AtomicLongFieldUpdater.newUpdater(ChannelOutboundBuffer.class, "totalPendingSize"); - } - TOTAL_PENDING_SIZE_UPDATER = pendingSizeUpdater; - } - - ChannelOutboundBuffer(AbstractChannel channel) { - this.channel = channel; - } - - /** - * Add given message to this {@link ChannelOutboundBuffer}. The given {@link ChannelPromise} will be notified once - * the message was written. - */ - public void addMessage(Object msg, int size, ChannelPromise promise) { - Entry entry = Entry.newInstance(msg, size, total(msg), promise); - if (tailEntry == null) { - flushedEntry = null; - tailEntry = entry; - } else { - Entry tail = tailEntry; - tail.next = entry; - tailEntry = entry; - } - if (unflushedEntry == null) { - unflushedEntry = entry; - } - - // increment pending bytes after adding message to the unflushed arrays. - // See https://github.com/netty/netty/issues/1619 - incrementPendingOutboundBytes(size, false); - } - - /** - * Add a flush to this {@link ChannelOutboundBuffer}. This means all previous added messages are marked as flushed - * and so you will be able to handle them. - */ - public void addFlush() { - // There is no need to process all entries if there was already a flush before and no new messages - // where added in the meantime. - // - // See https://github.com/netty/netty/issues/2577 - Entry entry = unflushedEntry; - if (entry != null) { - if (flushedEntry == null) { - // there is no flushedEntry yet, so start with the entry - flushedEntry = entry; - } - do { - flushed ++; - if (!entry.promise.setUncancellable()) { - // Was cancelled so make sure we free up memory and notify about the freed bytes - int pending = entry.cancel(); - decrementPendingOutboundBytes(pending, false, true); - } - entry = entry.next; - } while (entry != null); - - // All flushed so reset unflushedEntry - unflushedEntry = null; - } - } - - /** - * Increment the pending bytes which will be written at some point. - * This method is thread-safe! - */ - void incrementPendingOutboundBytes(long size) { - incrementPendingOutboundBytes(size, true); - } - - private void incrementPendingOutboundBytes(long size, boolean invokeLater) { - if (size == 0) { - return; - } - - long newWriteBufferSize = TOTAL_PENDING_SIZE_UPDATER.addAndGet(this, size); - if (newWriteBufferSize >= channel.config().getWriteBufferHighWaterMark()) { - setUnwritable(invokeLater); - } - } - - /** - * Decrement the pending bytes which will be written at some point. - * This method is thread-safe! - */ - void decrementPendingOutboundBytes(long size) { - decrementPendingOutboundBytes(size, true, true); - } - - private void decrementPendingOutboundBytes(long size, boolean invokeLater, boolean notifyWritability) { - if (size == 0) { - return; - } - - long newWriteBufferSize = TOTAL_PENDING_SIZE_UPDATER.addAndGet(this, -size); - if (notifyWritability && (newWriteBufferSize == 0 - || newWriteBufferSize <= channel.config().getWriteBufferLowWaterMark())) { - setWritable(invokeLater); - } - } - - private static long total(Object msg) { - if (msg instanceof ByteBuf) { - return ((ByteBuf) msg).readableBytes(); - } - if (msg instanceof FileRegion) { - return ((FileRegion) msg).count(); - } - if (msg instanceof ByteBufHolder) { - return ((ByteBufHolder) msg).content().readableBytes(); - } - return -1; - } - - /** - * Return the current message to write or {@code null} if nothing was flushed before and so is ready to be written. - */ - public Object current() { - Entry entry = flushedEntry; - if (entry == null) { - return null; - } - - return entry.msg; - } - - /** - * Notify the {@link ChannelPromise} of the current message about writing progress. - */ - public void progress(long amount) { - Entry e = flushedEntry; - assert e != null; - ChannelPromise p = e.promise; - if (p instanceof ChannelProgressivePromise) { - long progress = e.progress + amount; - e.progress = progress; - ((ChannelProgressivePromise) p).tryProgress(progress, e.total); - } - } - - /** - * Will remove the current message, mark its {@link ChannelPromise} as success and return {@code true}. If no - * flushed message exists at the time this method is called it will return {@code false} to signal that no more - * messages are ready to be handled. - */ - public boolean remove() { - Entry e = flushedEntry; - if (e == null) { - clearNioBuffers(); - return false; - } - Object msg = e.msg; - - ChannelPromise promise = e.promise; - int size = e.pendingSize; - - removeEntry(e); - - if (!e.cancelled) { - // only release message, notify and decrement if it was not canceled before. - ReferenceCountUtil.safeRelease(msg); - safeSuccess(promise); - decrementPendingOutboundBytes(size, false, true); - } - - // recycle the entry - e.recycle(); - - return true; - } - - /** - * Will remove the current message, mark its {@link ChannelPromise} as failure using the given {@link Throwable} - * and return {@code true}. If no flushed message exists at the time this method is called it will return - * {@code false} to signal that no more messages are ready to be handled. - */ - public boolean remove(Throwable cause) { - return remove0(cause, true); - } - - private boolean remove0(Throwable cause, boolean notifyWritability) { - Entry e = flushedEntry; - if (e == null) { - clearNioBuffers(); - return false; - } - Object msg = e.msg; - - ChannelPromise promise = e.promise; - int size = e.pendingSize; - - removeEntry(e); - - if (!e.cancelled) { - // only release message, fail and decrement if it was not canceled before. - ReferenceCountUtil.safeRelease(msg); - - safeFail(promise, cause); - decrementPendingOutboundBytes(size, false, notifyWritability); - } - - // recycle the entry - e.recycle(); - - return true; - } - - private void removeEntry(Entry e) { - if (-- flushed == 0) { - // processed everything - flushedEntry = null; - if (e == tailEntry) { - tailEntry = null; - unflushedEntry = null; - } - } else { - flushedEntry = e.next; - } - } - - /** - * Removes the fully written entries and update the reader index of the partially written entry. - * This operation assumes all messages in this buffer is {@link ByteBuf}. - */ - public void removeBytes(long writtenBytes) { - for (;;) { - Object msg = current(); - if (!(msg instanceof ByteBuf)) { - assert writtenBytes == 0; - break; - } - - final ByteBuf buf = (ByteBuf) msg; - final int readerIndex = buf.readerIndex(); - final int readableBytes = buf.writerIndex() - readerIndex; - - if (readableBytes <= writtenBytes) { - if (writtenBytes != 0) { - progress(readableBytes); - writtenBytes -= readableBytes; - } - remove(); - } else { // readableBytes > writtenBytes - if (writtenBytes != 0) { - buf.readerIndex(readerIndex + (int) writtenBytes); - progress(writtenBytes); - } - break; - } - } - clearNioBuffers(); - } - - // Clear all ByteBuffer from the array so these can be GC'ed. - // See https://github.com/netty/netty/issues/3837 - private void clearNioBuffers() { - int count = nioBufferCount; - if (count > 0) { - nioBufferCount = 0; - Arrays.fill(NIO_BUFFERS.get(), 0, count, null); - } - } - - /** - * Returns an array of direct NIO buffers if the currently pending messages are made of {@link ByteBuf} only. - * {@link #nioBufferCount()} and {@link #nioBufferSize()} will return the number of NIO buffers in the returned - * array and the total number of readable bytes of the NIO buffers respectively. - *

- * Note that the returned array is reused and thus should not escape - * {@link AbstractChannel#doWrite(ChannelOutboundBuffer)}. - * Refer to {@link NioSocketChannel#doWrite(ChannelOutboundBuffer)} for an example. - *

- */ - public ByteBuffer[] nioBuffers() { - long nioBufferSize = 0; - int nioBufferCount = 0; - final InternalThreadLocalMap threadLocalMap = InternalThreadLocalMap.get(); - ByteBuffer[] nioBuffers = NIO_BUFFERS.get(threadLocalMap); - Entry entry = flushedEntry; - while (isFlushedEntry(entry) && entry.msg instanceof ByteBuf) { - if (!entry.cancelled) { - ByteBuf buf = (ByteBuf) entry.msg; - final int readerIndex = buf.readerIndex(); - final int readableBytes = buf.writerIndex() - readerIndex; - - if (readableBytes > 0) { - if (Integer.MAX_VALUE - readableBytes < nioBufferSize) { - // If the nioBufferSize + readableBytes will overflow an Integer we stop populate the - // ByteBuffer array. This is done as bsd/osx don't allow to write more bytes then - // Integer.MAX_VALUE with one writev(...) call and so will return 'EINVAL', which will - // raise an IOException. On Linux it may work depending on the - // architecture and kernel but to be safe we also enforce the limit here. - // This said writing more the Integer.MAX_VALUE is not a good idea anyway. - // - // See also: - // - https://www.freebsd.org/cgi/man.cgi?query=write&sektion=2 - // - http://linux.die.net/man/2/writev - break; - } - nioBufferSize += readableBytes; - int count = entry.count; - if (count == -1) { - //noinspection ConstantValueVariableUse - entry.count = count = buf.nioBufferCount(); - } - int neededSpace = nioBufferCount + count; - if (neededSpace > nioBuffers.length) { - nioBuffers = expandNioBufferArray(nioBuffers, neededSpace, nioBufferCount); - NIO_BUFFERS.set(threadLocalMap, nioBuffers); - } - if (count == 1) { - ByteBuffer nioBuf = entry.buf; - if (nioBuf == null) { - // cache ByteBuffer as it may need to create a new ByteBuffer instance if its a - // derived buffer - entry.buf = nioBuf = buf.internalNioBuffer(readerIndex, readableBytes); - } - nioBuffers[nioBufferCount ++] = nioBuf; - } else { - ByteBuffer[] nioBufs = entry.bufs; - if (nioBufs == null) { - // cached ByteBuffers as they may be expensive to create in terms - // of Object allocation - entry.bufs = nioBufs = buf.nioBuffers(); - } - nioBufferCount = fillBufferArray(nioBufs, nioBuffers, nioBufferCount); - } - } - } - entry = entry.next; - } - this.nioBufferCount = nioBufferCount; - this.nioBufferSize = nioBufferSize; - - return nioBuffers; - } - - private static int fillBufferArray(ByteBuffer[] nioBufs, ByteBuffer[] nioBuffers, int nioBufferCount) { - for (ByteBuffer nioBuf: nioBufs) { - if (nioBuf == null) { - break; - } - nioBuffers[nioBufferCount ++] = nioBuf; - } - return nioBufferCount; - } - - private static ByteBuffer[] expandNioBufferArray(ByteBuffer[] array, int neededSpace, int size) { - int newCapacity = array.length; - do { - // double capacity until it is big enough - // See https://github.com/netty/netty/issues/1890 - newCapacity <<= 1; - - if (newCapacity < 0) { - throw new IllegalStateException(); - } - - } while (neededSpace > newCapacity); - - ByteBuffer[] newArray = new ByteBuffer[newCapacity]; - System.arraycopy(array, 0, newArray, 0, size); - - return newArray; - } - - /** - * Returns the number of {@link ByteBuffer} that can be written out of the {@link ByteBuffer} array that was - * obtained via {@link #nioBuffers()}. This method MUST be called after {@link #nioBuffers()} - * was called. - */ - public int nioBufferCount() { - return nioBufferCount; - } - - /** - * Returns the number of bytes that can be written out of the {@link ByteBuffer} array that was - * obtained via {@link #nioBuffers()}. This method MUST be called after {@link #nioBuffers()} - * was called. - */ - public long nioBufferSize() { - return nioBufferSize; - } - - /** - * Returns {@code true} if and only if {@linkplain #totalPendingWriteBytes() the total number of pending bytes} did - * not exceed the write watermark of the {@link Channel} and - * no {@linkplain #setUserDefinedWritability(int, boolean) user-defined writability flag} has been set to - * {@code false}. - */ - public boolean isWritable() { - return unwritable == 0; - } - - /** - * Returns {@code true} if and only if the user-defined writability flag at the specified index is set to - * {@code true}. - */ - public boolean getUserDefinedWritability(int index) { - return (unwritable & writabilityMask(index)) == 0; - } - - /** - * Sets a user-defined writability flag at the specified index. - */ - public void setUserDefinedWritability(int index, boolean writable) { - if (writable) { - setUserDefinedWritability(index); - } else { - clearUserDefinedWritability(index); - } - } - - private void setUserDefinedWritability(int index) { - final int mask = ~writabilityMask(index); - for (;;) { - final int oldValue = unwritable; - final int newValue = oldValue & mask; - if (UNWRITABLE_UPDATER.compareAndSet(this, oldValue, newValue)) { - if (oldValue != 0 && newValue == 0) { - fireChannelWritabilityChanged(true); - } - break; - } - } - } - - private void clearUserDefinedWritability(int index) { - final int mask = writabilityMask(index); - for (;;) { - final int oldValue = unwritable; - final int newValue = oldValue | mask; - if (UNWRITABLE_UPDATER.compareAndSet(this, oldValue, newValue)) { - if (oldValue == 0 && newValue != 0) { - fireChannelWritabilityChanged(true); - } - break; - } - } - } - - private static int writabilityMask(int index) { - if (index < 1 || index > 31) { - throw new IllegalArgumentException("index: " + index + " (expected: 1~31)"); - } - return 1 << index; - } - - private void setWritable(boolean invokeLater) { - for (;;) { - final int oldValue = unwritable; - final int newValue = oldValue & ~1; - if (UNWRITABLE_UPDATER.compareAndSet(this, oldValue, newValue)) { - if (oldValue != 0 && newValue == 0) { - fireChannelWritabilityChanged(invokeLater); - } - break; - } - } - } - - private void setUnwritable(boolean invokeLater) { - for (;;) { - final int oldValue = unwritable; - final int newValue = oldValue | 1; - if (UNWRITABLE_UPDATER.compareAndSet(this, oldValue, newValue)) { - if (oldValue == 0 && newValue != 0) { - fireChannelWritabilityChanged(invokeLater); - } - break; - } - } - } - - private void fireChannelWritabilityChanged(boolean invokeLater) { - final ChannelPipeline pipeline = channel.pipeline(); - if (invokeLater) { - Runnable task = fireChannelWritabilityChangedTask; - if (task == null) { - fireChannelWritabilityChangedTask = task = new Runnable() { - @Override - public void run() { - pipeline.fireChannelWritabilityChanged(); - } - }; - } - channel.eventLoop().execute(task); - } else { - pipeline.fireChannelWritabilityChanged(); - } - } - - /** - * Returns the number of flushed messages in this {@link ChannelOutboundBuffer}. - */ - public int size() { - return flushed; - } - - /** - * Returns {@code true} if there are flushed messages in this {@link ChannelOutboundBuffer} or {@code false} - * otherwise. - */ - public boolean isEmpty() { - return flushed == 0; - } - - void failFlushed(Throwable cause, boolean notify) { - // Make sure that this method does not reenter. A listener added to the current promise can be notified by the - // current thread in the tryFailure() call of the loop below, and the listener can trigger another fail() call - // indirectly (usually by closing the channel.) - // - // See https://github.com/netty/netty/issues/1501 - if (inFail) { - return; - } - - try { - inFail = true; - for (;;) { - if (!remove0(cause, notify)) { - break; - } - } - } finally { - inFail = false; - } - } - - void close(final ClosedChannelException cause) { - if (inFail) { - channel.eventLoop().execute(new Runnable() { - @Override - public void run() { - close(cause); - } - }); - return; - } - - inFail = true; - - if (channel.isOpen()) { - throw new IllegalStateException("close() must be invoked after the channel is closed."); - } - - if (!isEmpty()) { - throw new IllegalStateException("close() must be invoked after all flushed writes are handled."); - } - - // Release all unflushed messages. - try { - Entry e = unflushedEntry; - while (e != null) { - // Just decrease; do not trigger any events via decrementPendingOutboundBytes() - int size = e.pendingSize; - TOTAL_PENDING_SIZE_UPDATER.addAndGet(this, -size); - - if (!e.cancelled) { - ReferenceCountUtil.safeRelease(e.msg); - safeFail(e.promise, cause); - } - e = e.recycleAndGetNext(); - } - } finally { - inFail = false; - } - clearNioBuffers(); - } - - private static void safeSuccess(ChannelPromise promise) { - if (!(promise instanceof VoidChannelPromise) && !promise.trySuccess()) { - logger.warn("Failed to mark a promise as success because it is done already: {}", promise); - } - } - - private static void safeFail(ChannelPromise promise, Throwable cause) { - if (!(promise instanceof VoidChannelPromise) && !promise.tryFailure(cause)) { - logger.warn("Failed to mark a promise as failure because it's done already: {}", promise, cause); - } - } - - @Deprecated - public void recycle() { - // NOOP - } - - public long totalPendingWriteBytes() { - return totalPendingSize; - } - - /** - * Get how many bytes can be written until {@link #isWritable()} returns {@code false}. - * This quantity will always be non-negative. If {@link #isWritable()} is {@code false} then 0. - */ - public long bytesBeforeUnwritable() { - long bytes = channel.config().getWriteBufferHighWaterMark() - totalPendingSize; - // If bytes is negative we know we are not writable, but if bytes is non-negative we have to check writability. - // Note that totalPendingSize and isWritable() use different volatile variables that are not synchronized - // together. totalPendingSize will be updated before isWritable(). - if (bytes > 0) { - return isWritable() ? bytes : 0; - } - return 0; - } - - /** - * Get how many bytes must be drained from the underlying buffer until {@link #isWritable()} returns {@code true}. - * This quantity will always be non-negative. If {@link #isWritable()} is {@code true} then 0. - */ - public long bytesBeforeWritable() { - long bytes = totalPendingSize - channel.config().getWriteBufferLowWaterMark(); - // If bytes is negative we know we are writable, but if bytes is non-negative we have to check writability. - // Note that totalPendingSize and isWritable() use different volatile variables that are not synchronized - // together. totalPendingSize will be updated before isWritable(). - if (bytes > 0) { - return isWritable() ? 0 : bytes; - } - return 0; - } - - /** - * Call {@link MessageProcessor#processMessage(Object)} for each flushed message - * in this {@link ChannelOutboundBuffer} until {@link MessageProcessor#processMessage(Object)} - * returns {@code false} or there are no more flushed messages to process. - */ - public void forEachFlushedMessage(MessageProcessor processor) throws Exception { - if (processor == null) { - throw new NullPointerException("processor"); - } - - Entry entry = flushedEntry; - if (entry == null) { - return; - } - - do { - if (!entry.cancelled) { - if (!processor.processMessage(entry.msg)) { - return; - } - } - entry = entry.next; - } while (isFlushedEntry(entry)); - } - - private boolean isFlushedEntry(Entry e) { - return e != null && e != unflushedEntry; - } - - public interface MessageProcessor { - /** - * Will be called for each flushed message until it either there are no more flushed messages or this - * method returns {@code false}. - */ - boolean processMessage(Object msg) throws Exception; - } - - static final class Entry { - private static final Recycler RECYCLER = new Recycler() { - @Override - protected Entry newObject(Handle handle) { - return new Entry(handle); - } - }; - - private final Handle handle; - Entry next; - Object msg; - ByteBuffer[] bufs; - ByteBuffer buf; - ChannelPromise promise; - long progress; - long total; - int pendingSize; - int count = -1; - boolean cancelled; - - private Entry(Handle handle) { - this.handle = handle; - } - - static Entry newInstance(Object msg, int size, long total, ChannelPromise promise) { - Entry entry = RECYCLER.get(); - entry.msg = msg; - entry.pendingSize = size; - entry.total = total; - entry.promise = promise; - return entry; - } - - int cancel() { - if (!cancelled) { - cancelled = true; - int pSize = pendingSize; - - // release message and replace with an empty buffer - ReferenceCountUtil.safeRelease(msg); - msg = Unpooled.EMPTY_BUFFER; - - pendingSize = 0; - total = 0; - progress = 0; - bufs = null; - buf = null; - return pSize; - } - return 0; - } - - void recycle() { - next = null; - bufs = null; - buf = null; - msg = null; - promise = null; - progress = 0; - total = 0; - pendingSize = 0; - count = -1; - cancelled = false; - RECYCLER.recycle(this, handle); - } - - Entry recycleAndGetNext() { - Entry next = this.next; - recycle(); - return next; - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelOutboundHandler.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelOutboundHandler.java deleted file mode 100755 index 9f8e7c9202..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelOutboundHandler.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import java.net.SocketAddress; - -/** - * {@link ChannelHandler} which will get notified for IO-outbound-operations. - */ -public interface ChannelOutboundHandler extends ChannelHandler { - /** - * Called once a bind operation is made. - * - * @param ctx the {@link ChannelHandlerContext} for which the bind operation is made - * @param localAddress the {@link SocketAddress} to which it should bound - * @param promise the {@link ChannelPromise} to notify once the operation completes - * @throws Exception thrown if an error accour - */ - void bind(ChannelHandlerContext ctx, SocketAddress localAddress, ChannelPromise promise) throws Exception; - - /** - * Called once a connect operation is made. - * - * @param ctx the {@link ChannelHandlerContext} for which the connect operation is made - * @param remoteAddress the {@link SocketAddress} to which it should connect - * @param localAddress the {@link SocketAddress} which is used as source on connect - * @param promise the {@link ChannelPromise} to notify once the operation completes - * @throws Exception thrown if an error accour - */ - void connect( - ChannelHandlerContext ctx, SocketAddress remoteAddress, - SocketAddress localAddress, ChannelPromise promise) throws Exception; - - /** - * Called once a disconnect operation is made. - * - * @param ctx the {@link ChannelHandlerContext} for which the disconnect operation is made - * @param promise the {@link ChannelPromise} to notify once the operation completes - * @throws Exception thrown if an error accour - */ - void disconnect(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception; - - /** - * Called once a close operation is made. - * - * @param ctx the {@link ChannelHandlerContext} for which the close operation is made - * @param promise the {@link ChannelPromise} to notify once the operation completes - * @throws Exception thrown if an error accour - */ - void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception; - - /** - * Called once a deregister operation is made from the current registered {@link EventLoop}. - * - * @param ctx the {@link ChannelHandlerContext} for which the close operation is made - * @param promise the {@link ChannelPromise} to notify once the operation completes - * @throws Exception thrown if an error accour - */ - void deregister(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception; - - /** - * Intercepts {@link ChannelHandlerContext#read()}. - */ - void read(ChannelHandlerContext ctx) throws Exception; - - /** - * Called once a write operation is made. The write operation will write the messages through the - * {@link ChannelPipeline}. Those are then ready to be flushed to the actual {@link Channel} once - * {@link Channel#flush()} is called - * - * @param ctx the {@link ChannelHandlerContext} for which the write operation is made - * @param msg the message to write - * @param promise the {@link ChannelPromise} to notify once the operation completes - * @throws Exception thrown if an error accour - */ - void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception; - - /** - * Called once a flush operation is made. The flush operation will try to flush out all previous written messages - * that are pending. - * - * @param ctx the {@link ChannelHandlerContext} for which the flush operation is made - * @throws Exception thrown if an error accour - */ - void flush(ChannelHandlerContext ctx) throws Exception; -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelOutboundHandlerAdapter.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelOutboundHandlerAdapter.java deleted file mode 100755 index 8f32582582..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelOutboundHandlerAdapter.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import java.net.SocketAddress; - -/** - * Skelton implementation of a {@link ChannelOutboundHandler}. This implementation just forwards each method call via - * the {@link ChannelHandlerContext}. - */ -public class ChannelOutboundHandlerAdapter extends ChannelHandlerAdapter implements ChannelOutboundHandler { - - /** - * Calls {@link ChannelHandlerContext#bind(SocketAddress, ChannelPromise)} to forward - * to the next {@link ChannelOutboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void bind(ChannelHandlerContext ctx, SocketAddress localAddress, - ChannelPromise promise) throws Exception { - ctx.bind(localAddress, promise); - } - - /** - * Calls {@link ChannelHandlerContext#connect(SocketAddress, SocketAddress, ChannelPromise)} to forward - * to the next {@link ChannelOutboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress, - SocketAddress localAddress, ChannelPromise promise) throws Exception { - ctx.connect(remoteAddress, localAddress, promise); - } - - /** - * Calls {@link ChannelHandlerContext#disconnect(ChannelPromise)} to forward - * to the next {@link ChannelOutboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void disconnect(ChannelHandlerContext ctx, ChannelPromise promise) - throws Exception { - ctx.disconnect(promise); - } - - /** - * Calls {@link ChannelHandlerContext#close(ChannelPromise)} to forward - * to the next {@link ChannelOutboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void close(ChannelHandlerContext ctx, ChannelPromise promise) - throws Exception { - ctx.close(promise); - } - - /** - * Calls {@link ChannelHandlerContext#close(ChannelPromise)} to forward - * to the next {@link ChannelOutboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void deregister(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception { - ctx.deregister(promise); - } - - /** - * Calls {@link ChannelHandlerContext#read()} to forward - * to the next {@link ChannelOutboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void read(ChannelHandlerContext ctx) throws Exception { - ctx.read(); - } - - /** - * Calls {@link ChannelHandlerContext#write(Object)} to forward - * to the next {@link ChannelOutboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - ctx.write(msg, promise); - } - - /** - * Calls {@link ChannelHandlerContext#flush()} to forward - * to the next {@link ChannelOutboundHandler} in the {@link ChannelPipeline}. - * - * Sub-classes may override this method to change behavior. - */ - @Override - public void flush(ChannelHandlerContext ctx) throws Exception { - ctx.flush(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelPipeline.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelPipeline.java deleted file mode 100755 index 53fb778f3f..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelPipeline.java +++ /dev/null @@ -1,879 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import java.net.ConnectException; -import java.net.SocketAddress; -import java.nio.ByteBuffer; -import java.nio.channels.SocketChannel; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.NoSuchElementException; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.util.concurrent.DefaultEventExecutorGroup; -import com.ai.cloud.io.netty.util.concurrent.EventExecutor; -import com.ai.cloud.io.netty.util.concurrent.EventExecutorGroup; - - -/** - * A list of {@link ChannelHandler}s which handles or intercepts inbound events and outbound operations of a - * {@link Channel}. {@link ChannelPipeline} implements an advanced form of the - * Intercepting Filter pattern - * to give a user full control over how an event is handled and how the {@link ChannelHandler}s in a pipeline - * interact with each other. - * - *

Creation of a pipeline

- * - * Each channel has its own pipeline and it is created automatically when a new channel is created. - * - *

How an event flows in a pipeline

- * - * The following diagram describes how I/O events are processed by {@link ChannelHandler}s in a {@link ChannelPipeline} - * typically. An I/O event is handled by either a {@link ChannelInboundHandler} or a {@link ChannelOutboundHandler} - * and be forwarded to its closest handler by calling the event propagation methods defined in - * {@link ChannelHandlerContext}, such as {@link ChannelHandlerContext#fireChannelRead(Object)} and - * {@link ChannelHandlerContext#write(Object)}. - * - *
- *                                                 I/O Request
- *                                            via {@link Channel} or
- *                                        {@link ChannelHandlerContext}
- *                                                      |
- *  +---------------------------------------------------+---------------+
- *  |                           ChannelPipeline         |               |
- *  |                                                  \|/              |
- *  |    +---------------------+            +-----------+----------+    |
- *  |    | Inbound Handler  N  |            | Outbound Handler  1  |    |
- *  |    +----------+----------+            +-----------+----------+    |
- *  |              /|\                                  |               |
- *  |               |                                  \|/              |
- *  |    +----------+----------+            +-----------+----------+    |
- *  |    | Inbound Handler N-1 |            | Outbound Handler  2  |    |
- *  |    +----------+----------+            +-----------+----------+    |
- *  |              /|\                                  .               |
- *  |               .                                   .               |
- *  | ChannelHandlerContext.fireIN_EVT() ChannelHandlerContext.OUT_EVT()|
- *  |        [ method call]                       [method call]         |
- *  |               .                                   .               |
- *  |               .                                  \|/              |
- *  |    +----------+----------+            +-----------+----------+    |
- *  |    | Inbound Handler  2  |            | Outbound Handler M-1 |    |
- *  |    +----------+----------+            +-----------+----------+    |
- *  |              /|\                                  |               |
- *  |               |                                  \|/              |
- *  |    +----------+----------+            +-----------+----------+    |
- *  |    | Inbound Handler  1  |            | Outbound Handler  M  |    |
- *  |    +----------+----------+            +-----------+----------+    |
- *  |              /|\                                  |               |
- *  +---------------+-----------------------------------+---------------+
- *                  |                                  \|/
- *  +---------------+-----------------------------------+---------------+
- *  |               |                                   |               |
- *  |       [ Socket.read() ]                    [ Socket.write() ]     |
- *  |                                                                   |
- *  |  Netty Internal I/O Threads (Transport Implementation)            |
- *  +-------------------------------------------------------------------+
- * 
- * An inbound event is handled by the inbound handlers in the bottom-up direction as shown on the left side of the - * diagram. An inbound handler usually handles the inbound data generated by the I/O thread on the bottom of the - * diagram. The inbound data is often read from a remote peer via the actual input operation such as - * {@link SocketChannel#read(ByteBuffer)}. If an inbound event goes beyond the top inbound handler, it is discarded - * silently, or logged if it needs your attention. - *

- * An outbound event is handled by the outbound handler in the top-down direction as shown on the right side of the - * diagram. An outbound handler usually generates or transforms the outbound traffic such as write requests. - * If an outbound event goes beyond the bottom outbound handler, it is handled by an I/O thread associated with the - * {@link Channel}. The I/O thread often performs the actual output operation such as - * {@link SocketChannel#write(ByteBuffer)}. - *

- * For example, let us assume that we created the following pipeline: - *

- * {@link ChannelPipeline} p = ...;
- * p.addLast("1", new InboundHandlerA());
- * p.addLast("2", new InboundHandlerB());
- * p.addLast("3", new OutboundHandlerA());
- * p.addLast("4", new OutboundHandlerB());
- * p.addLast("5", new InboundOutboundHandlerX());
- * 
- * In the example above, the class whose name starts with {@code Inbound} means it is an inbound handler. - * The class whose name starts with {@code Outbound} means it is a outbound handler. - *

- * In the given example configuration, the handler evaluation order is 1, 2, 3, 4, 5 when an event goes inbound. - * When an event goes outbound, the order is 5, 4, 3, 2, 1. On top of this principle, {@link ChannelPipeline} skips - * the evaluation of certain handlers to shorten the stack depth: - *

    - *
  • 3 and 4 don't implement {@link ChannelInboundHandler}, and therefore the actual evaluation order of an inbound - * event will be: 1, 2, and 5.
  • - *
  • 1 and 2 don't implement {@link ChannelOutboundHandler}, and therefore the actual evaluation order of a - * outbound event will be: 5, 4, and 3.
  • - *
  • If 5 implements both {@link ChannelInboundHandler} and {@link ChannelOutboundHandler}, the evaluation order of - * an inbound and a outbound event could be 125 and 543 respectively.
  • - *
- * - *

Forwarding an event to the next handler

- * - * As you might noticed in the diagram shows, a handler has to invoke the event propagation methods in - * {@link ChannelHandlerContext} to forward an event to its next handler. Those methods include: - *
    - *
  • Inbound event propagation methods: - *
      - *
    • {@link ChannelHandlerContext#fireChannelRegistered()}
    • - *
    • {@link ChannelHandlerContext#fireChannelActive()}
    • - *
    • {@link ChannelHandlerContext#fireChannelRead(Object)}
    • - *
    • {@link ChannelHandlerContext#fireChannelReadComplete()}
    • - *
    • {@link ChannelHandlerContext#fireExceptionCaught(Throwable)}
    • - *
    • {@link ChannelHandlerContext#fireUserEventTriggered(Object)}
    • - *
    • {@link ChannelHandlerContext#fireChannelWritabilityChanged()}
    • - *
    • {@link ChannelHandlerContext#fireChannelInactive()}
    • - *
    • {@link ChannelHandlerContext#fireChannelUnregistered()}
    • - *
    - *
  • - *
  • Outbound event propagation methods: - *
      - *
    • {@link ChannelHandlerContext#bind(SocketAddress, ChannelPromise)}
    • - *
    • {@link ChannelHandlerContext#connect(SocketAddress, SocketAddress, ChannelPromise)}
    • - *
    • {@link ChannelHandlerContext#write(Object, ChannelPromise)}
    • - *
    • {@link ChannelHandlerContext#flush()}
    • - *
    • {@link ChannelHandlerContext#read()}
    • - *
    • {@link ChannelHandlerContext#disconnect(ChannelPromise)}
    • - *
    • {@link ChannelHandlerContext#close(ChannelPromise)}
    • - *
    • {@link ChannelHandlerContext#deregister(ChannelPromise)}
    • - *
    - *
  • - *
- * - * and the following example shows how the event propagation is usually done: - * - *
- * public class MyInboundHandler extends {@link ChannelInboundHandlerAdapter} {
- *     {@code @Override}
- *     public void channelActive({@link ChannelHandlerContext} ctx) {
- *         System.out.println("Connected!");
- *         ctx.fireChannelActive();
- *     }
- * }
- *
- * public clas MyOutboundHandler extends {@link ChannelOutboundHandlerAdapter} {
- *     {@code @Override}
- *     public void close({@link ChannelHandlerContext} ctx, {@link ChannelPromise} promise) {
- *         System.out.println("Closing ..");
- *         ctx.close(promise);
- *     }
- * }
- * 
- * - *

Building a pipeline

- *

- * A user is supposed to have one or more {@link ChannelHandler}s in a pipeline to receive I/O events (e.g. read) and - * to request I/O operations (e.g. write and close). For example, a typical server will have the following handlers - * in each channel's pipeline, but your mileage may vary depending on the complexity and characteristics of the - * protocol and business logic: - * - *

    - *
  1. Protocol Decoder - translates binary data (e.g. {@link ByteBuf}) into a Java object.
  2. - *
  3. Protocol Encoder - translates a Java object into binary data.
  4. - *
  5. Business Logic Handler - performs the actual business logic (e.g. database access).
  6. - *
- * - * and it could be represented as shown in the following example: - * - *
- * static final {@link EventExecutorGroup} group = new {@link DefaultEventExecutorGroup}(16);
- * ...
- *
- * {@link ChannelPipeline} pipeline = ch.pipeline();
- *
- * pipeline.addLast("decoder", new MyProtocolDecoder());
- * pipeline.addLast("encoder", new MyProtocolEncoder());
- *
- * // Tell the pipeline to run MyBusinessLogicHandler's event handler methods
- * // in a different thread than an I/O thread so that the I/O thread is not blocked by
- * // a time-consuming task.
- * // If your business logic is fully asynchronous or finished very quickly, you don't
- * // need to specify a group.
- * pipeline.addLast(group, "handler", new MyBusinessLogicHandler());
- * 
- * - *

Thread safety

- *

- * A {@link ChannelHandler} can be added or removed at any time because a {@link ChannelPipeline} is thread safe. - * For example, you can insert an encryption handler when sensitive information is about to be exchanged, and remove it - * after the exchange. - */ -public interface ChannelPipeline - extends Iterable> { - - /** - * Inserts a {@link ChannelHandler} at the first position of this pipeline. - * - * @param name the name of the handler to insert first - * @param handler the handler to insert first - * - * @throws IllegalArgumentException - * if there's an entry with the same name already in the pipeline - * @throws NullPointerException - * if the specified name or handler is {@code null} - */ - ChannelPipeline addFirst(String name, ChannelHandler handler); - - /** - * Inserts a {@link ChannelHandler} at the first position of this pipeline. - * - * @param group the {@link EventExecutorGroup} which will be used to execute the {@link ChannelHandler} - * methods - * @param name the name of the handler to insert first - * @param handler the handler to insert first - * - * @throws IllegalArgumentException - * if there's an entry with the same name already in the pipeline - * @throws NullPointerException - * if the specified name or handler is {@code null} - */ - ChannelPipeline addFirst(EventExecutorGroup group, String name, ChannelHandler handler); - - /** - * Appends a {@link ChannelHandler} at the last position of this pipeline. - * - * @param name the name of the handler to append - * @param handler the handler to append - * - * @throws IllegalArgumentException - * if there's an entry with the same name already in the pipeline - * @throws NullPointerException - * if the specified name or handler is {@code null} - */ - ChannelPipeline addLast(String name, ChannelHandler handler); - - /** - * Appends a {@link ChannelHandler} at the last position of this pipeline. - * - * @param group the {@link EventExecutorGroup} which will be used to execute the {@link ChannelHandler} - * methods - * @param name the name of the handler to append - * @param handler the handler to append - * - * @throws IllegalArgumentException - * if there's an entry with the same name already in the pipeline - * @throws NullPointerException - * if the specified name or handler is {@code null} - */ - ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler); - - /** - * Inserts a {@link ChannelHandler} before an existing handler of this - * pipeline. - * - * @param baseName the name of the existing handler - * @param name the name of the handler to insert before - * @param handler the handler to insert before - * - * @throws NoSuchElementException - * if there's no such entry with the specified {@code baseName} - * @throws IllegalArgumentException - * if there's an entry with the same name already in the pipeline - * @throws NullPointerException - * if the specified baseName, name, or handler is {@code null} - */ - ChannelPipeline addBefore(String baseName, String name, ChannelHandler handler); - - /** - * Inserts a {@link ChannelHandler} before an existing handler of this - * pipeline. - * - * @param group the {@link EventExecutorGroup} which will be used to execute the {@link ChannelHandler} - * methods - * @param baseName the name of the existing handler - * @param name the name of the handler to insert before - * @param handler the handler to insert before - * - * @throws NoSuchElementException - * if there's no such entry with the specified {@code baseName} - * @throws IllegalArgumentException - * if there's an entry with the same name already in the pipeline - * @throws NullPointerException - * if the specified baseName, name, or handler is {@code null} - */ - ChannelPipeline addBefore(EventExecutorGroup group, String baseName, String name, ChannelHandler handler); - - /** - * Inserts a {@link ChannelHandler} after an existing handler of this - * pipeline. - * - * @param baseName the name of the existing handler - * @param name the name of the handler to insert after - * @param handler the handler to insert after - * - * @throws NoSuchElementException - * if there's no such entry with the specified {@code baseName} - * @throws IllegalArgumentException - * if there's an entry with the same name already in the pipeline - * @throws NullPointerException - * if the specified baseName, name, or handler is {@code null} - */ - ChannelPipeline addAfter(String baseName, String name, ChannelHandler handler); - - /** - * Inserts a {@link ChannelHandler} after an existing handler of this - * pipeline. - * - * @param group the {@link EventExecutorGroup} which will be used to execute the {@link ChannelHandler} - * methods - * @param baseName the name of the existing handler - * @param name the name of the handler to insert after - * @param handler the handler to insert after - * - * @throws NoSuchElementException - * if there's no such entry with the specified {@code baseName} - * @throws IllegalArgumentException - * if there's an entry with the same name already in the pipeline - * @throws NullPointerException - * if the specified baseName, name, or handler is {@code null} - */ - ChannelPipeline addAfter(EventExecutorGroup group, String baseName, String name, ChannelHandler handler); - - /** - * Inserts a {@link ChannelHandler}s at the first position of this pipeline. - * - * @param handlers the handlers to insert first - * - */ - ChannelPipeline addFirst(ChannelHandler... handlers); - - /** - * Inserts a {@link ChannelHandler}s at the first position of this pipeline. - * - * @param group the {@link EventExecutorGroup} which will be used to execute the {@link ChannelHandler}s - * methods. - * @param handlers the handlers to insert first - * - */ - ChannelPipeline addFirst(EventExecutorGroup group, ChannelHandler... handlers); - - /** - * Inserts a {@link ChannelHandler}s at the last position of this pipeline. - * - * @param handlers the handlers to insert last - * - */ - ChannelPipeline addLast(ChannelHandler... handlers); - - /** - * Inserts a {@link ChannelHandler}s at the last position of this pipeline. - * - * @param group the {@link EventExecutorGroup} which will be used to execute the {@link ChannelHandler}s - * methods. - * @param handlers the handlers to insert last - * - */ - ChannelPipeline addLast(EventExecutorGroup group, ChannelHandler... handlers); - - /** - * Removes the specified {@link ChannelHandler} from this pipeline. - * - * @param handler the {@link ChannelHandler} to remove - * - * @throws NoSuchElementException - * if there's no such handler in this pipeline - * @throws NullPointerException - * if the specified handler is {@code null} - */ - ChannelPipeline remove(ChannelHandler handler); - - /** - * Removes the {@link ChannelHandler} with the specified name from this pipeline. - * - * @param name the name under which the {@link ChannelHandler} was stored. - * - * @return the removed handler - * - * @throws NoSuchElementException - * if there's no such handler with the specified name in this pipeline - * @throws NullPointerException - * if the specified name is {@code null} - */ - ChannelHandler remove(String name); - - /** - * Removes the {@link ChannelHandler} of the specified type from this pipeline. - * - * @param the type of the handler - * @param handlerType the type of the handler - * - * @return the removed handler - * - * @throws NoSuchElementException - * if there's no such handler of the specified type in this pipeline - * @throws NullPointerException - * if the specified handler type is {@code null} - */ - T remove(Class handlerType); - - /** - * Removes the first {@link ChannelHandler} in this pipeline. - * - * @return the removed handler - * - * @throws NoSuchElementException - * if this pipeline is empty - */ - ChannelHandler removeFirst(); - - /** - * Removes the last {@link ChannelHandler} in this pipeline. - * - * @return the removed handler - * - * @throws NoSuchElementException - * if this pipeline is empty - */ - ChannelHandler removeLast(); - - /** - * Replaces the specified {@link ChannelHandler} with a new handler in this pipeline. - * - * @param oldHandler the {@link ChannelHandler} to be replaced - * @param newName the name under which the replacement should be added - * @param newHandler the {@link ChannelHandler} which is used as replacement - * - * @return itself - - * @throws NoSuchElementException - * if the specified old handler does not exist in this pipeline - * @throws IllegalArgumentException - * if a handler with the specified new name already exists in this - * pipeline, except for the handler to be replaced - * @throws NullPointerException - * if the specified old handler, new name, or new handler is - * {@code null} - */ - ChannelPipeline replace(ChannelHandler oldHandler, String newName, ChannelHandler newHandler); - - /** - * Replaces the {@link ChannelHandler} of the specified name with a new handler in this pipeline. - * - * @param oldName the name of the {@link ChannelHandler} to be replaced - * @param newName the name under which the replacement should be added - * @param newHandler the {@link ChannelHandler} which is used as replacement - * - * @return the removed handler - * - * @throws NoSuchElementException - * if the handler with the specified old name does not exist in this pipeline - * @throws IllegalArgumentException - * if a handler with the specified new name already exists in this - * pipeline, except for the handler to be replaced - * @throws NullPointerException - * if the specified old handler, new name, or new handler is - * {@code null} - */ - ChannelHandler replace(String oldName, String newName, ChannelHandler newHandler); - - /** - * Replaces the {@link ChannelHandler} of the specified type with a new handler in this pipeline. - * - * @param oldHandlerType the type of the handler to be removed - * @param newName the name under which the replacement should be added - * @param newHandler the {@link ChannelHandler} which is used as replacement - * - * @return the removed handler - * - * @throws NoSuchElementException - * if the handler of the specified old handler type does not exist - * in this pipeline - * @throws IllegalArgumentException - * if a handler with the specified new name already exists in this - * pipeline, except for the handler to be replaced - * @throws NullPointerException - * if the specified old handler, new name, or new handler is - * {@code null} - */ - T replace(Class oldHandlerType, String newName, - ChannelHandler newHandler); - - /** - * Returns the first {@link ChannelHandler} in this pipeline. - * - * @return the first handler. {@code null} if this pipeline is empty. - */ - ChannelHandler first(); - - /** - * Returns the context of the first {@link ChannelHandler} in this pipeline. - * - * @return the context of the first handler. {@code null} if this pipeline is empty. - */ - ChannelHandlerContext firstContext(); - - /** - * Returns the last {@link ChannelHandler} in this pipeline. - * - * @return the last handler. {@code null} if this pipeline is empty. - */ - ChannelHandler last(); - - /** - * Returns the context of the last {@link ChannelHandler} in this pipeline. - * - * @return the context of the last handler. {@code null} if this pipeline is empty. - */ - ChannelHandlerContext lastContext(); - - /** - * Returns the {@link ChannelHandler} with the specified name in this - * pipeline. - * - * @return the handler with the specified name. - * {@code null} if there's no such handler in this pipeline. - */ - ChannelHandler get(String name); - - /** - * Returns the {@link ChannelHandler} of the specified type in this - * pipeline. - * - * @return the handler of the specified handler type. - * {@code null} if there's no such handler in this pipeline. - */ - T get(Class handlerType); - - /** - * Returns the context object of the specified {@link ChannelHandler} in - * this pipeline. - * - * @return the context object of the specified handler. - * {@code null} if there's no such handler in this pipeline. - */ - ChannelHandlerContext context(ChannelHandler handler); - - /** - * Returns the context object of the {@link ChannelHandler} with the - * specified name in this pipeline. - * - * @return the context object of the handler with the specified name. - * {@code null} if there's no such handler in this pipeline. - */ - ChannelHandlerContext context(String name); - - /** - * Returns the context object of the {@link ChannelHandler} of the - * specified type in this pipeline. - * - * @return the context object of the handler of the specified type. - * {@code null} if there's no such handler in this pipeline. - */ - ChannelHandlerContext context(Class handlerType); - - /** - * Returns the {@link Channel} that this pipeline is attached to. - * - * @return the channel. {@code null} if this pipeline is not attached yet. - */ - Channel channel(); - - /** - * Returns the {@link List} of the handler names. - */ - List names(); - - /** - * Converts this pipeline into an ordered {@link Map} whose keys are - * handler names and whose values are handlers. - */ - Map toMap(); - - /** - * A {@link Channel} was registered to its {@link EventLoop}. - * - * This will result in having the {@link ChannelInboundHandler#channelRegistered(ChannelHandlerContext)} method - * called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelPipeline fireChannelRegistered(); - - /** - * A {@link Channel} was unregistered from its {@link EventLoop}. - * - * This will result in having the {@link ChannelInboundHandler#channelUnregistered(ChannelHandlerContext)} method - * called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelPipeline fireChannelUnregistered(); - - /** - * A {@link Channel} is active now, which means it is connected. - * - * This will result in having the {@link ChannelInboundHandler#channelActive(ChannelHandlerContext)} method - * called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelPipeline fireChannelActive(); - - /** - * A {@link Channel} is inactive now, which means it is closed. - * - * This will result in having the {@link ChannelInboundHandler#channelInactive(ChannelHandlerContext)} method - * called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelPipeline fireChannelInactive(); - - /** - * A {@link Channel} received an {@link Throwable} in one of its inbound operations. - * - * This will result in having the {@link ChannelInboundHandler#exceptionCaught(ChannelHandlerContext, Throwable)} - * method called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelPipeline fireExceptionCaught(Throwable cause); - - /** - * A {@link Channel} received an user defined event. - * - * This will result in having the {@link ChannelInboundHandler#userEventTriggered(ChannelHandlerContext, Object)} - * method called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelPipeline fireUserEventTriggered(Object event); - - /** - * A {@link Channel} received a message. - * - * This will result in having the {@link ChannelInboundHandler#channelRead(ChannelHandlerContext, Object)} - * method called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelPipeline fireChannelRead(Object msg); - - /** - * Triggers an {@link ChannelInboundHandler#channelWritabilityChanged(ChannelHandlerContext)} - * event to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}. - */ - ChannelPipeline fireChannelReadComplete(); - - /** - * Triggers an {@link ChannelInboundHandler#channelWritabilityChanged(ChannelHandlerContext)} - * event to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}. - */ - ChannelPipeline fireChannelWritabilityChanged(); - - /** - * Request to bind to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation - * completes, either because the operation was successful or because of an error. - *

- * This will result in having the - * {@link ChannelOutboundHandler#bind(ChannelHandlerContext, SocketAddress, ChannelPromise)} method - * called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture bind(SocketAddress localAddress); - - /** - * Request to connect to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation - * completes, either because the operation was successful or because of an error. - *

- * If the connection fails because of a connection timeout, the {@link ChannelFuture} will get failed with - * a {@link ConnectTimeoutException}. If it fails because of connection refused a {@link ConnectException} - * will be used. - *

- * This will result in having the - * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture connect(SocketAddress remoteAddress); - - /** - * Request to connect to the given {@link SocketAddress} while bind to the localAddress and notify the - * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of - * an error. - *

- * This will result in having the - * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress); - - /** - * Request to disconnect from the remote peer and notify the {@link ChannelFuture} once the operation completes, - * either because the operation was successful or because of an error. - *

- * This will result in having the - * {@link ChannelOutboundHandler#disconnect(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture disconnect(); - - /** - * Request to close the {@link Channel} and notify the {@link ChannelFuture} once the operation completes, - * either because the operation was successful or because of - * an error. - * - * After it is closed it is not possible to reuse it again. - *

- * This will result in having the - * {@link ChannelOutboundHandler#close(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture close(); - - /** - * Request to deregister the {@link Channel} from the previous assigned {@link EventExecutor} and notify the - * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of - * an error. - *

- * This will result in having the - * {@link ChannelOutboundHandler#deregister(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - * - */ - ChannelFuture deregister(); - - /** - * Request to bind to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation - * completes, either because the operation was successful or because of an error. - * - * The given {@link ChannelPromise} will be notified. - *

- * This will result in having the - * {@link ChannelOutboundHandler#bind(ChannelHandlerContext, SocketAddress, ChannelPromise)} method - * called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise); - - /** - * Request to connect to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation - * completes, either because the operation was successful or because of an error. - * - * The given {@link ChannelFuture} will be notified. - * - *

- * If the connection fails because of a connection timeout, the {@link ChannelFuture} will get failed with - * a {@link ConnectTimeoutException}. If it fails because of connection refused a {@link ConnectException} - * will be used. - *

- * This will result in having the - * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise); - - /** - * Request to connect to the given {@link SocketAddress} while bind to the localAddress and notify the - * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of - * an error. - * - * The given {@link ChannelPromise} will be notified and also returned. - *

- * This will result in having the - * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise); - - /** - * Request to disconnect from the remote peer and notify the {@link ChannelFuture} once the operation completes, - * either because the operation was successful or because of an error. - * - * The given {@link ChannelPromise} will be notified. - *

- * This will result in having the - * {@link ChannelOutboundHandler#disconnect(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture disconnect(ChannelPromise promise); - - /** - * Request to close the {@link Channel} bound to this {@link ChannelPipeline} and notify the {@link ChannelFuture} - * once the operation completes, either because the operation was successful or because of - * an error. - * - * After it is closed it is not possible to reuse it again. - * The given {@link ChannelPromise} will be notified. - *

- * This will result in having the - * {@link ChannelOutboundHandler#close(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture close(ChannelPromise promise); - - /** - * Request to deregister the {@link Channel} bound this {@link ChannelPipeline} from the previous assigned - * {@link EventExecutor} and notify the {@link ChannelFuture} once the operation completes, either because the - * operation was successful or because of an error. - * - * The given {@link ChannelPromise} will be notified. - *

- * This will result in having the - * {@link ChannelOutboundHandler#deregister(ChannelHandlerContext, ChannelPromise)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelFuture deregister(ChannelPromise promise); - - /** - * Request to Read data from the {@link Channel} into the first inbound buffer, triggers an - * {@link ChannelInboundHandler#channelRead(ChannelHandlerContext, Object)} event if data was - * read, and triggers a - * {@link ChannelInboundHandler#channelReadComplete(ChannelHandlerContext) channelReadComplete} event so the - * handler can decide to continue reading. If there's a pending read operation already, this method does nothing. - *

- * This will result in having the - * {@link ChannelOutboundHandler#read(ChannelHandlerContext)} - * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the - * {@link Channel}. - */ - ChannelPipeline read(); - - /** - * Request to write a message via this {@link ChannelPipeline}. - * This method will not request to actual flush, so be sure to call {@link #flush()} - * once you want to request to flush all pending data to the actual transport. - */ - ChannelFuture write(Object msg); - - /** - * Request to write a message via this {@link ChannelPipeline}. - * This method will not request to actual flush, so be sure to call {@link #flush()} - * once you want to request to flush all pending data to the actual transport. - */ - ChannelFuture write(Object msg, ChannelPromise promise); - - /** - * Request to flush all pending messages. - */ - ChannelPipeline flush(); - - /** - * Shortcut for call {@link #write(Object, ChannelPromise)} and {@link #flush()}. - */ - ChannelFuture writeAndFlush(Object msg, ChannelPromise promise); - - /** - * Shortcut for call {@link #write(Object)} and {@link #flush()}. - */ - ChannelFuture writeAndFlush(Object msg); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelPipelineException.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelPipelineException.java deleted file mode 100755 index fd638bedee..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelPipelineException.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -/** - * A {@link ChannelException} which is thrown when a {@link ChannelPipeline} - * failed to execute an operation. - */ -public class ChannelPipelineException extends ChannelException { - - private static final long serialVersionUID = 3379174210419885980L; - - /** - * Creates a new instance. - */ - public ChannelPipelineException() { - } - - /** - * Creates a new instance. - */ - public ChannelPipelineException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Creates a new instance. - */ - public ChannelPipelineException(String message) { - super(message); - } - - /** - * Creates a new instance. - */ - public ChannelPipelineException(Throwable cause) { - super(cause); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelProgressiveFuture.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelProgressiveFuture.java deleted file mode 100755 index d8f9074dac..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelProgressiveFuture.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import com.ai.cloud.io.netty.util.concurrent.Future; -import com.ai.cloud.io.netty.util.concurrent.GenericFutureListener; -import com.ai.cloud.io.netty.util.concurrent.ProgressiveFuture; - -/** - * An special {@link ChannelFuture} which is used to indicate the {@link FileRegion} transfer progress - */ -public interface ChannelProgressiveFuture extends ChannelFuture, ProgressiveFuture { - @Override - ChannelProgressiveFuture addListener(GenericFutureListener> listener); - - @Override - ChannelProgressiveFuture addListeners(GenericFutureListener>... listeners); - - @Override - ChannelProgressiveFuture removeListener(GenericFutureListener> listener); - - @Override - ChannelProgressiveFuture removeListeners(GenericFutureListener>... listeners); - - @Override - ChannelProgressiveFuture sync() throws InterruptedException; - - @Override - ChannelProgressiveFuture syncUninterruptibly(); - - @Override - ChannelProgressiveFuture await() throws InterruptedException; - - @Override - ChannelProgressiveFuture awaitUninterruptibly(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelProgressiveFutureListener.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelProgressiveFutureListener.java deleted file mode 100755 index 65a931cf94..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelProgressiveFutureListener.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import java.util.EventListener; - -import com.ai.cloud.io.netty.util.concurrent.GenericProgressiveFutureListener; - -/** - * An {@link EventListener} listener which will be called once the sending task associated with future is - * being transferred. - */ -public interface ChannelProgressiveFutureListener extends GenericProgressiveFutureListener { - // Just a type alias -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelProgressivePromise.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelProgressivePromise.java deleted file mode 100755 index 660a1c7dfb..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelProgressivePromise.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import com.ai.cloud.io.netty.util.concurrent.Future; -import com.ai.cloud.io.netty.util.concurrent.GenericFutureListener; -import com.ai.cloud.io.netty.util.concurrent.ProgressivePromise; - -/** - * Special {@link ChannelPromise} which will be notified once the associated bytes is transferring. - */ -public interface ChannelProgressivePromise extends ProgressivePromise, ChannelProgressiveFuture, ChannelPromise { - - @Override - ChannelProgressivePromise addListener(GenericFutureListener> listener); - - @Override - ChannelProgressivePromise addListeners(GenericFutureListener>... listeners); - - @Override - ChannelProgressivePromise removeListener(GenericFutureListener> listener); - - @Override - ChannelProgressivePromise removeListeners(GenericFutureListener>... listeners); - - @Override - ChannelProgressivePromise sync() throws InterruptedException; - - @Override - ChannelProgressivePromise syncUninterruptibly(); - - @Override - ChannelProgressivePromise await() throws InterruptedException; - - @Override - ChannelProgressivePromise awaitUninterruptibly(); - - @Override - ChannelProgressivePromise setSuccess(Void result); - - @Override - ChannelProgressivePromise setSuccess(); - - @Override - ChannelProgressivePromise setFailure(Throwable cause); - - @Override - ChannelProgressivePromise setProgress(long progress, long total); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelPromise.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelPromise.java deleted file mode 100755 index 064479a011..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelPromise.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import com.ai.cloud.io.netty.util.concurrent.Future; -import com.ai.cloud.io.netty.util.concurrent.GenericFutureListener; -import com.ai.cloud.io.netty.util.concurrent.Promise; - -/** - * Special {@link ChannelFuture} which is writable. - */ -public interface ChannelPromise extends ChannelFuture, Promise { - - @Override - Channel channel(); - - @Override - ChannelPromise setSuccess(Void result); - - ChannelPromise setSuccess(); - - boolean trySuccess(); - - @Override - ChannelPromise setFailure(Throwable cause); - - @Override - ChannelPromise addListener(GenericFutureListener> listener); - - @Override - ChannelPromise addListeners(GenericFutureListener>... listeners); - - @Override - ChannelPromise removeListener(GenericFutureListener> listener); - - @Override - ChannelPromise removeListeners(GenericFutureListener>... listeners); - - @Override - ChannelPromise sync() throws InterruptedException; - - @Override - ChannelPromise syncUninterruptibly(); - - @Override - ChannelPromise await() throws InterruptedException; - - @Override - ChannelPromise awaitUninterruptibly(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelPromiseAggregator.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelPromiseAggregator.java deleted file mode 100755 index 6e8e6c654f..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelPromiseAggregator.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.channel; - -import com.ai.cloud.io.netty.util.concurrent.PromiseAggregator; - -/** - * Class which is used to consolidate multiple channel futures into one, by - * listening to the individual futures and producing an aggregated result - * (success/failure) when all futures have completed. - */ -public final class ChannelPromiseAggregator - extends PromiseAggregator - implements ChannelFutureListener { - - public ChannelPromiseAggregator(ChannelPromise aggregatePromise) { - super(aggregatePromise); - } - -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelPromiseNotifier.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelPromiseNotifier.java deleted file mode 100755 index 20714b11fa..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ChannelPromiseNotifier.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import com.ai.cloud.io.netty.util.concurrent.PromiseNotifier; - -/** - * ChannelFutureListener implementation which takes other {@link ChannelFuture}(s) and notifies them on completion. - */ -public final class ChannelPromiseNotifier - extends PromiseNotifier - implements ChannelFutureListener { - - /** - * Create a new instance - * - * @param promises the {@link ChannelPromise}s to notify once this {@link ChannelFutureListener} is notified. - */ - public ChannelPromiseNotifier(ChannelPromise... promises) { - super(promises); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/CombinedChannelDuplexHandler.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/CombinedChannelDuplexHandler.java deleted file mode 100755 index 674fe732cf..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/CombinedChannelDuplexHandler.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import java.net.SocketAddress; - -/** - * Combines a {@link ChannelInboundHandler} and a {@link ChannelOutboundHandler} into one {@link ChannelHandler}. - * - */ -public class CombinedChannelDuplexHandler - extends ChannelDuplexHandler { - - private I inboundHandler; - private O outboundHandler; - - /** - * Creates a new uninitialized instance. A class that extends this handler must invoke - * {@link #init(ChannelInboundHandler, ChannelOutboundHandler)} before adding this handler into a - * {@link ChannelPipeline}. - */ - protected CombinedChannelDuplexHandler() { } - - /** - * Creates a new instance that combines the specified two handlers into one. - */ - public CombinedChannelDuplexHandler(I inboundHandler, O outboundHandler) { - init(inboundHandler, outboundHandler); - } - - /** - * Initialized this handler with the specified handlers. - * - * @throws IllegalStateException if this handler was not constructed via the default constructor or - * if this handler does not implement all required handler interfaces - * @throws IllegalArgumentException if the specified handlers cannot be combined into one due to a conflict - * in the type hierarchy - */ - protected final void init(I inboundHandler, O outboundHandler) { - validate(inboundHandler, outboundHandler); - this.inboundHandler = inboundHandler; - this.outboundHandler = outboundHandler; - } - - private void validate(I inboundHandler, O outboundHandler) { - if (this.inboundHandler != null) { - throw new IllegalStateException( - "init() can not be invoked if " + CombinedChannelDuplexHandler.class.getSimpleName() + - " was constructed with non-default constructor."); - } - - if (inboundHandler == null) { - throw new NullPointerException("inboundHandler"); - } - if (outboundHandler == null) { - throw new NullPointerException("outboundHandler"); - } - if (inboundHandler instanceof ChannelOutboundHandler) { - throw new IllegalArgumentException( - "inboundHandler must not implement " + - ChannelOutboundHandler.class.getSimpleName() + " to get combined."); - } - if (outboundHandler instanceof ChannelInboundHandler) { - throw new IllegalArgumentException( - "outboundHandler must not implement " + - ChannelInboundHandler.class.getSimpleName() + " to get combined."); - } - } - - protected final I inboundHandler() { - return inboundHandler; - } - - protected final O outboundHandler() { - return outboundHandler; - } - - @Override - public void handlerAdded(ChannelHandlerContext ctx) throws Exception { - if (inboundHandler == null) { - throw new IllegalStateException( - "init() must be invoked before being added to a " + ChannelPipeline.class.getSimpleName() + - " if " + CombinedChannelDuplexHandler.class.getSimpleName() + - " was constructed with the default constructor."); - } - try { - inboundHandler.handlerAdded(ctx); - } finally { - outboundHandler.handlerAdded(ctx); - } - } - - @Override - public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { - try { - inboundHandler.handlerRemoved(ctx); - } finally { - outboundHandler.handlerRemoved(ctx); - } - } - - @Override - public void channelRegistered(ChannelHandlerContext ctx) throws Exception { - inboundHandler.channelRegistered(ctx); - } - - @Override - public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { - inboundHandler.channelUnregistered(ctx); - } - - @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { - inboundHandler.channelActive(ctx); - } - - @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { - inboundHandler.channelInactive(ctx); - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - inboundHandler.exceptionCaught(ctx, cause); - } - - @Override - public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { - inboundHandler.userEventTriggered(ctx, evt); - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - inboundHandler.channelRead(ctx, msg); - } - - @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { - inboundHandler.channelReadComplete(ctx); - } - - @Override - public void bind( - ChannelHandlerContext ctx, - SocketAddress localAddress, ChannelPromise promise) throws Exception { - outboundHandler.bind(ctx, localAddress, promise); - } - - @Override - public void connect( - ChannelHandlerContext ctx, - SocketAddress remoteAddress, SocketAddress localAddress, - ChannelPromise promise) throws Exception { - outboundHandler.connect(ctx, remoteAddress, localAddress, promise); - } - - @Override - public void disconnect(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception { - outboundHandler.disconnect(ctx, promise); - } - - @Override - public void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception { - outboundHandler.close(ctx, promise); - } - - @Override - public void deregister(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception { - outboundHandler.deregister(ctx, promise); - } - - @Override - public void read(ChannelHandlerContext ctx) throws Exception { - outboundHandler.read(ctx); - } - - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - outboundHandler.write(ctx, msg, promise); - } - - @Override - public void flush(ChannelHandlerContext ctx) throws Exception { - outboundHandler.flush(ctx); - } - - @Override - public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception { - inboundHandler.channelWritabilityChanged(ctx); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/CompleteChannelFuture.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/CompleteChannelFuture.java deleted file mode 100755 index c5f7ec026d..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/CompleteChannelFuture.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import com.ai.cloud.io.netty.util.concurrent.CompleteFuture; -import com.ai.cloud.io.netty.util.concurrent.EventExecutor; -import com.ai.cloud.io.netty.util.concurrent.Future; -import com.ai.cloud.io.netty.util.concurrent.GenericFutureListener; - -/** - * A skeletal {@link ChannelFuture} implementation which represents a - * {@link ChannelFuture} which has been completed already. - */ -abstract class CompleteChannelFuture extends CompleteFuture implements ChannelFuture { - - private final Channel channel; - - /** - * Creates a new instance. - * - * @param channel the {@link Channel} associated with this future - */ - protected CompleteChannelFuture(Channel channel, EventExecutor executor) { - super(executor); - if (channel == null) { - throw new NullPointerException("channel"); - } - this.channel = channel; - } - - @Override - protected EventExecutor executor() { - EventExecutor e = super.executor(); - if (e == null) { - return channel().eventLoop(); - } else { - return e; - } - } - - @Override - public ChannelFuture addListener(GenericFutureListener> listener) { - super.addListener(listener); - return this; - } - - @Override - public ChannelFuture addListeners(GenericFutureListener>... listeners) { - super.addListeners(listeners); - return this; - } - - @Override - public ChannelFuture removeListener(GenericFutureListener> listener) { - super.removeListener(listener); - return this; - } - - @Override - public ChannelFuture removeListeners(GenericFutureListener>... listeners) { - super.removeListeners(listeners); - return this; - } - - @Override - public ChannelFuture syncUninterruptibly() { - return this; - } - - @Override - public ChannelFuture sync() throws InterruptedException { - return this; - } - - @Override - public ChannelFuture await() throws InterruptedException { - return this; - } - - @Override - public ChannelFuture awaitUninterruptibly() { - return this; - } - - @Override - public Channel channel() { - return channel; - } - - @Override - public Void getNow() { - return null; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ConnectTimeoutException.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ConnectTimeoutException.java deleted file mode 100755 index 6a46da0cf3..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ConnectTimeoutException.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import java.net.ConnectException; - -/** - * {@link ConnectException} which will be thrown if a connection could - * not be established because of a connection timeout. - */ -public class ConnectTimeoutException extends ConnectException { - private static final long serialVersionUID = 2317065249988317463L; - - public ConnectTimeoutException(String msg) { - super(msg); - } - - public ConnectTimeoutException() { - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/DefaultAddressedEnvelope.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/DefaultAddressedEnvelope.java deleted file mode 100755 index 2a522d4fd1..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/DefaultAddressedEnvelope.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.channel; - -import java.net.SocketAddress; - -import com.ai.cloud.io.netty.util.ReferenceCountUtil; -import com.ai.cloud.io.netty.util.ReferenceCounted; -import com.ai.cloud.io.netty.util.internal.StringUtil; - -/** - * The default {@link AddressedEnvelope} implementation. - * - * @param the type of the wrapped message - * @param the type of the recipient address - */ -public class DefaultAddressedEnvelope implements AddressedEnvelope { - - private final M message; - private final A sender; - private final A recipient; - - /** - * Creates a new instance with the specified {@code message}, {@code recipient} address, and - * {@code sender} address. - */ - public DefaultAddressedEnvelope(M message, A recipient, A sender) { - if (message == null) { - throw new NullPointerException("message"); - } - - this.message = message; - this.sender = sender; - this.recipient = recipient; - } - - /** - * Creates a new instance with the specified {@code message} and {@code recipient} address. - * The sender address becomes {@code null}. - */ - public DefaultAddressedEnvelope(M message, A recipient) { - this(message, recipient, null); - } - - @Override - public M content() { - return message; - } - - @Override - public A sender() { - return sender; - } - - @Override - public A recipient() { - return recipient; - } - - @Override - public int refCnt() { - if (message instanceof ReferenceCounted) { - return ((ReferenceCounted) message).refCnt(); - } else { - return 1; - } - } - - @Override - public AddressedEnvelope retain() { - ReferenceCountUtil.retain(message); - return this; - } - - @Override - public AddressedEnvelope retain(int increment) { - ReferenceCountUtil.retain(message, increment); - return this; - } - - @Override - public boolean release() { - return ReferenceCountUtil.release(message); - } - - @Override - public boolean release(int decrement) { - return ReferenceCountUtil.release(message, decrement); - } - - @Override - public String toString() { - if (sender != null) { - return StringUtil.simpleClassName(this) + - '(' + sender + " => " + recipient + ", " + message + ')'; - } else { - return StringUtil.simpleClassName(this) + - "(=> " + recipient + ", " + message + ')'; - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/DefaultChannelConfig.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/DefaultChannelConfig.java deleted file mode 100755 index f556e84282..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/DefaultChannelConfig.java +++ /dev/null @@ -1,360 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; -import java.util.IdentityHashMap; -import java.util.Map; -import java.util.Map.Entry; - -import com.ai.cloud.io.netty.buffer.ByteBufAllocator; -import com.ai.cloud.io.netty.channel.nio.AbstractNioByteChannel; -import com.ai.cloud.io.netty.channel.socket.SocketChannelConfig; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - -import static com.ai.cloud.io.netty.channel.ChannelOption.*; - -/** - * The default {@link SocketChannelConfig} implementation. - */ -public class DefaultChannelConfig implements ChannelConfig { - - private static final RecvByteBufAllocator DEFAULT_RCVBUF_ALLOCATOR = AdaptiveRecvByteBufAllocator.DEFAULT; - private static final MessageSizeEstimator DEFAULT_MSG_SIZE_ESTIMATOR = DefaultMessageSizeEstimator.DEFAULT; - - private static final int DEFAULT_CONNECT_TIMEOUT = 30000; - - private static final AtomicIntegerFieldUpdater AUTOREAD_UPDATER; - - static { - AtomicIntegerFieldUpdater autoReadUpdater = - PlatformDependent.newAtomicIntegerFieldUpdater(DefaultChannelConfig.class, "autoRead"); - if (autoReadUpdater == null) { - autoReadUpdater = AtomicIntegerFieldUpdater.newUpdater(DefaultChannelConfig.class, "autoRead"); - } - AUTOREAD_UPDATER = autoReadUpdater; - } - - protected final Channel channel; - - private volatile ByteBufAllocator allocator = ByteBufAllocator.DEFAULT; - private volatile RecvByteBufAllocator rcvBufAllocator = DEFAULT_RCVBUF_ALLOCATOR; - private volatile MessageSizeEstimator msgSizeEstimator = DEFAULT_MSG_SIZE_ESTIMATOR; - - private volatile int connectTimeoutMillis = DEFAULT_CONNECT_TIMEOUT; - private volatile int maxMessagesPerRead; - private volatile int writeSpinCount = 16; - @SuppressWarnings("FieldMayBeFinal") - private volatile int autoRead = 1; - private volatile boolean autoClose = true; - private volatile int writeBufferHighWaterMark = 64 * 1024; - private volatile int writeBufferLowWaterMark = 32 * 1024; - - public DefaultChannelConfig(Channel channel) { - if (channel == null) { - throw new NullPointerException("channel"); - } - this.channel = channel; - - if (channel instanceof ServerChannel || channel instanceof AbstractNioByteChannel) { - // Server channels: Accept as many incoming connections as possible. - // NIO byte channels: Implemented to reduce unnecessary system calls even if it's > 1. - // See https://github.com/netty/netty/issues/2079 - // TODO: Add some property to ChannelMetadata so we can remove the ugly instanceof - maxMessagesPerRead = 16; - } else { - maxMessagesPerRead = 1; - } - } - - @Override - @SuppressWarnings("deprecation") - public Map, Object> getOptions() { - return getOptions( - null, - CONNECT_TIMEOUT_MILLIS, MAX_MESSAGES_PER_READ, WRITE_SPIN_COUNT, - ALLOCATOR, AUTO_READ, AUTO_CLOSE, RCVBUF_ALLOCATOR, WRITE_BUFFER_HIGH_WATER_MARK, - WRITE_BUFFER_LOW_WATER_MARK, MESSAGE_SIZE_ESTIMATOR); - } - - protected Map, Object> getOptions( - Map, Object> result, ChannelOption... options) { - if (result == null) { - result = new IdentityHashMap, Object>(); - } - for (ChannelOption o: options) { - result.put(o, getOption(o)); - } - return result; - } - - @SuppressWarnings("unchecked") - @Override - public boolean setOptions(Map, ?> options) { - if (options == null) { - throw new NullPointerException("options"); - } - - boolean setAllOptions = true; - for (Entry, ?> e: options.entrySet()) { - if (!setOption((ChannelOption) e.getKey(), e.getValue())) { - setAllOptions = false; - } - } - - return setAllOptions; - } - - @Override - @SuppressWarnings({ "unchecked", "deprecation" }) - public T getOption(ChannelOption option) { - if (option == null) { - throw new NullPointerException("option"); - } - - if (option == CONNECT_TIMEOUT_MILLIS) { - return (T) Integer.valueOf(getConnectTimeoutMillis()); - } - if (option == MAX_MESSAGES_PER_READ) { - return (T) Integer.valueOf(getMaxMessagesPerRead()); - } - if (option == WRITE_SPIN_COUNT) { - return (T) Integer.valueOf(getWriteSpinCount()); - } - if (option == ALLOCATOR) { - return (T) getAllocator(); - } - if (option == RCVBUF_ALLOCATOR) { - return (T) getRecvByteBufAllocator(); - } - if (option == AUTO_READ) { - return (T) Boolean.valueOf(isAutoRead()); - } - if (option == AUTO_CLOSE) { - return (T) Boolean.valueOf(isAutoClose()); - } - if (option == WRITE_BUFFER_HIGH_WATER_MARK) { - return (T) Integer.valueOf(getWriteBufferHighWaterMark()); - } - if (option == WRITE_BUFFER_LOW_WATER_MARK) { - return (T) Integer.valueOf(getWriteBufferLowWaterMark()); - } - if (option == MESSAGE_SIZE_ESTIMATOR) { - return (T) getMessageSizeEstimator(); - } - return null; - } - - @Override - @SuppressWarnings("deprecation") - public boolean setOption(ChannelOption option, T value) { - validate(option, value); - - if (option == CONNECT_TIMEOUT_MILLIS) { - setConnectTimeoutMillis((Integer) value); - } else if (option == MAX_MESSAGES_PER_READ) { - setMaxMessagesPerRead((Integer) value); - } else if (option == WRITE_SPIN_COUNT) { - setWriteSpinCount((Integer) value); - } else if (option == ALLOCATOR) { - setAllocator((ByteBufAllocator) value); - } else if (option == RCVBUF_ALLOCATOR) { - setRecvByteBufAllocator((RecvByteBufAllocator) value); - } else if (option == AUTO_READ) { - setAutoRead((Boolean) value); - } else if (option == AUTO_CLOSE) { - setAutoClose((Boolean) value); - } else if (option == WRITE_BUFFER_HIGH_WATER_MARK) { - setWriteBufferHighWaterMark((Integer) value); - } else if (option == WRITE_BUFFER_LOW_WATER_MARK) { - setWriteBufferLowWaterMark((Integer) value); - } else if (option == MESSAGE_SIZE_ESTIMATOR) { - setMessageSizeEstimator((MessageSizeEstimator) value); - } else { - return false; - } - - return true; - } - - protected void validate(ChannelOption option, T value) { - if (option == null) { - throw new NullPointerException("option"); - } - option.validate(value); - } - - @Override - public int getConnectTimeoutMillis() { - return connectTimeoutMillis; - } - - @Override - public ChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis) { - if (connectTimeoutMillis < 0) { - throw new IllegalArgumentException(String.format( - "connectTimeoutMillis: %d (expected: >= 0)", connectTimeoutMillis)); - } - this.connectTimeoutMillis = connectTimeoutMillis; - return this; - } - - @Override - public int getMaxMessagesPerRead() { - return maxMessagesPerRead; - } - - @Override - public ChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead) { - if (maxMessagesPerRead <= 0) { - throw new IllegalArgumentException("maxMessagesPerRead: " + maxMessagesPerRead + " (expected: > 0)"); - } - this.maxMessagesPerRead = maxMessagesPerRead; - return this; - } - - @Override - public int getWriteSpinCount() { - return writeSpinCount; - } - - @Override - public ChannelConfig setWriteSpinCount(int writeSpinCount) { - if (writeSpinCount <= 0) { - throw new IllegalArgumentException( - "writeSpinCount must be a positive integer."); - } - this.writeSpinCount = writeSpinCount; - return this; - } - - @Override - public ByteBufAllocator getAllocator() { - return allocator; - } - - @Override - public ChannelConfig setAllocator(ByteBufAllocator allocator) { - if (allocator == null) { - throw new NullPointerException("allocator"); - } - this.allocator = allocator; - return this; - } - - @Override - public RecvByteBufAllocator getRecvByteBufAllocator() { - return rcvBufAllocator; - } - - @Override - public ChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator) { - if (allocator == null) { - throw new NullPointerException("allocator"); - } - rcvBufAllocator = allocator; - return this; - } - - @Override - public boolean isAutoRead() { - return autoRead == 1; - } - - @Override - public ChannelConfig setAutoRead(boolean autoRead) { - boolean oldAutoRead = AUTOREAD_UPDATER.getAndSet(this, autoRead ? 1 : 0) == 1; - if (autoRead && !oldAutoRead) { - channel.read(); - } else if (!autoRead && oldAutoRead) { - autoReadCleared(); - } - return this; - } - - /** - * Is called once {@link #setAutoRead(boolean)} is called with {@code false} and {@link #isAutoRead()} was - * {@code true} before. - */ - protected void autoReadCleared() { } - - @Override - public boolean isAutoClose() { - return autoClose; - } - - @Override - public ChannelConfig setAutoClose(boolean autoClose) { - this.autoClose = autoClose; - return this; - } - - @Override - public int getWriteBufferHighWaterMark() { - return writeBufferHighWaterMark; - } - - @Override - public ChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) { - if (writeBufferHighWaterMark < getWriteBufferLowWaterMark()) { - throw new IllegalArgumentException( - "writeBufferHighWaterMark cannot be less than " + - "writeBufferLowWaterMark (" + getWriteBufferLowWaterMark() + "): " + - writeBufferHighWaterMark); - } - if (writeBufferHighWaterMark < 0) { - throw new IllegalArgumentException( - "writeBufferHighWaterMark must be >= 0"); - } - this.writeBufferHighWaterMark = writeBufferHighWaterMark; - return this; - } - - @Override - public int getWriteBufferLowWaterMark() { - return writeBufferLowWaterMark; - } - - @Override - public ChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark) { - if (writeBufferLowWaterMark > getWriteBufferHighWaterMark()) { - throw new IllegalArgumentException( - "writeBufferLowWaterMark cannot be greater than " + - "writeBufferHighWaterMark (" + getWriteBufferHighWaterMark() + "): " + - writeBufferLowWaterMark); - } - if (writeBufferLowWaterMark < 0) { - throw new IllegalArgumentException( - "writeBufferLowWaterMark must be >= 0"); - } - this.writeBufferLowWaterMark = writeBufferLowWaterMark; - return this; - } - - @Override - public MessageSizeEstimator getMessageSizeEstimator() { - return msgSizeEstimator; - } - - @Override - public ChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator) { - if (estimator == null) { - throw new NullPointerException("estimator"); - } - msgSizeEstimator = estimator; - return this; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/DefaultChannelHandlerContext.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/DefaultChannelHandlerContext.java deleted file mode 100755 index 8561c438d9..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/DefaultChannelHandlerContext.java +++ /dev/null @@ -1,45 +0,0 @@ -/* -* Copyright 2014 The Netty Project -* -* The Netty Project licenses this file to you under the Apache License, -* version 2.0 (the "License"); you may not use this file except in compliance -* with the License. You may obtain a copy of the License at: -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -* License for the specific language governing permissions and limitations -* under the License. -*/ -package com.ai.cloud.io.netty.channel; - -import com.ai.cloud.io.netty.util.concurrent.EventExecutorGroup; - -final class DefaultChannelHandlerContext extends AbstractChannelHandlerContext { - - private final ChannelHandler handler; - - DefaultChannelHandlerContext( - DefaultChannelPipeline pipeline, EventExecutorGroup group, String name, ChannelHandler handler) { - super(pipeline, group, name, isInbound(handler), isOutbound(handler)); - if (handler == null) { - throw new NullPointerException("handler"); - } - this.handler = handler; - } - - @Override - public ChannelHandler handler() { - return handler; - } - - private static boolean isInbound(ChannelHandler handler) { - return handler instanceof ChannelInboundHandler; - } - - private static boolean isOutbound(ChannelHandler handler) { - return handler instanceof ChannelOutboundHandler; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/DefaultChannelPipeline.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/DefaultChannelPipeline.java deleted file mode 100755 index d8419bfd09..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/DefaultChannelPipeline.java +++ /dev/null @@ -1,1135 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import java.net.SocketAddress; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.IdentityHashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.WeakHashMap; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; - -import com.ai.cloud.io.netty.channel.Channel.Unsafe; -import com.ai.cloud.io.netty.util.ReferenceCountUtil; -import com.ai.cloud.io.netty.util.concurrent.EventExecutor; -import com.ai.cloud.io.netty.util.concurrent.EventExecutorGroup; -import com.ai.cloud.io.netty.util.internal.OneTimeTask; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; -import com.ai.cloud.io.netty.util.internal.StringUtil; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * The default {@link ChannelPipeline} implementation. It is usually created - * by a {@link Channel} implementation when the {@link Channel} is created. - */ -final class DefaultChannelPipeline implements ChannelPipeline { - - static final InternalLogger logger = InternalLoggerFactory.getInstance(DefaultChannelPipeline.class); - - @SuppressWarnings("unchecked") - private static final WeakHashMap, String>[] nameCaches = - new WeakHashMap[Runtime.getRuntime().availableProcessors()]; - - static { - for (int i = 0; i < nameCaches.length; i ++) { - nameCaches[i] = new WeakHashMap, String>(); - } - } - - final AbstractChannel channel; - - final AbstractChannelHandlerContext head; - final AbstractChannelHandlerContext tail; - - private final Map name2ctx = - new HashMap(4); - - final Map childExecutors = - new IdentityHashMap(); - - public DefaultChannelPipeline(AbstractChannel channel) { - if (channel == null) { - throw new NullPointerException("channel"); - } - this.channel = channel; - - tail = new TailContext(this); - head = new HeadContext(this); - - head.next = tail; - tail.prev = head; - } - - @Override - public Channel channel() { - return channel; - } - - @Override - public ChannelPipeline addFirst(String name, ChannelHandler handler) { - return addFirst(null, name, handler); - } - - @Override - public ChannelPipeline addFirst(EventExecutorGroup group, final String name, ChannelHandler handler) { - synchronized (this) { - checkDuplicateName(name); - AbstractChannelHandlerContext newCtx = new DefaultChannelHandlerContext(this, group, name, handler); - addFirst0(name, newCtx); - } - - return this; - } - - private void addFirst0(String name, AbstractChannelHandlerContext newCtx) { - checkMultiplicity(newCtx); - - AbstractChannelHandlerContext nextCtx = head.next; - newCtx.prev = head; - newCtx.next = nextCtx; - head.next = newCtx; - nextCtx.prev = newCtx; - - name2ctx.put(name, newCtx); - - callHandlerAdded(newCtx); - } - - @Override - public ChannelPipeline addLast(String name, ChannelHandler handler) { - return addLast(null, name, handler); - } - - @Override - public ChannelPipeline addLast(EventExecutorGroup group, final String name, ChannelHandler handler) { - synchronized (this) { - checkDuplicateName(name); - - AbstractChannelHandlerContext newCtx = new DefaultChannelHandlerContext(this, group, name, handler); - addLast0(name, newCtx); - } - - return this; - } - - private void addLast0(final String name, AbstractChannelHandlerContext newCtx) { - checkMultiplicity(newCtx); - - AbstractChannelHandlerContext prev = tail.prev; - newCtx.prev = prev; - newCtx.next = tail; - prev.next = newCtx; - tail.prev = newCtx; - - name2ctx.put(name, newCtx); - - callHandlerAdded(newCtx); - } - - @Override - public ChannelPipeline addBefore(String baseName, String name, ChannelHandler handler) { - return addBefore(null, baseName, name, handler); - } - - @Override - public ChannelPipeline addBefore( - EventExecutorGroup group, String baseName, final String name, ChannelHandler handler) { - synchronized (this) { - AbstractChannelHandlerContext ctx = getContextOrDie(baseName); - checkDuplicateName(name); - AbstractChannelHandlerContext newCtx = new DefaultChannelHandlerContext(this, group, name, handler); - addBefore0(name, ctx, newCtx); - } - return this; - } - - private void addBefore0( - final String name, AbstractChannelHandlerContext ctx, AbstractChannelHandlerContext newCtx) { - checkMultiplicity(newCtx); - - newCtx.prev = ctx.prev; - newCtx.next = ctx; - ctx.prev.next = newCtx; - ctx.prev = newCtx; - - name2ctx.put(name, newCtx); - - callHandlerAdded(newCtx); - } - - @Override - public ChannelPipeline addAfter(String baseName, String name, ChannelHandler handler) { - return addAfter(null, baseName, name, handler); - } - - @Override - public ChannelPipeline addAfter( - EventExecutorGroup group, String baseName, final String name, ChannelHandler handler) { - synchronized (this) { - AbstractChannelHandlerContext ctx = getContextOrDie(baseName); - checkDuplicateName(name); - AbstractChannelHandlerContext newCtx = new DefaultChannelHandlerContext(this, group, name, handler); - - addAfter0(name, ctx, newCtx); - } - - return this; - } - - private void addAfter0(final String name, AbstractChannelHandlerContext ctx, AbstractChannelHandlerContext newCtx) { - checkDuplicateName(name); - checkMultiplicity(newCtx); - - newCtx.prev = ctx; - newCtx.next = ctx.next; - ctx.next.prev = newCtx; - ctx.next = newCtx; - - name2ctx.put(name, newCtx); - - callHandlerAdded(newCtx); - } - - @Override - public ChannelPipeline addFirst(ChannelHandler... handlers) { - return addFirst(null, handlers); - } - - @Override - public ChannelPipeline addFirst(EventExecutorGroup executor, ChannelHandler... handlers) { - if (handlers == null) { - throw new NullPointerException("handlers"); - } - if (handlers.length == 0 || handlers[0] == null) { - return this; - } - - int size; - for (size = 1; size < handlers.length; size ++) { - if (handlers[size] == null) { - break; - } - } - - for (int i = size - 1; i >= 0; i --) { - ChannelHandler h = handlers[i]; - addFirst(executor, generateName(h), h); - } - - return this; - } - - @Override - public ChannelPipeline addLast(ChannelHandler... handlers) { - return addLast(null, handlers); - } - - @Override - public ChannelPipeline addLast(EventExecutorGroup executor, ChannelHandler... handlers) { - if (handlers == null) { - throw new NullPointerException("handlers"); - } - - for (ChannelHandler h: handlers) { - if (h == null) { - break; - } - addLast(executor, generateName(h), h); - } - - return this; - } - - private String generateName(ChannelHandler handler) { - WeakHashMap, String> cache = nameCaches[(int) (Thread.currentThread().getId() % nameCaches.length)]; - Class handlerType = handler.getClass(); - String name; - synchronized (cache) { - name = cache.get(handlerType); - if (name == null) { - name = generateName0(handlerType); - cache.put(handlerType, name); - } - } - - synchronized (this) { - // It's not very likely for a user to put more than one handler of the same type, but make sure to avoid - // any name conflicts. Note that we don't cache the names generated here. - if (name2ctx.containsKey(name)) { - String baseName = name.substring(0, name.length() - 1); // Strip the trailing '0'. - for (int i = 1;; i ++) { - String newName = baseName + i; - if (!name2ctx.containsKey(newName)) { - name = newName; - break; - } - } - } - } - - return name; - } - - private static String generateName0(Class handlerType) { - return StringUtil.simpleClassName(handlerType) + "#0"; - } - - @Override - public ChannelPipeline remove(ChannelHandler handler) { - remove(getContextOrDie(handler)); - return this; - } - - @Override - public ChannelHandler remove(String name) { - return remove(getContextOrDie(name)).handler(); - } - - @SuppressWarnings("unchecked") - @Override - public T remove(Class handlerType) { - return (T) remove(getContextOrDie(handlerType)).handler(); - } - - private AbstractChannelHandlerContext remove(final AbstractChannelHandlerContext ctx) { - assert ctx != head && ctx != tail; - - AbstractChannelHandlerContext context; - Future future; - - synchronized (this) { - if (!ctx.channel().isRegistered() || ctx.executor().inEventLoop()) { - remove0(ctx); - return ctx; - } else { - future = ctx.executor().submit(new Runnable() { - @Override - public void run() { - synchronized (DefaultChannelPipeline.this) { - remove0(ctx); - } - } - }); - context = ctx; - } - } - - // Run the following 'waiting' code outside of the above synchronized block - // in order to avoid deadlock - - waitForFuture(future); - - return context; - } - - void remove0(AbstractChannelHandlerContext ctx) { - AbstractChannelHandlerContext prev = ctx.prev; - AbstractChannelHandlerContext next = ctx.next; - prev.next = next; - next.prev = prev; - name2ctx.remove(ctx.name()); - callHandlerRemoved(ctx); - } - - @Override - public ChannelHandler removeFirst() { - if (head.next == tail) { - throw new NoSuchElementException(); - } - return remove(head.next).handler(); - } - - @Override - public ChannelHandler removeLast() { - if (head.next == tail) { - throw new NoSuchElementException(); - } - return remove(tail.prev).handler(); - } - - @Override - public ChannelPipeline replace(ChannelHandler oldHandler, String newName, ChannelHandler newHandler) { - replace(getContextOrDie(oldHandler), newName, newHandler); - return this; - } - - @Override - public ChannelHandler replace(String oldName, String newName, ChannelHandler newHandler) { - return replace(getContextOrDie(oldName), newName, newHandler); - } - - @Override - @SuppressWarnings("unchecked") - public T replace( - Class oldHandlerType, String newName, ChannelHandler newHandler) { - return (T) replace(getContextOrDie(oldHandlerType), newName, newHandler); - } - - private ChannelHandler replace( - final AbstractChannelHandlerContext ctx, final String newName, - ChannelHandler newHandler) { - - assert ctx != head && ctx != tail; - - Future future; - synchronized (this) { - boolean sameName = ctx.name().equals(newName); - if (!sameName) { - checkDuplicateName(newName); - } - - final AbstractChannelHandlerContext newCtx = - new DefaultChannelHandlerContext(this, ctx.executor, newName, newHandler); - - if (!newCtx.channel().isRegistered() || newCtx.executor().inEventLoop()) { - replace0(ctx, newName, newCtx); - return ctx.handler(); - } else { - future = newCtx.executor().submit(new Runnable() { - @Override - public void run() { - synchronized (DefaultChannelPipeline.this) { - replace0(ctx, newName, newCtx); - } - } - }); - } - } - - // Run the following 'waiting' code outside of the above synchronized block - // in order to avoid deadlock - - waitForFuture(future); - - return ctx.handler(); - } - - private void replace0(AbstractChannelHandlerContext oldCtx, String newName, - AbstractChannelHandlerContext newCtx) { - checkMultiplicity(newCtx); - - AbstractChannelHandlerContext prev = oldCtx.prev; - AbstractChannelHandlerContext next = oldCtx.next; - newCtx.prev = prev; - newCtx.next = next; - - // Finish the replacement of oldCtx with newCtx in the linked list. - // Note that this doesn't mean events will be sent to the new handler immediately - // because we are currently at the event handler thread and no more than one handler methods can be invoked - // at the same time (we ensured that in replace().) - prev.next = newCtx; - next.prev = newCtx; - - if (!oldCtx.name().equals(newName)) { - name2ctx.remove(oldCtx.name()); - } - name2ctx.put(newName, newCtx); - - // update the reference to the replacement so forward of buffered content will work correctly - oldCtx.prev = newCtx; - oldCtx.next = newCtx; - - // Invoke newHandler.handlerAdded() first (i.e. before oldHandler.handlerRemoved() is invoked) - // because callHandlerRemoved() will trigger inboundBufferUpdated() or flush() on newHandler and those - // event handlers must be called after handlerAdded(). - callHandlerAdded(newCtx); - callHandlerRemoved(oldCtx); - } - - private static void checkMultiplicity(ChannelHandlerContext ctx) { - ChannelHandler handler = ctx.handler(); - if (handler instanceof ChannelHandlerAdapter) { - ChannelHandlerAdapter h = (ChannelHandlerAdapter) handler; - if (!h.isSharable() && h.added) { - throw new ChannelPipelineException( - h.getClass().getName() + - " is not a @Sharable handler, so can't be added or removed multiple times."); - } - h.added = true; - } - } - - private void callHandlerAdded(final ChannelHandlerContext ctx) { - if (ctx.channel().isRegistered() && !ctx.executor().inEventLoop()) { - ctx.executor().execute(new Runnable() { - @Override - public void run() { - callHandlerAdded0(ctx); - } - }); - return; - } - callHandlerAdded0(ctx); - } - - private void callHandlerAdded0(final ChannelHandlerContext ctx) { - try { - ctx.handler().handlerAdded(ctx); - } catch (Throwable t) { - boolean removed = false; - try { - remove((AbstractChannelHandlerContext) ctx); - removed = true; - } catch (Throwable t2) { - if (logger.isWarnEnabled()) { - logger.warn("Failed to remove a handler: " + ctx.name(), t2); - } - } - - if (removed) { - fireExceptionCaught(new ChannelPipelineException( - ctx.handler().getClass().getName() + - ".handlerAdded() has thrown an exception; removed.", t)); - } else { - fireExceptionCaught(new ChannelPipelineException( - ctx.handler().getClass().getName() + - ".handlerAdded() has thrown an exception; also failed to remove.", t)); - } - } - } - - private void callHandlerRemoved(final AbstractChannelHandlerContext ctx) { - if (ctx.channel().isRegistered() && !ctx.executor().inEventLoop()) { - ctx.executor().execute(new Runnable() { - @Override - public void run() { - callHandlerRemoved0(ctx); - } - }); - return; - } - callHandlerRemoved0(ctx); - } - - private void callHandlerRemoved0(final AbstractChannelHandlerContext ctx) { - // Notify the complete removal. - try { - ctx.handler().handlerRemoved(ctx); - ctx.setRemoved(); - } catch (Throwable t) { - fireExceptionCaught(new ChannelPipelineException( - ctx.handler().getClass().getName() + ".handlerRemoved() has thrown an exception.", t)); - } - } - - /** - * Waits for a future to finish. If the task is interrupted, then the current thread will be interrupted. - * It is expected that the task performs any appropriate locking. - *

- * If the internal call throws a {@link Throwable}, but it is not an instance of {@link Error} or - * {@link RuntimeException}, then it is wrapped inside a {@link ChannelPipelineException} and that is - * thrown instead.

- * - * @param future wait for this future - * @see Future#get() - * @throws Error if the task threw this. - * @throws RuntimeException if the task threw this. - * @throws ChannelPipelineException with a {@link Throwable} as a cause, if the task threw another type of - * {@link Throwable}. - */ - private static void waitForFuture(Future future) { - try { - future.get(); - } catch (ExecutionException ex) { - // In the arbitrary case, we can throw Error, RuntimeException, and Exception - PlatformDependent.throwException(ex.getCause()); - } catch (InterruptedException ex) { - // Interrupt the calling thread (note that this method is not called from the event loop) - Thread.currentThread().interrupt(); - } - } - - @Override - public ChannelHandler first() { - ChannelHandlerContext first = firstContext(); - if (first == null) { - return null; - } - return first.handler(); - } - - @Override - public ChannelHandlerContext firstContext() { - AbstractChannelHandlerContext first = head.next; - if (first == tail) { - return null; - } - return head.next; - } - - @Override - public ChannelHandler last() { - AbstractChannelHandlerContext last = tail.prev; - if (last == head) { - return null; - } - return last.handler(); - } - - @Override - public ChannelHandlerContext lastContext() { - AbstractChannelHandlerContext last = tail.prev; - if (last == head) { - return null; - } - return last; - } - - @Override - public ChannelHandler get(String name) { - ChannelHandlerContext ctx = context(name); - if (ctx == null) { - return null; - } else { - return ctx.handler(); - } - } - - @SuppressWarnings("unchecked") - @Override - public T get(Class handlerType) { - ChannelHandlerContext ctx = context(handlerType); - if (ctx == null) { - return null; - } else { - return (T) ctx.handler(); - } - } - - @Override - public ChannelHandlerContext context(String name) { - if (name == null) { - throw new NullPointerException("name"); - } - - synchronized (this) { - return name2ctx.get(name); - } - } - - @Override - public ChannelHandlerContext context(ChannelHandler handler) { - if (handler == null) { - throw new NullPointerException("handler"); - } - - AbstractChannelHandlerContext ctx = head.next; - for (;;) { - - if (ctx == null) { - return null; - } - - if (ctx.handler() == handler) { - return ctx; - } - - ctx = ctx.next; - } - } - - @Override - public ChannelHandlerContext context(Class handlerType) { - if (handlerType == null) { - throw new NullPointerException("handlerType"); - } - - AbstractChannelHandlerContext ctx = head.next; - for (;;) { - if (ctx == null) { - return null; - } - if (handlerType.isAssignableFrom(ctx.handler().getClass())) { - return ctx; - } - ctx = ctx.next; - } - } - - @Override - public List names() { - List list = new ArrayList(); - AbstractChannelHandlerContext ctx = head.next; - for (;;) { - if (ctx == null) { - return list; - } - list.add(ctx.name()); - ctx = ctx.next; - } - } - - @Override - public Map toMap() { - Map map = new LinkedHashMap(); - AbstractChannelHandlerContext ctx = head.next; - for (;;) { - if (ctx == tail) { - return map; - } - map.put(ctx.name(), ctx.handler()); - ctx = ctx.next; - } - } - - @Override - public Iterator> iterator() { - return toMap().entrySet().iterator(); - } - - /** - * Returns the {@link String} representation of this pipeline. - */ - @Override - public String toString() { - StringBuilder buf = new StringBuilder() - .append(StringUtil.simpleClassName(this)) - .append('{'); - AbstractChannelHandlerContext ctx = head.next; - for (;;) { - if (ctx == tail) { - break; - } - - buf.append('(') - .append(ctx.name()) - .append(" = ") - .append(ctx.handler().getClass().getName()) - .append(')'); - - ctx = ctx.next; - if (ctx == tail) { - break; - } - - buf.append(", "); - } - buf.append('}'); - return buf.toString(); - } - - @Override - public ChannelPipeline fireChannelRegistered() { - head.fireChannelRegistered(); - return this; - } - - @Override - public ChannelPipeline fireChannelUnregistered() { - head.fireChannelUnregistered(); - - // Remove all handlers sequentially if channel is closed and unregistered. - if (!channel.isOpen()) { - destroy(); - } - return this; - } - - /** - * Removes all handlers from the pipeline one by one from tail (exclusive) to head (exclusive) to trigger - * handlerRemoved(). - * - * Note that we traverse up the pipeline ({@link #destroyUp(AbstractChannelHandlerContext)}) - * before traversing down ({@link #destroyDown(Thread, AbstractChannelHandlerContext)}) so that - * the handlers are removed after all events are handled. - * - * See: https://github.com/netty/netty/issues/3156 - */ - private void destroy() { - destroyUp(head.next); - } - - private void destroyUp(AbstractChannelHandlerContext ctx) { - final Thread currentThread = Thread.currentThread(); - final AbstractChannelHandlerContext tail = this.tail; - for (;;) { - if (ctx == tail) { - destroyDown(currentThread, tail.prev); - break; - } - - final EventExecutor executor = ctx.executor(); - if (!executor.inEventLoop(currentThread)) { - final AbstractChannelHandlerContext finalCtx = ctx; - executor.execute(new OneTimeTask() { - @Override - public void run() { - destroyUp(finalCtx); - } - }); - break; - } - - ctx = ctx.next; - } - } - - private void destroyDown(Thread currentThread, AbstractChannelHandlerContext ctx) { - // We have reached at tail; now traverse backwards. - final AbstractChannelHandlerContext head = this.head; - for (;;) { - if (ctx == head) { - break; - } - - final EventExecutor executor = ctx.executor(); - if (executor.inEventLoop(currentThread)) { - synchronized (this) { - remove0(ctx); - } - } else { - final AbstractChannelHandlerContext finalCtx = ctx; - executor.execute(new OneTimeTask() { - @Override - public void run() { - destroyDown(Thread.currentThread(), finalCtx); - } - }); - break; - } - - ctx = ctx.prev; - } - } - - @Override - public ChannelPipeline fireChannelActive() { - head.fireChannelActive(); - - if (channel.config().isAutoRead()) { - channel.read(); - } - - return this; - } - - @Override - public ChannelPipeline fireChannelInactive() { - head.fireChannelInactive(); - return this; - } - - @Override - public ChannelPipeline fireExceptionCaught(Throwable cause) { - head.fireExceptionCaught(cause); - return this; - } - - @Override - public ChannelPipeline fireUserEventTriggered(Object event) { - head.fireUserEventTriggered(event); - return this; - } - - @Override - public ChannelPipeline fireChannelRead(Object msg) { - head.fireChannelRead(msg); - return this; - } - - @Override - public ChannelPipeline fireChannelReadComplete() { - head.fireChannelReadComplete(); - if (channel.config().isAutoRead()) { - read(); - } - return this; - } - - @Override - public ChannelPipeline fireChannelWritabilityChanged() { - head.fireChannelWritabilityChanged(); - return this; - } - - @Override - public ChannelFuture bind(SocketAddress localAddress) { - return tail.bind(localAddress); - } - - @Override - public ChannelFuture connect(SocketAddress remoteAddress) { - return tail.connect(remoteAddress); - } - - @Override - public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress) { - return tail.connect(remoteAddress, localAddress); - } - - @Override - public ChannelFuture disconnect() { - return tail.disconnect(); - } - - @Override - public ChannelFuture close() { - return tail.close(); - } - - @Override - public ChannelFuture deregister() { - return tail.deregister(); - } - - @Override - public ChannelPipeline flush() { - tail.flush(); - return this; - } - - @Override - public ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise) { - return tail.bind(localAddress, promise); - } - - @Override - public ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise) { - return tail.connect(remoteAddress, promise); - } - - @Override - public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) { - return tail.connect(remoteAddress, localAddress, promise); - } - - @Override - public ChannelFuture disconnect(ChannelPromise promise) { - return tail.disconnect(promise); - } - - @Override - public ChannelFuture close(ChannelPromise promise) { - return tail.close(promise); - } - - @Override - public ChannelFuture deregister(final ChannelPromise promise) { - return tail.deregister(promise); - } - - @Override - public ChannelPipeline read() { - tail.read(); - return this; - } - - @Override - public ChannelFuture write(Object msg) { - return tail.write(msg); - } - - @Override - public ChannelFuture write(Object msg, ChannelPromise promise) { - return tail.write(msg, promise); - } - - @Override - public ChannelFuture writeAndFlush(Object msg, ChannelPromise promise) { - return tail.writeAndFlush(msg, promise); - } - - @Override - public ChannelFuture writeAndFlush(Object msg) { - return tail.writeAndFlush(msg); - } - - private void checkDuplicateName(String name) { - if (name2ctx.containsKey(name)) { - throw new IllegalArgumentException("Duplicate handler name: " + name); - } - } - - private AbstractChannelHandlerContext getContextOrDie(String name) { - AbstractChannelHandlerContext ctx = (AbstractChannelHandlerContext) context(name); - if (ctx == null) { - throw new NoSuchElementException(name); - } else { - return ctx; - } - } - - private AbstractChannelHandlerContext getContextOrDie(ChannelHandler handler) { - AbstractChannelHandlerContext ctx = (AbstractChannelHandlerContext) context(handler); - if (ctx == null) { - throw new NoSuchElementException(handler.getClass().getName()); - } else { - return ctx; - } - } - - private AbstractChannelHandlerContext getContextOrDie(Class handlerType) { - AbstractChannelHandlerContext ctx = (AbstractChannelHandlerContext) context(handlerType); - if (ctx == null) { - throw new NoSuchElementException(handlerType.getName()); - } else { - return ctx; - } - } - - // A special catch-all handler that handles both bytes and messages. - static final class TailContext extends AbstractChannelHandlerContext implements ChannelInboundHandler { - - private static final String TAIL_NAME = generateName0(TailContext.class); - - TailContext(DefaultChannelPipeline pipeline) { - super(pipeline, null, TAIL_NAME, true, false); - } - - @Override - public ChannelHandler handler() { - return this; - } - - @Override - public void channelRegistered(ChannelHandlerContext ctx) throws Exception { } - - @Override - public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { } - - @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { } - - @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { } - - @Override - public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception { } - - @Override - public void handlerAdded(ChannelHandlerContext ctx) throws Exception { } - - @Override - public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { } - - @Override - public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { - // This may not be a configuration error and so don't log anything. - // The event may be superfluous for the current pipeline configuration. - ReferenceCountUtil.release(evt); - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - try { - logger.warn( - "An exceptionCaught() event was fired, and it reached at the tail of the pipeline. " + - "It usually means the last handler in the pipeline did not handle the exception.", - cause); - } finally { - ReferenceCountUtil.release(cause); - } - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - try { - logger.debug( - "Discarded inbound message {} that reached at the tail of the pipeline. " + - "Please check your pipeline configuration.", msg); - } finally { - ReferenceCountUtil.release(msg); - } - } - - @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { } - } - - static final class HeadContext extends AbstractChannelHandlerContext implements ChannelOutboundHandler { - - private static final String HEAD_NAME = generateName0(HeadContext.class); - - protected final Unsafe unsafe; - - HeadContext(DefaultChannelPipeline pipeline) { - super(pipeline, null, HEAD_NAME, false, true); - unsafe = pipeline.channel().unsafe(); - } - - @Override - public ChannelHandler handler() { - return this; - } - - @Override - public void handlerAdded(ChannelHandlerContext ctx) throws Exception { - // NOOP - } - - @Override - public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { - // NOOP - } - - @Override - public void bind( - ChannelHandlerContext ctx, SocketAddress localAddress, ChannelPromise promise) - throws Exception { - unsafe.bind(localAddress, promise); - } - - @Override - public void connect( - ChannelHandlerContext ctx, - SocketAddress remoteAddress, SocketAddress localAddress, - ChannelPromise promise) throws Exception { - unsafe.connect(remoteAddress, localAddress, promise); - } - - @Override - public void disconnect(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception { - unsafe.disconnect(promise); - } - - @Override - public void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception { - unsafe.close(promise); - } - - @Override - public void deregister(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception { - unsafe.deregister(promise); - } - - @Override - public void read(ChannelHandlerContext ctx) { - unsafe.beginRead(); - } - - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - unsafe.write(msg, promise); - } - - @Override - public void flush(ChannelHandlerContext ctx) throws Exception { - unsafe.flush(); - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - ctx.fireExceptionCaught(cause); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/DefaultChannelProgressivePromise.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/DefaultChannelProgressivePromise.java deleted file mode 100755 index b5eedb46d0..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/DefaultChannelProgressivePromise.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import com.ai.cloud.io.netty.channel.ChannelFlushPromiseNotifier.FlushCheckpoint; -import com.ai.cloud.io.netty.util.concurrent.DefaultProgressivePromise; -import com.ai.cloud.io.netty.util.concurrent.EventExecutor; -import com.ai.cloud.io.netty.util.concurrent.Future; -import com.ai.cloud.io.netty.util.concurrent.GenericFutureListener; - -/** - * The default {@link ChannelProgressivePromise} implementation. It is recommended to use - * {@link Channel#newProgressivePromise()} to create a new {@link ChannelProgressivePromise} rather than calling the - * constructor explicitly. - */ -public class DefaultChannelProgressivePromise - extends DefaultProgressivePromise implements ChannelProgressivePromise, FlushCheckpoint { - - private final Channel channel; - private long checkpoint; - - /** - * Creates a new instance. - * - * @param channel - * the {@link Channel} associated with this future - */ - public DefaultChannelProgressivePromise(Channel channel) { - this.channel = channel; - } - - /** - * Creates a new instance. - * - * @param channel - * the {@link Channel} associated with this future - */ - public DefaultChannelProgressivePromise(Channel channel, EventExecutor executor) { - super(executor); - this.channel = channel; - } - - @Override - protected EventExecutor executor() { - EventExecutor e = super.executor(); - if (e == null) { - return channel().eventLoop(); - } else { - return e; - } - } - - @Override - public Channel channel() { - return channel; - } - - @Override - public ChannelProgressivePromise setSuccess() { - return setSuccess(null); - } - - @Override - public ChannelProgressivePromise setSuccess(Void result) { - super.setSuccess(result); - return this; - } - - @Override - public boolean trySuccess() { - return trySuccess(null); - } - - @Override - public ChannelProgressivePromise setFailure(Throwable cause) { - super.setFailure(cause); - return this; - } - - @Override - public ChannelProgressivePromise setProgress(long progress, long total) { - super.setProgress(progress, total); - return this; - } - - @Override - public ChannelProgressivePromise addListener(GenericFutureListener> listener) { - super.addListener(listener); - return this; - } - - @Override - public ChannelProgressivePromise addListeners(GenericFutureListener>... listeners) { - super.addListeners(listeners); - return this; - } - - @Override - public ChannelProgressivePromise removeListener(GenericFutureListener> listener) { - super.removeListener(listener); - return this; - } - - @Override - public ChannelProgressivePromise removeListeners( - GenericFutureListener>... listeners) { - super.removeListeners(listeners); - return this; - } - - @Override - public ChannelProgressivePromise sync() throws InterruptedException { - super.sync(); - return this; - } - - @Override - public ChannelProgressivePromise syncUninterruptibly() { - super.syncUninterruptibly(); - return this; - } - - @Override - public ChannelProgressivePromise await() throws InterruptedException { - super.await(); - return this; - } - - @Override - public ChannelProgressivePromise awaitUninterruptibly() { - super.awaitUninterruptibly(); - return this; - } - - @Override - public long flushCheckpoint() { - return checkpoint; - } - - @Override - public void flushCheckpoint(long checkpoint) { - this.checkpoint = checkpoint; - } - - @Override - public ChannelProgressivePromise promise() { - return this; - } - - @Override - protected void checkDeadLock() { - if (channel().isRegistered()) { - super.checkDeadLock(); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/DefaultChannelPromise.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/DefaultChannelPromise.java deleted file mode 100755 index da0be92fe6..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/DefaultChannelPromise.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import com.ai.cloud.io.netty.channel.ChannelFlushPromiseNotifier.FlushCheckpoint; -import com.ai.cloud.io.netty.util.concurrent.DefaultPromise; -import com.ai.cloud.io.netty.util.concurrent.EventExecutor; -import com.ai.cloud.io.netty.util.concurrent.Future; -import com.ai.cloud.io.netty.util.concurrent.GenericFutureListener; - -/** - * The default {@link ChannelPromise} implementation. It is recommended to use {@link Channel#newPromise()} to create - * a new {@link ChannelPromise} rather than calling the constructor explicitly. - */ -public class DefaultChannelPromise extends DefaultPromise implements ChannelPromise, FlushCheckpoint { - - private final Channel channel; - private long checkpoint; - - /** - * Creates a new instance. - * - * @param channel - * the {@link Channel} associated with this future - */ - public DefaultChannelPromise(Channel channel) { - this.channel = channel; - } - - /** - * Creates a new instance. - * - * @param channel - * the {@link Channel} associated with this future - */ - public DefaultChannelPromise(Channel channel, EventExecutor executor) { - super(executor); - this.channel = channel; - } - - @Override - protected EventExecutor executor() { - EventExecutor e = super.executor(); - if (e == null) { - return channel().eventLoop(); - } else { - return e; - } - } - - @Override - public Channel channel() { - return channel; - } - - @Override - public ChannelPromise setSuccess() { - return setSuccess(null); - } - - @Override - public ChannelPromise setSuccess(Void result) { - super.setSuccess(result); - return this; - } - - @Override - public boolean trySuccess() { - return trySuccess(null); - } - - @Override - public ChannelPromise setFailure(Throwable cause) { - super.setFailure(cause); - return this; - } - - @Override - public ChannelPromise addListener(GenericFutureListener> listener) { - super.addListener(listener); - return this; - } - - @Override - public ChannelPromise addListeners(GenericFutureListener>... listeners) { - super.addListeners(listeners); - return this; - } - - @Override - public ChannelPromise removeListener(GenericFutureListener> listener) { - super.removeListener(listener); - return this; - } - - @Override - public ChannelPromise removeListeners(GenericFutureListener>... listeners) { - super.removeListeners(listeners); - return this; - } - - @Override - public ChannelPromise sync() throws InterruptedException { - super.sync(); - return this; - } - - @Override - public ChannelPromise syncUninterruptibly() { - super.syncUninterruptibly(); - return this; - } - - @Override - public ChannelPromise await() throws InterruptedException { - super.await(); - return this; - } - - @Override - public ChannelPromise awaitUninterruptibly() { - super.awaitUninterruptibly(); - return this; - } - - @Override - public long flushCheckpoint() { - return checkpoint; - } - - @Override - public void flushCheckpoint(long checkpoint) { - this.checkpoint = checkpoint; - } - - @Override - public ChannelPromise promise() { - return this; - } - - @Override - protected void checkDeadLock() { - if (channel().isRegistered()) { - super.checkDeadLock(); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/DefaultFileRegion.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/DefaultFileRegion.java deleted file mode 100755 index 9b32d8f6e0..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/DefaultFileRegion.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.channels.FileChannel; -import java.nio.channels.WritableByteChannel; - -import com.ai.cloud.io.netty.util.AbstractReferenceCounted; -import com.ai.cloud.io.netty.util.IllegalReferenceCountException; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * Default {@link FileRegion} implementation which transfer data from a {@link FileChannel} or {@link File}. - * - * Be aware that the {@link FileChannel} will be automatically closed once {@link #refCnt()} returns - * {@code 0}. - */ -public class DefaultFileRegion extends AbstractReferenceCounted implements FileRegion { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(DefaultFileRegion.class); - private final File f; - private final long position; - private final long count; - private long transfered; - private FileChannel file; - - /** - * Create a new instance - * - * @param file the {@link FileChannel} which should be transfered - * @param position the position from which the transfer should start - * @param count the number of bytes to transfer - */ - public DefaultFileRegion(FileChannel file, long position, long count) { - if (file == null) { - throw new NullPointerException("file"); - } - if (position < 0) { - throw new IllegalArgumentException("position must be >= 0 but was " + position); - } - if (count < 0) { - throw new IllegalArgumentException("count must be >= 0 but was " + count); - } - this.file = file; - this.position = position; - this.count = count; - f = null; - } - - /** - * Create a new instance using the given {@link File}. The {@link File} will be opened lazily or - * explicitly via {@link #open()}. - * - * @param f the {@link File} which should be transfered - * @param position the position from which the transfer should start - * @param count the number of bytes to transfer - */ - public DefaultFileRegion(File f, long position, long count) { - if (f == null) { - throw new NullPointerException("f"); - } - if (position < 0) { - throw new IllegalArgumentException("position must be >= 0 but was " + position); - } - if (count < 0) { - throw new IllegalArgumentException("count must be >= 0 but was " + count); - } - this.position = position; - this.count = count; - this.f = f; - } - - /** - * Returns {@code true} if the {@link FileRegion} has a open file-descriptor - */ - public boolean isOpen() { - return file != null; - } - - /** - * Explicitly open the underlying file-descriptor if not done yet. - */ - public void open() throws IOException { - if (!isOpen() && refCnt() > 0) { - // Only open if this DefaultFileRegion was not released yet. - file = new RandomAccessFile(f, "r").getChannel(); - } - } - - @Override - public long position() { - return position; - } - - @Override - public long count() { - return count; - } - - @Override - public long transfered() { - return transfered; - } - - @Override - public long transferTo(WritableByteChannel target, long position) throws IOException { - long count = this.count - position; - if (count < 0 || position < 0) { - throw new IllegalArgumentException( - "position out of range: " + position + - " (expected: 0 - " + (this.count - 1) + ')'); - } - if (count == 0) { - return 0L; - } - if (refCnt() == 0) { - throw new IllegalReferenceCountException(0); - } - // Call open to make sure fc is initialized. This is a no-oop if we called it before. - open(); - - long written = file.transferTo(this.position + position, count, target); - if (written > 0) { - transfered += written; - } - return written; - } - - @Override - protected void deallocate() { - FileChannel file = this.file; - - if (file == null) { - return; - } - this.file = null; - - try { - file.close(); - } catch (IOException e) { - if (logger.isWarnEnabled()) { - logger.warn("Failed to close a file.", e); - } - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/DefaultMessageSizeEstimator.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/DefaultMessageSizeEstimator.java deleted file mode 100755 index af619478d0..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/DefaultMessageSizeEstimator.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.ByteBufHolder; - -/** - * Default {@link MessageSizeEstimator} implementation which supports the estimation of the size of - * {@link ByteBuf}, {@link ByteBufHolder} and {@link FileRegion}. - */ -public final class DefaultMessageSizeEstimator implements MessageSizeEstimator { - - private static final class HandleImpl implements Handle { - private final int unknownSize; - - private HandleImpl(int unknownSize) { - this.unknownSize = unknownSize; - } - - @Override - public int size(Object msg) { - if (msg instanceof ByteBuf) { - return ((ByteBuf) msg).readableBytes(); - } - if (msg instanceof ByteBufHolder) { - return ((ByteBufHolder) msg).content().readableBytes(); - } - if (msg instanceof FileRegion) { - return 0; - } - return unknownSize; - } - } - - /** - * Return the default implementation which returns {@code 8} for unknown messages. - */ - public static final MessageSizeEstimator DEFAULT = new DefaultMessageSizeEstimator(8); - - private final Handle handle; - - /** - * Create a new instance - * - * @param unknownSize The size which is returned for unknown messages. - */ - public DefaultMessageSizeEstimator(int unknownSize) { - if (unknownSize < 0) { - throw new IllegalArgumentException("unknownSize: " + unknownSize + " (expected: >= 0)"); - } - handle = new HandleImpl(unknownSize); - } - - @Override - public Handle newHandle() { - return handle; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/EventLoop.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/EventLoop.java deleted file mode 100755 index 3e1a9aae2c..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/EventLoop.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import com.ai.cloud.io.netty.util.concurrent.EventExecutor; - -/** - * Will handle all the I/O operations for a {@link Channel} once registered. - * - * One {@link EventLoop} instance will usually handle more then one {@link Channel} but this may depend on - * implementation details and internals. - * - */ -public interface EventLoop extends EventExecutor, EventLoopGroup { - @Override - EventLoopGroup parent(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/EventLoopException.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/EventLoopException.java deleted file mode 100755 index af78a4f31b..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/EventLoopException.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -/** - * Special {@link ChannelException} which will be thrown by {@link EventLoop} and {@link EventLoopGroup} - * implementations when an error occurs. - */ -public class EventLoopException extends ChannelException { - - private static final long serialVersionUID = -8969100344583703616L; - - public EventLoopException() { - } - - public EventLoopException(String message, Throwable cause) { - super(message, cause); - } - - public EventLoopException(String message) { - super(message); - } - - public EventLoopException(Throwable cause) { - super(cause); - } - -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/EventLoopGroup.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/EventLoopGroup.java deleted file mode 100755 index 51ffe8ff31..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/EventLoopGroup.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import com.ai.cloud.io.netty.util.concurrent.EventExecutorGroup; - -/** - * Special {@link EventExecutorGroup} which allows registering {@link Channel}s that get - * processed for later selection during the event loop. - * - */ -public interface EventLoopGroup extends EventExecutorGroup { - /** - * Return the next {@link EventLoop} to use - */ - @Override - EventLoop next(); - - /** - * Register a {@link Channel} with this {@link EventLoop}. The returned {@link ChannelFuture} - * will get notified once the registration was complete. - */ - ChannelFuture register(Channel channel); - - /** - * Register a {@link Channel} with this {@link EventLoop}. The passed {@link ChannelFuture} - * will get notified once the registration was complete and also will get returned. - */ - ChannelFuture register(Channel channel, ChannelPromise promise); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/FailedChannelFuture.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/FailedChannelFuture.java deleted file mode 100755 index 68a6ac2834..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/FailedChannelFuture.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import com.ai.cloud.io.netty.util.concurrent.EventExecutor; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - -/** - * The {@link CompleteChannelFuture} which is failed already. It is - * recommended to use {@link Channel#newFailedFuture(Throwable)} - * instead of calling the constructor of this future. - */ -final class FailedChannelFuture extends CompleteChannelFuture { - - private final Throwable cause; - - /** - * Creates a new instance. - * - * @param channel the {@link Channel} associated with this future - * @param cause the cause of failure - */ - FailedChannelFuture(Channel channel, EventExecutor executor, Throwable cause) { - super(channel, executor); - if (cause == null) { - throw new NullPointerException("cause"); - } - this.cause = cause; - } - - @Override - public Throwable cause() { - return cause; - } - - @Override - public boolean isSuccess() { - return false; - } - - @Override - public ChannelFuture sync() { - PlatformDependent.throwException(cause); - return this; - } - - @Override - public ChannelFuture syncUninterruptibly() { - PlatformDependent.throwException(cause); - return this; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/FileRegion.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/FileRegion.java deleted file mode 100755 index 223c30e45d..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/FileRegion.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import java.io.IOException; -import java.nio.channels.FileChannel; -import java.nio.channels.WritableByteChannel; - -import com.ai.cloud.io.netty.util.ReferenceCounted; - -/** - * A region of a file that is sent via a {@link Channel} which supports - * zero-copy file transfer. - * - *

Upgrade your JDK / JRE

- * - * {@link FileChannel#transferTo(long, long, WritableByteChannel)} has at least - * four known bugs in the old versions of Sun JDK and perhaps its derived ones. - * Please upgrade your JDK to 1.6.0_18 or later version if you are going to use - * zero-copy file transfer. - *
    - *
  • 5103988 - * - FileChannel.transferTo() should return -1 for EAGAIN instead throws IOException
  • - *
  • 6253145 - * - FileChannel.transferTo() on Linux fails when going beyond 2GB boundary
  • - *
  • 6427312 - * - FileChannel.transferTo() throws IOException "system call interrupted"
  • - *
  • 6470086 - * - FileChannel.transferTo(2147483647, 1, channel) causes "Value too large" exception
  • - *
- * - *

Check your operating system and JDK / JRE

- * - * If your operating system (or JDK / JRE) does not support zero-copy file - * transfer, sending a file with {@link FileRegion} might fail or yield worse - * performance. For example, sending a large file doesn't work well in Windows. - * - *

Not all transports support it

- * - * Currently, the NIO transport is the only transport that supports {@link FileRegion}. - */ -public interface FileRegion extends ReferenceCounted { - - /** - * Returns the offset in the file where the transfer began. - */ - long position(); - - /** - * Return the bytes which was transfered already - */ - long transfered(); - - /** - * Returns the number of bytes to transfer. - */ - long count(); - - /** - * Transfers the content of this file region to the specified channel. - * - * @param target the destination of the transfer - * @param position the relative offset of the file where the transfer - * begins from. For example, 0 will make the - * transfer start from {@link #position()}th byte and - * {@link #count()} - 1 will make the last - * byte of the region transferred. - */ - long transferTo(WritableByteChannel target, long position) throws IOException; -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/FixedRecvByteBufAllocator.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/FixedRecvByteBufAllocator.java deleted file mode 100755 index 6957e2d156..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/FixedRecvByteBufAllocator.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.ByteBufAllocator; - - -/** - * The {@link RecvByteBufAllocator} that always yields the same buffer - * size prediction. This predictor ignores the feed back from the I/O thread. - */ -public class FixedRecvByteBufAllocator implements RecvByteBufAllocator { - - private static final class HandleImpl implements Handle { - - private final int bufferSize; - - HandleImpl(int bufferSize) { - this.bufferSize = bufferSize; - } - - @Override - public ByteBuf allocate(ByteBufAllocator alloc) { - return alloc.ioBuffer(bufferSize); - } - - @Override - public int guess() { - return bufferSize; - } - - @Override - public void record(int actualReadBytes) { } - } - - private final Handle handle; - - /** - * Creates a new predictor that always returns the same prediction of - * the specified buffer size. - */ - public FixedRecvByteBufAllocator(int bufferSize) { - if (bufferSize <= 0) { - throw new IllegalArgumentException( - "bufferSize must greater than 0: " + bufferSize); - } - - handle = new HandleImpl(bufferSize); - } - - @Override - public Handle newHandle() { - return handle; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/MessageSizeEstimator.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/MessageSizeEstimator.java deleted file mode 100755 index 69490ce8e5..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/MessageSizeEstimator.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -/** - * Responsible to estimate size of a message. The size represent how much memory the message will ca. reserve in - * memory. - */ -public interface MessageSizeEstimator { - - /** - * Creates a new handle. The handle provides the actual operations. - */ - Handle newHandle(); - - interface Handle { - - /** - * Calculate the size of the given message. - * - * @param msg The message for which the size should be calculated - * @return size The size in bytes. The returned size must be >= 0 - */ - int size(Object msg); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/MultithreadEventLoopGroup.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/MultithreadEventLoopGroup.java deleted file mode 100755 index 4974dd33ae..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/MultithreadEventLoopGroup.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import java.util.concurrent.ThreadFactory; - -import com.ai.cloud.io.netty.util.concurrent.DefaultThreadFactory; -import com.ai.cloud.io.netty.util.concurrent.MultithreadEventExecutorGroup; -import com.ai.cloud.io.netty.util.internal.SystemPropertyUtil; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * Abstract base class for {@link EventLoopGroup} implementations that handles their tasks with multiple threads at - * the same time. - */ -public abstract class MultithreadEventLoopGroup extends MultithreadEventExecutorGroup implements EventLoopGroup { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(MultithreadEventLoopGroup.class); - - private static final int DEFAULT_EVENT_LOOP_THREADS; - - static { - DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt( - "io.netty.eventLoopThreads", Runtime.getRuntime().availableProcessors() * 2)); - - if (logger.isDebugEnabled()) { - logger.debug("-Dio.netty.eventLoopThreads: {}", DEFAULT_EVENT_LOOP_THREADS); - } - } - - /** - * @see {@link MultithreadEventExecutorGroup#MultithreadEventExecutorGroup(int, ThreadFactory, Object...)} - */ - protected MultithreadEventLoopGroup(int nThreads, ThreadFactory threadFactory, Object... args) { - super(nThreads == 0? DEFAULT_EVENT_LOOP_THREADS : nThreads, threadFactory, args); - } - - @Override - protected ThreadFactory newDefaultThreadFactory() { - return new DefaultThreadFactory(getClass(), Thread.MAX_PRIORITY); - } - - @Override - public EventLoop next() { - return (EventLoop) super.next(); - } - - @Override - public ChannelFuture register(Channel channel) { - return next().register(channel); - } - - @Override - public ChannelFuture register(Channel channel, ChannelPromise promise) { - return next().register(channel, promise); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/PendingWriteQueue.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/PendingWriteQueue.java deleted file mode 100755 index 6940f6210a..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/PendingWriteQueue.java +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import com.ai.cloud.io.netty.util.Recycler; -import com.ai.cloud.io.netty.util.ReferenceCountUtil; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * A queue of write operations which are pending for later execution. It also updates the - * {@linkplain Channel#isWritable() writability} of the associated {@link Channel}, so that - * the pending write operations are also considered to determine the writability. - */ -public final class PendingWriteQueue { - private static final InternalLogger logger = InternalLoggerFactory.getInstance(PendingWriteQueue.class); - - private final ChannelHandlerContext ctx; - private final ChannelOutboundBuffer buffer; - private final MessageSizeEstimator.Handle estimatorHandle; - - // head and tail pointers for the linked-list structure. If empty head and tail are null. - private PendingWrite head; - private PendingWrite tail; - private int size; - - public PendingWriteQueue(ChannelHandlerContext ctx) { - if (ctx == null) { - throw new NullPointerException("ctx"); - } - this.ctx = ctx; - buffer = ctx.channel().unsafe().outboundBuffer(); - estimatorHandle = ctx.channel().config().getMessageSizeEstimator().newHandle(); - } - - /** - * Returns {@code true} if there are no pending write operations left in this queue. - */ - public boolean isEmpty() { - assert ctx.executor().inEventLoop(); - return head == null; - } - - /** - * Returns the number of pending write operations. - */ - public int size() { - assert ctx.executor().inEventLoop(); - return size; - } - - /** - * Add the given {@code msg} and {@link ChannelPromise}. - */ - public void add(Object msg, ChannelPromise promise) { - assert ctx.executor().inEventLoop(); - if (msg == null) { - throw new NullPointerException("msg"); - } - if (promise == null) { - throw new NullPointerException("promise"); - } - int messageSize = estimatorHandle.size(msg); - if (messageSize < 0) { - // Size may be unknow so just use 0 - messageSize = 0; - } - PendingWrite write = PendingWrite.newInstance(msg, messageSize, promise); - PendingWrite currentTail = tail; - if (currentTail == null) { - tail = head = write; - } else { - currentTail.next = write; - tail = write; - } - size ++; - // We need to guard against null as channel.unsafe().outboundBuffer() may returned null - // if the channel was already closed when constructing the PendingWriteQueue. - // See https://github.com/netty/netty/issues/3967 - if (buffer != null) { - buffer.incrementPendingOutboundBytes(write.size); - } - } - - /** - * Remove all pending write operation and fail them with the given {@link Throwable}. The message will be released - * via {@link ReferenceCountUtil#safeRelease(Object)}. - */ - public void removeAndFailAll(Throwable cause) { - assert ctx.executor().inEventLoop(); - if (cause == null) { - throw new NullPointerException("cause"); - } - // Guard against re-entrance by directly reset - PendingWrite write = head; - head = tail = null; - size = 0; - - while (write != null) { - PendingWrite next = write.next; - ReferenceCountUtil.safeRelease(write.msg); - ChannelPromise promise = write.promise; - recycle(write, false); - safeFail(promise, cause); - write = next; - } - assertEmpty(); - } - - /** - * Remove a pending write operation and fail it with the given {@link Throwable}. The message will be released via - * {@link ReferenceCountUtil#safeRelease(Object)}. - */ - public void removeAndFail(Throwable cause) { - assert ctx.executor().inEventLoop(); - if (cause == null) { - throw new NullPointerException("cause"); - } - PendingWrite write = head; - - if (write == null) { - return; - } - ReferenceCountUtil.safeRelease(write.msg); - ChannelPromise promise = write.promise; - safeFail(promise, cause); - recycle(write, true); - } - - /** - * Remove all pending write operation and performs them via - * {@link ChannelHandlerContext#write(Object, ChannelPromise)}. - * - * @return {@link ChannelFuture} if something was written and {@code null} - * if the {@link PendingWriteQueue} is empty. - */ - public ChannelFuture removeAndWriteAll() { - assert ctx.executor().inEventLoop(); - - if (size == 1) { - // No need to use ChannelPromiseAggregator for this case. - return removeAndWrite(); - } - PendingWrite write = head; - if (write == null) { - // empty so just return null - return null; - } - - // Guard against re-entrance by directly reset - head = tail = null; - size = 0; - - ChannelPromise p = ctx.newPromise(); - ChannelPromiseAggregator aggregator = new ChannelPromiseAggregator(p); - while (write != null) { - PendingWrite next = write.next; - Object msg = write.msg; - ChannelPromise promise = write.promise; - recycle(write, false); - ctx.write(msg, promise); - aggregator.add(promise); - write = next; - } - assertEmpty(); - return p; - } - - private void assertEmpty() { - assert tail == null && head == null && size == 0; - } - - /** - * Removes a pending write operation and performs it via - * {@link ChannelHandlerContext#write(Object, ChannelPromise)}. - * - * @return {@link ChannelFuture} if something was written and {@code null} - * if the {@link PendingWriteQueue} is empty. - */ - public ChannelFuture removeAndWrite() { - assert ctx.executor().inEventLoop(); - PendingWrite write = head; - if (write == null) { - return null; - } - Object msg = write.msg; - ChannelPromise promise = write.promise; - recycle(write, true); - return ctx.write(msg, promise); - } - - /** - * Removes a pending write operation and release it's message via {@link ReferenceCountUtil#safeRelease(Object)}. - * - * @return {@link ChannelPromise} of the pending write or {@code null} if the queue is empty. - * - */ - public ChannelPromise remove() { - assert ctx.executor().inEventLoop(); - PendingWrite write = head; - if (write == null) { - return null; - } - ChannelPromise promise = write.promise; - ReferenceCountUtil.safeRelease(write.msg); - recycle(write, true); - return promise; - } - - /** - * Return the current message or {@code null} if empty. - */ - public Object current() { - assert ctx.executor().inEventLoop(); - PendingWrite write = head; - if (write == null) { - return null; - } - return write.msg; - } - - private void recycle(PendingWrite write, boolean update) { - final PendingWrite next = write.next; - final long writeSize = write.size; - - if (update) { - if (next == null) { - // Handled last PendingWrite so rest head and tail - // Guard against re-entrance by directly reset - head = tail = null; - size = 0; - } else { - head = next; - size --; - assert size > 0; - } - } - - write.recycle(); - // We need to guard against null as channel.unsafe().outboundBuffer() may returned null - // if the channel was already closed when constructing the PendingWriteQueue. - // See https://github.com/netty/netty/issues/3967 - if (buffer != null) { - buffer.decrementPendingOutboundBytes(writeSize); - } - } - - private static void safeFail(ChannelPromise promise, Throwable cause) { - if (!(promise instanceof VoidChannelPromise) && !promise.tryFailure(cause)) { - logger.warn("Failed to mark a promise as failure because it's done already: {}", promise, cause); - } - } - - /** - * Holds all meta-data and construct the linked-list structure. - */ - static final class PendingWrite { - private static final Recycler RECYCLER = new Recycler() { - @Override - protected PendingWrite newObject(Handle handle) { - return new PendingWrite(handle); - } - }; - - private final Recycler.Handle handle; - private PendingWrite next; - private long size; - private ChannelPromise promise; - private Object msg; - - private PendingWrite(Recycler.Handle handle) { - this.handle = handle; - } - - static PendingWrite newInstance(Object msg, int size, ChannelPromise promise) { - PendingWrite write = RECYCLER.get(); - write.size = size; - write.msg = msg; - write.promise = promise; - return write; - } - - private void recycle() { - size = 0; - next = null; - msg = null; - promise = null; - RECYCLER.recycle(this, handle); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/RecvByteBufAllocator.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/RecvByteBufAllocator.java deleted file mode 100755 index 511f771e4d..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/RecvByteBufAllocator.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.ByteBufAllocator; - -/** - * Allocates a new receive buffer whose capacity is probably large enough to read all inbound data and small enough - * not to waste its space. - */ -public interface RecvByteBufAllocator { - - /** - * Creates a new handle. The handle provides the actual operations and keeps the internal information which is - * required for predicting an optimal buffer capacity. - */ - Handle newHandle(); - - interface Handle { - /** - * Creates a new receive buffer whose capacity is probably large enough to read all inbound data and small - * enough not to waste its space. - */ - ByteBuf allocate(ByteBufAllocator alloc); - - /** - * Similar to {@link #allocate(ByteBufAllocator)} except that it does not allocate anything but just tells the - * capacity. - */ - int guess(); - - /** - * Records the the actual number of read bytes in the previous read operation so that the allocator allocates - * the buffer with potentially more correct capacity. - * - * @param actualReadBytes the actual number of read bytes in the previous read operation - */ - void record(int actualReadBytes); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ServerChannel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ServerChannel.java deleted file mode 100755 index e3c8761aca..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ServerChannel.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import com.ai.cloud.io.netty.channel.socket.ServerSocketChannel; - -/** - * A {@link Channel} that accepts an incoming connection attempt and creates - * its child {@link Channel}s by accepting them. {@link ServerSocketChannel} is - * a good example. - */ -public interface ServerChannel extends Channel { - // This is a tag interface. -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/SimpleChannelInboundHandler.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/SimpleChannelInboundHandler.java deleted file mode 100755 index 8f3c8e81c7..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/SimpleChannelInboundHandler.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import com.ai.cloud.io.netty.util.ReferenceCountUtil; -import com.ai.cloud.io.netty.util.internal.TypeParameterMatcher; - -/** - * {@link ChannelInboundHandlerAdapter} which allows to explicit only handle a specific type of messages. - * - * For example here is an implementation which only handle {@link String} messages. - * - *
- *     public class StringHandler extends
- *             {@link SimpleChannelInboundHandler}<{@link String}> {
- *
- *         {@code @Override}
- *         protected void channelRead0({@link ChannelHandlerContext} ctx, {@link String} message)
- *                 throws {@link Exception} {
- *             System.out.println(message);
- *         }
- *     }
- * 
- * - * Be aware that depending of the constructor parameters it will release all handled messages by pass them to - * {@link ReferenceCountUtil#release(Object)}. In this case you may need to use - * {@link ReferenceCountUtil#retain(Object)} if you pass the object to the next handler in the {@link ChannelPipeline}. - * - *

Forward compatibility notice

- *

- * Please keep in mind that {@link #channelRead0(ChannelHandlerContext, I)} will be renamed to - * {@code messageReceived(ChannelHandlerContext, I)} in 5.0. - *

- */ -public abstract class SimpleChannelInboundHandler extends ChannelInboundHandlerAdapter { - - private final TypeParameterMatcher matcher; - private final boolean autoRelease; - - /** - * @see {@link #SimpleChannelInboundHandler(boolean)} with {@code true} as boolean parameter. - */ - protected SimpleChannelInboundHandler() { - this(true); - } - - /** - * Create a new instance which will try to detect the types to match out of the type parameter of the class. - * - * @param autoRelease {@code true} if handled messages should be released automatically by pass them to - * {@link ReferenceCountUtil#release(Object)}. - */ - protected SimpleChannelInboundHandler(boolean autoRelease) { - matcher = TypeParameterMatcher.find(this, SimpleChannelInboundHandler.class, "I"); - this.autoRelease = autoRelease; - } - - /** - * @see {@link #SimpleChannelInboundHandler(Class, boolean)} with {@code true} as boolean value. - */ - protected SimpleChannelInboundHandler(Class inboundMessageType) { - this(inboundMessageType, true); - } - - /** - * Create a new instance - * - * @param inboundMessageType The type of messages to match - * @param autoRelease {@code true} if handled messages should be released automatically by pass them to - * {@link ReferenceCountUtil#release(Object)}. - */ - protected SimpleChannelInboundHandler(Class inboundMessageType, boolean autoRelease) { - matcher = TypeParameterMatcher.get(inboundMessageType); - this.autoRelease = autoRelease; - } - - /** - * Returns {@code true} if the given message should be handled. If {@code false} it will be passed to the next - * {@link ChannelInboundHandler} in the {@link ChannelPipeline}. - */ - public boolean acceptInboundMessage(Object msg) throws Exception { - return matcher.match(msg); - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - boolean release = true; - try { - if (acceptInboundMessage(msg)) { - @SuppressWarnings("unchecked") - I imsg = (I) msg; - channelRead0(ctx, imsg); - } else { - release = false; - ctx.fireChannelRead(msg); - } - } finally { - if (autoRelease && release) { - ReferenceCountUtil.release(msg); - } - } - } - - /** - * Please keep in mind that this method will be renamed to - * {@code messageReceived(ChannelHandlerContext, I)} in 5.0. - * - * Is called for each message of type {@link I}. - * - * @param ctx the {@link ChannelHandlerContext} which this {@link SimpleChannelInboundHandler} - * belongs to - * @param msg the message to handle - * @throws Exception is thrown if an error occurred - */ - protected abstract void channelRead0(ChannelHandlerContext ctx, I msg) throws Exception; -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/SingleThreadEventLoop.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/SingleThreadEventLoop.java deleted file mode 100755 index bf7cd17089..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/SingleThreadEventLoop.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import java.util.concurrent.ThreadFactory; - -import com.ai.cloud.io.netty.util.concurrent.EventExecutorGroup; -import com.ai.cloud.io.netty.util.concurrent.SingleThreadEventExecutor; - -/** - * Abstract base class for {@link EventLoop}'s that execute all its submitted tasks in a single thread. - * - */ -public abstract class SingleThreadEventLoop extends SingleThreadEventExecutor implements EventLoop { - - /** - * @see {@link SingleThreadEventExecutor#SingleThreadEventExecutor(EventExecutorGroup, ThreadFactory, boolean)} - */ - protected SingleThreadEventLoop(EventLoopGroup parent, ThreadFactory threadFactory, boolean addTaskWakesUp) { - super(parent, threadFactory, addTaskWakesUp); - } - - @Override - public EventLoopGroup parent() { - return (EventLoopGroup) super.parent(); - } - - @Override - public EventLoop next() { - return (EventLoop) super.next(); - } - - @Override - public ChannelFuture register(Channel channel) { - return register(channel, new DefaultChannelPromise(channel, this)); - } - - @Override - public ChannelFuture register(final Channel channel, final ChannelPromise promise) { - if (channel == null) { - throw new NullPointerException("channel"); - } - if (promise == null) { - throw new NullPointerException("promise"); - } - - channel.unsafe().register(this, promise); - return promise; - } - - @Override - protected boolean wakesUpForTask(Runnable task) { - return !(task instanceof NonWakeupRunnable); - } - - /** - * Marker interface for {@link Runnable} that will not trigger an {@link #wakeup(boolean)} in all cases. - */ - interface NonWakeupRunnable extends Runnable { } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/SucceededChannelFuture.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/SucceededChannelFuture.java deleted file mode 100755 index 539447c816..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/SucceededChannelFuture.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import com.ai.cloud.io.netty.util.concurrent.EventExecutor; - -/** - * The {@link CompleteChannelFuture} which is succeeded already. It is - * recommended to use {@link Channel#newSucceededFuture()} instead of - * calling the constructor of this future. - */ -final class SucceededChannelFuture extends CompleteChannelFuture { - - /** - * Creates a new instance. - * - * @param channel the {@link Channel} associated with this future - */ - SucceededChannelFuture(Channel channel, EventExecutor executor) { - super(channel, executor); - } - - @Override - public Throwable cause() { - return null; - } - - @Override - public boolean isSuccess() { - return true; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ThreadPerChannelEventLoop.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ThreadPerChannelEventLoop.java deleted file mode 100755 index c45d14556b..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ThreadPerChannelEventLoop.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -/** - * {@link SingleThreadEventLoop} which is used to handle OIO {@link Channel}'s. So in general there will be - * one {@link ThreadPerChannelEventLoop} per {@link Channel}. - * - */ -public class ThreadPerChannelEventLoop extends SingleThreadEventLoop { - - private final ThreadPerChannelEventLoopGroup parent; - private Channel ch; - - public ThreadPerChannelEventLoop(ThreadPerChannelEventLoopGroup parent) { - super(parent, parent.threadFactory, true); - this.parent = parent; - } - - @Override - public ChannelFuture register(Channel channel, ChannelPromise promise) { - return super.register(channel, promise).addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - if (future.isSuccess()) { - ch = future.channel(); - } else { - deregister(); - } - } - }); - } - - @Override - protected void run() { - for (;;) { - Runnable task = takeTask(); - if (task != null) { - task.run(); - updateLastExecutionTime(); - } - - Channel ch = this.ch; - if (isShuttingDown()) { - if (ch != null) { - ch.unsafe().close(ch.unsafe().voidPromise()); - } - if (confirmShutdown()) { - break; - } - } else { - if (ch != null) { - // Handle deregistration - if (!ch.isRegistered()) { - runAllTasks(); - deregister(); - } - } - } - } - } - - protected void deregister() { - ch = null; - parent.activeChildren.remove(this); - parent.idleChildren.add(this); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ThreadPerChannelEventLoopGroup.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ThreadPerChannelEventLoopGroup.java deleted file mode 100755 index af50ca66b6..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/ThreadPerChannelEventLoopGroup.java +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - - -import java.util.Collections; -import java.util.Iterator; -import java.util.Queue; -import java.util.Set; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.Executors; -import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; - -import com.ai.cloud.io.netty.util.concurrent.AbstractEventExecutorGroup; -import com.ai.cloud.io.netty.util.concurrent.DefaultPromise; -import com.ai.cloud.io.netty.util.concurrent.EventExecutor; -import com.ai.cloud.io.netty.util.concurrent.Future; -import com.ai.cloud.io.netty.util.concurrent.FutureListener; -import com.ai.cloud.io.netty.util.concurrent.GlobalEventExecutor; -import com.ai.cloud.io.netty.util.concurrent.Promise; -import com.ai.cloud.io.netty.util.internal.EmptyArrays; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; -import com.ai.cloud.io.netty.util.internal.ReadOnlyIterator; - -/** - * An {@link EventLoopGroup} that creates one {@link EventLoop} per {@link Channel}. - */ -public class ThreadPerChannelEventLoopGroup extends AbstractEventExecutorGroup implements EventLoopGroup { - - private final Object[] childArgs; - private final int maxChannels; - final ThreadFactory threadFactory; - final Set activeChildren = - Collections.newSetFromMap(PlatformDependent.newConcurrentHashMap()); - final Queue idleChildren = new ConcurrentLinkedQueue(); - private final ChannelException tooManyChannels; - - private volatile boolean shuttingDown; - private final Promise terminationFuture = new DefaultPromise(GlobalEventExecutor.INSTANCE); - private final FutureListener childTerminationListener = new FutureListener() { - @Override - public void operationComplete(Future future) throws Exception { - // Inefficient, but works. - if (isTerminated()) { - terminationFuture.trySuccess(null); - } - } - }; - - /** - * Create a new {@link ThreadPerChannelEventLoopGroup} with no limit in place. - */ - protected ThreadPerChannelEventLoopGroup() { - this(0); - } - - /** - * Create a new {@link ThreadPerChannelEventLoopGroup}. - * - * @param maxChannels the maximum number of channels to handle with this instance. Once you try to register - * a new {@link Channel} and the maximum is exceed it will throw an - * {@link ChannelException} on the {@link #register(Channel)} and - * {@link #register(Channel, ChannelPromise)} method. - * Use {@code 0} to use no limit - */ - protected ThreadPerChannelEventLoopGroup(int maxChannels) { - this(maxChannels, Executors.defaultThreadFactory()); - } - - /** - * Create a new {@link ThreadPerChannelEventLoopGroup}. - * - * @param maxChannels the maximum number of channels to handle with this instance. Once you try to register - * a new {@link Channel} and the maximum is exceed it will throw an - * {@link ChannelException} on the {@link #register(Channel)} and - * {@link #register(Channel, ChannelPromise)} method. - * Use {@code 0} to use no limit - * @param threadFactory the {@link ThreadFactory} used to create new {@link Thread} instances that handle the - * registered {@link Channel}s - * @param args arguments which will passed to each {@link #newChild(Object...)} call. - */ - protected ThreadPerChannelEventLoopGroup(int maxChannels, ThreadFactory threadFactory, Object... args) { - if (maxChannels < 0) { - throw new IllegalArgumentException(String.format( - "maxChannels: %d (expected: >= 0)", maxChannels)); - } - if (threadFactory == null) { - throw new NullPointerException("threadFactory"); - } - - if (args == null) { - childArgs = EmptyArrays.EMPTY_OBJECTS; - } else { - childArgs = args.clone(); - } - - this.maxChannels = maxChannels; - this.threadFactory = threadFactory; - - tooManyChannels = new ChannelException("too many channels (max: " + maxChannels + ')'); - tooManyChannels.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); - } - - /** - * Creates a new {@link EventLoop}. The default implementation creates a new {@link ThreadPerChannelEventLoop}. - */ - protected ThreadPerChannelEventLoop newChild( - @SuppressWarnings("UnusedParameters") Object... args) throws Exception { - return new ThreadPerChannelEventLoop(this); - } - - @Override - public Iterator iterator() { - return new ReadOnlyIterator(activeChildren.iterator()); - } - - @Override - public EventLoop next() { - throw new UnsupportedOperationException(); - } - - @Override - public Future shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit) { - shuttingDown = true; - - for (EventLoop l: activeChildren) { - l.shutdownGracefully(quietPeriod, timeout, unit); - } - for (EventLoop l: idleChildren) { - l.shutdownGracefully(quietPeriod, timeout, unit); - } - - // Notify the future if there was no children. - if (isTerminated()) { - terminationFuture.trySuccess(null); - } - - return terminationFuture(); - } - - @Override - public Future terminationFuture() { - return terminationFuture; - } - - @Override - @Deprecated - public void shutdown() { - shuttingDown = true; - - for (EventLoop l: activeChildren) { - l.shutdown(); - } - for (EventLoop l: idleChildren) { - l.shutdown(); - } - - // Notify the future if there was no children. - if (isTerminated()) { - terminationFuture.trySuccess(null); - } - } - - @Override - public boolean isShuttingDown() { - for (EventLoop l: activeChildren) { - if (!l.isShuttingDown()) { - return false; - } - } - for (EventLoop l: idleChildren) { - if (!l.isShuttingDown()) { - return false; - } - } - return true; - } - - @Override - public boolean isShutdown() { - for (EventLoop l: activeChildren) { - if (!l.isShutdown()) { - return false; - } - } - for (EventLoop l: idleChildren) { - if (!l.isShutdown()) { - return false; - } - } - return true; - } - - @Override - public boolean isTerminated() { - for (EventLoop l: activeChildren) { - if (!l.isTerminated()) { - return false; - } - } - for (EventLoop l: idleChildren) { - if (!l.isTerminated()) { - return false; - } - } - return true; - } - - @Override - public boolean awaitTermination(long timeout, TimeUnit unit) - throws InterruptedException { - long deadline = System.nanoTime() + unit.toNanos(timeout); - for (EventLoop l: activeChildren) { - for (;;) { - long timeLeft = deadline - System.nanoTime(); - if (timeLeft <= 0) { - return isTerminated(); - } - if (l.awaitTermination(timeLeft, TimeUnit.NANOSECONDS)) { - break; - } - } - } - for (EventLoop l: idleChildren) { - for (;;) { - long timeLeft = deadline - System.nanoTime(); - if (timeLeft <= 0) { - return isTerminated(); - } - if (l.awaitTermination(timeLeft, TimeUnit.NANOSECONDS)) { - break; - } - } - } - return isTerminated(); - } - - @Override - public ChannelFuture register(Channel channel) { - if (channel == null) { - throw new NullPointerException("channel"); - } - try { - EventLoop l = nextChild(); - return l.register(channel, new DefaultChannelPromise(channel, l)); - } catch (Throwable t) { - return new FailedChannelFuture(channel, GlobalEventExecutor.INSTANCE, t); - } - } - - @Override - public ChannelFuture register(Channel channel, ChannelPromise promise) { - if (channel == null) { - throw new NullPointerException("channel"); - } - try { - return nextChild().register(channel, promise); - } catch (Throwable t) { - promise.setFailure(t); - return promise; - } - } - - private EventLoop nextChild() throws Exception { - if (shuttingDown) { - throw new RejectedExecutionException("shutting down"); - } - - ThreadPerChannelEventLoop loop = idleChildren.poll(); - if (loop == null) { - if (maxChannels > 0 && activeChildren.size() >= maxChannels) { - throw tooManyChannels; - } - loop = newChild(childArgs); - loop.terminationFuture().addListener(childTerminationListener); - } - activeChildren.add(loop); - return loop; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/VoidChannelPromise.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/VoidChannelPromise.java deleted file mode 100755 index 1ea1f97951..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/VoidChannelPromise.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel; - -import java.util.concurrent.TimeUnit; - -import com.ai.cloud.io.netty.util.concurrent.AbstractFuture; -import com.ai.cloud.io.netty.util.concurrent.Future; -import com.ai.cloud.io.netty.util.concurrent.GenericFutureListener; - -final class VoidChannelPromise extends AbstractFuture implements ChannelPromise { - - private final Channel channel; - private final boolean fireException; - - /** - * Creates a new instance. - * - * @param channel the {@link Channel} associated with this future - */ - VoidChannelPromise(Channel channel, boolean fireException) { - if (channel == null) { - throw new NullPointerException("channel"); - } - this.channel = channel; - this.fireException = fireException; - } - - @Override - public VoidChannelPromise addListener(GenericFutureListener> listener) { - fail(); - return this; - } - - @Override - public VoidChannelPromise addListeners(GenericFutureListener>... listeners) { - fail(); - return this; - } - - @Override - public VoidChannelPromise removeListener(GenericFutureListener> listener) { - // NOOP - return this; - } - - @Override - public VoidChannelPromise removeListeners(GenericFutureListener>... listeners) { - // NOOP - return this; - } - - @Override - public VoidChannelPromise await() throws InterruptedException { - if (Thread.interrupted()) { - throw new InterruptedException(); - } - return this; - } - - @Override - public boolean await(long timeout, TimeUnit unit) { - fail(); - return false; - } - - @Override - public boolean await(long timeoutMillis) { - fail(); - return false; - } - - @Override - public VoidChannelPromise awaitUninterruptibly() { - fail(); - return this; - } - - @Override - public boolean awaitUninterruptibly(long timeout, TimeUnit unit) { - fail(); - return false; - } - - @Override - public boolean awaitUninterruptibly(long timeoutMillis) { - fail(); - return false; - } - - @Override - public Channel channel() { - return channel; - } - - @Override - public boolean isDone() { - return false; - } - - @Override - public boolean isSuccess() { - return false; - } - - @Override - public boolean setUncancellable() { - return true; - } - - @Override - public boolean isCancellable() { - return false; - } - - @Override - public boolean isCancelled() { - return false; - } - - @Override - public Throwable cause() { - return null; - } - - @Override - public VoidChannelPromise sync() { - fail(); - return this; - } - - @Override - public VoidChannelPromise syncUninterruptibly() { - fail(); - return this; - } - @Override - public VoidChannelPromise setFailure(Throwable cause) { - fireException(cause); - return this; - } - - @Override - public VoidChannelPromise setSuccess() { - return this; - } - - @Override - public boolean tryFailure(Throwable cause) { - fireException(cause); - return false; - } - - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - return false; - } - - @Override - public boolean trySuccess() { - return false; - } - - private static void fail() { - throw new IllegalStateException("void future"); - } - - @Override - public VoidChannelPromise setSuccess(Void result) { - return this; - } - - @Override - public boolean trySuccess(Void result) { - return false; - } - - @Override - public Void getNow() { - return null; - } - - private void fireException(Throwable cause) { - // Only fire the exception if the channel is open and registered - // if not the pipeline is not setup and so it would hit the tail - // of the pipeline. - // See https://github.com/netty/netty/issues/1517 - if (fireException && channel.isRegistered()) { - channel.pipeline().fireExceptionCaught(cause); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/embedded/EmbeddedChannel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/embedded/EmbeddedChannel.java deleted file mode 100755 index 584ae26f41..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/embedded/EmbeddedChannel.java +++ /dev/null @@ -1,421 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.embedded; - -import java.net.SocketAddress; -import java.nio.channels.ClosedChannelException; -import java.util.ArrayDeque; -import java.util.Queue; - -import com.ai.cloud.io.netty.channel.AbstractChannel; -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelConfig; -import com.ai.cloud.io.netty.channel.ChannelFuture; -import com.ai.cloud.io.netty.channel.ChannelHandler; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelInboundHandlerAdapter; -import com.ai.cloud.io.netty.channel.ChannelInitializer; -import com.ai.cloud.io.netty.channel.ChannelMetadata; -import com.ai.cloud.io.netty.channel.ChannelOutboundBuffer; -import com.ai.cloud.io.netty.channel.ChannelPipeline; -import com.ai.cloud.io.netty.channel.ChannelPromise; -import com.ai.cloud.io.netty.channel.DefaultChannelConfig; -import com.ai.cloud.io.netty.channel.EventLoop; -import com.ai.cloud.io.netty.util.ReferenceCountUtil; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; -import com.ai.cloud.io.netty.util.internal.RecyclableArrayList; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * Base class for {@link Channel} implementations that are used in an embedded fashion. - */ -public class EmbeddedChannel extends AbstractChannel { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(EmbeddedChannel.class); - - private static final ChannelMetadata METADATA = new ChannelMetadata(false); - - private final EmbeddedEventLoop loop = new EmbeddedEventLoop(); - private final ChannelConfig config = new DefaultChannelConfig(this); - private final SocketAddress localAddress = new EmbeddedSocketAddress(); - private final SocketAddress remoteAddress = new EmbeddedSocketAddress(); - private Queue inboundMessages; - private Queue outboundMessages; - private Throwable lastException; - private int state; // 0 = OPEN, 1 = ACTIVE, 2 = CLOSED - - /** - * Create a new instance - * - * @param handlers the @link ChannelHandler}s which will be add in the {@link ChannelPipeline} - */ - public EmbeddedChannel(final ChannelHandler... handlers) { - super(null); - - if (handlers == null) { - throw new NullPointerException("handlers"); - } - - ChannelPipeline p = pipeline(); - p.addLast(new ChannelInitializer() { - @Override - protected void initChannel(Channel ch) throws Exception { - ChannelPipeline pipeline = ch.pipeline(); - for (ChannelHandler h: handlers) { - if (h == null) { - break; - } - pipeline.addLast(h); - } - } - }); - - ChannelFuture future = loop.register(this); - assert future.isDone(); - p.addLast(new LastInboundHandler()); - } - - @Override - public ChannelMetadata metadata() { - return METADATA; - } - - @Override - public ChannelConfig config() { - return config; - } - - @Override - public boolean isOpen() { - return state < 2; - } - - @Override - public boolean isActive() { - return state == 1; - } - - /** - * Returns the {@link Queue} which holds all the {@link Object}s that were received by this {@link Channel}. - */ - public Queue inboundMessages() { - if (inboundMessages == null) { - inboundMessages = new ArrayDeque(); - } - return inboundMessages; - } - - /** - * @deprecated use {@link #inboundMessages()} - */ - @Deprecated - public Queue lastInboundBuffer() { - return inboundMessages(); - } - - /** - * Returns the {@link Queue} which holds all the {@link Object}s that were written by this {@link Channel}. - */ - public Queue outboundMessages() { - if (outboundMessages == null) { - outboundMessages = new ArrayDeque(); - } - return outboundMessages; - } - - /** - * @deprecated use {@link #outboundMessages()} - */ - @Deprecated - public Queue lastOutboundBuffer() { - return outboundMessages(); - } - - /** - * Return received data from this {@link Channel} - */ - public Object readInbound() { - return poll(inboundMessages); - } - - /** - * Read data froum the outbound. This may return {@code null} if nothing is readable. - */ - public Object readOutbound() { - return poll(outboundMessages); - } - - /** - * Write messages to the inbound of this {@link Channel}. - * - * @param msgs the messages to be written - * - * @return {@code true} if the write operation did add something to the inbound buffer - */ - public boolean writeInbound(Object... msgs) { - ensureOpen(); - if (msgs.length == 0) { - return isNotEmpty(inboundMessages); - } - - ChannelPipeline p = pipeline(); - for (Object m: msgs) { - p.fireChannelRead(m); - } - p.fireChannelReadComplete(); - runPendingTasks(); - checkException(); - return isNotEmpty(inboundMessages); - } - - /** - * Write messages to the outbound of this {@link Channel}. - * - * @param msgs the messages to be written - * @return bufferReadable returns {@code true} if the write operation did add something to the outbound buffer - */ - public boolean writeOutbound(Object... msgs) { - ensureOpen(); - if (msgs.length == 0) { - return isNotEmpty(outboundMessages); - } - - RecyclableArrayList futures = RecyclableArrayList.newInstance(msgs.length); - try { - for (Object m: msgs) { - if (m == null) { - break; - } - futures.add(write(m)); - } - - flush(); - - int size = futures.size(); - for (int i = 0; i < size; i++) { - ChannelFuture future = (ChannelFuture) futures.get(i); - assert future.isDone(); - if (future.cause() != null) { - recordException(future.cause()); - } - } - - runPendingTasks(); - checkException(); - return isNotEmpty(outboundMessages); - } finally { - futures.recycle(); - } - } - - /** - * Mark this {@link Channel} as finished. Any futher try to write data to it will fail. - * - * @return bufferReadable returns {@code true} if any of the used buffers has something left to read - */ - public boolean finish() { - close(); - checkException(); - return isNotEmpty(inboundMessages) || isNotEmpty(outboundMessages); - } - - private void finishPendingTasks() { - runPendingTasks(); - // Cancel all scheduled tasks that are left. - loop.cancelScheduledTasks(); - } - - @Override - public final ChannelFuture close() { - ChannelFuture future = super.close(); - finishPendingTasks(); - return future; - } - - @Override - public final ChannelFuture disconnect() { - ChannelFuture future = super.disconnect(); - finishPendingTasks(); - return future; - } - - @Override - public final ChannelFuture close(ChannelPromise promise) { - ChannelFuture future = super.close(promise); - finishPendingTasks(); - return future; - } - - @Override - public final ChannelFuture disconnect(ChannelPromise promise) { - ChannelFuture future = super.disconnect(promise); - finishPendingTasks(); - return future; - } - - private static boolean isNotEmpty(Queue queue) { - return queue != null && !queue.isEmpty(); - } - - private static Object poll(Queue queue) { - return queue != null ? queue.poll() : null; - } - - /** - * Run all tasks (which also includes scheduled tasks) that are pending in the {@link EventLoop} - * for this {@link Channel} - */ - public void runPendingTasks() { - try { - loop.runTasks(); - } catch (Exception e) { - recordException(e); - } - - try { - loop.runScheduledTasks(); - } catch (Exception e) { - recordException(e); - } - } - - /** - * Run all pending scheduled tasks in the {@link EventLoop} for this {@link Channel} and return the - * {@code nanoseconds} when the next scheduled task is ready to run. If no other task was scheduled it will return - * {@code -1}. - */ - public long runScheduledPendingTasks() { - try { - return loop.runScheduledTasks(); - } catch (Exception e) { - recordException(e); - return loop.nextScheduledTask(); - } - } - - private void recordException(Throwable cause) { - if (lastException == null) { - lastException = cause; - } else { - logger.warn( - "More than one exception was raised. " + - "Will report only the first one and log others.", cause); - } - } - - /** - * Check if there was any {@link Throwable} received and if so rethrow it. - */ - public void checkException() { - Throwable t = lastException; - if (t == null) { - return; - } - - lastException = null; - - PlatformDependent.throwException(t); - } - - /** - * Ensure the {@link Channel} is open and of not throw an exception. - */ - protected final void ensureOpen() { - if (!isOpen()) { - recordException(new ClosedChannelException()); - checkException(); - } - } - - @Override - protected boolean isCompatible(EventLoop loop) { - return loop instanceof EmbeddedEventLoop; - } - - @Override - protected SocketAddress localAddress0() { - return isActive()? localAddress : null; - } - - @Override - protected SocketAddress remoteAddress0() { - return isActive()? remoteAddress : null; - } - - @Override - protected void doRegister() throws Exception { - state = 1; - } - - @Override - protected void doBind(SocketAddress localAddress) throws Exception { - // NOOP - } - - @Override - protected void doDisconnect() throws Exception { - doClose(); - } - - @Override - protected void doClose() throws Exception { - state = 2; - } - - @Override - protected void doBeginRead() throws Exception { - // NOOP - } - - @Override - protected AbstractUnsafe newUnsafe() { - return new DefaultUnsafe(); - } - - @Override - protected void doWrite(ChannelOutboundBuffer in) throws Exception { - for (;;) { - Object msg = in.current(); - if (msg == null) { - break; - } - - ReferenceCountUtil.retain(msg); - outboundMessages().add(msg); - in.remove(); - } - } - - private class DefaultUnsafe extends AbstractUnsafe { - @Override - public void connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) { - safeSetSuccess(promise); - } - } - - private final class LastInboundHandler extends ChannelInboundHandlerAdapter { - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - inboundMessages().add(msg); - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - recordException(cause); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/embedded/EmbeddedEventLoop.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/embedded/EmbeddedEventLoop.java deleted file mode 100755 index d999e58bae..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/embedded/EmbeddedEventLoop.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.embedded; - -import java.util.ArrayDeque; -import java.util.Queue; -import java.util.concurrent.TimeUnit; - -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelFuture; -import com.ai.cloud.io.netty.channel.ChannelPromise; -import com.ai.cloud.io.netty.channel.DefaultChannelPromise; -import com.ai.cloud.io.netty.channel.EventLoop; -import com.ai.cloud.io.netty.channel.EventLoopGroup; -import com.ai.cloud.io.netty.util.concurrent.AbstractScheduledEventExecutor; -import com.ai.cloud.io.netty.util.concurrent.Future; - -final class EmbeddedEventLoop extends AbstractScheduledEventExecutor implements EventLoop { - - private final Queue tasks = new ArrayDeque(2); - - @Override - public void execute(Runnable command) { - if (command == null) { - throw new NullPointerException("command"); - } - tasks.add(command); - } - - void runTasks() { - for (;;) { - Runnable task = tasks.poll(); - if (task == null) { - break; - } - - task.run(); - } - } - - long runScheduledTasks() { - long time = AbstractScheduledEventExecutor.nanoTime(); - for (;;) { - Runnable task = pollScheduledTask(time); - if (task == null) { - return nextScheduledTaskNano(); - } - - task.run(); - } - } - - long nextScheduledTask() { - return nextScheduledTaskNano(); - } - - @Override - protected void cancelScheduledTasks() { - super.cancelScheduledTasks(); - } - - @Override - public Future shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit) { - throw new UnsupportedOperationException(); - } - - @Override - public Future terminationFuture() { - throw new UnsupportedOperationException(); - } - - @Override - @Deprecated - public void shutdown() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isShuttingDown() { - return false; - } - - @Override - public boolean isShutdown() { - return false; - } - - @Override - public boolean isTerminated() { - return false; - } - - @Override - public boolean awaitTermination(long timeout, TimeUnit unit) - throws InterruptedException { - Thread.sleep(unit.toMillis(timeout)); - return false; - } - - @Override - public ChannelFuture register(Channel channel) { - return register(channel, new DefaultChannelPromise(channel, this)); - } - - @Override - public ChannelFuture register(Channel channel, ChannelPromise promise) { - channel.unsafe().register(this, promise); - return promise; - } - - @Override - public boolean inEventLoop() { - return true; - } - - @Override - public boolean inEventLoop(Thread thread) { - return true; - } - - @Override - public EventLoop next() { - return this; - } - - @Override - public EventLoopGroup parent() { - return this; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/embedded/EmbeddedSocketAddress.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/embedded/EmbeddedSocketAddress.java deleted file mode 100755 index 515c4f760b..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/embedded/EmbeddedSocketAddress.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.embedded; - -import java.net.SocketAddress; - -final class EmbeddedSocketAddress extends SocketAddress { - private static final long serialVersionUID = 1400788804624980619L; - - @Override - public String toString() { - return "embedded"; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/embedded/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/embedded/package-info.java deleted file mode 100755 index 2d1a6fb900..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/embedded/package-info.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * A virtual {@link Channel} that helps wrapping a series of handlers to - * unit test the handlers or use them in non-I/O context. - */ -package com.ai.cloud.io.netty.channel.embedded; - diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/AbstractEpollChannel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/AbstractEpollChannel.java deleted file mode 100755 index eb890442c6..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/AbstractEpollChannel.java +++ /dev/null @@ -1,398 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.epoll; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.nio.ByteBuffer; -import java.nio.channels.UnresolvedAddressException; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.ByteBufAllocator; -import com.ai.cloud.io.netty.buffer.ByteBufUtil; -import com.ai.cloud.io.netty.buffer.Unpooled; -import com.ai.cloud.io.netty.channel.AbstractChannel; -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelMetadata; -import com.ai.cloud.io.netty.channel.ChannelOption; -import com.ai.cloud.io.netty.channel.EventLoop; -import com.ai.cloud.io.netty.channel.socket.ChannelInputShutdownEvent; -import com.ai.cloud.io.netty.channel.unix.Socket; -import com.ai.cloud.io.netty.channel.unix.UnixChannel; -import com.ai.cloud.io.netty.util.ReferenceCountUtil; -import com.ai.cloud.io.netty.util.internal.OneTimeTask; - -import static com.ai.cloud.io.netty.util.internal.ObjectUtil.checkNotNull; - -abstract class AbstractEpollChannel extends AbstractChannel implements UnixChannel { - private static final ChannelMetadata DATA = new ChannelMetadata(false); - private final int readFlag; - private final Socket fileDescriptor; - protected int flags = Native.EPOLLET; - - protected volatile boolean active; - - AbstractEpollChannel(Socket fd, int flag) { - this(null, fd, flag, false); - } - - AbstractEpollChannel(Channel parent, Socket fd, int flag, boolean active) { - super(parent); - fileDescriptor = checkNotNull(fd, "fd"); - readFlag = flag; - flags |= flag; - this.active = active; - } - - void setFlag(int flag) throws IOException { - if (!isFlagSet(flag)) { - flags |= flag; - modifyEvents(); - } - } - - void clearFlag(int flag) throws IOException { - if (isFlagSet(flag)) { - flags &= ~flag; - modifyEvents(); - } - } - - boolean isFlagSet(int flag) { - return (flags & flag) != 0; - } - - @Override - public final Socket fd() { - return fileDescriptor; - } - - @Override - public abstract EpollChannelConfig config(); - - @Override - public boolean isActive() { - return active; - } - - @Override - public ChannelMetadata metadata() { - return DATA; - } - - @Override - protected void doClose() throws Exception { - this.active = false; - Socket fd = fileDescriptor; - try { - // deregister from epoll now and shutdown the socket. - doDeregister(); - if (!fd.isShutdown()) { - try { - fd().shutdown(); - } catch (IOException ignored) { - // The FD will be closed, so if shutdown fails there is nothing we can do. - } - } - } finally { - // Ensure the file descriptor is closed in all cases. - fd.close(); - } - } - - @Override - protected void doDisconnect() throws Exception { - doClose(); - } - - @Override - protected boolean isCompatible(EventLoop loop) { - return loop instanceof EpollEventLoop; - } - - @Override - public boolean isOpen() { - return fileDescriptor.isOpen(); - } - - @Override - protected void doDeregister() throws Exception { - ((EpollEventLoop) eventLoop()).remove(this); - } - - @Override - protected void doBeginRead() throws Exception { - // Channel.read() or ChannelHandlerContext.read() was called - ((AbstractEpollUnsafe) unsafe()).readPending = true; - - setFlag(readFlag); - } - - final void clearEpollIn() { - // Only clear if registered with an EventLoop as otherwise - if (isRegistered()) { - final EventLoop loop = eventLoop(); - final AbstractEpollUnsafe unsafe = (AbstractEpollUnsafe) unsafe(); - if (loop.inEventLoop()) { - unsafe.clearEpollIn0(); - } else { - // schedule a task to clear the EPOLLIN as it is not safe to modify it directly - loop.execute(new OneTimeTask() { - @Override - public void run() { - if (!config().isAutoRead() && !unsafe.readPending) { - // Still no read triggered so clear it now - unsafe.clearEpollIn0(); - } - } - }); - } - } else { - // The EventLoop is not registered atm so just update the flags so the correct value - // will be used once the channel is registered - flags &= ~readFlag; - } - } - - private void modifyEvents() throws IOException { - if (isOpen() && isRegistered()) { - ((EpollEventLoop) eventLoop()).modify(this); - } - } - - @Override - protected void doRegister() throws Exception { - EpollEventLoop loop = (EpollEventLoop) eventLoop(); - loop.add(this); - } - - @Override - protected abstract AbstractEpollUnsafe newUnsafe(); - - /** - * Returns an off-heap copy of the specified {@link ByteBuf}, and releases the original one. - */ - protected final ByteBuf newDirectBuffer(ByteBuf buf) { - return newDirectBuffer(buf, buf); - } - - /** - * Returns an off-heap copy of the specified {@link ByteBuf}, and releases the specified holder. - * The caller must ensure that the holder releases the original {@link ByteBuf} when the holder is released by - * this method. - */ - protected final ByteBuf newDirectBuffer(Object holder, ByteBuf buf) { - final int readableBytes = buf.readableBytes(); - if (readableBytes == 0) { - ReferenceCountUtil.safeRelease(holder); - return Unpooled.EMPTY_BUFFER; - } - - final ByteBufAllocator alloc = alloc(); - if (alloc.isDirectBufferPooled()) { - return newDirectBuffer0(holder, buf, alloc, readableBytes); - } - - final ByteBuf directBuf = ByteBufUtil.threadLocalDirectBuffer(); - if (directBuf == null) { - return newDirectBuffer0(holder, buf, alloc, readableBytes); - } - - directBuf.writeBytes(buf, buf.readerIndex(), readableBytes); - ReferenceCountUtil.safeRelease(holder); - return directBuf; - } - - private static ByteBuf newDirectBuffer0(Object holder, ByteBuf buf, ByteBufAllocator alloc, int capacity) { - final ByteBuf directBuf = alloc.directBuffer(capacity); - directBuf.writeBytes(buf, buf.readerIndex(), capacity); - ReferenceCountUtil.safeRelease(holder); - return directBuf; - } - - protected static void checkResolvable(InetSocketAddress addr) { - if (addr.isUnresolved()) { - throw new UnresolvedAddressException(); - } - } - - /** - * Read bytes into the given {@link ByteBuf} and return the amount. - */ - protected final int doReadBytes(ByteBuf byteBuf) throws Exception { - int writerIndex = byteBuf.writerIndex(); - int localReadAmount; - if (byteBuf.hasMemoryAddress()) { - localReadAmount = fileDescriptor.readAddress(byteBuf.memoryAddress(), writerIndex, byteBuf.capacity()); - } else { - ByteBuffer buf = byteBuf.internalNioBuffer(writerIndex, byteBuf.writableBytes()); - localReadAmount = fileDescriptor.read(buf, buf.position(), buf.limit()); - } - if (localReadAmount > 0) { - byteBuf.writerIndex(writerIndex + localReadAmount); - } - return localReadAmount; - } - - protected final int doWriteBytes(ByteBuf buf, int writeSpinCount) throws Exception { - int readableBytes = buf.readableBytes(); - int writtenBytes = 0; - if (buf.hasMemoryAddress()) { - long memoryAddress = buf.memoryAddress(); - int readerIndex = buf.readerIndex(); - int writerIndex = buf.writerIndex(); - for (int i = writeSpinCount - 1; i >= 0; i--) { - int localFlushedAmount = fileDescriptor.writeAddress(memoryAddress, readerIndex, writerIndex); - if (localFlushedAmount > 0) { - writtenBytes += localFlushedAmount; - if (writtenBytes == readableBytes) { - return writtenBytes; - } - readerIndex += localFlushedAmount; - } else { - break; - } - } - } else { - ByteBuffer nioBuf; - if (buf.nioBufferCount() == 1) { - nioBuf = buf.internalNioBuffer(buf.readerIndex(), buf.readableBytes()); - } else { - nioBuf = buf.nioBuffer(); - } - for (int i = writeSpinCount - 1; i >= 0; i--) { - int pos = nioBuf.position(); - int limit = nioBuf.limit(); - int localFlushedAmount = fileDescriptor.write(nioBuf, pos, limit); - if (localFlushedAmount > 0) { - nioBuf.position(pos + localFlushedAmount); - writtenBytes += localFlushedAmount; - if (writtenBytes == readableBytes) { - return writtenBytes; - } - } else { - break; - } - } - } - if (writtenBytes < readableBytes) { - // Returned EAGAIN need to set EPOLLOUT - setFlag(Native.EPOLLOUT); - } - return writtenBytes; - } - - protected abstract class AbstractEpollUnsafe extends AbstractUnsafe { - protected boolean readPending; - private boolean rdHup; - - /** - * Called once EPOLLIN event is ready to be processed - */ - abstract void epollInReady(); - - public final boolean isRdHup() { - return rdHup; - } - - /** - * Called once EPOLLRDHUP event is ready to be processed - */ - final void epollRdHupReady() { - // This must happen before we attempt to read. This will ensure reading continues until an error occurs. - rdHup = true; - - if (isActive()) { - // If it is still active, we need to call epollInReady as otherwise we may miss to - // read pending data from the underlying file descriptor. - // See https://github.com/netty/netty/issues/3709 - epollInReady(); - - // Clear the EPOLLRDHUP flag to prevent continuously getting woken up on this event. - clearEpollRdHup(); - } - - // epollInReady may call this, but we should ensure that it gets called. - shutdownInput(); - } - - /** - * Clear the {@link Native#EPOLLRDHUP} flag from EPOLL, and close on failure. - */ - private void clearEpollRdHup() { - try { - clearFlag(Native.EPOLLRDHUP); - } catch (IOException e) { - pipeline().fireExceptionCaught(e); - close(voidPromise()); - } - } - - /** - * Shutdown the input side of the channel. - */ - void shutdownInput() { - if (!fd().isInputShutdown()) { - if (Boolean.TRUE.equals(config().getOption(ChannelOption.ALLOW_HALF_CLOSURE))) { - try { - fd().shutdown(true, false); - clearEpollIn0(); - pipeline().fireUserEventTriggered(ChannelInputShutdownEvent.INSTANCE); - } catch (IOException e) { - pipeline().fireExceptionCaught(e); - close(voidPromise()); - } - } else { - close(voidPromise()); - } - } - } - - @Override - protected void flush0() { - // Flush immediately only when there's no pending flush. - // If there's a pending flush operation, event loop will call forceFlush() later, - // and thus there's no need to call it now. - if (isFlagSet(Native.EPOLLOUT)) { - return; - } - super.flush0(); - } - - /** - * Called once a EPOLLOUT event is ready to be processed - */ - void epollOutReady() { - if (fd().isOutputShutdown()) { - return; - } - // directly call super.flush0() to force a flush now - super.flush0(); - } - - protected final void clearEpollIn0() { - assert eventLoop().inEventLoop(); - try { - clearFlag(readFlag); - } catch (IOException e) { - // When this happens there is something completely wrong with either the filedescriptor or epoll, - // so fire the exception through the pipeline and close the Channel. - pipeline().fireExceptionCaught(e); - unsafe().close(unsafe().voidPromise()); - } - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/AbstractEpollServerChannel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/AbstractEpollServerChannel.java deleted file mode 100755 index 68299d14b0..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/AbstractEpollServerChannel.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.epoll; - -import java.net.InetSocketAddress; -import java.net.SocketAddress; - -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelConfig; -import com.ai.cloud.io.netty.channel.ChannelOutboundBuffer; -import com.ai.cloud.io.netty.channel.ChannelPipeline; -import com.ai.cloud.io.netty.channel.ChannelPromise; -import com.ai.cloud.io.netty.channel.EventLoop; -import com.ai.cloud.io.netty.channel.ServerChannel; -import com.ai.cloud.io.netty.channel.unix.FileDescriptor; -import com.ai.cloud.io.netty.channel.unix.Socket; - - -public abstract class AbstractEpollServerChannel extends AbstractEpollChannel implements ServerChannel { - - /** - * @deprecated Use {@link #AbstractEpollServerChannel(Socket, boolean)}. - */ - protected AbstractEpollServerChannel(int fd) { - this(new Socket(fd), false); - } - - /** - * @deprecated Use {@link #AbstractEpollServerChannel(Socket, boolean)}. - */ - @Deprecated - protected AbstractEpollServerChannel(FileDescriptor fd) { - this(new Socket(fd.intValue())); - } - - /** - * @deprecated Use {@link #AbstractEpollServerChannel(Socket, boolean)}. - */ - @Deprecated - protected AbstractEpollServerChannel(Socket fd) { - this(fd, fd.getSoError() == 0); - } - - protected AbstractEpollServerChannel(Socket fd, boolean active) { - super(null, fd, Native.EPOLLIN, active); - } - - @Override - protected boolean isCompatible(EventLoop loop) { - return loop instanceof EpollEventLoop; - } - - @Override - protected InetSocketAddress remoteAddress0() { - return null; - } - - @Override - protected AbstractEpollUnsafe newUnsafe() { - return new EpollServerSocketUnsafe(); - } - - @Override - protected void doWrite(ChannelOutboundBuffer in) throws Exception { - throw new UnsupportedOperationException(); - } - - @Override - protected Object filterOutboundMessage(Object msg) throws Exception { - throw new UnsupportedOperationException(); - } - - abstract Channel newChildChannel(int fd, byte[] remote, int offset, int len) throws Exception; - - final class EpollServerSocketUnsafe extends AbstractEpollUnsafe { - // Will hold the remote address after accept(...) was sucesssful. - // We need 24 bytes for the address as maximum + 1 byte for storing the length. - // So use 26 bytes as it's a power of two. - private final byte[] acceptedAddress = new byte[26]; - - @Override - public void connect(SocketAddress socketAddress, SocketAddress socketAddress2, ChannelPromise channelPromise) { - // Connect not supported by ServerChannel implementations - channelPromise.setFailure(new UnsupportedOperationException()); - } - - @Override - void epollInReady() { - assert eventLoop().inEventLoop(); - if (fd().isInputShutdown()) { - return; - } - boolean edgeTriggered = isFlagSet(Native.EPOLLET); - - final ChannelConfig config = config(); - if (!readPending && !edgeTriggered && !config.isAutoRead()) { - // ChannelConfig.setAutoRead(false) was called in the meantime - clearEpollIn0(); - return; - } - - final ChannelPipeline pipeline = pipeline(); - Throwable exception = null; - try { - try { - // if edgeTriggered is used we need to read all messages as we are not notified again otherwise. - final int maxMessagesPerRead = edgeTriggered - ? Integer.MAX_VALUE : config.getMaxMessagesPerRead(); - int messages = 0; - do { - int socketFd = fd().accept(acceptedAddress); - if (socketFd == -1) { - // this means everything was handled for now - break; - } - readPending = false; - - try { - int len = acceptedAddress[0]; - pipeline.fireChannelRead(newChildChannel(socketFd, acceptedAddress, 1, len)); - } catch (Throwable t) { - // keep on reading as we use epoll ET and need to consume everything from the socket - pipeline.fireChannelReadComplete(); - pipeline.fireExceptionCaught(t); - } finally { - if (!edgeTriggered && !config.isAutoRead()) { - // This is not using EPOLLET so we can stop reading - // ASAP as we will get notified again later with - // pending data - break; - } - } - } while (++ messages < maxMessagesPerRead || isRdHup()); - } catch (Throwable t) { - exception = t; - } - pipeline.fireChannelReadComplete(); - - if (exception != null) { - pipeline.fireExceptionCaught(exception); - } - } finally { - // Check if there is a readPending which was not processed yet. - // This could be for two reasons: - // * The user called Channel.read() or ChannelHandlerContext.read() in channelRead(...) method - // * The user called Channel.read() or ChannelHandlerContext.read() in channelReadComplete(...) method - // - // See https://github.com/netty/netty/issues/2254 - if (!readPending && !config.isAutoRead()) { - clearEpollIn0(); - } - } - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/AbstractEpollStreamChannel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/AbstractEpollStreamChannel.java deleted file mode 100755 index 66e6ead418..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/AbstractEpollStreamChannel.java +++ /dev/null @@ -1,1081 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.epoll; - -import java.io.IOException; -import java.net.SocketAddress; -import java.nio.ByteBuffer; -import java.nio.channels.ClosedChannelException; -import java.util.Queue; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.ByteBufAllocator; -import com.ai.cloud.io.netty.buffer.CompositeByteBuf; -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelConfig; -import com.ai.cloud.io.netty.channel.ChannelFuture; -import com.ai.cloud.io.netty.channel.ChannelFutureListener; -import com.ai.cloud.io.netty.channel.ChannelOutboundBuffer; -import com.ai.cloud.io.netty.channel.ChannelPipeline; -import com.ai.cloud.io.netty.channel.ChannelPromise; -import com.ai.cloud.io.netty.channel.ConnectTimeoutException; -import com.ai.cloud.io.netty.channel.DefaultFileRegion; -import com.ai.cloud.io.netty.channel.EventLoop; -import com.ai.cloud.io.netty.channel.RecvByteBufAllocator; -import com.ai.cloud.io.netty.channel.unix.FileDescriptor; -import com.ai.cloud.io.netty.channel.unix.Socket; -import com.ai.cloud.io.netty.util.internal.EmptyArrays; -import com.ai.cloud.io.netty.util.internal.MpscLinkedQueueNode; -import com.ai.cloud.io.netty.util.internal.OneTimeTask; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; -import com.ai.cloud.io.netty.util.internal.StringUtil; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -import static com.ai.cloud.io.netty.channel.unix.FileDescriptor.pipe; -import static com.ai.cloud.io.netty.util.internal.ObjectUtil.checkNotNull; - -public abstract class AbstractEpollStreamChannel extends AbstractEpollChannel { - - private static final String EXPECTED_TYPES = - " (expected: " + StringUtil.simpleClassName(ByteBuf.class) + ", " + - StringUtil.simpleClassName(DefaultFileRegion.class) + ')'; - private static final InternalLogger logger = InternalLoggerFactory.getInstance(AbstractEpollStreamChannel.class); - static final ClosedChannelException CLOSED_CHANNEL_EXCEPTION = new ClosedChannelException(); - - static { - CLOSED_CHANNEL_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); - } - - /** - * The future of the current connection attempt. If not null, subsequent - * connection attempts will fail. - */ - private ChannelPromise connectPromise; - private ScheduledFuture connectTimeoutFuture; - private SocketAddress requestedRemoteAddress; - private final Queue spliceQueue = PlatformDependent.newMpscQueue(); - - // Lazy init these if we need to splice(...) - private FileDescriptor pipeIn; - private FileDescriptor pipeOut; - - /** - * @deprecated Use {@link #AbstractEpollStreamChannel(Channel, Socket)}. - */ - @Deprecated - protected AbstractEpollStreamChannel(Channel parent, int fd) { - this(parent, new Socket(fd)); - } - - /** - * @deprecated Use {@link #AbstractEpollStreamChannel(Socket, boolean)}. - */ - @Deprecated - protected AbstractEpollStreamChannel(int fd) { - this(new Socket(fd)); - } - - /** - * @deprecated Use {@link #AbstractEpollStreamChannel(Socket, boolean)}. - */ - @Deprecated - protected AbstractEpollStreamChannel(FileDescriptor fd) { - this(new Socket(fd.intValue())); - } - - /** - * @deprecated Use {@link #AbstractEpollStreamChannel(Socket, boolean)}. - */ - @Deprecated - protected AbstractEpollStreamChannel(Socket fd) { - this(fd, fd.getSoError() == 0); - } - - protected AbstractEpollStreamChannel(Channel parent, Socket fd) { - super(parent, fd, Native.EPOLLIN, true); - // Add EPOLLRDHUP so we are notified once the remote peer close the connection. - flags |= Native.EPOLLRDHUP; - } - - protected AbstractEpollStreamChannel(Socket fd, boolean active) { - super(null, fd, Native.EPOLLIN, active); - // Add EPOLLRDHUP so we are notified once the remote peer close the connection. - flags |= Native.EPOLLRDHUP; - } - - @Override - protected AbstractEpollUnsafe newUnsafe() { - return new EpollStreamUnsafe(); - } - - /** - * Splice from this {@link AbstractEpollStreamChannel} to another {@link AbstractEpollStreamChannel}. - * The {@code len} is the number of bytes to splice. If using {@link Integer#MAX_VALUE} it will - * splice until the {@link ChannelFuture} was canceled or it was failed. - * - * Please note: - *
    - *
  • both channels need to be registered to the same {@link EventLoop}, otherwise an - * {@link IllegalArgumentException} is thrown.
  • - *
  • {@link EpollChannelConfig#getEpollMode()} must be {@link EpollMode#LEVEL_TRIGGERED} for this and the - * target {@link AbstractEpollStreamChannel}
  • - *
- * - */ - public final ChannelFuture spliceTo(final AbstractEpollStreamChannel ch, final int len) { - return spliceTo(ch, len, newPromise()); - } - - /** - * Splice from this {@link AbstractEpollStreamChannel} to another {@link AbstractEpollStreamChannel}. - * The {@code len} is the number of bytes to splice. If using {@link Integer#MAX_VALUE} it will - * splice until the {@link ChannelFuture} was canceled or it was failed. - * - * Please note: - *
    - *
  • both channels need to be registered to the same {@link EventLoop}, otherwise an - * {@link IllegalArgumentException} is thrown.
  • - *
  • {@link EpollChannelConfig#getEpollMode()} must be {@link EpollMode#LEVEL_TRIGGERED} for this and the - * target {@link AbstractEpollStreamChannel}
  • - *
- * - */ - public final ChannelFuture spliceTo(final AbstractEpollStreamChannel ch, final int len, - final ChannelPromise promise) { - if (ch.eventLoop() != eventLoop()) { - throw new IllegalArgumentException("EventLoops are not the same."); - } - if (len < 0) { - throw new IllegalArgumentException("len: " + len + " (expected: >= 0)"); - } - if (ch.config().getEpollMode() != EpollMode.LEVEL_TRIGGERED - || config().getEpollMode() != EpollMode.LEVEL_TRIGGERED) { - throw new IllegalStateException("spliceTo() supported only when using " + EpollMode.LEVEL_TRIGGERED); - } - checkNotNull(promise, "promise"); - if (!isOpen()) { - promise.tryFailure(CLOSED_CHANNEL_EXCEPTION); - } else { - SpliceInTask task = new SpliceInChannelTask(ch, len, checkNotNull(promise, "promise")); - spliceQueue.add(task); - failSpliceIfClosed(promise); - } - return promise; - } - - /** - * Splice from this {@link AbstractEpollStreamChannel} to another {@link FileDescriptor}. - * The {@code offset} is the offset for the {@link FileDescriptor} and {@code len} is the - * number of bytes to splice. If using {@link Integer#MAX_VALUE} it will splice until the - * {@link ChannelFuture} was canceled or it was failed. - * - * Please note: - *
    - *
  • {@link EpollChannelConfig#getEpollMode()} must be {@link EpollMode#LEVEL_TRIGGERED} for this - * {@link AbstractEpollStreamChannel}
  • - *
  • the {@link FileDescriptor} will not be closed after the {@link ChannelFuture} is notified
  • - *
- */ - public final ChannelFuture spliceTo(final FileDescriptor ch, final int offset, final int len) { - return spliceTo(ch, offset, len, newPromise()); - } - - /** - * Splice from this {@link AbstractEpollStreamChannel} to another {@link FileDescriptor}. - * The {@code offset} is the offset for the {@link FileDescriptor} and {@code len} is the - * number of bytes to splice. If using {@link Integer#MAX_VALUE} it will splice until the - * {@link ChannelFuture} was canceled or it was failed. - * - * Please note: - *
    - *
  • {@link EpollChannelConfig#getEpollMode()} must be {@link EpollMode#LEVEL_TRIGGERED} for this - * {@link AbstractEpollStreamChannel}
  • - *
  • the {@link FileDescriptor} will not be closed after the {@link ChannelPromise} is notified
  • - *
- */ - public final ChannelFuture spliceTo(final FileDescriptor ch, final int offset, final int len, - final ChannelPromise promise) { - if (len < 0) { - throw new IllegalArgumentException("len: " + len + " (expected: >= 0)"); - } - if (offset < 0) { - throw new IllegalArgumentException("offset must be >= 0 but was " + offset); - } - if (config().getEpollMode() != EpollMode.LEVEL_TRIGGERED) { - throw new IllegalStateException("spliceTo() supported only when using " + EpollMode.LEVEL_TRIGGERED); - } - checkNotNull(promise, "promise"); - if (!isOpen()) { - promise.tryFailure(CLOSED_CHANNEL_EXCEPTION); - } else { - SpliceInTask task = new SpliceFdTask(ch, offset, len, checkNotNull(promise, "promise")); - spliceQueue.add(task); - failSpliceIfClosed(promise); - } - return promise; - } - - private void failSpliceIfClosed(ChannelPromise promise) { - if (!isOpen()) { - // Seems like the Channel was closed in the meantime try to fail the promise to prevent any - // cases where a future may not be notified otherwise. - if (promise.tryFailure(CLOSED_CHANNEL_EXCEPTION)) { - eventLoop().execute(new OneTimeTask() { - @Override - public void run() { - // Call this via the EventLoop as it is a MPSC queue. - clearSpliceQueue(); - } - }); - } - } - } - - /** - * Write bytes form the given {@link ByteBuf} to the underlying {@link java.nio.channels.Channel}. - * @param buf the {@link ByteBuf} from which the bytes should be written - */ - private boolean writeBytes(ChannelOutboundBuffer in, ByteBuf buf, int writeSpinCount) throws Exception { - int readableBytes = buf.readableBytes(); - if (readableBytes == 0) { - in.remove(); - return true; - } - - if (buf.hasMemoryAddress() || buf.nioBufferCount() == 1) { - int writtenBytes = doWriteBytes(buf, writeSpinCount); - in.removeBytes(writtenBytes); - return writtenBytes == readableBytes; - } else { - ByteBuffer[] nioBuffers = buf.nioBuffers(); - return writeBytesMultiple(in, nioBuffers, nioBuffers.length, readableBytes, writeSpinCount); - } - } - - private boolean writeBytesMultiple( - ChannelOutboundBuffer in, IovArray array, int writeSpinCount) throws IOException { - - long expectedWrittenBytes = array.size(); - final long initialExpectedWrittenBytes = expectedWrittenBytes; - - int cnt = array.count(); - - assert expectedWrittenBytes != 0; - assert cnt != 0; - - boolean done = false; - int offset = 0; - int end = offset + cnt; - for (int i = writeSpinCount - 1; i >= 0; i--) { - long localWrittenBytes = fd().writevAddresses(array.memoryAddress(offset), cnt); - if (localWrittenBytes == 0) { - break; - } - expectedWrittenBytes -= localWrittenBytes; - - if (expectedWrittenBytes == 0) { - // Written everything, just break out here (fast-path) - done = true; - break; - } - - do { - long bytes = array.processWritten(offset, localWrittenBytes); - if (bytes == -1) { - // incomplete write - break; - } else { - offset++; - cnt--; - localWrittenBytes -= bytes; - } - } while (offset < end && localWrittenBytes > 0); - } - in.removeBytes(initialExpectedWrittenBytes - expectedWrittenBytes); - return done; - } - - private boolean writeBytesMultiple( - ChannelOutboundBuffer in, ByteBuffer[] nioBuffers, - int nioBufferCnt, long expectedWrittenBytes, int writeSpinCount) throws IOException { - - assert expectedWrittenBytes != 0; - final long initialExpectedWrittenBytes = expectedWrittenBytes; - - boolean done = false; - int offset = 0; - int end = offset + nioBufferCnt; - for (int i = writeSpinCount - 1; i >= 0; i--) { - long localWrittenBytes = fd().writev(nioBuffers, offset, nioBufferCnt); - if (localWrittenBytes == 0) { - break; - } - expectedWrittenBytes -= localWrittenBytes; - - if (expectedWrittenBytes == 0) { - // Written everything, just break out here (fast-path) - done = true; - break; - } - do { - ByteBuffer buffer = nioBuffers[offset]; - int pos = buffer.position(); - int bytes = buffer.limit() - pos; - if (bytes > localWrittenBytes) { - buffer.position(pos + (int) localWrittenBytes); - // incomplete write - break; - } else { - offset++; - nioBufferCnt--; - localWrittenBytes -= bytes; - } - } while (offset < end && localWrittenBytes > 0); - } - - in.removeBytes(initialExpectedWrittenBytes - expectedWrittenBytes); - return done; - } - - /** - * Write a {@link DefaultFileRegion} - * - * @param region the {@link DefaultFileRegion} from which the bytes should be written - * @return amount the amount of written bytes - */ - private boolean writeFileRegion( - ChannelOutboundBuffer in, DefaultFileRegion region, int writeSpinCount) throws Exception { - final long regionCount = region.count(); - if (region.transfered() >= regionCount) { - in.remove(); - return true; - } - - final long baseOffset = region.position(); - boolean done = false; - long flushedAmount = 0; - - for (int i = writeSpinCount - 1; i >= 0; i--) { - final long offset = region.transfered(); - final long localFlushedAmount = - Native.sendfile(fd().intValue(), region, baseOffset, offset, regionCount - offset); - if (localFlushedAmount == 0) { - break; - } - - flushedAmount += localFlushedAmount; - if (region.transfered() >= regionCount) { - done = true; - break; - } - } - - if (flushedAmount > 0) { - in.progress(flushedAmount); - } - - if (done) { - in.remove(); - } - return done; - } - - @Override - protected void doWrite(ChannelOutboundBuffer in) throws Exception { - int writeSpinCount = config().getWriteSpinCount(); - for (;;) { - final int msgCount = in.size(); - - if (msgCount == 0) { - // Wrote all messages. - clearFlag(Native.EPOLLOUT); - // Return here so we not set the EPOLLOUT flag. - return; - } - - // Do gathering write if the outbounf buffer entries start with more than one ByteBuf. - if (msgCount > 1 && in.current() instanceof ByteBuf) { - if (!doWriteMultiple(in, writeSpinCount)) { - // Break the loop and so set EPOLLOUT flag. - break; - } - - // We do not break the loop here even if the outbound buffer was flushed completely, - // because a user might have triggered another write and flush when we notify his or her - // listeners. - } else { // msgCount == 1 - if (!doWriteSingle(in, writeSpinCount)) { - // Break the loop and so set EPOLLOUT flag. - break; - } - } - } - // Underlying descriptor can not accept all data currently, so set the EPOLLOUT flag to be woken up - // when it can accept more data. - setFlag(Native.EPOLLOUT); - } - - protected boolean doWriteSingle(ChannelOutboundBuffer in, int writeSpinCount) throws Exception { - // The outbound buffer contains only one message or it contains a file region. - Object msg = in.current(); - if (msg instanceof ByteBuf) { - ByteBuf buf = (ByteBuf) msg; - if (!writeBytes(in, buf, writeSpinCount)) { - // was not able to write everything so break here we will get notified later again once - // the network stack can handle more writes. - return false; - } - } else if (msg instanceof DefaultFileRegion) { - DefaultFileRegion region = (DefaultFileRegion) msg; - if (!writeFileRegion(in, region, writeSpinCount)) { - // was not able to write everything so break here we will get notified later again once - // the network stack can handle more writes. - return false; - } - } else if (msg instanceof SpliceOutTask) { - if (!((SpliceOutTask) msg).spliceOut()) { - return false; - } - in.remove(); - } else { - // Should never reach here. - throw new Error(); - } - - return true; - } - - private boolean doWriteMultiple(ChannelOutboundBuffer in, int writeSpinCount) throws Exception { - if (PlatformDependent.hasUnsafe()) { - // this means we can cast to IovArray and write the IovArray directly. - IovArray array = IovArrayThreadLocal.get(in); - int cnt = array.count(); - if (cnt >= 1) { - // TODO: Handle the case where cnt == 1 specially. - if (!writeBytesMultiple(in, array, writeSpinCount)) { - // was not able to write everything so break here we will get notified later again once - // the network stack can handle more writes. - return false; - } - } else { // cnt == 0, which means the outbound buffer contained empty buffers only. - in.removeBytes(0); - } - } else { - ByteBuffer[] buffers = in.nioBuffers(); - int cnt = in.nioBufferCount(); - if (cnt >= 1) { - // TODO: Handle the case where cnt == 1 specially. - if (!writeBytesMultiple(in, buffers, cnt, in.nioBufferSize(), writeSpinCount)) { - // was not able to write everything so break here we will get notified later again once - // the network stack can handle more writes. - return false; - } - } else { // cnt == 0, which means the outbound buffer contained empty buffers only. - in.removeBytes(0); - } - } - - return true; - } - - @Override - protected Object filterOutboundMessage(Object msg) { - if (msg instanceof ByteBuf) { - ByteBuf buf = (ByteBuf) msg; - if (!buf.hasMemoryAddress() && (PlatformDependent.hasUnsafe() || !buf.isDirect())) { - if (buf instanceof CompositeByteBuf) { - // Special handling of CompositeByteBuf to reduce memory copies if some of the Components - // in the CompositeByteBuf are backed by a memoryAddress. - CompositeByteBuf comp = (CompositeByteBuf) buf; - if (!comp.isDirect() || comp.nioBufferCount() > Native.IOV_MAX) { - // more then 1024 buffers for gathering writes so just do a memory copy. - buf = newDirectBuffer(buf); - assert buf.hasMemoryAddress(); - } - } else { - // We can only handle buffers with memory address so we need to copy if a non direct is - // passed to write. - buf = newDirectBuffer(buf); - assert buf.hasMemoryAddress(); - } - } - return buf; - } - - if (msg instanceof DefaultFileRegion || msg instanceof SpliceOutTask) { - return msg; - } - - throw new UnsupportedOperationException( - "unsupported message type: " + StringUtil.simpleClassName(msg) + EXPECTED_TYPES); - } - - protected void shutdownOutput0(final ChannelPromise promise) { - try { - fd().shutdown(false, true); - promise.setSuccess(); - } catch (Throwable cause) { - promise.setFailure(cause); - } - } - - @Override - protected void doClose() throws Exception { - try { - ChannelPromise promise = connectPromise; - if (promise != null) { - // Use tryFailure() instead of setFailure() to avoid the race against cancel(). - promise.tryFailure(CLOSED_CHANNEL_EXCEPTION); - connectPromise = null; - } - - ScheduledFuture future = connectTimeoutFuture; - if (future != null) { - future.cancel(false); - connectTimeoutFuture = null; - } - // Calling super.doClose() first so splceTo(...) will fail on next call. - super.doClose(); - } finally { - safeClosePipe(pipeIn); - safeClosePipe(pipeOut); - clearSpliceQueue(); - } - } - - private void clearSpliceQueue() { - for (;;) { - SpliceInTask task = spliceQueue.poll(); - if (task == null) { - break; - } - task.promise.tryFailure(CLOSED_CHANNEL_EXCEPTION); - } - } - - /** - * Connect to the remote peer - */ - protected boolean doConnect(SocketAddress remoteAddress, SocketAddress localAddress) throws Exception { - if (localAddress != null) { - fd().bind(localAddress); - } - - boolean success = false; - try { - boolean connected = fd().connect(remoteAddress); - if (!connected) { - setFlag(Native.EPOLLOUT); - } - success = true; - return connected; - } finally { - if (!success) { - doClose(); - } - } - } - - private void safeClosePipe(FileDescriptor fd) { - if (fd != null) { - try { - fd.close(); - } catch (IOException e) { - if (logger.isWarnEnabled()) { - logger.warn("Error while closing a pipe", e); - } - } - } - } - - class EpollStreamUnsafe extends AbstractEpollUnsafe { - - private RecvByteBufAllocator.Handle allocHandle; - - private boolean handleReadException(ChannelPipeline pipeline, ByteBuf byteBuf, Throwable cause, boolean close) { - if (byteBuf != null) { - if (byteBuf.isReadable()) { - readPending = false; - pipeline.fireChannelRead(byteBuf); - } else { - byteBuf.release(); - } - } - pipeline.fireChannelReadComplete(); - pipeline.fireExceptionCaught(cause); - if (close || cause instanceof IOException) { - shutdownInput(); - return true; - } - return false; - } - - @Override - public void connect( - final SocketAddress remoteAddress, final SocketAddress localAddress, final ChannelPromise promise) { - if (!promise.setUncancellable() || !ensureOpen(promise)) { - return; - } - - try { - if (connectPromise != null) { - throw new IllegalStateException("connection attempt already made"); - } - - boolean wasActive = isActive(); - if (doConnect(remoteAddress, localAddress)) { - fulfillConnectPromise(promise, wasActive); - } else { - connectPromise = promise; - requestedRemoteAddress = remoteAddress; - - // Schedule connect timeout. - int connectTimeoutMillis = config().getConnectTimeoutMillis(); - if (connectTimeoutMillis > 0) { - connectTimeoutFuture = eventLoop().schedule(new Runnable() { - @Override - public void run() { - ChannelPromise connectPromise = AbstractEpollStreamChannel.this.connectPromise; - ConnectTimeoutException cause = - new ConnectTimeoutException("connection timed out: " + remoteAddress); - if (connectPromise != null && connectPromise.tryFailure(cause)) { - close(voidPromise()); - } - } - }, connectTimeoutMillis, TimeUnit.MILLISECONDS); - } - - promise.addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - if (future.isCancelled()) { - if (connectTimeoutFuture != null) { - connectTimeoutFuture.cancel(false); - } - connectPromise = null; - close(voidPromise()); - } - } - }); - } - } catch (Throwable t) { - closeIfClosed(); - promise.tryFailure(annotateConnectException(t, remoteAddress)); - } - } - - private void fulfillConnectPromise(ChannelPromise promise, boolean wasActive) { - if (promise == null) { - // Closed via cancellation and the promise has been notified already. - return; - } - active = true; - - // trySuccess() will return false if a user cancelled the connection attempt. - boolean promiseSet = promise.trySuccess(); - - // Regardless if the connection attempt was cancelled, channelActive() event should be triggered, - // because what happened is what happened. - if (!wasActive && isActive()) { - pipeline().fireChannelActive(); - } - - // If a user cancelled the connection attempt, close the channel, which is followed by channelInactive(). - if (!promiseSet) { - close(voidPromise()); - } - } - - private void fulfillConnectPromise(ChannelPromise promise, Throwable cause) { - if (promise == null) { - // Closed via cancellation and the promise has been notified already. - return; - } - - // Use tryFailure() instead of setFailure() to avoid the race against cancel(). - promise.tryFailure(cause); - closeIfClosed(); - } - - private void finishConnect() { - // Note this method is invoked by the event loop only if the connection attempt was - // neither cancelled nor timed out. - - assert eventLoop().inEventLoop(); - - boolean connectStillInProgress = false; - try { - boolean wasActive = isActive(); - if (!doFinishConnect()) { - connectStillInProgress = true; - return; - } - fulfillConnectPromise(connectPromise, wasActive); - } catch (Throwable t) { - fulfillConnectPromise(connectPromise, annotateConnectException(t, requestedRemoteAddress)); - } finally { - if (!connectStillInProgress) { - // Check for null as the connectTimeoutFuture is only created if a connectTimeoutMillis > 0 is used - // See https://github.com/netty/netty/issues/1770 - if (connectTimeoutFuture != null) { - connectTimeoutFuture.cancel(false); - } - connectPromise = null; - } - } - } - - @Override - void epollOutReady() { - if (connectPromise != null) { - // pending connect which is now complete so handle it. - finishConnect(); - } else { - super.epollOutReady(); - } - } - - /** - * Finish the connect - */ - private boolean doFinishConnect() throws Exception { - if (fd().finishConnect()) { - clearFlag(Native.EPOLLOUT); - return true; - } else { - setFlag(Native.EPOLLOUT); - return false; - } - } - - @Override - void epollInReady() { - if (fd().isInputShutdown()) { - return; - } - final ChannelConfig config = config(); - boolean edgeTriggered = isFlagSet(Native.EPOLLET); - - if (!readPending && !edgeTriggered && !config.isAutoRead()) { - // ChannelConfig.setAutoRead(false) was called in the meantime - clearEpollIn0(); - return; - } - - final ChannelPipeline pipeline = pipeline(); - final ByteBufAllocator allocator = config.getAllocator(); - RecvByteBufAllocator.Handle allocHandle = this.allocHandle; - if (allocHandle == null) { - this.allocHandle = allocHandle = config.getRecvByteBufAllocator().newHandle(); - } - - ByteBuf byteBuf = null; - boolean close = false; - try { - // if edgeTriggered is used we need to read all messages as we are not notified again otherwise. - final int maxMessagesPerRead = edgeTriggered - ? Integer.MAX_VALUE : config.getMaxMessagesPerRead(); - int messages = 0; - int totalReadAmount = 0; - do { - SpliceInTask spliceTask = spliceQueue.peek(); - if (spliceTask != null) { - if (spliceTask.spliceIn(allocHandle)) { - // We need to check if it is still active as if not we removed all SpliceTasks in - // doClose(...) - if (isActive()) { - spliceQueue.remove(); - } - continue; - } else { - break; - } - } - - // we use a direct buffer here as the native implementations only be able - // to handle direct buffers. - byteBuf = allocHandle.allocate(allocator); - int writable = byteBuf.writableBytes(); - int localReadAmount = doReadBytes(byteBuf); - if (localReadAmount <= 0) { - // not was read release the buffer - byteBuf.release(); - close = localReadAmount < 0; - break; - } - readPending = false; - pipeline.fireChannelRead(byteBuf); - byteBuf = null; - - if (totalReadAmount >= Integer.MAX_VALUE - localReadAmount) { - allocHandle.record(totalReadAmount); - - // Avoid overflow. - totalReadAmount = localReadAmount; - } else { - totalReadAmount += localReadAmount; - } - - if (localReadAmount < writable) { - // Read less than what the buffer can hold, - // which might mean we drained the recv buffer completely. - break; - } - if (!edgeTriggered && !config.isAutoRead()) { - // This is not using EPOLLET so we can stop reading - // ASAP as we will get notified again later with - // pending data - break; - } - } while (++ messages < maxMessagesPerRead || isRdHup()); - - pipeline.fireChannelReadComplete(); - allocHandle.record(totalReadAmount); - - if (close) { - shutdownInput(); - close = false; - } - } catch (Throwable t) { - boolean closed = handleReadException(pipeline, byteBuf, t, close); - if (!closed) { - // trigger a read again as there may be something left to read and because of epoll ET we - // will not get notified again until we read everything from the socket - eventLoop().execute(new Runnable() { - @Override - public void run() { - epollInReady(); - } - }); - } - } finally { - // Check if there is a readPending which was not processed yet. - // This could be for two reasons: - // * The user called Channel.read() or ChannelHandlerContext.read() in channelRead(...) method - // * The user called Channel.read() or ChannelHandlerContext.read() in channelReadComplete(...) method - // - // See https://github.com/netty/netty/issues/2254 - if (!readPending && !config.isAutoRead()) { - clearEpollIn0(); - } - } - } - } - - protected abstract class SpliceInTask extends MpscLinkedQueueNode { - final ChannelPromise promise; - int len; - - protected SpliceInTask(int len, ChannelPromise promise) { - this.promise = promise; - this.len = len; - } - - @Override - public SpliceInTask value() { - return this; - } - - abstract boolean spliceIn(RecvByteBufAllocator.Handle handle) throws IOException; - - protected final int spliceIn(FileDescriptor pipeOut, RecvByteBufAllocator.Handle handle) throws IOException { - // calculate the maximum amount of data we are allowed to splice - int length = Math.min(handle.guess(), len); - int splicedIn = 0; - for (;;) { - // Splicing until there is nothing left to splice. - int localSplicedIn = Native.splice(fd().intValue(), -1, pipeOut.intValue(), -1, length); - if (localSplicedIn == 0) { - break; - } - splicedIn += localSplicedIn; - length -= localSplicedIn; - } - - // record the number of bytes we spliced before - handle.record(splicedIn); - return splicedIn; - } - } - - // Let it directly implement channelFutureListener as well to reduce object creation. - private final class SpliceInChannelTask extends SpliceInTask implements ChannelFutureListener { - private final AbstractEpollStreamChannel ch; - - SpliceInChannelTask(AbstractEpollStreamChannel ch, int len, ChannelPromise promise) { - super(len, promise); - this.ch = ch; - } - - @Override - public void operationComplete(ChannelFuture future) throws Exception { - if (!future.isSuccess()) { - promise.setFailure(future.cause()); - } - } - - @Override - public boolean spliceIn(RecvByteBufAllocator.Handle handle) throws IOException { - assert ch.eventLoop().inEventLoop(); - if (len == 0) { - promise.setSuccess(); - return true; - } - try { - // We create the pipe on the target channel as this will allow us to just handle pending writes - // later in a correct fashion without get into any ordering issues when spliceTo(...) is called - // on multiple Channels pointing to one target Channel. - FileDescriptor pipeOut = ch.pipeOut; - if (pipeOut == null) { - // Create a new pipe as non was created before. - FileDescriptor[] pipe = pipe(); - ch.pipeIn = pipe[0]; - pipeOut = ch.pipeOut = pipe[1]; - } - - int splicedIn = spliceIn(pipeOut, handle); - if (splicedIn > 0) { - // Integer.MAX_VALUE is a special value which will result in splice forever. - if (len != Integer.MAX_VALUE) { - len -= splicedIn; - } - - // Depending on if we are done with splicing inbound data we set the right promise for the - // outbound splicing. - final ChannelPromise splicePromise; - if (len == 0) { - splicePromise = promise; - } else { - splicePromise = ch.newPromise().addListener(this); - } - - boolean autoRead = config().isAutoRead(); - - // Just call unsafe().write(...) and flush() as we not want to traverse the whole pipeline for this - // case. - ch.unsafe().write(new SpliceOutTask(ch, splicedIn, autoRead), splicePromise); - ch.unsafe().flush(); - if (autoRead && !splicePromise.isDone()) { - // Write was not done which means the target channel was not writable. In this case we need to - // disable reading until we are done with splicing to the target channel because: - // - // - The user may want to to trigger another splice operation once the splicing was complete. - config().setAutoRead(false); - } - } - - return len == 0; - } catch (Throwable cause) { - promise.setFailure(cause); - return true; - } - } - } - - private final class SpliceOutTask { - private final AbstractEpollStreamChannel ch; - private final boolean autoRead; - private int len; - - SpliceOutTask(AbstractEpollStreamChannel ch, int len, boolean autoRead) { - this.ch = ch; - this.len = len; - this.autoRead = autoRead; - } - - public boolean spliceOut() throws Exception { - assert ch.eventLoop().inEventLoop(); - try { - int splicedOut = Native.splice(ch.pipeIn.intValue(), -1, ch.fd().intValue(), -1, len); - len -= splicedOut; - if (len == 0) { - if (autoRead) { - // AutoRead was used and we spliced everything so start reading again - config().setAutoRead(true); - } - return true; - } - return false; - } catch (IOException e) { - if (autoRead) { - // AutoRead was used and we spliced everything so start reading again - config().setAutoRead(true); - } - throw e; - } - } - } - - private final class SpliceFdTask extends SpliceInTask { - private final FileDescriptor fd; - private final ChannelPromise promise; - private int offset; - - SpliceFdTask(FileDescriptor fd, int offset, int len, ChannelPromise promise) { - super(len, promise); - this.fd = fd; - this.promise = promise; - this.offset = offset; - } - - @Override - public SpliceFdTask value() { - return this; - } - - @Override - public boolean spliceIn(RecvByteBufAllocator.Handle handle) throws IOException { - assert eventLoop().inEventLoop(); - if (len == 0) { - promise.setSuccess(); - return true; - } - - try { - FileDescriptor[] pipe = pipe(); - FileDescriptor pipeIn = pipe[0]; - FileDescriptor pipeOut = pipe[1]; - try { - int splicedIn = spliceIn(pipeOut, handle); - if (splicedIn > 0) { - // Integer.MAX_VALUE is a special value which will result in splice forever. - if (len != Integer.MAX_VALUE) { - len -= splicedIn; - } - do { - int splicedOut = Native.splice(pipeIn.intValue(), -1, fd.intValue(), offset, splicedIn); - splicedIn -= splicedOut; - } while (splicedIn > 0); - if (len == 0) { - promise.setSuccess(); - return true; - } - } - return false; - } finally { - safeClosePipe(pipeIn); - safeClosePipe(pipeOut); - } - } catch (Throwable cause) { - promise.setFailure(cause); - return true; - } - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/Epoll.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/Epoll.java deleted file mode 100755 index bce43c9487..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/Epoll.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.epoll; - -import com.ai.cloud.io.netty.channel.unix.FileDescriptor; - -/** - * Tells if {@code netty-transport-native-epoll} is supported. - */ -public final class Epoll { - - private static final Throwable UNAVAILABILITY_CAUSE; - - static { - Throwable cause = null; - FileDescriptor epollFd = null; - FileDescriptor eventFd = null; - try { - epollFd = Native.newEpollCreate(); - eventFd = Native.newEventFd(); - } catch (Throwable t) { - cause = t; - } finally { - if (epollFd != null) { - try { - epollFd.close(); - } catch (Exception ignore) { - // ignore - } - } - if (eventFd != null) { - try { - eventFd.close(); - } catch (Exception ignore) { - // ignore - } - } - } - - if (cause != null) { - UNAVAILABILITY_CAUSE = cause; - } else { - UNAVAILABILITY_CAUSE = null; - } - } - - /** - * Returns {@code true} if and only if the - * {@code netty-transport-native-epoll} is available. - */ - public static boolean isAvailable() { - return UNAVAILABILITY_CAUSE == null; - } - - /** - * Ensure that {@code netty-transport-native-epoll} is - * available. - * - * @throws UnsatisfiedLinkError if unavailable - */ - public static void ensureAvailability() { - if (UNAVAILABILITY_CAUSE != null) { - throw (Error) new UnsatisfiedLinkError( - "failed to load the required native library").initCause(UNAVAILABILITY_CAUSE); - } - } - - /** - * Returns the cause of unavailability of - * {@code netty-transport-native-epoll}. - * - * @return the cause if unavailable. {@code null} if available. - */ - public static Throwable unavailabilityCause() { - return UNAVAILABILITY_CAUSE; - } - - private Epoll() { } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollChannelConfig.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollChannelConfig.java deleted file mode 100755 index 49f9374a91..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollChannelConfig.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.epoll; - -import java.io.IOException; -import java.util.Map; - -import com.ai.cloud.io.netty.buffer.ByteBufAllocator; -import com.ai.cloud.io.netty.channel.ChannelException; -import com.ai.cloud.io.netty.channel.ChannelOption; -import com.ai.cloud.io.netty.channel.DefaultChannelConfig; -import com.ai.cloud.io.netty.channel.MessageSizeEstimator; -import com.ai.cloud.io.netty.channel.RecvByteBufAllocator; - -public class EpollChannelConfig extends DefaultChannelConfig { - final AbstractEpollChannel channel; - - EpollChannelConfig(AbstractEpollChannel channel) { - super(channel); - this.channel = channel; - } - - @Override - public Map, Object> getOptions() { - return getOptions(super.getOptions(), EpollChannelOption.EPOLL_MODE); - } - - @SuppressWarnings("unchecked") - @Override - public T getOption(ChannelOption option) { - if (option == EpollChannelOption.EPOLL_MODE) { - return (T) getEpollMode(); - } - return super.getOption(option); - } - - @Override - public boolean setOption(ChannelOption option, T value) { - validate(option, value); - if (option == EpollChannelOption.EPOLL_MODE) { - setEpollMode((EpollMode) value); - } else { - return super.setOption(option, value); - } - return true; - } - - @Override - public EpollChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis) { - super.setConnectTimeoutMillis(connectTimeoutMillis); - return this; - } - - @Override - public EpollChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead) { - super.setMaxMessagesPerRead(maxMessagesPerRead); - return this; - } - - @Override - public EpollChannelConfig setWriteSpinCount(int writeSpinCount) { - super.setWriteSpinCount(writeSpinCount); - return this; - } - - @Override - public EpollChannelConfig setAllocator(ByteBufAllocator allocator) { - super.setAllocator(allocator); - return this; - } - - @Override - public EpollChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator) { - super.setRecvByteBufAllocator(allocator); - return this; - } - - @Override - public EpollChannelConfig setAutoRead(boolean autoRead) { - super.setAutoRead(autoRead); - return this; - } - - @Override - public EpollChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) { - super.setWriteBufferHighWaterMark(writeBufferHighWaterMark); - return this; - } - - @Override - public EpollChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark) { - super.setWriteBufferLowWaterMark(writeBufferLowWaterMark); - return this; - } - - @Override - public EpollChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator) { - super.setMessageSizeEstimator(estimator); - return this; - } - - /** - * Return the {@link EpollMode} used. Default is - * {@link EpollMode#EDGE_TRIGGERED}. If you want to use {@link #isAutoRead()} {@code false} or - * {@link #getMaxMessagesPerRead()} and have an accurate behaviour you should use - * {@link EpollMode#LEVEL_TRIGGERED}. - */ - public EpollMode getEpollMode() { - return channel.isFlagSet(Native.EPOLLET) - ? EpollMode.EDGE_TRIGGERED : EpollMode.LEVEL_TRIGGERED; - } - - /** - * Set the {@link EpollMode} used. Default is - * {@link EpollMode#EDGE_TRIGGERED}. If you want to use {@link #isAutoRead()} {@code false} or - * {@link #getMaxMessagesPerRead()} and have an accurate behaviour you should use - * {@link EpollMode#LEVEL_TRIGGERED}. - * - * Be aware this config setting can only be adjusted before the channel was registered. - */ - public EpollChannelConfig setEpollMode(EpollMode mode) { - if (mode == null) { - throw new NullPointerException("mode"); - } - try { - switch (mode) { - case EDGE_TRIGGERED: - checkChannelNotRegistered(); - channel.setFlag(Native.EPOLLET); - break; - case LEVEL_TRIGGERED: - checkChannelNotRegistered(); - channel.clearFlag(Native.EPOLLET); - break; - default: - throw new Error(); - } - } catch (IOException e) { - throw new ChannelException(e); - } - return this; - } - - private void checkChannelNotRegistered() { - if (channel.isRegistered()) { - throw new IllegalStateException("EpollMode can only be changed before channel is registered"); - } - } - - @Override - protected final void autoReadCleared() { - channel.clearEpollIn(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollChannelOption.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollChannelOption.java deleted file mode 100755 index 0bc9b6b46b..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollChannelOption.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.epoll; - -import java.net.InetAddress; -import java.util.Map; - -import com.ai.cloud.io.netty.channel.ChannelOption; -import com.ai.cloud.io.netty.channel.unix.DomainSocketReadMode; - -public final class EpollChannelOption extends ChannelOption { - - public static final ChannelOption TCP_CORK = valueOf("TCP_CORK"); - public static final ChannelOption SO_REUSEPORT = valueOf("SO_REUSEPORT"); - public static final ChannelOption TCP_NOTSENT_LOWAT = valueOf("TCP_NOTSENT_LOWAT"); - public static final ChannelOption TCP_KEEPIDLE = valueOf("TCP_KEEPIDLE"); - public static final ChannelOption TCP_KEEPINTVL = valueOf("TCP_KEEPINTVL"); - public static final ChannelOption TCP_KEEPCNT = valueOf("TCP_KEEPCNT"); - public static final ChannelOption TCP_USER_TIMEOUT = valueOf("TCP_USER_TIMEOUT"); - public static final ChannelOption IP_FREEBIND = valueOf("IP_FREEBIND"); - public static final ChannelOption TCP_FASTOPEN = valueOf("TCP_FASTOPEN"); - - public static final ChannelOption DOMAIN_SOCKET_READ_MODE = - valueOf("DOMAIN_SOCKET_READ_MODE"); - - public static final ChannelOption EPOLL_MODE = - valueOf("EPOLL_MODE"); - - public static final ChannelOption> TCP_MD5SIG = valueOf("TCP_MD5SIG"); - - @SuppressWarnings({ "unused", "deprecation" }) - private EpollChannelOption(String name) { - super(name); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollDatagramChannel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollDatagramChannel.java deleted file mode 100755 index ee167df93d..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollDatagramChannel.java +++ /dev/null @@ -1,616 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.epoll; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.NetworkInterface; -import java.net.SocketAddress; -import java.net.SocketException; -import java.nio.ByteBuffer; -import java.nio.channels.NotYetConnectedException; -import java.util.ArrayList; -import java.util.List; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.CompositeByteBuf; -import com.ai.cloud.io.netty.channel.AddressedEnvelope; -import com.ai.cloud.io.netty.channel.ChannelFuture; -import com.ai.cloud.io.netty.channel.ChannelMetadata; -import com.ai.cloud.io.netty.channel.ChannelOption; -import com.ai.cloud.io.netty.channel.ChannelOutboundBuffer; -import com.ai.cloud.io.netty.channel.ChannelPipeline; -import com.ai.cloud.io.netty.channel.ChannelPromise; -import com.ai.cloud.io.netty.channel.DefaultAddressedEnvelope; -import com.ai.cloud.io.netty.channel.RecvByteBufAllocator; -import com.ai.cloud.io.netty.channel.socket.DatagramChannel; -import com.ai.cloud.io.netty.channel.socket.DatagramChannelConfig; -import com.ai.cloud.io.netty.channel.socket.DatagramPacket; -import com.ai.cloud.io.netty.channel.unix.DatagramSocketAddress; -import com.ai.cloud.io.netty.channel.unix.FileDescriptor; -import com.ai.cloud.io.netty.channel.unix.Socket; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; -import com.ai.cloud.io.netty.util.internal.StringUtil; - -import static com.ai.cloud.io.netty.channel.unix.Socket.newSocketDgram; - -/** - * {@link DatagramChannel} implementation that uses linux EPOLL Edge-Triggered Mode for - * maximal performance. - */ -public final class EpollDatagramChannel extends AbstractEpollChannel implements DatagramChannel { - private static final ChannelMetadata METADATA = new ChannelMetadata(true); - private static final String EXPECTED_TYPES = - " (expected: " + StringUtil.simpleClassName(DatagramPacket.class) + ", " + - StringUtil.simpleClassName(AddressedEnvelope.class) + '<' + - StringUtil.simpleClassName(ByteBuf.class) + ", " + - StringUtil.simpleClassName(InetSocketAddress.class) + ">, " + - StringUtil.simpleClassName(ByteBuf.class) + ')'; - - private volatile InetSocketAddress local; - private volatile InetSocketAddress remote; - private volatile boolean connected; - private final EpollDatagramChannelConfig config; - - public EpollDatagramChannel() { - super(newSocketDgram(), Native.EPOLLIN); - config = new EpollDatagramChannelConfig(this); - } - - /** - * @deprecated Use {@link #EpollDatagramChannel(Socket)}. - */ - @Deprecated - public EpollDatagramChannel(FileDescriptor fd) { - this(new Socket(fd.intValue())); - } - - public EpollDatagramChannel(Socket fd) { - super(null, fd, Native.EPOLLIN, true); - // As we create an EpollDatagramChannel from a FileDescriptor we should try to obtain the remote and local - // address from it. This is needed as the FileDescriptor may be bound already. - local = fd.localAddress(); - config = new EpollDatagramChannelConfig(this); - } - - @Override - public InetSocketAddress remoteAddress() { - return (InetSocketAddress) super.remoteAddress(); - } - - @Override - public InetSocketAddress localAddress() { - return (InetSocketAddress) super.localAddress(); - } - - @Override - public ChannelMetadata metadata() { - return METADATA; - } - - @Override - @SuppressWarnings("deprecation") - public boolean isActive() { - return fd().isOpen() && - (config.getOption(ChannelOption.DATAGRAM_CHANNEL_ACTIVE_ON_REGISTRATION) && isRegistered() - || active); - } - - @Override - public boolean isConnected() { - return connected; - } - - @Override - public ChannelFuture joinGroup(InetAddress multicastAddress) { - return joinGroup(multicastAddress, newPromise()); - } - - @Override - public ChannelFuture joinGroup(InetAddress multicastAddress, ChannelPromise promise) { - try { - return joinGroup( - multicastAddress, - NetworkInterface.getByInetAddress(localAddress().getAddress()), - null, promise); - } catch (SocketException e) { - promise.setFailure(e); - } - return promise; - } - - @Override - public ChannelFuture joinGroup( - InetSocketAddress multicastAddress, NetworkInterface networkInterface) { - return joinGroup(multicastAddress, networkInterface, newPromise()); - } - - @Override - public ChannelFuture joinGroup( - InetSocketAddress multicastAddress, NetworkInterface networkInterface, - ChannelPromise promise) { - return joinGroup(multicastAddress.getAddress(), networkInterface, null, promise); - } - - @Override - public ChannelFuture joinGroup( - InetAddress multicastAddress, NetworkInterface networkInterface, InetAddress source) { - return joinGroup(multicastAddress, networkInterface, source, newPromise()); - } - - @Override - public ChannelFuture joinGroup( - final InetAddress multicastAddress, final NetworkInterface networkInterface, - final InetAddress source, final ChannelPromise promise) { - - if (multicastAddress == null) { - throw new NullPointerException("multicastAddress"); - } - - if (networkInterface == null) { - throw new NullPointerException("networkInterface"); - } - - promise.setFailure(new UnsupportedOperationException("Multicast not supported")); - return promise; - } - - @Override - public ChannelFuture leaveGroup(InetAddress multicastAddress) { - return leaveGroup(multicastAddress, newPromise()); - } - - @Override - public ChannelFuture leaveGroup(InetAddress multicastAddress, ChannelPromise promise) { - try { - return leaveGroup( - multicastAddress, NetworkInterface.getByInetAddress(localAddress().getAddress()), null, promise); - } catch (SocketException e) { - promise.setFailure(e); - } - return promise; - } - - @Override - public ChannelFuture leaveGroup( - InetSocketAddress multicastAddress, NetworkInterface networkInterface) { - return leaveGroup(multicastAddress, networkInterface, newPromise()); - } - - @Override - public ChannelFuture leaveGroup( - InetSocketAddress multicastAddress, - NetworkInterface networkInterface, ChannelPromise promise) { - return leaveGroup(multicastAddress.getAddress(), networkInterface, null, promise); - } - - @Override - public ChannelFuture leaveGroup( - InetAddress multicastAddress, NetworkInterface networkInterface, InetAddress source) { - return leaveGroup(multicastAddress, networkInterface, source, newPromise()); - } - - @Override - public ChannelFuture leaveGroup( - final InetAddress multicastAddress, final NetworkInterface networkInterface, final InetAddress source, - final ChannelPromise promise) { - if (multicastAddress == null) { - throw new NullPointerException("multicastAddress"); - } - if (networkInterface == null) { - throw new NullPointerException("networkInterface"); - } - - promise.setFailure(new UnsupportedOperationException("Multicast not supported")); - - return promise; - } - - @Override - public ChannelFuture block( - InetAddress multicastAddress, NetworkInterface networkInterface, - InetAddress sourceToBlock) { - return block(multicastAddress, networkInterface, sourceToBlock, newPromise()); - } - - @Override - public ChannelFuture block( - final InetAddress multicastAddress, final NetworkInterface networkInterface, - final InetAddress sourceToBlock, final ChannelPromise promise) { - if (multicastAddress == null) { - throw new NullPointerException("multicastAddress"); - } - if (sourceToBlock == null) { - throw new NullPointerException("sourceToBlock"); - } - - if (networkInterface == null) { - throw new NullPointerException("networkInterface"); - } - promise.setFailure(new UnsupportedOperationException("Multicast not supported")); - return promise; - } - - @Override - public ChannelFuture block(InetAddress multicastAddress, InetAddress sourceToBlock) { - return block(multicastAddress, sourceToBlock, newPromise()); - } - - @Override - public ChannelFuture block( - InetAddress multicastAddress, InetAddress sourceToBlock, ChannelPromise promise) { - try { - return block( - multicastAddress, - NetworkInterface.getByInetAddress(localAddress().getAddress()), - sourceToBlock, promise); - } catch (Throwable e) { - promise.setFailure(e); - } - return promise; - } - - @Override - protected AbstractEpollUnsafe newUnsafe() { - return new EpollDatagramChannelUnsafe(); - } - - @Override - protected InetSocketAddress localAddress0() { - return local; - } - - @Override - protected InetSocketAddress remoteAddress0() { - return remote; - } - - @Override - protected void doBind(SocketAddress localAddress) throws Exception { - InetSocketAddress addr = (InetSocketAddress) localAddress; - checkResolvable(addr); - fd().bind(addr); - local = fd().localAddress(); - active = true; - } - - @Override - protected void doWrite(ChannelOutboundBuffer in) throws Exception { - for (;;) { - Object msg = in.current(); - if (msg == null) { - // Wrote all messages. - clearFlag(Native.EPOLLOUT); - break; - } - - try { - // Check if sendmmsg(...) is supported which is only the case for GLIBC 2.14+ - if (Native.IS_SUPPORTING_SENDMMSG && in.size() > 1) { - NativeDatagramPacketArray array = NativeDatagramPacketArray.getInstance(in); - int cnt = array.count(); - - if (cnt >= 1) { - // Try to use gathering writes via sendmmsg(...) syscall. - int offset = 0; - NativeDatagramPacketArray.NativeDatagramPacket[] packets = array.packets(); - - while (cnt > 0) { - int send = Native.sendmmsg(fd().intValue(), packets, offset, cnt); - if (send == 0) { - // Did not write all messages. - setFlag(Native.EPOLLOUT); - return; - } - for (int i = 0; i < send; i++) { - in.remove(); - } - cnt -= send; - offset += send; - } - continue; - } - } - boolean done = false; - for (int i = config().getWriteSpinCount() - 1; i >= 0; i--) { - if (doWriteMessage(msg)) { - done = true; - break; - } - } - - if (done) { - in.remove(); - } else { - // Did not write all messages. - setFlag(Native.EPOLLOUT); - break; - } - } catch (IOException e) { - // Continue on write error as a DatagramChannel can write to multiple remote peers - // - // See https://github.com/netty/netty/issues/2665 - in.remove(e); - } - } - } - - private boolean doWriteMessage(Object msg) throws Exception { - final ByteBuf data; - InetSocketAddress remoteAddress; - if (msg instanceof AddressedEnvelope) { - @SuppressWarnings("unchecked") - AddressedEnvelope envelope = - (AddressedEnvelope) msg; - data = envelope.content(); - remoteAddress = envelope.recipient(); - } else { - data = (ByteBuf) msg; - remoteAddress = null; - } - - final int dataLen = data.readableBytes(); - if (dataLen == 0) { - return true; - } - - if (remoteAddress == null) { - remoteAddress = remote; - if (remoteAddress == null) { - throw new NotYetConnectedException(); - } - } - - final int writtenBytes; - if (data.hasMemoryAddress()) { - long memoryAddress = data.memoryAddress(); - writtenBytes = fd().sendToAddress(memoryAddress, data.readerIndex(), data.writerIndex(), - remoteAddress.getAddress(), remoteAddress.getPort()); - } else if (data instanceof CompositeByteBuf) { - IovArray array = IovArrayThreadLocal.get((CompositeByteBuf) data); - int cnt = array.count(); - assert cnt != 0; - - writtenBytes = fd().sendToAddresses(array.memoryAddress(0), - cnt, remoteAddress.getAddress(), remoteAddress.getPort()); - } else { - ByteBuffer nioData = data.internalNioBuffer(data.readerIndex(), data.readableBytes()); - writtenBytes = fd().sendTo(nioData, nioData.position(), nioData.limit(), - remoteAddress.getAddress(), remoteAddress.getPort()); - } - - return writtenBytes > 0; - } - - @Override - protected Object filterOutboundMessage(Object msg) { - if (msg instanceof DatagramPacket) { - DatagramPacket packet = (DatagramPacket) msg; - ByteBuf content = packet.content(); - if (content.hasMemoryAddress()) { - return msg; - } - - if (content.isDirect() && content instanceof CompositeByteBuf) { - // Special handling of CompositeByteBuf to reduce memory copies if some of the Components - // in the CompositeByteBuf are backed by a memoryAddress. - CompositeByteBuf comp = (CompositeByteBuf) content; - if (comp.isDirect() && comp.nioBufferCount() <= Native.IOV_MAX) { - return msg; - } - } - // We can only handle direct buffers so we need to copy if a non direct is - // passed to write. - return new DatagramPacket(newDirectBuffer(packet, content), packet.recipient()); - } - - if (msg instanceof ByteBuf) { - ByteBuf buf = (ByteBuf) msg; - if (!buf.hasMemoryAddress() && (PlatformDependent.hasUnsafe() || !buf.isDirect())) { - if (buf instanceof CompositeByteBuf) { - // Special handling of CompositeByteBuf to reduce memory copies if some of the Components - // in the CompositeByteBuf are backed by a memoryAddress. - CompositeByteBuf comp = (CompositeByteBuf) buf; - if (!comp.isDirect() || comp.nioBufferCount() > Native.IOV_MAX) { - // more then 1024 buffers for gathering writes so just do a memory copy. - buf = newDirectBuffer(buf); - assert buf.hasMemoryAddress(); - } - } else { - // We can only handle buffers with memory address so we need to copy if a non direct is - // passed to write. - buf = newDirectBuffer(buf); - assert buf.hasMemoryAddress(); - } - } - return buf; - } - - if (msg instanceof AddressedEnvelope) { - @SuppressWarnings("unchecked") - AddressedEnvelope e = (AddressedEnvelope) msg; - if (e.content() instanceof ByteBuf && - (e.recipient() == null || e.recipient() instanceof InetSocketAddress)) { - - ByteBuf content = (ByteBuf) e.content(); - if (content.hasMemoryAddress()) { - return e; - } - if (content instanceof CompositeByteBuf) { - // Special handling of CompositeByteBuf to reduce memory copies if some of the Components - // in the CompositeByteBuf are backed by a memoryAddress. - CompositeByteBuf comp = (CompositeByteBuf) content; - if (comp.isDirect() && comp.nioBufferCount() <= Native.IOV_MAX) { - return e; - } - } - // We can only handle direct buffers so we need to copy if a non direct is - // passed to write. - return new DefaultAddressedEnvelope( - newDirectBuffer(e, content), (InetSocketAddress) e.recipient()); - } - } - - throw new UnsupportedOperationException( - "unsupported message type: " + StringUtil.simpleClassName(msg) + EXPECTED_TYPES); - } - - @Override - public EpollDatagramChannelConfig config() { - return config; - } - - @Override - protected void doDisconnect() throws Exception { - connected = false; - } - - final class EpollDatagramChannelUnsafe extends AbstractEpollUnsafe { - - private RecvByteBufAllocator.Handle allocHandle; - private final List readBuf = new ArrayList(); - - @Override - public void connect(SocketAddress remote, SocketAddress local, ChannelPromise channelPromise) { - boolean success = false; - try { - try { - boolean wasActive = isActive(); - InetSocketAddress remoteAddress = (InetSocketAddress) remote; - if (local != null) { - InetSocketAddress localAddress = (InetSocketAddress) local; - doBind(localAddress); - } - - checkResolvable(remoteAddress); - EpollDatagramChannel.this.remote = remoteAddress; - EpollDatagramChannel.this.local = fd().localAddress(); - success = true; - - // Regardless if the connection attempt was cancelled, channelActive() event should be triggered, - // because what happened is what happened. - if (!wasActive && isActive()) { - pipeline().fireChannelActive(); - } - } finally { - if (!success) { - doClose(); - } else { - channelPromise.setSuccess(); - connected = true; - } - } - } catch (Throwable cause) { - channelPromise.setFailure(cause); - } - } - - @Override - void epollInReady() { - assert eventLoop().inEventLoop(); - if (fd().isInputShutdown()) { - return; - } - DatagramChannelConfig config = config(); - boolean edgeTriggered = isFlagSet(Native.EPOLLET); - - if (!readPending && !edgeTriggered && !config.isAutoRead()) { - // ChannelConfig.setAutoRead(false) was called in the meantime - clearEpollIn0(); - return; - } - - RecvByteBufAllocator.Handle allocHandle = this.allocHandle; - if (allocHandle == null) { - this.allocHandle = allocHandle = config.getRecvByteBufAllocator().newHandle(); - } - - final ChannelPipeline pipeline = pipeline(); - Throwable exception = null; - try { - // if edgeTriggered is used we need to read all messages as we are not notified again otherwise. - final int maxMessagesPerRead = edgeTriggered - ? Integer.MAX_VALUE : config.getMaxMessagesPerRead(); - int messages = 0; - do { - ByteBuf data = null; - try { - data = allocHandle.allocate(config.getAllocator()); - int writerIndex = data.writerIndex(); - DatagramSocketAddress remoteAddress; - if (data.hasMemoryAddress()) { - // has a memory address so use optimized call - remoteAddress = fd().recvFromAddress(data.memoryAddress(), data.writerIndex(), - data.capacity()); - } else { - ByteBuffer nioData = data.internalNioBuffer(data.writerIndex(), data.writableBytes()); - remoteAddress = fd().recvFrom(nioData, nioData.position(), nioData.limit()); - } - - if (remoteAddress == null) { - break; - } - - int readBytes = remoteAddress.receivedAmount(); - data.writerIndex(data.writerIndex() + readBytes); - allocHandle.record(readBytes); - readPending = false; - - readBuf.add(new DatagramPacket(data, (InetSocketAddress) localAddress(), remoteAddress)); - data = null; - } catch (Throwable t) { - // We do not break from the loop here and remember the last exception, - // because we need to consume everything from the socket used with epoll ET. - exception = t; - } finally { - if (data != null) { - data.release(); - } - if (!edgeTriggered && !config.isAutoRead()) { - // This is not using EPOLLET so we can stop reading - // ASAP as we will get notified again later with - // pending data - break; - } - } - } while (++ messages < maxMessagesPerRead || isRdHup()); - - int size = readBuf.size(); - for (int i = 0; i < size; i ++) { - pipeline.fireChannelRead(readBuf.get(i)); - } - - readBuf.clear(); - pipeline.fireChannelReadComplete(); - - if (exception != null) { - pipeline.fireExceptionCaught(exception); - } - } finally { - // Check if there is a readPending which was not processed yet. - // This could be for two reasons: - // * The user called Channel.read() or ChannelHandlerContext.read() in channelRead(...) method - // * The user called Channel.read() or ChannelHandlerContext.read() in channelReadComplete(...) method - // - // See https://github.com/netty/netty/issues/2254 - if (!readPending && !config.isAutoRead()) { - clearEpollIn(); - } - } - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollDatagramChannelConfig.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollDatagramChannelConfig.java deleted file mode 100755 index af279f234c..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollDatagramChannelConfig.java +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.epoll; - -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.util.Map; - -import com.ai.cloud.io.netty.buffer.ByteBufAllocator; -import com.ai.cloud.io.netty.channel.ChannelOption; -import com.ai.cloud.io.netty.channel.FixedRecvByteBufAllocator; -import com.ai.cloud.io.netty.channel.MessageSizeEstimator; -import com.ai.cloud.io.netty.channel.RecvByteBufAllocator; -import com.ai.cloud.io.netty.channel.socket.DatagramChannelConfig; - -public final class EpollDatagramChannelConfig extends EpollChannelConfig implements DatagramChannelConfig { - private static final RecvByteBufAllocator DEFAULT_RCVBUF_ALLOCATOR = new FixedRecvByteBufAllocator(2048); - private final EpollDatagramChannel datagramChannel; - private boolean activeOnOpen; - - EpollDatagramChannelConfig(EpollDatagramChannel channel) { - super(channel); - datagramChannel = channel; - setRecvByteBufAllocator(DEFAULT_RCVBUF_ALLOCATOR); - } - - @Override - @SuppressWarnings("deprecation") - public Map, Object> getOptions() { - return getOptions( - super.getOptions(), - ChannelOption.SO_BROADCAST, ChannelOption.SO_RCVBUF, ChannelOption.SO_SNDBUF, - ChannelOption.SO_REUSEADDR, ChannelOption.IP_MULTICAST_LOOP_DISABLED, - ChannelOption.IP_MULTICAST_ADDR, ChannelOption.IP_MULTICAST_IF, ChannelOption.IP_MULTICAST_TTL, - ChannelOption.IP_TOS, ChannelOption.DATAGRAM_CHANNEL_ACTIVE_ON_REGISTRATION, - EpollChannelOption.SO_REUSEPORT); - } - - @SuppressWarnings({ "unchecked", "deprecation" }) - @Override - public T getOption(ChannelOption option) { - if (option == ChannelOption.SO_BROADCAST) { - return (T) Boolean.valueOf(isBroadcast()); - } - if (option == ChannelOption.SO_RCVBUF) { - return (T) Integer.valueOf(getReceiveBufferSize()); - } - if (option == ChannelOption.SO_SNDBUF) { - return (T) Integer.valueOf(getSendBufferSize()); - } - if (option == ChannelOption.SO_REUSEADDR) { - return (T) Boolean.valueOf(isReuseAddress()); - } - if (option == ChannelOption.IP_MULTICAST_LOOP_DISABLED) { - return (T) Boolean.valueOf(isLoopbackModeDisabled()); - } - if (option == ChannelOption.IP_MULTICAST_ADDR) { - return (T) getInterface(); - } - if (option == ChannelOption.IP_MULTICAST_IF) { - return (T) getNetworkInterface(); - } - if (option == ChannelOption.IP_MULTICAST_TTL) { - return (T) Integer.valueOf(getTimeToLive()); - } - if (option == ChannelOption.IP_TOS) { - return (T) Integer.valueOf(getTrafficClass()); - } - if (option == ChannelOption.DATAGRAM_CHANNEL_ACTIVE_ON_REGISTRATION) { - return (T) Boolean.valueOf(activeOnOpen); - } - if (option == EpollChannelOption.SO_REUSEPORT) { - return (T) Boolean.valueOf(isReusePort()); - } - return super.getOption(option); - } - - @Override - @SuppressWarnings("deprecation") - public boolean setOption(ChannelOption option, T value) { - validate(option, value); - - if (option == ChannelOption.SO_BROADCAST) { - setBroadcast((Boolean) value); - } else if (option == ChannelOption.SO_RCVBUF) { - setReceiveBufferSize((Integer) value); - } else if (option == ChannelOption.SO_SNDBUF) { - setSendBufferSize((Integer) value); - } else if (option == ChannelOption.SO_REUSEADDR) { - setReuseAddress((Boolean) value); - } else if (option == ChannelOption.IP_MULTICAST_LOOP_DISABLED) { - setLoopbackModeDisabled((Boolean) value); - } else if (option == ChannelOption.IP_MULTICAST_ADDR) { - setInterface((InetAddress) value); - } else if (option == ChannelOption.IP_MULTICAST_IF) { - setNetworkInterface((NetworkInterface) value); - } else if (option == ChannelOption.IP_MULTICAST_TTL) { - setTimeToLive((Integer) value); - } else if (option == ChannelOption.IP_TOS) { - setTrafficClass((Integer) value); - } else if (option == ChannelOption.DATAGRAM_CHANNEL_ACTIVE_ON_REGISTRATION) { - setActiveOnOpen((Boolean) value); - } else if (option == EpollChannelOption.SO_REUSEPORT) { - setReusePort((Boolean) value); - } else { - return super.setOption(option, value); - } - - return true; - } - - private void setActiveOnOpen(boolean activeOnOpen) { - if (channel.isRegistered()) { - throw new IllegalStateException("Can only changed before channel was registered"); - } - this.activeOnOpen = activeOnOpen; - } - - @Override - public EpollDatagramChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator) { - super.setMessageSizeEstimator(estimator); - return this; - } - - @Override - public EpollDatagramChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark) { - super.setWriteBufferLowWaterMark(writeBufferLowWaterMark); - return this; - } - - @Override - public EpollDatagramChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) { - super.setWriteBufferHighWaterMark(writeBufferHighWaterMark); - return this; - } - - @Override - public EpollDatagramChannelConfig setAutoClose(boolean autoClose) { - super.setAutoClose(autoClose); - return this; - } - - @Override - public EpollDatagramChannelConfig setAutoRead(boolean autoRead) { - super.setAutoRead(autoRead); - return this; - } - - @Override - public EpollDatagramChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator) { - super.setRecvByteBufAllocator(allocator); - return this; - } - - @Override - public EpollDatagramChannelConfig setWriteSpinCount(int writeSpinCount) { - super.setWriteSpinCount(writeSpinCount); - return this; - } - - @Override - public EpollDatagramChannelConfig setAllocator(ByteBufAllocator allocator) { - super.setAllocator(allocator); - return this; - } - - @Override - public EpollDatagramChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis) { - super.setConnectTimeoutMillis(connectTimeoutMillis); - return this; - } - - @Override - public EpollDatagramChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead) { - super.setMaxMessagesPerRead(maxMessagesPerRead); - return this; - } - - @Override - public int getSendBufferSize() { - return datagramChannel.fd().getSendBufferSize(); - } - - @Override - public EpollDatagramChannelConfig setSendBufferSize(int sendBufferSize) { - datagramChannel.fd().setSendBufferSize(sendBufferSize); - return this; - } - - @Override - public int getReceiveBufferSize() { - return datagramChannel.fd().getReceiveBufferSize(); - } - - @Override - public EpollDatagramChannelConfig setReceiveBufferSize(int receiveBufferSize) { - datagramChannel.fd().setReceiveBufferSize(receiveBufferSize); - return this; - } - - @Override - public int getTrafficClass() { - return Native.getTrafficClass(datagramChannel.fd().intValue()); - } - - @Override - public EpollDatagramChannelConfig setTrafficClass(int trafficClass) { - Native.setTrafficClass(datagramChannel.fd().intValue(), trafficClass); - return this; - } - - @Override - public boolean isReuseAddress() { - return Native.isReuseAddress(datagramChannel.fd().intValue()) == 1; - } - - @Override - public EpollDatagramChannelConfig setReuseAddress(boolean reuseAddress) { - Native.setReuseAddress(datagramChannel.fd().intValue(), reuseAddress ? 1 : 0); - return this; - } - - @Override - public boolean isBroadcast() { - return Native.isBroadcast(datagramChannel.fd().intValue()) == 1; - } - - @Override - public EpollDatagramChannelConfig setBroadcast(boolean broadcast) { - Native.setBroadcast(datagramChannel.fd().intValue(), broadcast ? 1 : 0); - return this; - } - - @Override - public boolean isLoopbackModeDisabled() { - return false; - } - - @Override - public DatagramChannelConfig setLoopbackModeDisabled(boolean loopbackModeDisabled) { - throw new UnsupportedOperationException("Multicast not supported"); - } - - @Override - public int getTimeToLive() { - return -1; - } - - @Override - public EpollDatagramChannelConfig setTimeToLive(int ttl) { - throw new UnsupportedOperationException("Multicast not supported"); - } - - @Override - public InetAddress getInterface() { - return null; - } - - @Override - public EpollDatagramChannelConfig setInterface(InetAddress interfaceAddress) { - throw new UnsupportedOperationException("Multicast not supported"); - } - - @Override - public NetworkInterface getNetworkInterface() { - return null; - } - - @Override - public EpollDatagramChannelConfig setNetworkInterface(NetworkInterface networkInterface) { - throw new UnsupportedOperationException("Multicast not supported"); - } - - @Override - public EpollDatagramChannelConfig setEpollMode(EpollMode mode) { - super.setEpollMode(mode); - return this; - } - - /** - * Returns {@code true} if the SO_REUSEPORT option is set. - */ - public boolean isReusePort() { - return Native.isReusePort(datagramChannel.fd().intValue()) == 1; - } - - /** - * Set the SO_REUSEPORT option on the underlying Channel. This will allow to bind multiple - * {@link EpollSocketChannel}s to the same port and so accept connections with multiple threads. - * - * Be aware this method needs be called before {@link EpollDatagramChannel#bind(java.net.SocketAddress)} to have - * any affect. - */ - public EpollDatagramChannelConfig setReusePort(boolean reusePort) { - Native.setReusePort(datagramChannel.fd().intValue(), reusePort ? 1 : 0); - return this; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollDomainSocketChannel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollDomainSocketChannel.java deleted file mode 100755 index 9cf69cb201..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollDomainSocketChannel.java +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.epoll; - -import java.net.SocketAddress; - -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelConfig; -import com.ai.cloud.io.netty.channel.ChannelOutboundBuffer; -import com.ai.cloud.io.netty.channel.ChannelPipeline; -import com.ai.cloud.io.netty.channel.unix.DomainSocketAddress; -import com.ai.cloud.io.netty.channel.unix.DomainSocketChannel; -import com.ai.cloud.io.netty.channel.unix.FileDescriptor; -import com.ai.cloud.io.netty.channel.unix.Socket; - -import static com.ai.cloud.io.netty.channel.unix.Socket.newSocketDomain; - -public final class EpollDomainSocketChannel extends AbstractEpollStreamChannel implements DomainSocketChannel { - private final EpollDomainSocketChannelConfig config = new EpollDomainSocketChannelConfig(this); - - private volatile DomainSocketAddress local; - private volatile DomainSocketAddress remote; - - public EpollDomainSocketChannel() { - super(newSocketDomain(), false); - } - - /** - * @deprecated Use {@link #EpollDomainSocketChannel(Channel, Socket)}. - */ - @Deprecated - public EpollDomainSocketChannel(Channel parent, FileDescriptor fd) { - super(parent, new Socket(fd.intValue())); - } - - /** - * @deprecated Use {@link #EpollDomainSocketChannel(Socket, boolean)}. - *

- * Creates a new {@link EpollDomainSocketChannel} from an existing {@link FileDescriptor} - */ - @Deprecated - public EpollDomainSocketChannel(FileDescriptor fd) { - super(fd); - } - - public EpollDomainSocketChannel(Channel parent, Socket fd) { - super(parent, fd); - } - - /** - * Creates a new {@link EpollDomainSocketChannel} from an existing {@link FileDescriptor} - */ - public EpollDomainSocketChannel(Socket fd, boolean active) { - super(fd, active); - } - - @Override - protected AbstractEpollUnsafe newUnsafe() { - return new EpollDomainUnsafe(); - } - - @Override - protected DomainSocketAddress localAddress0() { - return local; - } - - @Override - protected DomainSocketAddress remoteAddress0() { - return remote; - } - - @Override - protected void doBind(SocketAddress localAddress) throws Exception { - fd().bind(localAddress); - local = (DomainSocketAddress) localAddress; - } - - @Override - public EpollDomainSocketChannelConfig config() { - return config; - } - - @Override - protected boolean doConnect(SocketAddress remoteAddress, SocketAddress localAddress) throws Exception { - if (super.doConnect(remoteAddress, localAddress)) { - local = (DomainSocketAddress) localAddress; - remote = (DomainSocketAddress) remoteAddress; - return true; - } - return false; - } - - @Override - public DomainSocketAddress remoteAddress() { - return (DomainSocketAddress) super.remoteAddress(); - } - - @Override - public DomainSocketAddress localAddress() { - return (DomainSocketAddress) super.localAddress(); - } - - @Override - protected boolean doWriteSingle(ChannelOutboundBuffer in, int writeSpinCount) throws Exception { - Object msg = in.current(); - if (msg instanceof FileDescriptor && Native.sendFd(fd().intValue(), ((FileDescriptor) msg).intValue()) > 0) { - // File descriptor was written, so remove it. - in.remove(); - return true; - } - return super.doWriteSingle(in, writeSpinCount); - } - - @Override - protected Object filterOutboundMessage(Object msg) { - if (msg instanceof FileDescriptor) { - return msg; - } - return super.filterOutboundMessage(msg); - } - - private final class EpollDomainUnsafe extends EpollStreamUnsafe { - @Override - void epollInReady() { - switch (config().getReadMode()) { - case BYTES: - super.epollInReady(); - break; - case FILE_DESCRIPTORS: - epollInReadFd(); - break; - default: - throw new Error(); - } - } - - private void epollInReadFd() { - if (fd().isInputShutdown()) { - return; - } - boolean edgeTriggered = isFlagSet(Native.EPOLLET); - final ChannelConfig config = config(); - if (!readPending && !edgeTriggered && !config.isAutoRead()) { - // ChannelConfig.setAutoRead(false) was called in the meantime - clearEpollIn0(); - return; - } - - final ChannelPipeline pipeline = pipeline(); - - try { - // if edgeTriggered is used we need to read all messages as we are not notified again otherwise. - final int maxMessagesPerRead = edgeTriggered - ? Integer.MAX_VALUE : config.getMaxMessagesPerRead(); - int messages = 0; - do { - int socketFd = Native.recvFd(fd().intValue()); - if (socketFd == 0) { - break; - } - if (socketFd == -1) { - close(voidPromise()); - return; - } - readPending = false; - - try { - pipeline.fireChannelRead(new FileDescriptor(socketFd)); - } catch (Throwable t) { - // keep on reading as we use epoll ET and need to consume everything from the socket - pipeline.fireChannelReadComplete(); - pipeline.fireExceptionCaught(t); - } finally { - if (!edgeTriggered && !config.isAutoRead()) { - // This is not using EPOLLET so we can stop reading - // ASAP as we will get notified again later with - // pending data - break; - } - } - } while (++ messages < maxMessagesPerRead || isRdHup()); - - pipeline.fireChannelReadComplete(); - - } catch (Throwable t) { - pipeline.fireChannelReadComplete(); - pipeline.fireExceptionCaught(t); - // trigger a read again as there may be something left to read and because of epoll ET we - // will not get notified again until we read everything from the socket - eventLoop().execute(new Runnable() { - @Override - public void run() { - epollInReady(); - } - }); - } finally { - // Check if there is a readPending which was not processed yet. - // This could be for two reasons: - // * The user called Channel.read() or ChannelHandlerContext.read() in channelRead(...) method - // * The user called Channel.read() or ChannelHandlerContext.read() in channelReadComplete(...) method - // - // See https://github.com/netty/netty/issues/2254 - if (!readPending && !config.isAutoRead()) { - clearEpollIn0(); - } - } - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollDomainSocketChannelConfig.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollDomainSocketChannelConfig.java deleted file mode 100755 index e713a9b477..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollDomainSocketChannelConfig.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.epoll; - -import java.util.Map; - -import com.ai.cloud.io.netty.buffer.ByteBufAllocator; -import com.ai.cloud.io.netty.channel.ChannelOption; -import com.ai.cloud.io.netty.channel.MessageSizeEstimator; -import com.ai.cloud.io.netty.channel.RecvByteBufAllocator; -import com.ai.cloud.io.netty.channel.unix.DomainSocketChannelConfig; -import com.ai.cloud.io.netty.channel.unix.DomainSocketReadMode; - -public final class EpollDomainSocketChannelConfig extends EpollChannelConfig - implements DomainSocketChannelConfig { - private volatile DomainSocketReadMode mode = DomainSocketReadMode.BYTES; - - EpollDomainSocketChannelConfig(AbstractEpollChannel channel) { - super(channel); - } - - @Override - public Map, Object> getOptions() { - return getOptions(super.getOptions(), EpollChannelOption.DOMAIN_SOCKET_READ_MODE); - } - - @SuppressWarnings("unchecked") - @Override - public T getOption(ChannelOption option) { - if (option == EpollChannelOption.DOMAIN_SOCKET_READ_MODE) { - return (T) getReadMode(); - } - return super.getOption(option); - } - - @Override - public boolean setOption(ChannelOption option, T value) { - validate(option, value); - - if (option == EpollChannelOption.DOMAIN_SOCKET_READ_MODE) { - setReadMode((DomainSocketReadMode) value); - } else { - return super.setOption(option, value); - } - - return true; - } - @Override - public EpollDomainSocketChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead) { - super.setMaxMessagesPerRead(maxMessagesPerRead); - return this; - } - - @Override - public EpollDomainSocketChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis) { - super.setConnectTimeoutMillis(connectTimeoutMillis); - return this; - } - - @Override - public EpollDomainSocketChannelConfig setWriteSpinCount(int writeSpinCount) { - super.setWriteSpinCount(writeSpinCount); - return this; - } - - @Override - public EpollDomainSocketChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator) { - super.setRecvByteBufAllocator(allocator); - return this; - } - - @Override - public EpollDomainSocketChannelConfig setAllocator(ByteBufAllocator allocator) { - super.setAllocator(allocator); - return this; - } - - @Override - public EpollDomainSocketChannelConfig setAutoClose(boolean autoClose) { - super.setAutoClose(autoClose); - return this; - } - - @Override - public EpollDomainSocketChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator) { - super.setMessageSizeEstimator(estimator); - return this; - } - - @Override - public EpollDomainSocketChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark) { - super.setWriteBufferLowWaterMark(writeBufferLowWaterMark); - return this; - } - - @Override - public EpollDomainSocketChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) { - super.setWriteBufferHighWaterMark(writeBufferHighWaterMark); - return this; - } - - @Override - public EpollDomainSocketChannelConfig setAutoRead(boolean autoRead) { - super.setAutoRead(autoRead); - return this; - } - - @Override - public EpollDomainSocketChannelConfig setEpollMode(EpollMode mode) { - super.setEpollMode(mode); - return this; - } - - @Override - public EpollDomainSocketChannelConfig setReadMode(DomainSocketReadMode mode) { - if (mode == null) { - throw new NullPointerException("mode"); - } - this.mode = mode; - return this; - } - - @Override - public DomainSocketReadMode getReadMode() { - return mode; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollEventArray.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollEventArray.java deleted file mode 100755 index 71f488e746..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollEventArray.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.epoll; - -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - -/** - * This is an internal datastructure which can be directly passed to epoll_wait to reduce the overhead. - * - * typedef union epoll_data { - * void *ptr; - * int fd; - * uint32_t u32; - * uint64_t u64; - * } epoll_data_t; - * - * struct epoll_event { - * uint32_t events; // Epoll events - * epoll_data_t data; // User data variable - * }; - * - * We use {@code fd} if the {@code epoll_data union} to store the actual file descriptor of an - * {@link AbstractEpollChannel} and so be able to map it later. - */ -final class EpollEventArray { - // Size of the epoll_event struct - private static final int EPOLL_EVENT_SIZE = Native.sizeofEpollEvent(); - // The offsiet of the data union in the epoll_event struct - private static final int EPOLL_DATA_OFFSET = Native.offsetofEpollData(); - - private long memoryAddress; - private int length; - - EpollEventArray(int length) { - if (length < 1) { - throw new IllegalArgumentException("length must be >= 1 but was " + length); - } - this.length = length; - memoryAddress = allocate(length); - } - - private static long allocate(int length) { - return PlatformDependent.allocateMemory(length * EPOLL_EVENT_SIZE); - } - - /** - * Return the {@code memoryAddress} which points to the start of this {@link EpollEventArray}. - */ - long memoryAddress() { - return memoryAddress; - } - - /** - * Return the length of the {@link EpollEventArray} which represent the maximum number of {@code epoll_events} - * that can be stored in it. - */ - int length() { - return length; - } - - /** - * Increase the storage of this {@link EpollEventArray}. - */ - void increase() { - // double the size - length <<= 1; - free(); - memoryAddress = allocate(length); - } - - /** - * Free this {@link EpollEventArray}. Any usage after calling this method may segfault the JVM! - */ - void free() { - PlatformDependent.freeMemory(memoryAddress); - } - - /** - * Return the events for the {@code epoll_event} on this index. - */ - int events(int index) { - return PlatformDependent.getInt(memoryAddress + index * EPOLL_EVENT_SIZE); - } - - /** - * Return the file descriptor for the {@code epoll_event} on this index. - */ - int fd(int index) { - return PlatformDependent.getInt(memoryAddress + index * EPOLL_EVENT_SIZE + EPOLL_DATA_OFFSET); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollEventLoop.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollEventLoop.java deleted file mode 100755 index a9746cfa4e..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollEventLoop.java +++ /dev/null @@ -1,381 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.epoll; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Queue; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; - -import com.ai.cloud.io.netty.channel.EventLoop; -import com.ai.cloud.io.netty.channel.EventLoopGroup; -import com.ai.cloud.io.netty.channel.SingleThreadEventLoop; -import com.ai.cloud.io.netty.channel.epoll.AbstractEpollChannel.AbstractEpollUnsafe; -import com.ai.cloud.io.netty.channel.unix.FileDescriptor; -import com.ai.cloud.io.netty.util.collection.IntObjectHashMap; -import com.ai.cloud.io.netty.util.collection.IntObjectMap; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * {@link EventLoop} which uses epoll under the covers. Only works on Linux! - */ -final class EpollEventLoop extends SingleThreadEventLoop { - private static final InternalLogger logger = InternalLoggerFactory.getInstance(EpollEventLoop.class); - private static final AtomicIntegerFieldUpdater WAKEN_UP_UPDATER; - - static { - AtomicIntegerFieldUpdater updater = - PlatformDependent.newAtomicIntegerFieldUpdater(EpollEventLoop.class, "wakenUp"); - if (updater == null) { - updater = AtomicIntegerFieldUpdater.newUpdater(EpollEventLoop.class, "wakenUp"); - } - WAKEN_UP_UPDATER = updater; - } - - private final FileDescriptor epollFd; - private final FileDescriptor eventFd; - private final IntObjectMap channels = new IntObjectHashMap(4096); - private final boolean allowGrowing; - private final EpollEventArray events; - - @SuppressWarnings("unused") - private volatile int wakenUp; - private volatile int ioRatio = 50; - - EpollEventLoop(EventLoopGroup parent, ThreadFactory threadFactory, int maxEvents) { - super(parent, threadFactory, false); - if (maxEvents == 0) { - allowGrowing = true; - events = new EpollEventArray(4096); - } else { - allowGrowing = false; - events = new EpollEventArray(maxEvents); - } - boolean success = false; - FileDescriptor epollFd = null; - FileDescriptor eventFd = null; - try { - this.epollFd = epollFd = Native.newEpollCreate(); - this.eventFd = eventFd = Native.newEventFd(); - try { - Native.epollCtlAdd(epollFd.intValue(), eventFd.intValue(), Native.EPOLLIN); - } catch (IOException e) { - throw new IllegalStateException("Unable to add eventFd filedescriptor to epoll", e); - } - success = true; - } finally { - if (!success) { - if (epollFd != null) { - try { - epollFd.close(); - } catch (Exception e) { - // ignore - } - } - if (eventFd != null) { - try { - eventFd.close(); - } catch (Exception e) { - // ignore - } - } - } - } - } - - @Override - protected void wakeup(boolean inEventLoop) { - if (!inEventLoop && WAKEN_UP_UPDATER.compareAndSet(this, 0, 1)) { - // write to the evfd which will then wake-up epoll_wait(...) - Native.eventFdWrite(eventFd.intValue(), 1L); - } - } - - /** - * Register the given epoll with this {@link com.ai.cloud.io.netty.channel.EventLoop}. - */ - void add(AbstractEpollChannel ch) throws IOException { - assert inEventLoop(); - int fd = ch.fd().intValue(); - Native.epollCtlAdd(epollFd.intValue(), fd, ch.flags); - channels.put(fd, ch); - } - - /** - * The flags of the given epoll was modified so update the registration - */ - void modify(AbstractEpollChannel ch) throws IOException { - assert inEventLoop(); - Native.epollCtlMod(epollFd.intValue(), ch.fd().intValue(), ch.flags); - } - - /** - * Deregister the given epoll from this {@link EventLoop}. - */ - void remove(AbstractEpollChannel ch) throws IOException { - assert inEventLoop(); - - if (ch.isOpen()) { - int fd = ch.fd().intValue(); - if (channels.remove(fd) != null) { - // Remove the epoll. This is only needed if it's still open as otherwise it will be automatically - // removed once the file-descriptor is closed. - Native.epollCtlDel(epollFd.intValue(), ch.fd().intValue()); - } - } - } - - @Override - protected Queue newTaskQueue() { - // This event loop never calls takeTask() - return PlatformDependent.newMpscQueue(); - } - - /** - * Returns the percentage of the desired amount of time spent for I/O in the event loop. - */ - public int getIoRatio() { - return ioRatio; - } - - /** - * Sets the percentage of the desired amount of time spent for I/O in the event loop. The default value is - * {@code 50}, which means the event loop will try to spend the same amount of time for I/O as for non-I/O tasks. - */ - public void setIoRatio(int ioRatio) { - if (ioRatio <= 0 || ioRatio > 100) { - throw new IllegalArgumentException("ioRatio: " + ioRatio + " (expected: 0 < ioRatio <= 100)"); - } - this.ioRatio = ioRatio; - } - - private int epollWait(boolean oldWakenUp) throws IOException { - int selectCnt = 0; - long currentTimeNanos = System.nanoTime(); - long selectDeadLineNanos = currentTimeNanos + delayNanos(currentTimeNanos); - for (;;) { - long timeoutMillis = (selectDeadLineNanos - currentTimeNanos + 500000L) / 1000000L; - if (timeoutMillis <= 0) { - if (selectCnt == 0) { - int ready = Native.epollWait(epollFd.intValue(), events, 0); - if (ready > 0) { - return ready; - } - } - break; - } - - int selectedKeys = Native.epollWait(epollFd.intValue(), events, (int) timeoutMillis); - selectCnt ++; - - if (selectedKeys != 0 || oldWakenUp || wakenUp == 1 || hasTasks() || hasScheduledTasks()) { - // - Selected something, - // - waken up by user, or - // - the task queue has a pending task. - // - a scheduled task is ready for processing - return selectedKeys; - } - currentTimeNanos = System.nanoTime(); - } - return 0; - } - - @Override - protected void run() { - for (;;) { - boolean oldWakenUp = WAKEN_UP_UPDATER.getAndSet(this, 0) == 1; - try { - int ready; - if (hasTasks()) { - // Non blocking just return what is ready directly without block - ready = Native.epollWait(epollFd.intValue(), events, 0); - } else { - ready = epollWait(oldWakenUp); - - // 'wakenUp.compareAndSet(false, true)' is always evaluated - // before calling 'selector.wakeup()' to reduce the wake-up - // overhead. (Selector.wakeup() is an expensive operation.) - // - // However, there is a race condition in this approach. - // The race condition is triggered when 'wakenUp' is set to - // true too early. - // - // 'wakenUp' is set to true too early if: - // 1) Selector is waken up between 'wakenUp.set(false)' and - // 'selector.select(...)'. (BAD) - // 2) Selector is waken up between 'selector.select(...)' and - // 'if (wakenUp.get()) { ... }'. (OK) - // - // In the first case, 'wakenUp' is set to true and the - // following 'selector.select(...)' will wake up immediately. - // Until 'wakenUp' is set to false again in the next round, - // 'wakenUp.compareAndSet(false, true)' will fail, and therefore - // any attempt to wake up the Selector will fail, too, causing - // the following 'selector.select(...)' call to block - // unnecessarily. - // - // To fix this problem, we wake up the selector again if wakenUp - // is true immediately after selector.select(...). - // It is inefficient in that it wakes up the selector for both - // the first case (BAD - wake-up required) and the second case - // (OK - no wake-up required). - - if (wakenUp == 1) { - Native.eventFdWrite(eventFd.intValue(), 1L); - } - } - - final int ioRatio = this.ioRatio; - if (ioRatio == 100) { - if (ready > 0) { - processReady(events, ready); - } - runAllTasks(); - } else { - final long ioStartTime = System.nanoTime(); - - if (ready > 0) { - processReady(events, ready); - } - - final long ioTime = System.nanoTime() - ioStartTime; - runAllTasks(ioTime * (100 - ioRatio) / ioRatio); - } - if (allowGrowing && ready == events.length()) { - //increase the size of the array as we needed the whole space for the events - events.increase(); - } - if (isShuttingDown()) { - closeAll(); - if (confirmShutdown()) { - break; - } - } - } catch (Throwable t) { - logger.warn("Unexpected exception in the selector loop.", t); - - // Prevent possible consecutive immediate failures that lead to - // excessive CPU consumption. - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - // Ignore. - } - } - } - } - - private void closeAll() { - try { - Native.epollWait(epollFd.intValue(), events, 0); - } catch (IOException ignore) { - // ignore on close - } - Collection array = new ArrayList(channels.size()); - - for (IntObjectMap.Entry entry: channels.entries()) { - array.add(entry.value()); - } - - for (AbstractEpollChannel ch: array) { - ch.unsafe().close(ch.unsafe().voidPromise()); - } - } - - private void processReady(EpollEventArray events, int ready) { - for (int i = 0; i < ready; i ++) { - final int fd = events.fd(i); - if (fd == eventFd.intValue()) { - // consume wakeup event - Native.eventFdRead(eventFd.intValue()); - } else { - final long ev = events.events(i); - - AbstractEpollChannel ch = channels.get(fd); - if (ch != null) { - // Don't change the ordering of processing EPOLLOUT | EPOLLRDHUP / EPOLLIN if you're not 100% - // sure about it! - // Re-ordering can easily introduce bugs and bad side-effects, as we found out painfully in the - // past. - AbstractEpollUnsafe unsafe = (AbstractEpollUnsafe) ch.unsafe(); - - // First check for EPOLLOUT as we may need to fail the connect ChannelPromise before try - // to read from the file descriptor. - // See https://github.com/netty/netty/issues/3785 - // - // It is possible for an EPOLLOUT or EPOLLERR to be generated when a connection is refused. - // In either case epollOutReady() will do the correct thing (finish connecting, or fail - // the connection). - // See https://github.com/netty/netty/issues/3848 - if ((ev & (Native.EPOLLERR | Native.EPOLLOUT)) != 0) { - // Force flush of data as the epoll is writable again - unsafe.epollOutReady(); - } - - // Check EPOLLIN before EPOLLRDHUP to ensure all data is read before shutting down the input. - // See https://github.com/netty/netty/issues/4317. - // - // If EPOLLIN or EPOLLERR was received and the channel is still open call epollInReady(). This will - // try to read from the underlying file descriptor and so notify the user about the error. - if ((ev & (Native.EPOLLERR | Native.EPOLLIN)) != 0) { - // The Channel is still open and there is something to read. Do it now. - unsafe.epollInReady(); - } - - // Check if EPOLLRDHUP was set, this will notify us for connection-reset in which case - // we may close the channel directly or try to read more data depending on the state of the - // Channel and als depending on the AbstractEpollChannel subtype. - if ((ev & Native.EPOLLRDHUP) != 0) { - unsafe.epollRdHupReady(); - } - } else { - // We received an event for an fd which we not use anymore. Remove it from the epoll_event set. - try { - Native.epollCtlDel(epollFd.intValue(), fd); - } catch (IOException ignore) { - // This can happen but is nothing we need to worry about as we only try to delete - // the fd from the epoll set as we not found it in our mappings. So this call to - // epollCtlDel(...) is just to ensure we cleanup stuff and so may fail if it was - // deleted before or the file descriptor was closed before. - } - } - } - } - } - - @Override - protected void cleanup() { - try { - try { - epollFd.close(); - } catch (IOException e) { - logger.warn("Failed to close the epoll fd.", e); - } - try { - eventFd.close(); - } catch (IOException e) { - logger.warn("Failed to close the event fd.", e); - } - } finally { - // release native memory - events.free(); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollEventLoopGroup.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollEventLoopGroup.java deleted file mode 100755 index b8ceea23e0..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollEventLoopGroup.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.epoll; - -import java.util.concurrent.ThreadFactory; - -import com.ai.cloud.io.netty.channel.EventLoopGroup; -import com.ai.cloud.io.netty.channel.MultithreadEventLoopGroup; -import com.ai.cloud.io.netty.util.concurrent.EventExecutor; - -/** - * {@link EventLoopGroup} which uses epoll under the covers. Because of this - * it only works on linux. - */ -public final class EpollEventLoopGroup extends MultithreadEventLoopGroup { - - /** - * Create a new instance using the default number of threads and the default {@link ThreadFactory}. - */ - public EpollEventLoopGroup() { - this(0); - } - - /** - * Create a new instance using the specified number of threads and the default {@link ThreadFactory}. - */ - public EpollEventLoopGroup(int nThreads) { - this(nThreads, null); - } - - /** - * Create a new instance using the specified number of threads and the given {@link ThreadFactory}. - */ - @SuppressWarnings("deprecation") - public EpollEventLoopGroup(int nThreads, ThreadFactory threadFactory) { - this(nThreads, threadFactory, 0); - } - - /** - * Create a new instance using the specified number of threads, the given {@link ThreadFactory} and the given - * maximal amount of epoll events to handle per epollWait(...). - * - * @deprecated Use {@link #EpollEventLoopGroup(int)}, {@link #EpollEventLoopGroup(int)} or - * {@link #EpollEventLoopGroup(int, ThreadFactory)} - */ - @Deprecated - public EpollEventLoopGroup(int nThreads, ThreadFactory threadFactory, int maxEventsAtOnce) { - super(nThreads, threadFactory, maxEventsAtOnce); - } - - /** - * Sets the percentage of the desired amount of time spent for I/O in the child event loops. The default value is - * {@code 50}, which means the event loop will try to spend the same amount of time for I/O as for non-I/O tasks. - */ - public void setIoRatio(int ioRatio) { - for (EventExecutor e: children()) { - ((EpollEventLoop) e).setIoRatio(ioRatio); - } - } - - @Override - protected EventExecutor newChild(ThreadFactory threadFactory, Object... args) throws Exception { - return new EpollEventLoop(this, threadFactory, (Integer) args[0]); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollMode.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollMode.java deleted file mode 100755 index 955300e6aa..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollMode.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.epoll; - -/** - * The epoll mode to use. - */ -public enum EpollMode { - - /** - * Use {@code EPOLLET} (edge-triggered). - * - * @see man 7 epoll. - */ - EDGE_TRIGGERED, - - /** - * Do not use {@code EPOLLET} (level-triggered). - * - * @see man 7 epoll. - */ - LEVEL_TRIGGERED -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollServerChannelConfig.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollServerChannelConfig.java deleted file mode 100755 index 5bdbc345a7..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollServerChannelConfig.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.epoll; - -import java.net.InetAddress; -import java.util.Map; - -import com.ai.cloud.io.netty.buffer.ByteBufAllocator; -import com.ai.cloud.io.netty.channel.ChannelOption; -import com.ai.cloud.io.netty.channel.MessageSizeEstimator; -import com.ai.cloud.io.netty.channel.RecvByteBufAllocator; -import com.ai.cloud.io.netty.util.NetUtil; - -import static com.ai.cloud.io.netty.channel.ChannelOption.SO_BACKLOG; -import static com.ai.cloud.io.netty.channel.ChannelOption.SO_RCVBUF; -import static com.ai.cloud.io.netty.channel.ChannelOption.SO_REUSEADDR; -import static com.ai.cloud.io.netty.channel.epoll.EpollChannelOption.TCP_MD5SIG; - -public class EpollServerChannelConfig extends EpollChannelConfig { - protected final AbstractEpollChannel channel; - private volatile int backlog = NetUtil.SOMAXCONN; - private volatile int pendingFastOpenRequestsThreshold; - - EpollServerChannelConfig(AbstractEpollChannel channel) { - super(channel); - this.channel = channel; - } - - @Override - public Map, Object> getOptions() { - return getOptions(super.getOptions(), SO_RCVBUF, SO_REUSEADDR, SO_BACKLOG, EpollChannelOption.TCP_FASTOPEN); - } - - @SuppressWarnings("unchecked") - @Override - public T getOption(ChannelOption option) { - if (option == SO_RCVBUF) { - return (T) Integer.valueOf(getReceiveBufferSize()); - } - if (option == SO_REUSEADDR) { - return (T) Boolean.valueOf(isReuseAddress()); - } - if (option == SO_BACKLOG) { - return (T) Integer.valueOf(getBacklog()); - } - if (option == EpollChannelOption.TCP_FASTOPEN) { - return (T) Integer.valueOf(getTcpFastopen()); - } - return super.getOption(option); - } - - @Override - public boolean setOption(ChannelOption option, T value) { - validate(option, value); - - if (option == SO_RCVBUF) { - setReceiveBufferSize((Integer) value); - } else if (option == SO_REUSEADDR) { - setReuseAddress((Boolean) value); - } else if (option == SO_BACKLOG) { - setBacklog((Integer) value); - } else if (option == TCP_MD5SIG) { - @SuppressWarnings("unchecked") - final Map m = (Map) value; - ((EpollServerSocketChannel) channel).setTcpMd5Sig(m); - } else if (option == EpollChannelOption.TCP_FASTOPEN) { - setTcpFastopen((Integer) value); - } else { - return super.setOption(option, value); - } - - return true; - } - - public boolean isReuseAddress() { - return Native.isReuseAddress(channel.fd().intValue()) == 1; - } - - public EpollServerChannelConfig setReuseAddress(boolean reuseAddress) { - Native.setReuseAddress(channel.fd().intValue(), reuseAddress ? 1 : 0); - return this; - } - - public int getReceiveBufferSize() { - return channel.fd().getReceiveBufferSize(); - } - - public EpollServerChannelConfig setReceiveBufferSize(int receiveBufferSize) { - channel.fd().setReceiveBufferSize(receiveBufferSize); - return this; - } - - public int getBacklog() { - return backlog; - } - - public EpollServerChannelConfig setBacklog(int backlog) { - if (backlog < 0) { - throw new IllegalArgumentException("backlog: " + backlog); - } - this.backlog = backlog; - return this; - } - - /** - * Returns threshold value of number of pending for fast open connect. - * - * @see RFC 7413 Passive Open - */ - public int getTcpFastopen() { - return pendingFastOpenRequestsThreshold; - } - - /** - * Enables tcpFastOpen on the server channel. If the underlying os doesnt support TCP_FASTOPEN setting this has no - * effect. This has to be set before doing listen on the socket otherwise this takes no effect. - * - * @param pendingFastOpenRequestsThreshold number of requests to be pending for fastopen at a given point in time - * for security. @see RFC 7413 Passive Open - * - * @see RFC 7413 TCP FastOpen - */ - public EpollServerChannelConfig setTcpFastopen(int pendingFastOpenRequestsThreshold) { - if (this.pendingFastOpenRequestsThreshold < 0) { - throw new IllegalArgumentException("pendingFastOpenRequestsThreshold: " + pendingFastOpenRequestsThreshold); - } - this.pendingFastOpenRequestsThreshold = pendingFastOpenRequestsThreshold; - return this; - } - - @Override - public EpollServerChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis) { - super.setConnectTimeoutMillis(connectTimeoutMillis); - return this; - } - - @Override - public EpollServerChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead) { - super.setMaxMessagesPerRead(maxMessagesPerRead); - return this; - } - - @Override - public EpollServerChannelConfig setWriteSpinCount(int writeSpinCount) { - super.setWriteSpinCount(writeSpinCount); - return this; - } - - @Override - public EpollServerChannelConfig setAllocator(ByteBufAllocator allocator) { - super.setAllocator(allocator); - return this; - } - - @Override - public EpollServerChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator) { - super.setRecvByteBufAllocator(allocator); - return this; - } - - @Override - public EpollServerChannelConfig setAutoRead(boolean autoRead) { - super.setAutoRead(autoRead); - return this; - } - - @Override - public EpollServerChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) { - super.setWriteBufferHighWaterMark(writeBufferHighWaterMark); - return this; - } - - @Override - public EpollServerChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark) { - super.setWriteBufferLowWaterMark(writeBufferLowWaterMark); - return this; - } - - @Override - public EpollServerChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator) { - super.setMessageSizeEstimator(estimator); - return this; - } - - @Override - public EpollServerChannelConfig setEpollMode(EpollMode mode) { - super.setEpollMode(mode); - return this; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollServerDomainSocketChannel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollServerDomainSocketChannel.java deleted file mode 100755 index 0fd3a820ae..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollServerDomainSocketChannel.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.epoll; - -import java.io.File; -import java.net.SocketAddress; - -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.unix.DomainSocketAddress; -import com.ai.cloud.io.netty.channel.unix.FileDescriptor; -import com.ai.cloud.io.netty.channel.unix.ServerDomainSocketChannel; -import com.ai.cloud.io.netty.channel.unix.Socket; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -import static com.ai.cloud.io.netty.channel.unix.Socket.newSocketDomain; - - -public final class EpollServerDomainSocketChannel extends AbstractEpollServerChannel - implements ServerDomainSocketChannel { - private static final InternalLogger logger = InternalLoggerFactory.getInstance( - EpollServerDomainSocketChannel.class); - - private final EpollServerChannelConfig config = new EpollServerChannelConfig(this); - private volatile DomainSocketAddress local; - - public EpollServerDomainSocketChannel() { - super(newSocketDomain(), false); - } - - /** - * @deprecated Use {@link #EpollServerDomainSocketChannel(Socket, boolean)}. - * Creates a new {@link EpollServerDomainSocketChannel} from an existing {@link FileDescriptor}. - */ - public EpollServerDomainSocketChannel(FileDescriptor fd) { - super(fd); - } - - /** - * @deprecated Use {@link #EpollServerDomainSocketChannel(Socket, boolean)}. - */ - public EpollServerDomainSocketChannel(Socket fd) { - super(fd); - } - - public EpollServerDomainSocketChannel(Socket fd, boolean active) { - super(fd, active); - } - - @Override - protected Channel newChildChannel(int fd, byte[] addr, int offset, int len) throws Exception { - return new EpollDomainSocketChannel(this, new Socket(fd)); - } - - @Override - protected DomainSocketAddress localAddress0() { - return local; - } - - @Override - protected void doBind(SocketAddress localAddress) throws Exception { - fd().bind(localAddress); - fd().listen(config.getBacklog()); - local = (DomainSocketAddress) localAddress; - } - - @Override - protected void doClose() throws Exception { - try { - super.doClose(); - } finally { - DomainSocketAddress local = this.local; - if (local != null) { - // Delete the socket file if possible. - File socketFile = new File(local.path()); - boolean success = socketFile.delete(); - if (!success && logger.isDebugEnabled()) { - logger.debug("Failed to delete a domain socket file: {}", local.path()); - } - } - } - } - - @Override - public EpollServerChannelConfig config() { - return config; - } - - @Override - public DomainSocketAddress remoteAddress() { - return (DomainSocketAddress) super.remoteAddress(); - } - - @Override - public DomainSocketAddress localAddress() { - return (DomainSocketAddress) super.localAddress(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollServerSocketChannel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollServerSocketChannel.java deleted file mode 100755 index 8f956ce581..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollServerSocketChannel.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.epoll; - -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.util.Collection; -import java.util.Collections; -import java.util.Map; - -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.EventLoop; -import com.ai.cloud.io.netty.channel.socket.ServerSocketChannel; -import com.ai.cloud.io.netty.channel.unix.FileDescriptor; -import com.ai.cloud.io.netty.channel.unix.Socket; - -import static com.ai.cloud.io.netty.channel.unix.NativeInetAddress.address; -import static com.ai.cloud.io.netty.channel.unix.Socket.newSocketStream; - -/** - * {@link ServerSocketChannel} implementation that uses linux EPOLL Edge-Triggered Mode for - * maximal performance. - */ -public final class EpollServerSocketChannel extends AbstractEpollServerChannel implements ServerSocketChannel { - - private final EpollServerSocketChannelConfig config; - private volatile InetSocketAddress local; - private volatile Collection tcpMd5SigAddresses = Collections.emptyList(); - - public EpollServerSocketChannel() { - super(newSocketStream(), false); - config = new EpollServerSocketChannelConfig(this); - } - - /** - * @deprecated Use {@link #EpollServerSocketChannel(Socket, boolean)}. - * Creates a new {@link EpollServerSocketChannel} from an existing {@link FileDescriptor}. - */ - @Deprecated - public EpollServerSocketChannel(FileDescriptor fd) { - // Must call this constructor to ensure this object's local address is configured correctly. - // The local address can only be obtained from a Socket object. - this(new Socket(fd.intValue())); - } - - /** - * @deprecated Use {@link #EpollServerSocketChannel(Socket, boolean)}. - * Creates a new {@link EpollServerSocketChannel} from an existing {@link Socket}. - */ - @Deprecated - public EpollServerSocketChannel(Socket fd) { - super(fd); - // As we create an EpollServerSocketChannel from a FileDescriptor we should try to obtain the remote and local - // address from it. This is needed as the FileDescriptor may be bound already. - local = fd.localAddress(); - config = new EpollServerSocketChannelConfig(this); - } - - public EpollServerSocketChannel(Socket fd, boolean active) { - super(fd, active); - // As we create an EpollServerSocketChannel from a FileDescriptor we should try to obtain the remote and local - // address from it. This is needed as the FileDescriptor may be bound already. - local = fd.localAddress(); - config = new EpollServerSocketChannelConfig(this); - } - - @Override - protected boolean isCompatible(EventLoop loop) { - return loop instanceof EpollEventLoop; - } - - @Override - protected void doBind(SocketAddress localAddress) throws Exception { - InetSocketAddress addr = (InetSocketAddress) localAddress; - checkResolvable(addr); - fd().bind(addr); - local = fd().localAddress(); - if (Native.IS_SUPPORTING_TCP_FASTOPEN && config.getTcpFastopen() > 0) { - Native.setTcpFastopen(fd().intValue(), config.getTcpFastopen()); - } - fd().listen(config.getBacklog()); - active = true; - } - - @Override - public InetSocketAddress remoteAddress() { - return (InetSocketAddress) super.remoteAddress(); - } - - @Override - public InetSocketAddress localAddress() { - return (InetSocketAddress) super.localAddress(); - } - - @Override - public EpollServerSocketChannelConfig config() { - return config; - } - - @Override - protected InetSocketAddress localAddress0() { - return local; - } - - @Override - protected Channel newChildChannel(int fd, byte[] address, int offset, int len) throws Exception { - return new EpollSocketChannel(this, new Socket(fd), address(address, offset, len)); - } - - Collection tcpMd5SigAddresses() { - return tcpMd5SigAddresses; - } - - void setTcpMd5Sig(Map keys) { - this.tcpMd5SigAddresses = TcpMd5Util.newTcpMd5Sigs(this, tcpMd5SigAddresses, keys); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollServerSocketChannelConfig.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollServerSocketChannelConfig.java deleted file mode 100755 index 7fd40064b3..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollServerSocketChannelConfig.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.epoll; - -import java.net.InetAddress; -import java.util.Map; - -import com.ai.cloud.io.netty.buffer.ByteBufAllocator; -import com.ai.cloud.io.netty.channel.ChannelOption; -import com.ai.cloud.io.netty.channel.MessageSizeEstimator; -import com.ai.cloud.io.netty.channel.RecvByteBufAllocator; -import com.ai.cloud.io.netty.channel.socket.ServerSocketChannelConfig; - -public final class EpollServerSocketChannelConfig extends EpollServerChannelConfig - implements ServerSocketChannelConfig { - - EpollServerSocketChannelConfig(EpollServerSocketChannel channel) { - super(channel); - - // Use SO_REUSEADDR by default as java.nio does the same. - // - // See https://github.com/netty/netty/issues/2605 - setReuseAddress(true); - } - - @Override - public Map, Object> getOptions() { - return getOptions(super.getOptions(), EpollChannelOption.SO_REUSEPORT, EpollChannelOption.IP_FREEBIND); - } - - @SuppressWarnings("unchecked") - @Override - public T getOption(ChannelOption option) { - if (option == EpollChannelOption.SO_REUSEPORT) { - return (T) Boolean.valueOf(isReusePort()); - } - if (option == EpollChannelOption.IP_FREEBIND) { - return (T) Boolean.valueOf(isFreeBind()); - } - return super.getOption(option); - } - - @Override - public boolean setOption(ChannelOption option, T value) { - validate(option, value); - - if (option == EpollChannelOption.SO_REUSEPORT) { - setReusePort((Boolean) value); - } else if (option == EpollChannelOption.IP_FREEBIND) { - setFreeBind((Boolean) value); - } else if (option == EpollChannelOption.TCP_MD5SIG) { - @SuppressWarnings("unchecked") - final Map m = (Map) value; - setTcpMd5Sig(m); - } else { - return super.setOption(option, value); - } - - return true; - } - - @Override - public EpollServerSocketChannelConfig setReuseAddress(boolean reuseAddress) { - super.setReuseAddress(reuseAddress); - return this; - } - - @Override - public EpollServerSocketChannelConfig setReceiveBufferSize(int receiveBufferSize) { - super.setReceiveBufferSize(receiveBufferSize); - return this; - } - - @Override - public EpollServerSocketChannelConfig setPerformancePreferences(int connectionTime, int latency, int bandwidth) { - return this; - } - - @Override - public EpollServerSocketChannelConfig setBacklog(int backlog) { - super.setBacklog(backlog); - return this; - } - - @Override - public EpollServerSocketChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis) { - super.setConnectTimeoutMillis(connectTimeoutMillis); - return this; - } - - @Override - public EpollServerSocketChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead) { - super.setMaxMessagesPerRead(maxMessagesPerRead); - return this; - } - - @Override - public EpollServerSocketChannelConfig setWriteSpinCount(int writeSpinCount) { - super.setWriteSpinCount(writeSpinCount); - return this; - } - - @Override - public EpollServerSocketChannelConfig setAllocator(ByteBufAllocator allocator) { - super.setAllocator(allocator); - return this; - } - - @Override - public EpollServerSocketChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator) { - super.setRecvByteBufAllocator(allocator); - return this; - } - - @Override - public EpollServerSocketChannelConfig setAutoRead(boolean autoRead) { - super.setAutoRead(autoRead); - return this; - } - - @Override - public EpollServerSocketChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) { - super.setWriteBufferHighWaterMark(writeBufferHighWaterMark); - return this; - } - - @Override - public EpollServerSocketChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark) { - super.setWriteBufferLowWaterMark(writeBufferLowWaterMark); - return this; - } - - @Override - public EpollServerSocketChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator) { - super.setMessageSizeEstimator(estimator); - return this; - } - - /** - * Set the {@code TCP_MD5SIG} option on the socket. See {@code linux/tcp.h} for more details. - * Keys can only be set on, not read to prevent a potential leak, as they are confidential. - * Allowing them being read would mean anyone with access to the channel could get them. - */ - public EpollServerSocketChannelConfig setTcpMd5Sig(Map keys) { - ((EpollServerSocketChannel) channel).setTcpMd5Sig(keys); - return this; - } - - /** - * Returns {@code true} if the SO_REUSEPORT option is set. - */ - public boolean isReusePort() { - return Native.isReusePort(channel.fd().intValue()) == 1; - } - - /** - * Set the SO_REUSEPORT option on the underlying Channel. This will allow to bind multiple - * {@link EpollSocketChannel}s to the same port and so accept connections with multiple threads. - * - * Be aware this method needs be called before {@link EpollSocketChannel#bind(java.net.SocketAddress)} to have - * any affect. - */ - public EpollServerSocketChannelConfig setReusePort(boolean reusePort) { - Native.setReusePort(channel.fd().intValue(), reusePort ? 1 : 0); - return this; - } - - /** - * Returns {@code true} if IP_FREEBIND is enabled, - * {@code false} otherwise. - */ - public boolean isFreeBind() { - return Native.isIpFreeBind(channel.fd().intValue()) != 0; - } - - /** - * If {@code true} is used IP_FREEBIND is enabled, - * {@code false} for disable it. Default is disabled. - */ - public EpollServerSocketChannelConfig setFreeBind(boolean freeBind) { - Native.setIpFreeBind(channel.fd().intValue(), freeBind ? 1: 0); - return this; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollSocketChannel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollSocketChannel.java deleted file mode 100755 index 440a8ac315..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollSocketChannel.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.epoll; - -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.util.Collection; -import java.util.Collections; -import java.util.Map; -import java.util.concurrent.Executor; - -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelFuture; -import com.ai.cloud.io.netty.channel.ChannelPromise; -import com.ai.cloud.io.netty.channel.EventLoop; -import com.ai.cloud.io.netty.channel.socket.ServerSocketChannel; -import com.ai.cloud.io.netty.channel.socket.SocketChannel; -import com.ai.cloud.io.netty.channel.unix.FileDescriptor; -import com.ai.cloud.io.netty.channel.unix.Socket; -import com.ai.cloud.io.netty.util.concurrent.GlobalEventExecutor; -import com.ai.cloud.io.netty.util.internal.OneTimeTask; - -import static com.ai.cloud.io.netty.channel.unix.Socket.newSocketStream; - -/** - * {@link SocketChannel} implementation that uses linux EPOLL Edge-Triggered Mode for - * maximal performance. - */ -public final class EpollSocketChannel extends AbstractEpollStreamChannel implements SocketChannel { - - private final EpollSocketChannelConfig config; - - private volatile InetSocketAddress local; - private volatile InetSocketAddress remote; - private volatile Collection tcpMd5SigAddresses = Collections.emptyList(); - - EpollSocketChannel(Channel parent, Socket fd, InetSocketAddress remote) { - super(parent, fd); - config = new EpollSocketChannelConfig(this); - // Directly cache the remote and local addresses - // See https://github.com/netty/netty/issues/2359 - this.remote = remote; - local = fd.localAddress(); - - if (parent instanceof EpollServerSocketChannel) { - tcpMd5SigAddresses = ((EpollServerSocketChannel) parent).tcpMd5SigAddresses(); - } - } - - public EpollSocketChannel() { - super(newSocketStream(), false); - config = new EpollSocketChannelConfig(this); - } - - /** - * @deprecated Use {@link #EpollSocketChannel(Socket, boolean)}. - */ - @Deprecated - public EpollSocketChannel(FileDescriptor fd) { - super(fd); - // As we create an EpollSocketChannel from a FileDescriptor we should try to obtain the remote and local - // address from it. This is needed as the FileDescriptor may be bound/connected already. - remote = fd().remoteAddress(); - local = fd().localAddress(); - config = new EpollSocketChannelConfig(this); - } - - /** - * Creates a new {@link EpollSocketChannel} from an existing {@link FileDescriptor}. - */ - public EpollSocketChannel(Socket fd, boolean active) { - super(fd, active); - // As we create an EpollSocketChannel from a FileDescriptor we should try to obtain the remote and local - // address from it. This is needed as the FileDescriptor may be bound/connected already. - remote = fd.remoteAddress(); - local = fd.localAddress(); - config = new EpollSocketChannelConfig(this); - } - - /** - * Returns the {@code TCP_INFO} for the current socket. See man 7 tcp. - */ - public EpollTcpInfo tcpInfo() { - return tcpInfo(new EpollTcpInfo()); - } - - /** - * Updates and returns the {@code TCP_INFO} for the current socket. - * See man 7 tcp. - */ - public EpollTcpInfo tcpInfo(EpollTcpInfo info) { - Native.tcpInfo(fd().intValue(), info); - return info; - } - - @Override - public InetSocketAddress remoteAddress() { - return (InetSocketAddress) super.remoteAddress(); - } - - @Override - public InetSocketAddress localAddress() { - return (InetSocketAddress) super.localAddress(); - } - - @Override - protected SocketAddress localAddress0() { - return local; - } - - @Override - protected SocketAddress remoteAddress0() { - if (remote == null) { - // Remote address not know, try to get it now. - InetSocketAddress address = fd().remoteAddress(); - if (address != null) { - remote = address; - } - return address; - } - return remote; - } - - @Override - protected void doBind(SocketAddress local) throws Exception { - InetSocketAddress localAddress = (InetSocketAddress) local; - fd().bind(localAddress); - this.local = fd().localAddress(); - } - - @Override - public EpollSocketChannelConfig config() { - return config; - } - - @Override - public boolean isInputShutdown() { - return fd().isInputShutdown(); - } - - @Override - public boolean isOutputShutdown() { - return fd().isOutputShutdown(); - } - - @Override - public ChannelFuture shutdownOutput() { - return shutdownOutput(newPromise()); - } - - @Override - public ChannelFuture shutdownOutput(final ChannelPromise promise) { - Executor closeExecutor = ((EpollSocketChannelUnsafe) unsafe()).closeExecutor(); - if (closeExecutor != null) { - closeExecutor.execute(new OneTimeTask() { - @Override - public void run() { - shutdownOutput0(promise); - } - }); - } else { - EventLoop loop = eventLoop(); - if (loop.inEventLoop()) { - shutdownOutput0(promise); - } else { - loop.execute(new OneTimeTask() { - @Override - public void run() { - shutdownOutput0(promise); - } - }); - } - } - return promise; - } - - @Override - public ServerSocketChannel parent() { - return (ServerSocketChannel) super.parent(); - } - - @Override - protected AbstractEpollUnsafe newUnsafe() { - return new EpollSocketChannelUnsafe(); - } - - @Override - protected boolean doConnect(SocketAddress remoteAddress, SocketAddress localAddress) throws Exception { - if (localAddress != null) { - checkResolvable((InetSocketAddress) localAddress); - } - checkResolvable((InetSocketAddress) remoteAddress); - boolean connected = super.doConnect(remoteAddress, localAddress); - if (connected) { - remote = (InetSocketAddress) remoteAddress; - return true; - } - // We always need to set the localAddress even if not connected yet - // - // See https://github.com/netty/netty/issues/3463 - local = fd().localAddress(); - return connected; - } - - private final class EpollSocketChannelUnsafe extends EpollStreamUnsafe { - @Override - protected Executor closeExecutor() { - // Check isOpen() first as otherwise it will throw a RuntimeException - // when call getSoLinger() as the fd is not valid anymore. - if (isOpen() && config().getSoLinger() > 0) { - return GlobalEventExecutor.INSTANCE; - } - return null; - } - } - - void setTcpMd5Sig(Map keys) { - this.tcpMd5SigAddresses = TcpMd5Util.newTcpMd5Sigs(this, tcpMd5SigAddresses, keys); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollSocketChannelConfig.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollSocketChannelConfig.java deleted file mode 100755 index 4c2ba4d476..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollSocketChannelConfig.java +++ /dev/null @@ -1,412 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.epoll; - -import java.net.InetAddress; -import java.util.Map; - -import com.ai.cloud.io.netty.buffer.ByteBufAllocator; -import com.ai.cloud.io.netty.channel.ChannelOption; -import com.ai.cloud.io.netty.channel.MessageSizeEstimator; -import com.ai.cloud.io.netty.channel.RecvByteBufAllocator; -import com.ai.cloud.io.netty.channel.socket.SocketChannelConfig; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - -import static com.ai.cloud.io.netty.channel.ChannelOption.*; - -public final class EpollSocketChannelConfig extends EpollChannelConfig implements SocketChannelConfig { - private static final long MAX_UINT32_T = 0xFFFFFFFFL; - private final EpollSocketChannel channel; - private volatile boolean allowHalfClosure; - - /** - * Creates a new instance. - */ - EpollSocketChannelConfig(EpollSocketChannel channel) { - super(channel); - - this.channel = channel; - if (PlatformDependent.canEnableTcpNoDelayByDefault()) { - setTcpNoDelay(true); - } - } - - @Override - public Map, Object> getOptions() { - return getOptions( - super.getOptions(), - SO_RCVBUF, SO_SNDBUF, TCP_NODELAY, SO_KEEPALIVE, SO_REUSEADDR, SO_LINGER, IP_TOS, - ALLOW_HALF_CLOSURE, EpollChannelOption.TCP_CORK, EpollChannelOption.TCP_NOTSENT_LOWAT, - EpollChannelOption.TCP_KEEPCNT, EpollChannelOption.TCP_KEEPIDLE, EpollChannelOption.TCP_KEEPINTVL, - EpollChannelOption.TCP_MD5SIG); - } - - @SuppressWarnings("unchecked") - @Override - public T getOption(ChannelOption option) { - if (option == SO_RCVBUF) { - return (T) Integer.valueOf(getReceiveBufferSize()); - } - if (option == SO_SNDBUF) { - return (T) Integer.valueOf(getSendBufferSize()); - } - if (option == TCP_NODELAY) { - return (T) Boolean.valueOf(isTcpNoDelay()); - } - if (option == SO_KEEPALIVE) { - return (T) Boolean.valueOf(isKeepAlive()); - } - if (option == SO_REUSEADDR) { - return (T) Boolean.valueOf(isReuseAddress()); - } - if (option == SO_LINGER) { - return (T) Integer.valueOf(getSoLinger()); - } - if (option == IP_TOS) { - return (T) Integer.valueOf(getTrafficClass()); - } - if (option == ALLOW_HALF_CLOSURE) { - return (T) Boolean.valueOf(isAllowHalfClosure()); - } - if (option == EpollChannelOption.TCP_CORK) { - return (T) Boolean.valueOf(isTcpCork()); - } - if (option == EpollChannelOption.TCP_NOTSENT_LOWAT) { - return (T) Long.valueOf(getTcpNotSentLowAt()); - } - if (option == EpollChannelOption.TCP_KEEPIDLE) { - return (T) Integer.valueOf(getTcpKeepIdle()); - } - if (option == EpollChannelOption.TCP_KEEPINTVL) { - return (T) Integer.valueOf(getTcpKeepIntvl()); - } - if (option == EpollChannelOption.TCP_KEEPCNT) { - return (T) Integer.valueOf(getTcpKeepCnt()); - } - if (option == EpollChannelOption.TCP_USER_TIMEOUT) { - return (T) Integer.valueOf(getTcpUserTimeout()); - } - return super.getOption(option); - } - - @Override - public boolean setOption(ChannelOption option, T value) { - validate(option, value); - - if (option == SO_RCVBUF) { - setReceiveBufferSize((Integer) value); - } else if (option == SO_SNDBUF) { - setSendBufferSize((Integer) value); - } else if (option == TCP_NODELAY) { - setTcpNoDelay((Boolean) value); - } else if (option == SO_KEEPALIVE) { - setKeepAlive((Boolean) value); - } else if (option == SO_REUSEADDR) { - setReuseAddress((Boolean) value); - } else if (option == SO_LINGER) { - setSoLinger((Integer) value); - } else if (option == IP_TOS) { - setTrafficClass((Integer) value); - } else if (option == ALLOW_HALF_CLOSURE) { - setAllowHalfClosure((Boolean) value); - } else if (option == EpollChannelOption.TCP_CORK) { - setTcpCork((Boolean) value); - } else if (option == EpollChannelOption.TCP_NOTSENT_LOWAT) { - setTcpNotSentLowAt((Long) value); - } else if (option == EpollChannelOption.TCP_KEEPIDLE) { - setTcpKeepIdle((Integer) value); - } else if (option == EpollChannelOption.TCP_KEEPCNT) { - setTcpKeepCntl((Integer) value); - } else if (option == EpollChannelOption.TCP_KEEPINTVL) { - setTcpKeepIntvl((Integer) value); - } else if (option == EpollChannelOption.TCP_USER_TIMEOUT) { - setTcpUserTimeout((Integer) value); - } else if (option == EpollChannelOption.TCP_MD5SIG) { - @SuppressWarnings("unchecked") - final Map m = (Map) value; - setTcpMd5Sig(m); - } else { - return super.setOption(option, value); - } - - return true; - } - - @Override - public int getReceiveBufferSize() { - return channel.fd().getReceiveBufferSize(); - } - - @Override - public int getSendBufferSize() { - return channel.fd().getSendBufferSize(); - } - - @Override - public int getSoLinger() { - return channel.fd().getSoLinger(); - } - - @Override - public int getTrafficClass() { - return Native.getTrafficClass(channel.fd().intValue()); - } - - @Override - public boolean isKeepAlive() { - return channel.fd().isKeepAlive(); - } - - @Override - public boolean isReuseAddress() { - return Native.isReuseAddress(channel.fd().intValue()) == 1; - } - - @Override - public boolean isTcpNoDelay() { - return channel.fd().isTcpNoDelay(); - } - - /** - * Get the {@code TCP_CORK} option on the socket. See {@code man 7 tcp} for more details. - */ - public boolean isTcpCork() { - return channel.fd().isTcpCork(); - } - - /** - * Get the {@code TCP_NOTSENT_LOWAT} option on the socket. See {@code man 7 tcp} for more details. - * @return value is a uint32_t - */ - public long getTcpNotSentLowAt() { - return Native.getTcpNotSentLowAt(channel.fd().intValue()) & MAX_UINT32_T; - } - - /** - * Get the {@code TCP_KEEPIDLE} option on the socket. See {@code man 7 tcp} for more details. - */ - public int getTcpKeepIdle() { - return Native.getTcpKeepIdle(channel.fd().intValue()); - } - - /** - * Get the {@code TCP_KEEPINTVL} option on the socket. See {@code man 7 tcp} for more details. - */ - public int getTcpKeepIntvl() { - return Native.getTcpKeepIntvl(channel.fd().intValue()); - } - - /** - * Get the {@code TCP_KEEPCNT} option on the socket. See {@code man 7 tcp} for more details. - */ - public int getTcpKeepCnt() { - return Native.getTcpKeepCnt(channel.fd().intValue()); - } - - /** - * Get the {@code TCP_USER_TIMEOUT} option on the socket. See {@code man 7 tcp} for more details. - */ - public int getTcpUserTimeout() { - return Native.getTcpUserTimeout(channel.fd().intValue()); - } - - @Override - public EpollSocketChannelConfig setKeepAlive(boolean keepAlive) { - channel.fd().setKeepAlive(keepAlive); - return this; - } - - @Override - public EpollSocketChannelConfig setPerformancePreferences( - int connectionTime, int latency, int bandwidth) { - return this; - } - - @Override - public EpollSocketChannelConfig setReceiveBufferSize(int receiveBufferSize) { - channel.fd().setReceiveBufferSize(receiveBufferSize); - return this; - } - - @Override - public EpollSocketChannelConfig setReuseAddress(boolean reuseAddress) { - Native.setReuseAddress(channel.fd().intValue(), reuseAddress ? 1 : 0); - return this; - } - - @Override - public EpollSocketChannelConfig setSendBufferSize(int sendBufferSize) { - channel.fd().setSendBufferSize(sendBufferSize); - return this; - } - - @Override - public EpollSocketChannelConfig setSoLinger(int soLinger) { - channel.fd().setSoLinger(soLinger); - return this; - } - - @Override - public EpollSocketChannelConfig setTcpNoDelay(boolean tcpNoDelay) { - channel.fd().setTcpNoDelay(tcpNoDelay); - return this; - } - - /** - * Set the {@code TCP_CORK} option on the socket. See {@code man 7 tcp} for more details. - */ - public EpollSocketChannelConfig setTcpCork(boolean tcpCork) { - channel.fd().setTcpCork(tcpCork); - return this; - } - - /** - * Set the {@code TCP_NOTSENT_LOWAT} option on the socket. See {@code man 7 tcp} for more details. - * @param tcpNotSentLowAt is a uint32_t - */ - public EpollSocketChannelConfig setTcpNotSentLowAt(long tcpNotSentLowAt) { - if (tcpNotSentLowAt < 0 || tcpNotSentLowAt > MAX_UINT32_T) { - throw new IllegalArgumentException("tcpNotSentLowAt must be a uint32_t"); - } - Native.setTcpNotSentLowAt(channel.fd().intValue(), (int) tcpNotSentLowAt); - return this; - } - - @Override - public EpollSocketChannelConfig setTrafficClass(int trafficClass) { - Native.setTrafficClass(channel.fd().intValue(), trafficClass); - return this; - } - - /** - * Set the {@code TCP_KEEPIDLE} option on the socket. See {@code man 7 tcp} for more details. - */ - public EpollSocketChannelConfig setTcpKeepIdle(int seconds) { - Native.setTcpKeepIdle(channel.fd().intValue(), seconds); - return this; - } - - /** - * Set the {@code TCP_KEEPINTVL} option on the socket. See {@code man 7 tcp} for more details. - */ - public EpollSocketChannelConfig setTcpKeepIntvl(int seconds) { - Native.setTcpKeepIntvl(channel.fd().intValue(), seconds); - return this; - } - - /** - * Set the {@code TCP_KEEPCNT} option on the socket. See {@code man 7 tcp} for more details. - */ - public EpollSocketChannelConfig setTcpKeepCntl(int probes) { - Native.setTcpKeepCnt(channel.fd().intValue(), probes); - return this; - } - - /** - * Set the {@code TCP_USER_TIMEOUT} option on the socket. See {@code man 7 tcp} for more details. - */ - public EpollSocketChannelConfig setTcpUserTimeout(int milliseconds) { - Native.setTcpUserTimeout(channel.fd().intValue(), milliseconds); - return this; - } - - /* - * Set the {@code TCP_MD5SIG} option on the socket. See {@code linux/tcp.h} for more details. - * Keys can only be set on, not read to prevent a potential leak, as they are confidential. - * Allowing them being read would mean anyone with access to the channel could get them. - */ - public EpollSocketChannelConfig setTcpMd5Sig(Map keys) { - channel.setTcpMd5Sig(keys); - return this; - } - - @Override - public boolean isAllowHalfClosure() { - return allowHalfClosure; - } - - @Override - public EpollSocketChannelConfig setAllowHalfClosure(boolean allowHalfClosure) { - this.allowHalfClosure = allowHalfClosure; - return this; - } - - @Override - public EpollSocketChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis) { - super.setConnectTimeoutMillis(connectTimeoutMillis); - return this; - } - - @Override - public EpollSocketChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead) { - super.setMaxMessagesPerRead(maxMessagesPerRead); - return this; - } - - @Override - public EpollSocketChannelConfig setWriteSpinCount(int writeSpinCount) { - super.setWriteSpinCount(writeSpinCount); - return this; - } - - @Override - public EpollSocketChannelConfig setAllocator(ByteBufAllocator allocator) { - super.setAllocator(allocator); - return this; - } - - @Override - public EpollSocketChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator) { - super.setRecvByteBufAllocator(allocator); - return this; - } - - @Override - public EpollSocketChannelConfig setAutoRead(boolean autoRead) { - super.setAutoRead(autoRead); - return this; - } - - @Override - public EpollSocketChannelConfig setAutoClose(boolean autoClose) { - super.setAutoClose(autoClose); - return this; - } - - @Override - public EpollSocketChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) { - super.setWriteBufferHighWaterMark(writeBufferHighWaterMark); - return this; - } - - @Override - public EpollSocketChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark) { - super.setWriteBufferLowWaterMark(writeBufferLowWaterMark); - return this; - } - - @Override - public EpollSocketChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator) { - super.setMessageSizeEstimator(estimator); - return this; - } - - @Override - public EpollSocketChannelConfig setEpollMode(EpollMode mode) { - super.setEpollMode(mode); - return this; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollTcpInfo.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollTcpInfo.java deleted file mode 100755 index 85f1fdd548..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/EpollTcpInfo.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.epoll; - -/** - *

- * struct tcp_info - * { - * __u8 tcpi_state; - * __u8 tcpi_ca_state; - * __u8 tcpi_retransmits; - * __u8 tcpi_probes; - * __u8 tcpi_backoff; - * __u8 tcpi_options; - * __u8 tcpi_snd_wscale : 4, tcpi_rcv_wscale : 4; - * - * __u32 tcpi_rto; - * __u32 tcpi_ato; - * __u32 tcpi_snd_mss; - * __u32 tcpi_rcv_mss; - * - * __u32 tcpi_unacked; - * __u32 tcpi_sacked; - * __u32 tcpi_lost; - * __u32 tcpi_retrans; - * __u32 tcpi_fackets; - * - * __u32 tcpi_last_data_sent; - * __u32 tcpi_last_ack_sent; - * __u32 tcpi_last_data_recv; - * __u32 tcpi_last_ack_recv; - * - * __u32 tcpi_pmtu; - * __u32 tcpi_rcv_ssthresh; - * __u32 tcpi_rtt; - * __u32 tcpi_rttvar; - * __u32 tcpi_snd_ssthresh; - * __u32 tcpi_snd_cwnd; - * __u32 tcpi_advmss; - * __u32 tcpi_reordering; - * - * __u32 tcpi_rcv_rtt; - * __u32 tcpi_rcv_space; - * - * __u32 tcpi_total_retrans; - * }; - *

- */ -public final class EpollTcpInfo { - - final int[] info = new int[32]; - - public int state() { - return info[0] & 0xFF; - } - - public int caState() { - return info[1] & 0xFF; - } - - public int retransmits() { - return info[2] & 0xFF; - } - - public int probes() { - return info[3] & 0xFF; - } - - public int backoff() { - return info[4] & 0xFF; - } - - public int options() { - return info[5] & 0xFF; - } - - public int sndWscale() { - return info[6] & 0xFF; - } - - public int rcvWscale() { - return info[7] & 0xFF; - } - - public long rto() { - return info[8] & 0xFFFFFFFFL; - } - - public long ato() { - return info[9] & 0xFFFFFFFFL; - } - - public long sndMss() { - return info[10] & 0xFFFFFFFFL; - } - - public long rcvMss() { - return info[11] & 0xFFFFFFFFL; - } - - public long unacked() { - return info[12] & 0xFFFFFFFFL; - } - - public long sacked() { - return info[13] & 0xFFFFFFFFL; - } - - public long lost() { - return info[14] & 0xFFFFFFFFL; - } - - public long retrans() { - return info[15] & 0xFFFFFFFFL; - } - - public long fackets() { - return info[16] & 0xFFFFFFFFL; - } - - public long lastDataSent() { - return info[17] & 0xFFFFFFFFL; - } - - public long lastAckSent() { - return info[18] & 0xFFFFFFFFL; - } - - public long lastDataRecv() { - return info[19] & 0xFFFFFFFFL; - } - - public long lastAckRecv() { - return info[20] & 0xFFFFFFFFL; - } - - public long pmtu() { - return info[21] & 0xFFFFFFFFL; - } - - public long rcvSsthresh() { - return info[22] & 0xFFFFFFFFL; - } - - public long rtt() { - return info[23] & 0xFFFFFFFFL; - } - - public long rttvar() { - return info[24] & 0xFFFFFFFFL; - } - - public long sndSsthresh() { - return info[25] & 0xFFFFFFFFL; - } - - public long sndCwnd() { - return info[26] & 0xFFFFFFFFL; - } - - public long advmss() { - return info[27] & 0xFFFFFFFFL; - } - - public long reordering() { - return info[28] & 0xFFFFFFFFL; - } - - public long rcvRtt() { - return info[29] & 0xFFFFFFFFL; - } - - public long rcvSpace() { - return info[30] & 0xFFFFFFFFL; - } - - public long totalRetrans() { - return info[31] & 0xFFFFFFFFL; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/IovArray.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/IovArray.java deleted file mode 100755 index 5ece517704..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/IovArray.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.epoll; - -import java.nio.ByteBuffer; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.CompositeByteBuf; -import com.ai.cloud.io.netty.channel.ChannelOutboundBuffer.MessageProcessor; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - -/** - * Represent an array of struct array and so can be passed directly over via JNI without the need to do any more - * array copies. - * - * The buffers are written out directly into direct memory to match the struct iov. See also {@code man writev}. - * - *
- * struct iovec {
- *   void  *iov_base;
- *   size_t iov_len;
- * };
- * 
- * - * See also - * Efficient JNI programming IV: Wrapping native data objects. - */ -final class IovArray implements MessageProcessor { - - /** The size of an address which should be 8 for 64 bits and 4 for 32 bits. */ - private static final int ADDRESS_SIZE = PlatformDependent.addressSize(); - - /** - * The size of an {@code iovec} struct in bytes. This is calculated as we have 2 entries each of the size of the - * address. - */ - private static final int IOV_SIZE = 2 * ADDRESS_SIZE; - - /** - * The needed memory to hold up to {@link Native#IOV_MAX} iov entries, where {@link Native#IOV_MAX} signified - * the maximum number of {@code iovec} structs that can be passed to {@code writev(...)}. - */ - private static final int CAPACITY = Native.IOV_MAX * IOV_SIZE; - - private final long memoryAddress; - private int count; - private long size; - - IovArray() { - memoryAddress = PlatformDependent.allocateMemory(CAPACITY); - } - - void clear() { - count = 0; - size = 0; - } - - /** - * Try to add the given {@link ByteBuf}. Returns {@code true} on success, - * {@code false} otherwise. - */ - boolean add(ByteBuf buf) { - if (count == Native.IOV_MAX) { - // No more room! - return false; - } - - final int len = buf.readableBytes(); - if (len == 0) { - // No need to add an empty buffer. - // We return true here because we want ChannelOutboundBuffer.forEachFlushedMessage() to continue - // fetching the next buffers. - return true; - } - - final long addr = buf.memoryAddress(); - final int offset = buf.readerIndex(); - return add(addr, offset, len); - } - - private boolean add(long addr, int offset, int len) { - if (len == 0) { - // No need to add an empty buffer. - return true; - } - - final long baseOffset = memoryAddress(count++); - final long lengthOffset = baseOffset + ADDRESS_SIZE; - - if (Native.SSIZE_MAX - len < size) { - // If the size + len will overflow an SSIZE_MAX we stop populate the IovArray. This is done as linux - // not allow to write more bytes then SSIZE_MAX with one writev(...) call and so will - // return 'EINVAL', which will raise an IOException. - // - // See also: - // - http://linux.die.net/man/2/writev - return false; - } - size += len; - - if (ADDRESS_SIZE == 8) { - // 64bit - PlatformDependent.putLong(baseOffset, addr + offset); - PlatformDependent.putLong(lengthOffset, len); - } else { - assert ADDRESS_SIZE == 4; - PlatformDependent.putInt(baseOffset, (int) addr + offset); - PlatformDependent.putInt(lengthOffset, len); - } - return true; - } - - /** - * Try to add the given {@link CompositeByteBuf}. Returns {@code true} on success, - * {@code false} otherwise. - */ - boolean add(CompositeByteBuf buf) { - ByteBuffer[] buffers = buf.nioBuffers(); - if (count + buffers.length >= Native.IOV_MAX) { - // No more room! - return false; - } - for (int i = 0; i < buffers.length; i++) { - ByteBuffer nioBuffer = buffers[i]; - int offset = nioBuffer.position(); - int len = nioBuffer.limit() - nioBuffer.position(); - if (len == 0) { - // No need to add an empty buffer so just continue - continue; - } - long addr = PlatformDependent.directBufferAddress(nioBuffer); - - if (!add(addr, offset, len)) { - return false; - } - } - return true; - } - - /** - * Process the written iov entries. This will return the length of the iov entry on the given index if it is - * smaller then the given {@code written} value. Otherwise it returns {@code -1}. - */ - long processWritten(int index, long written) { - long baseOffset = memoryAddress(index); - long lengthOffset = baseOffset + ADDRESS_SIZE; - if (ADDRESS_SIZE == 8) { - // 64bit - long len = PlatformDependent.getLong(lengthOffset); - if (len > written) { - long offset = PlatformDependent.getLong(baseOffset); - PlatformDependent.putLong(baseOffset, offset + written); - PlatformDependent.putLong(lengthOffset, len - written); - return -1; - } - return len; - } else { - assert ADDRESS_SIZE == 4; - long len = PlatformDependent.getInt(lengthOffset); - if (len > written) { - int offset = PlatformDependent.getInt(baseOffset); - PlatformDependent.putInt(baseOffset, (int) (offset + written)); - PlatformDependent.putInt(lengthOffset, (int) (len - written)); - return -1; - } - return len; - } - } - - /** - * Returns the number if iov entries. - */ - int count() { - return count; - } - - /** - * Returns the size in bytes - */ - long size() { - return size; - } - - /** - * Returns the {@code memoryAddress} for the given {@code offset}. - */ - long memoryAddress(int offset) { - return memoryAddress + IOV_SIZE * offset; - } - - /** - * Release the {@link IovArray}. Once release further using of it may crash the JVM! - */ - void release() { - PlatformDependent.freeMemory(memoryAddress); - } - - @Override - public boolean processMessage(Object msg) throws Exception { - if (msg instanceof ByteBuf) { - if (msg instanceof CompositeByteBuf) { - return add((CompositeByteBuf) msg); - } else { - return add((ByteBuf) msg); - } - } - return false; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/IovArrayThreadLocal.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/IovArrayThreadLocal.java deleted file mode 100755 index c2da5ca670..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/IovArrayThreadLocal.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.epoll; - -import com.ai.cloud.io.netty.buffer.CompositeByteBuf; -import com.ai.cloud.io.netty.channel.ChannelOutboundBuffer; -import com.ai.cloud.io.netty.util.concurrent.FastThreadLocal; - -/** - * Allow to obtain {@link IovArray} instances. - */ -final class IovArrayThreadLocal { - - private static final FastThreadLocal ARRAY = new FastThreadLocal() { - @Override - protected IovArray initialValue() throws Exception { - return new IovArray(); - } - - @Override - protected void onRemoval(IovArray value) throws Exception { - // free the direct memory now - value.release(); - } - }; - - /** - * Returns a {@link IovArray} which is filled with the flushed messages of {@link ChannelOutboundBuffer}. - */ - static IovArray get(ChannelOutboundBuffer buffer) throws Exception { - IovArray array = ARRAY.get(); - array.clear(); - buffer.forEachFlushedMessage(array); - return array; - } - - /** - * Returns a {@link IovArray} which is filled with the {@link CompositeByteBuf}. - */ - static IovArray get(CompositeByteBuf buf) throws Exception { - IovArray array = ARRAY.get(); - array.clear(); - array.add(buf); - return array; - } - - private IovArrayThreadLocal() { } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/Native.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/Native.java deleted file mode 100755 index 97d9a6aa73..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/Native.java +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.epoll; - -import java.io.IOException; -import java.net.InetAddress; -import java.util.Locale; - -import com.ai.cloud.io.netty.channel.DefaultFileRegion; -import com.ai.cloud.io.netty.channel.unix.FileDescriptor; -import com.ai.cloud.io.netty.channel.unix.NativeInetAddress; -import com.ai.cloud.io.netty.channel.unix.Errors.NativeIoException; -import com.ai.cloud.io.netty.util.internal.NativeLibraryLoader; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; -import com.ai.cloud.io.netty.util.internal.SystemPropertyUtil; - -import static com.ai.cloud.io.netty.channel.unix.Errors.ERRNO_EAGAIN_NEGATIVE; -import static com.ai.cloud.io.netty.channel.unix.Errors.ERRNO_EPIPE_NEGATIVE; -import static com.ai.cloud.io.netty.channel.unix.Errors.ERRNO_EWOULDBLOCK_NEGATIVE; -import static com.ai.cloud.io.netty.channel.unix.Errors.ioResult; -import static com.ai.cloud.io.netty.channel.unix.Errors.newConnectionResetException; -import static com.ai.cloud.io.netty.channel.unix.Errors.newIOException; - -/** - * Native helper methods - * - * Internal usage only! - */ -public final class Native { - static { - String name = SystemPropertyUtil.get("os.name").toLowerCase(Locale.UK).trim(); - if (!name.startsWith("linux")) { - throw new IllegalStateException("Only supported on Linux"); - } - NativeLibraryLoader.load("netty-transport-native-epoll", PlatformDependent.getClassLoader(Native.class)); - } - - // EventLoop operations and constants - public static final int EPOLLIN = epollin(); - public static final int EPOLLOUT = epollout(); - public static final int EPOLLRDHUP = epollrdhup(); - public static final int EPOLLET = epollet(); - public static final int EPOLLERR = epollerr(); - - public static final int IOV_MAX = iovMax(); - public static final int UIO_MAX_IOV = uioMaxIov(); - public static final boolean IS_SUPPORTING_SENDMMSG = isSupportingSendmmsg(); - public static final boolean IS_SUPPORTING_TCP_FASTOPEN = isSupportingTcpFastopen(); - public static final long SSIZE_MAX = ssizeMax(); - public static final int TCP_MD5SIG_MAXKEYLEN = tcpMd5SigMaxKeyLen(); - - private static final NativeIoException CONNECTION_RESET_EXCEPTION_SENDFILE; - private static final NativeIoException CONNECTION_RESET_EXCEPTION_SENDMMSG; - private static final NativeIoException CONNECTION_RESET_EXCEPTION_SPLICE; - - static { - CONNECTION_RESET_EXCEPTION_SENDFILE = newConnectionResetException("syscall:sendfile(...)", - ERRNO_EPIPE_NEGATIVE); - CONNECTION_RESET_EXCEPTION_SENDMMSG = newConnectionResetException("syscall:sendmmsg(...)", - ERRNO_EPIPE_NEGATIVE); - CONNECTION_RESET_EXCEPTION_SPLICE = newConnectionResetException("syscall:splice(...)", - ERRNO_EPIPE_NEGATIVE); - } - - public static FileDescriptor newEventFd() { - return new FileDescriptor(eventFd()); - } - - private static native int eventFd(); - public static native void eventFdWrite(int fd, long value); - public static native void eventFdRead(int fd); - - public static FileDescriptor newEpollCreate() { - return new FileDescriptor(epollCreate()); - } - - private static native int epollCreate(); - - public static int epollWait(int efd, EpollEventArray events, int timeout) throws IOException { - int ready = epollWait0(efd, events.memoryAddress(), events.length(), timeout); - if (ready < 0) { - throw newIOException("epoll_wait", ready); - } - return ready; - } - private static native int epollWait0(int efd, long address, int len, int timeout); - - public static void epollCtlAdd(int efd, final int fd, final int flags) throws IOException { - int res = epollCtlAdd0(efd, fd, flags); - if (res < 0) { - throw newIOException("epoll_ctl", res); - } - } - private static native int epollCtlAdd0(int efd, final int fd, final int flags); - - public static void epollCtlMod(int efd, final int fd, final int flags) throws IOException { - int res = epollCtlMod0(efd, fd, flags); - if (res < 0) { - throw newIOException("epoll_ctl", res); - } - } - private static native int epollCtlMod0(int efd, final int fd, final int flags); - - public static void epollCtlDel(int efd, final int fd) throws IOException { - int res = epollCtlDel0(efd, fd); - if (res < 0) { - throw newIOException("epoll_ctl", res); - } - } - private static native int epollCtlDel0(int efd, final int fd); - - // File-descriptor operations - public static int splice(int fd, long offIn, int fdOut, long offOut, long len) throws IOException { - int res = splice0(fd, offIn, fdOut, offOut, len); - if (res >= 0) { - return res; - } - return ioResult("splice", res, CONNECTION_RESET_EXCEPTION_SPLICE); - } - - private static native int splice0(int fd, long offIn, int fdOut, long offOut, long len); - - public static long sendfile( - int dest, DefaultFileRegion src, long baseOffset, long offset, long length) throws IOException { - // Open the file-region as it may be created via the lazy constructor. This is needed as we directly access - // the FileChannel field directly via JNI - src.open(); - - long res = sendfile0(dest, src, baseOffset, offset, length); - if (res >= 0) { - return res; - } - return ioResult("sendfile", (int) res, CONNECTION_RESET_EXCEPTION_SENDFILE); - } - - private static native long sendfile0( - int dest, DefaultFileRegion src, long baseOffset, long offset, long length) throws IOException; - - public static int sendmmsg( - int fd, NativeDatagramPacketArray.NativeDatagramPacket[] msgs, int offset, int len) throws IOException { - int res = sendmmsg0(fd, msgs, offset, len); - if (res >= 0) { - return res; - } - return ioResult("sendmmsg", res, CONNECTION_RESET_EXCEPTION_SENDMMSG); - } - - private static native int sendmmsg0( - int fd, NativeDatagramPacketArray.NativeDatagramPacket[] msgs, int offset, int len); - - private static native boolean isSupportingSendmmsg(); - private static native boolean isSupportingTcpFastopen(); - - public static int recvFd(int fd) throws IOException { - int res = recvFd0(fd); - if (res > 0) { - return res; - } - if (res == 0) { - return -1; - } - - if (res == ERRNO_EAGAIN_NEGATIVE || res == ERRNO_EWOULDBLOCK_NEGATIVE) { - // Everything consumed so just return -1 here. - return 0; - } - throw newIOException("recvFd", res); - } - - private static native int recvFd0(int fd); - - public static int sendFd(int socketFd, int fd) throws IOException { - int res = sendFd0(socketFd, fd); - if (res >= 0) { - return res; - } - if (res == ERRNO_EAGAIN_NEGATIVE || res == ERRNO_EWOULDBLOCK_NEGATIVE) { - // Everything consumed so just return -1 here. - return -1; - } - throw newIOException("sendFd", res); - } - - private static native int sendFd0(int socketFd, int fd); - - // Socket option operations - public static native int isReuseAddress(int fd); - public static native int isReusePort(int fd); - public static native int getTcpNotSentLowAt(int fd); - public static native int getTrafficClass(int fd); - public static native int isBroadcast(int fd); - public static native int getTcpKeepIdle(int fd); - public static native int getTcpKeepIntvl(int fd); - public static native int getTcpKeepCnt(int fd); - public static native int getTcpUserTimeout(int milliseconds); - public static native int isIpFreeBind(int fd); - - public static native void setReuseAddress(int fd, int reuseAddress); - public static native void setReusePort(int fd, int reuseAddress); - public static native void setTcpFastopen(int fd, int tcpFastopenBacklog); - public static native void setTcpNotSentLowAt(int fd, int tcpNotSentLowAt); - public static native void setTrafficClass(int fd, int tcpNoDelay); - public static native void setBroadcast(int fd, int broadcast); - public static native void setTcpKeepIdle(int fd, int seconds); - public static native void setTcpKeepIntvl(int fd, int seconds); - public static native void setTcpKeepCnt(int fd, int probes); - public static native void setTcpUserTimeout(int fd, int milliseconds); - public static native void setIpFreeBind(int fd, int freeBind); - public static void tcpInfo(int fd, EpollTcpInfo info) { - tcpInfo0(fd, info.info); - } - - private static native void tcpInfo0(int fd, int[] array); - - public static void setTcpMd5Sig(int fd, InetAddress address, byte[] key) { - final NativeInetAddress a = NativeInetAddress.newInstance(address); - setTcpMd5Sig0(fd, a.address(), a.scopeId(), key); - } - - private static native void setTcpMd5Sig0(int fd, byte[] address, int scopeId, byte[] key); - - public static native String kernelVersion(); - - private static native int iovMax(); - - private static native int uioMaxIov(); - - // epoll_event related - public static native int sizeofEpollEvent(); - public static native int offsetofEpollData(); - - private static native int epollin(); - private static native int epollout(); - private static native int epollrdhup(); - private static native int epollet(); - private static native int epollerr(); - - private static native long ssizeMax(); - private static native int tcpMd5SigMaxKeyLen(); - - private Native() { - // utility - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/NativeDatagramPacketArray.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/NativeDatagramPacketArray.java deleted file mode 100755 index 4c00ddf50f..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/NativeDatagramPacketArray.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.epoll; - -import static com.ai.cloud.io.netty.channel.unix.NativeInetAddress.ipv4MappedIpv6Address; - -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.InetSocketAddress; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelOutboundBuffer; -import com.ai.cloud.io.netty.channel.socket.DatagramPacket; -import com.ai.cloud.io.netty.util.concurrent.FastThreadLocal; - -/** - * Support sendmmsg(...) on linux with GLIBC 2.14+ - */ -final class NativeDatagramPacketArray implements ChannelOutboundBuffer.MessageProcessor { - - private static final FastThreadLocal ARRAY = - new FastThreadLocal() { - @Override - protected NativeDatagramPacketArray initialValue() throws Exception { - return new NativeDatagramPacketArray(); - } - - @Override - protected void onRemoval(NativeDatagramPacketArray value) throws Exception { - NativeDatagramPacket[] array = value.packets; - // Release all packets - for (int i = 0; i < array.length; i++) { - array[i].release(); - } - } - }; - - // Use UIO_MAX_IOV as this is the maximum number we can write with one sendmmsg(...) call. - private final NativeDatagramPacket[] packets = new NativeDatagramPacket[Native.UIO_MAX_IOV]; - private int count; - - private NativeDatagramPacketArray() { - for (int i = 0; i < packets.length; i++) { - packets[i] = new NativeDatagramPacket(); - } - } - - /** - * Try to add the given {@link DatagramPacket}. Returns {@code true} on success, - * {@code false} otherwise. - */ - boolean add(DatagramPacket packet) { - if (count == packets.length) { - return false; - } - ByteBuf content = packet.content(); - int len = content.readableBytes(); - if (len == 0) { - return true; - } - NativeDatagramPacket p = packets[count]; - InetSocketAddress recipient = packet.recipient(); - if (!p.init(content, recipient)) { - return false; - } - - count++; - return true; - } - - @Override - public boolean processMessage(Object msg) throws Exception { - return msg instanceof DatagramPacket && add((DatagramPacket) msg); - } - - /** - * Returns the count - */ - int count() { - return count; - } - - /** - * Returns an array with {@link #count()} {@link NativeDatagramPacket}s filled. - */ - NativeDatagramPacket[] packets() { - return packets; - } - - /** - * Returns a {@link NativeDatagramPacketArray} which is filled with the flushed messages of - * {@link ChannelOutboundBuffer}. - */ - static NativeDatagramPacketArray getInstance(ChannelOutboundBuffer buffer) throws Exception { - NativeDatagramPacketArray array = ARRAY.get(); - array.count = 0; - buffer.forEachFlushedMessage(array); - return array; - } - - /** - * Used to pass needed data to JNI. - */ - @SuppressWarnings("unused") - static final class NativeDatagramPacket { - // Each NativeDatagramPackets holds a IovArray which is used for gathering writes. - // This is ok as NativeDatagramPacketArray is always obtained via a FastThreadLocal and - // so the memory needed is quite small anyway. - private final IovArray array = new IovArray(); - - // This is the actual struct iovec* - private long memoryAddress; - private int count; - - private byte[] addr; - private int scopeId; - private int port; - - private void release() { - array.release(); - } - - /** - * Init this instance and return {@code true} if the init was successful. - */ - private boolean init(ByteBuf buf, InetSocketAddress recipient) { - array.clear(); - if (!array.add(buf)) { - return false; - } - // always start from offset 0 - memoryAddress = array.memoryAddress(0); - count = array.count(); - - InetAddress address = recipient.getAddress(); - if (address instanceof Inet6Address) { - addr = address.getAddress(); - scopeId = ((Inet6Address) address).getScopeId(); - } else { - addr = ipv4MappedIpv6Address(address.getAddress()); - scopeId = 0; - } - port = recipient.getPort(); - return true; - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/TcpMd5Util.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/TcpMd5Util.java deleted file mode 100755 index 5fe9926dbc..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/TcpMd5Util.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.epoll; - -import java.net.InetAddress; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Map; -import java.util.Map.Entry; - -import com.ai.cloud.io.netty.util.internal.ObjectUtil; - -final class TcpMd5Util { - - static Collection newTcpMd5Sigs(AbstractEpollChannel channel, Collection current, - Map newKeys) { - ObjectUtil.checkNotNull(channel, "channel"); - ObjectUtil.checkNotNull(current, "current"); - ObjectUtil.checkNotNull(newKeys, "newKeys"); - - // Validate incoming values - for (Entry e : newKeys.entrySet()) { - final byte[] key = e.getValue(); - if (e.getKey() == null) { - throw new IllegalArgumentException("newKeys contains an entry with null address: " + newKeys); - } - if (key == null) { - throw new NullPointerException("newKeys[" + e.getKey() + ']'); - } - if (key.length == 0) { - throw new IllegalArgumentException("newKeys[" + e.getKey() + "] has an empty key."); - } - if (key.length > Native.TCP_MD5SIG_MAXKEYLEN) { - throw new IllegalArgumentException("newKeys[" + e.getKey() + - "] has a key with invalid length; should not exceed the maximum length (" + - Native.TCP_MD5SIG_MAXKEYLEN + ')'); - } - } - - // Remove mappings not present in the new set. - for (InetAddress addr : current) { - if (!newKeys.containsKey(addr)) { - Native.setTcpMd5Sig(channel.fd().intValue(), addr, null); - } - } - - if (newKeys.isEmpty()) { - return Collections.emptySet(); - } - - // Set new mappings and store addresses which we set. - final Collection addresses = new ArrayList(newKeys.size()); - for (Entry e : newKeys.entrySet()) { - Native.setTcpMd5Sig(channel.fd().intValue(), e.getKey(), e.getValue()); - addresses.add(e.getKey()); - } - - return addresses; - } - - private TcpMd5Util() { - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/package-info.java deleted file mode 100755 index 2ffb228189..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/epoll/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * Optimized transport for linux which uses EPOLL Edge-Triggered Mode - * for maximal performance. - */ -package com.ai.cloud.io.netty.channel.epoll; diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/ChannelGroup.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/ChannelGroup.java deleted file mode 100755 index 630acc46e6..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/ChannelGroup.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.group; - -import java.util.Set; - -import com.ai.cloud.io.netty.bootstrap.ServerBootstrap; -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.ByteBufHolder; -import com.ai.cloud.io.netty.buffer.Unpooled; -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelInboundHandlerAdapter; -import com.ai.cloud.io.netty.channel.EventLoop; -import com.ai.cloud.io.netty.channel.ServerChannel; -import com.ai.cloud.io.netty.util.CharsetUtil; -import com.ai.cloud.io.netty.util.concurrent.GlobalEventExecutor; - -/** - * A thread-safe {@link Set} that contains open {@link Channel}s and provides - * various bulk operations on them. Using {@link ChannelGroup}, you can - * categorize {@link Channel}s into a meaningful group (e.g. on a per-service - * or per-state basis.) A closed {@link Channel} is automatically removed from - * the collection, so that you don't need to worry about the life cycle of the - * added {@link Channel}. A {@link Channel} can belong to more than one - * {@link ChannelGroup}. - * - *

Broadcast a message to multiple {@link Channel}s

- *

- * If you need to broadcast a message to more than one {@link Channel}, you can - * add the {@link Channel}s associated with the recipients and call {@link ChannelGroup#write(Object)}: - *

- * {@link ChannelGroup} recipients =
- *         new {@link DefaultChannelGroup}({@link GlobalEventExecutor}.INSTANCE);
- * recipients.add(channelA);
- * recipients.add(channelB);
- * ..
- * recipients.write({@link Unpooled}.copiedBuffer(
- *         "Service will shut down for maintenance in 5 minutes.",
- *         {@link CharsetUtil}.UTF_8));
- * 
- * - *

Simplify shutdown process with {@link ChannelGroup}

- *

- * If both {@link ServerChannel}s and non-{@link ServerChannel}s exist in the - * same {@link ChannelGroup}, any requested I/O operations on the group are - * performed for the {@link ServerChannel}s first and then for the others. - *

- * This rule is very useful when you shut down a server in one shot: - * - *

- * {@link ChannelGroup} allChannels =
- *         new {@link DefaultChannelGroup}({@link GlobalEventExecutor}.INSTANCE);
- *
- * public static void main(String[] args) throws Exception {
- *     {@link ServerBootstrap} b = new {@link ServerBootstrap}(..);
- *     ...
- *     b.childHandler(new MyHandler());
- *
- *     // Start the server
- *     b.getPipeline().addLast("handler", new MyHandler());
- *     {@link Channel} serverChannel = b.bind(..).sync();
- *     allChannels.add(serverChannel);
- *
- *     ... Wait until the shutdown signal reception ...
- *
- *     // Close the serverChannel and then all accepted connections.
- *     allChannels.close().awaitUninterruptibly();
- * }
- *
- * public class MyHandler extends {@link ChannelInboundHandlerAdapter} {
- *     {@code @Override}
- *     public void channelActive({@link ChannelHandlerContext} ctx) {
- *         // closed on shutdown.
- *         allChannels.add(ctx.channel());
- *         super.channelActive(ctx);
- *     }
- * }
- * 
- */ -public interface ChannelGroup extends Set, Comparable { - - /** - * Returns the name of this group. A group name is purely for helping - * you to distinguish one group from others. - */ - String name(); - - /** - * Writes the specified {@code message} to all {@link Channel}s in this - * group. If the specified {@code message} is an instance of - * {@link ByteBuf}, it is automatically - * {@linkplain ByteBuf#duplicate() duplicated} to avoid a race - * condition. The same is true for {@link ByteBufHolder}. Please note that this operation is asynchronous as - * {@link Channel#write(Object)} is. - * - * @return itself - */ - ChannelGroupFuture write(Object message); - - /** - * Writes the specified {@code message} to all {@link Channel}s in this - * group that match the given {@link ChannelMatcher}. If the specified {@code message} is an instance of - * {@link ByteBuf}, it is automatically - * {@linkplain ByteBuf#duplicate() duplicated} to avoid a race - * condition. The same is true for {@link ByteBufHolder}. Please note that this operation is asynchronous as - * {@link Channel#write(Object)} is. - * - * @return the {@link ChannelGroupFuture} instance that notifies when - * the operation is done for all channels - */ - ChannelGroupFuture write(Object message, ChannelMatcher matcher); - - /** - * Flush all {@link Channel}s in this - * group. If the specified {@code messages} are an instance of - * {@link ByteBuf}, it is automatically - * {@linkplain ByteBuf#duplicate() duplicated} to avoid a race - * condition. Please note that this operation is asynchronous as - * {@link Channel#write(Object)} is. - * - * @return the {@link ChannelGroupFuture} instance that notifies when - * the operation is done for all channels - */ - ChannelGroup flush(); - - /** - * Flush all {@link Channel}s in this group that match the given {@link ChannelMatcher}. - * If the specified {@code messages} are an instance of - * {@link ByteBuf}, it is automatically - * {@linkplain ByteBuf#duplicate() duplicated} to avoid a race - * condition. Please note that this operation is asynchronous as - * {@link Channel#write(Object)} is. - * - * @return the {@link ChannelGroupFuture} instance that notifies when - * the operation is done for all channels - */ - ChannelGroup flush(ChannelMatcher matcher); - - /** - * Shortcut for calling {@link #write(Object)} and {@link #flush()}. - */ - ChannelGroupFuture writeAndFlush(Object message); - - /** - * @deprecated Use {@link #writeAndFlush(Object)} instead. - */ - @Deprecated - ChannelGroupFuture flushAndWrite(Object message); - - /** - * Shortcut for calling {@link #write(Object)} and {@link #flush()} and only act on - * {@link Channel}s that match the {@link ChannelMatcher}. - */ - ChannelGroupFuture writeAndFlush(Object message, ChannelMatcher matcher); - - /** - * @deprecated Use {@link #writeAndFlush(Object, ChannelMatcher)} instead. - */ - @Deprecated - ChannelGroupFuture flushAndWrite(Object message, ChannelMatcher matcher); - - /** - * Disconnects all {@link Channel}s in this group from their remote peers. - * - * @return the {@link ChannelGroupFuture} instance that notifies when - * the operation is done for all channels - */ - ChannelGroupFuture disconnect(); - - /** - * Disconnects all {@link Channel}s in this group from their remote peers, - * that match the given {@link ChannelMatcher}. - * - * @return the {@link ChannelGroupFuture} instance that notifies when - * the operation is done for all channels - */ - ChannelGroupFuture disconnect(ChannelMatcher matcher); - - /** - * Closes all {@link Channel}s in this group. If the {@link Channel} is - * connected to a remote peer or bound to a local address, it is - * automatically disconnected and unbound. - * - * @return the {@link ChannelGroupFuture} instance that notifies when - * the operation is done for all channels - */ - ChannelGroupFuture close(); - - /** - * Closes all {@link Channel}s in this group that match the given {@link ChannelMatcher}. - * If the {@link Channel} is connected to a remote peer or bound to a local address, it is - * automatically disconnected and unbound. - * - * @return the {@link ChannelGroupFuture} instance that notifies when - * the operation is done for all channels - */ - ChannelGroupFuture close(ChannelMatcher matcher); - - /** - * @deprecated This method will be removed in the next major feature release. - * - * Deregister all {@link Channel}s in this group from their {@link EventLoop}. - * Please note that this operation is asynchronous as {@link Channel#deregister()} is. - * - * @return the {@link ChannelGroupFuture} instance that notifies when - * the operation is done for all channels - */ - @Deprecated - ChannelGroupFuture deregister(); - - /** - * @deprecated This method will be removed in the next major feature release. - * - * Deregister all {@link Channel}s in this group from their {@link EventLoop} that match the given - * {@link ChannelMatcher}. Please note that this operation is asynchronous as {@link Channel#deregister()} is. - * - * @return the {@link ChannelGroupFuture} instance that notifies when - * the operation is done for all channels - */ - @Deprecated - ChannelGroupFuture deregister(ChannelMatcher matcher); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/ChannelGroupException.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/ChannelGroupException.java deleted file mode 100755 index 57d183d990..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/ChannelGroupException.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.group; - -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.Map; - -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelException; -import com.ai.cloud.io.netty.channel.ChannelFuture; - -/** - * {@link ChannelException} which holds {@link ChannelFuture}s that failed because of an error. - */ -public class ChannelGroupException extends ChannelException implements Iterable> { - private static final long serialVersionUID = -4093064295562629453L; - private final Collection> failed; - - public ChannelGroupException(Collection> causes) { - if (causes == null) { - throw new NullPointerException("causes"); - } - if (causes.isEmpty()) { - throw new IllegalArgumentException("causes must be non empty"); - } - failed = Collections.unmodifiableCollection(causes); - } - - /** - * Returns a {@link Iterator} which contains all the {@link Throwable} that was a cause of the failure and the - * related id of the {@link Channel}. - */ - @Override - public Iterator> iterator() { - return failed.iterator(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/ChannelGroupFuture.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/ChannelGroupFuture.java deleted file mode 100755 index 12cd61572f..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/ChannelGroupFuture.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.group; - -import java.util.Iterator; - -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelFuture; -import com.ai.cloud.io.netty.channel.ChannelHandler; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.util.concurrent.Future; -import com.ai.cloud.io.netty.util.concurrent.GenericFutureListener; - -/** - * The result of an asynchronous {@link ChannelGroup} operation. - * {@link ChannelGroupFuture} is composed of {@link ChannelFuture}s which - * represent the outcome of the individual I/O operations that affect the - * {@link Channel}s in the {@link ChannelGroup}. - * - *

- * All I/O operations in {@link ChannelGroup} are asynchronous. It means any - * I/O calls will return immediately with no guarantee that the requested I/O - * operations have been completed at the end of the call. Instead, you will be - * returned with a {@link ChannelGroupFuture} instance which tells you when the - * requested I/O operations have succeeded, failed, or cancelled. - *

- * Various methods are provided to let you check if the I/O operations has been - * completed, wait for the completion, and retrieve the result of the I/O - * operation. It also allows you to add more than one - * {@link ChannelGroupFutureListener} so you can get notified when the I/O - * operation have been completed. - * - *

Prefer {@link #addListener(GenericFutureListener)} to {@link #await()}

- * - * It is recommended to prefer {@link #addListener(GenericFutureListener)} to - * {@link #await()} wherever possible to get notified when I/O operations are - * done and to do any follow-up tasks. - *

- * {@link #addListener(GenericFutureListener)} is non-blocking. It simply - * adds the specified {@link ChannelGroupFutureListener} to the - * {@link ChannelGroupFuture}, and I/O thread will notify the listeners when - * the I/O operations associated with the future is done. - * {@link ChannelGroupFutureListener} yields the best performance and resource - * utilization because it does not block at all, but it could be tricky to - * implement a sequential logic if you are not used to event-driven programming. - *

- * By contrast, {@link #await()} is a blocking operation. Once called, the - * caller thread blocks until all I/O operations are done. It is easier to - * implement a sequential logic with {@link #await()}, but the caller thread - * blocks unnecessarily until all I/O operations are done and there's relatively - * expensive cost of inter-thread notification. Moreover, there's a chance of - * dead lock in a particular circumstance, which is described below. - * - *

Do not call {@link #await()} inside {@link ChannelHandler}

- *

- * The event handler methods in {@link ChannelHandler} is often called by - * an I/O thread. If {@link #await()} is called by an event handler - * method, which is called by the I/O thread, the I/O operation it is waiting - * for might never be complete because {@link #await()} can block the I/O - * operation it is waiting for, which is a dead lock. - *

- * // BAD - NEVER DO THIS
- * {@code @Override}
- * public void messageReceived({@link ChannelHandlerContext} ctx, ShutdownMessage msg) {
- *     {@link ChannelGroup} allChannels = MyServer.getAllChannels();
- *     {@link ChannelGroupFuture} future = allChannels.close();
- *     future.awaitUninterruptibly();
- *     // Perform post-shutdown operation
- *     // ...
- *
- * }
- *
- * // GOOD
- * {@code @Override}
- * public void messageReceived(ChannelHandlerContext ctx, ShutdownMessage msg) {
- *     {@link ChannelGroup} allChannels = MyServer.getAllChannels();
- *     {@link ChannelGroupFuture} future = allChannels.close();
- *     future.addListener(new {@link ChannelGroupFutureListener}() {
- *         public void operationComplete({@link ChannelGroupFuture} future) {
- *             // Perform post-closure operation
- *             // ...
- *         }
- *     });
- * }
- * 
- *

- * In spite of the disadvantages mentioned above, there are certainly the cases - * where it is more convenient to call {@link #await()}. In such a case, please - * make sure you do not call {@link #await()} in an I/O thread. Otherwise, - * {@link IllegalStateException} will be raised to prevent a dead lock. - */ -public interface ChannelGroupFuture extends Future, Iterable { - - /** - * Returns the {@link ChannelGroup} which is associated with this future. - */ - ChannelGroup group(); - - /** - * Returns the {@link ChannelFuture} of the individual I/O operation which - * is associated with the specified {@link Channel}. - * - * @return the matching {@link ChannelFuture} if found. - * {@code null} otherwise. - */ - ChannelFuture find(Channel channel); - - /** - * Returns {@code true} if and only if all I/O operations associated with - * this future were successful without any failure. - */ - @Override - boolean isSuccess(); - - @Override - ChannelGroupException cause(); - - /** - * Returns {@code true} if and only if the I/O operations associated with - * this future were partially successful with some failure. - */ - boolean isPartialSuccess(); - - /** - * Returns {@code true} if and only if the I/O operations associated with - * this future have failed partially with some success. - */ - boolean isPartialFailure(); - - @Override - ChannelGroupFuture addListener(GenericFutureListener> listener); - - @Override - ChannelGroupFuture addListeners(GenericFutureListener>... listeners); - - @Override - ChannelGroupFuture removeListener(GenericFutureListener> listener); - - @Override - ChannelGroupFuture removeListeners(GenericFutureListener>... listeners); - - @Override - ChannelGroupFuture await() throws InterruptedException; - - @Override - ChannelGroupFuture awaitUninterruptibly(); - - @Override - ChannelGroupFuture syncUninterruptibly(); - - @Override - ChannelGroupFuture sync() throws InterruptedException; - - /** - * Returns the {@link Iterator} that enumerates all {@link ChannelFuture}s - * which are associated with this future. Please note that the returned - * {@link Iterator} is is unmodifiable, which means a {@link ChannelFuture} - * cannot be removed from this future. - */ - @Override - Iterator iterator(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/ChannelGroupFutureListener.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/ChannelGroupFutureListener.java deleted file mode 100755 index 32bf453f8d..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/ChannelGroupFutureListener.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.group; - -import com.ai.cloud.io.netty.util.concurrent.GenericFutureListener; - -/** - * Listens to the result of a {@link ChannelGroupFuture}. The result of the - * asynchronous {@link ChannelGroup} I/O operations is notified once this - * listener is added by calling {@link ChannelGroupFuture#addListener(GenericFutureListener)} - * and all I/O operations are complete. - */ -public interface ChannelGroupFutureListener extends GenericFutureListener { - -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/ChannelMatcher.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/ChannelMatcher.java deleted file mode 100755 index 46a4f2d0a4..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/ChannelMatcher.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.group; - - -import com.ai.cloud.io.netty.channel.Channel; - -/** - * Allows to only match some {@link Channel}'s for operations in {@link ChannelGroup}. - * - * {@link ChannelMatchers} provide you with helper methods for usual needed implementations. - */ -public interface ChannelMatcher { - - /** - * Returns {@code true} if the operation should be also executed on the given {@link Channel}. - */ - boolean matches(Channel channel); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/ChannelMatchers.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/ChannelMatchers.java deleted file mode 100755 index 4f069ef788..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/ChannelMatchers.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.group; - -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ServerChannel; - -/** - * Helper class which provides often used {@link ChannelMatcher} implementations. - */ -public final class ChannelMatchers { - - private static final ChannelMatcher ALL_MATCHER = new ChannelMatcher() { - @Override - public boolean matches(Channel channel) { - return true; - } - }; - - private static final ChannelMatcher SERVER_CHANNEL_MATCHER = isInstanceOf(ServerChannel.class); - private static final ChannelMatcher NON_SERVER_CHANNEL_MATCHER = isNotInstanceOf(ServerChannel.class); - - private ChannelMatchers() { - // static methods only - } - - /** - * Returns a {@link ChannelMatcher} that matches all {@link Channel}s. - */ - public static ChannelMatcher all() { - return ALL_MATCHER; - } - - /** - * Returns a {@link ChannelMatcher} that matches all {@link Channel}s except the given. - */ - public static ChannelMatcher isNot(Channel channel) { - return invert(is(channel)); - } - - /** - * Returns a {@link ChannelMatcher} that matches the given {@link Channel}. - */ - public static ChannelMatcher is(Channel channel) { - return new InstanceMatcher(channel); - } - - /** - * Returns a {@link ChannelMatcher} that matches all {@link Channel}s that are an instance of sub-type of - * the given class. - */ - public static ChannelMatcher isInstanceOf(Class clazz) { - return new ClassMatcher(clazz); - } - - /** - * Returns a {@link ChannelMatcher} that matches all {@link Channel}s that are not an - * instance of sub-type of the given class. - */ - public static ChannelMatcher isNotInstanceOf(Class clazz) { - return invert(isInstanceOf(clazz)); - } - - /** - * Returns a {@link ChannelMatcher} that matches all {@link Channel}s that are of type {@link ServerChannel}. - */ - public static ChannelMatcher isServerChannel() { - return SERVER_CHANNEL_MATCHER; - } - - /** - * Returns a {@link ChannelMatcher} that matches all {@link Channel}s that are not of type - * {@link ServerChannel}. - */ - public static ChannelMatcher isNonServerChannel() { - return NON_SERVER_CHANNEL_MATCHER; - } - - /** - * Invert the given {@link ChannelMatcher}. - */ - public static ChannelMatcher invert(ChannelMatcher matcher) { - return new InvertMatcher(matcher); - } - - /** - * Return a composite of the given {@link ChannelMatcher}s. This means all {@link ChannelMatcher} must - * return {@code true} to match. - */ - public static ChannelMatcher compose(ChannelMatcher... matchers) { - if (matchers.length < 1) { - throw new IllegalArgumentException("matchers must at least contain one element"); - } - if (matchers.length == 1) { - return matchers[0]; - } - return new CompositeMatcher(matchers); - } - - private static final class CompositeMatcher implements ChannelMatcher { - private final ChannelMatcher[] matchers; - - CompositeMatcher(ChannelMatcher... matchers) { - this.matchers = matchers; - } - - @Override - public boolean matches(Channel channel) { - for (ChannelMatcher m: matchers) { - if (!m.matches(channel)) { - return false; - } - } - return true; - } - } - - private static final class InvertMatcher implements ChannelMatcher { - private final ChannelMatcher matcher; - - InvertMatcher(ChannelMatcher matcher) { - this.matcher = matcher; - } - - @Override - public boolean matches(Channel channel) { - return !matcher.matches(channel); - } - } - - private static final class InstanceMatcher implements ChannelMatcher { - private final Channel channel; - - InstanceMatcher(Channel channel) { - this.channel = channel; - } - - @Override - public boolean matches(Channel ch) { - return channel == ch; - } - } - - private static final class ClassMatcher implements ChannelMatcher { - private final Class clazz; - - ClassMatcher(Class clazz) { - this.clazz = clazz; - } - - @Override - public boolean matches(Channel ch) { - return clazz.isInstance(ch); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/CombinedIterator.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/CombinedIterator.java deleted file mode 100755 index e5085d8a7f..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/CombinedIterator.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.group; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -/** - */ -final class CombinedIterator implements Iterator { - - private final Iterator i1; - private final Iterator i2; - private Iterator currentIterator; - - CombinedIterator(Iterator i1, Iterator i2) { - if (i1 == null) { - throw new NullPointerException("i1"); - } - if (i2 == null) { - throw new NullPointerException("i2"); - } - this.i1 = i1; - this.i2 = i2; - currentIterator = i1; - } - - @Override - public boolean hasNext() { - for (;;) { - if (currentIterator.hasNext()) { - return true; - } - - if (currentIterator == i1) { - currentIterator = i2; - } else { - return false; - } - } - } - - @Override - public E next() { - for (;;) { - try { - return currentIterator.next(); - } catch (NoSuchElementException e) { - if (currentIterator == i1) { - currentIterator = i2; - } else { - throw e; - } - } - } - } - - @Override - public void remove() { - currentIterator.remove(); - } - -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/DefaultChannelGroup.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/DefaultChannelGroup.java deleted file mode 100755 index 3fe0b87631..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/DefaultChannelGroup.java +++ /dev/null @@ -1,440 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.group; - -import java.util.AbstractSet; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.ByteBufHolder; -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelFuture; -import com.ai.cloud.io.netty.channel.ChannelFutureListener; -import com.ai.cloud.io.netty.channel.ServerChannel; -import com.ai.cloud.io.netty.util.ReferenceCountUtil; -import com.ai.cloud.io.netty.util.concurrent.EventExecutor; -import com.ai.cloud.io.netty.util.internal.ConcurrentSet; -import com.ai.cloud.io.netty.util.internal.StringUtil; - -/** - * The default {@link ChannelGroup} implementation. - */ -public class DefaultChannelGroup extends AbstractSet implements ChannelGroup { - - private static final AtomicInteger nextId = new AtomicInteger(); - private final String name; - private final EventExecutor executor; - private final ConcurrentSet serverChannels = new ConcurrentSet(); - private final ConcurrentSet nonServerChannels = new ConcurrentSet(); - private final ChannelFutureListener remover = new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - remove(future.channel()); - } - }; - private final boolean stayClosed; - private volatile boolean closed; - - /** - * Creates a new group with a generated name and the provided {@link EventExecutor} to notify the - * {@link ChannelGroupFuture}s. - */ - public DefaultChannelGroup(EventExecutor executor) { - this(executor, false); - } - - /** - * Creates a new group with the specified {@code name} and {@link EventExecutor} to notify the - * {@link ChannelGroupFuture}s. Please note that different groups can have the same name, which means no - * duplicate check is done against group names. - */ - public DefaultChannelGroup(String name, EventExecutor executor) { - this(name, executor, false); - } - - /** - * Creates a new group with a generated name and the provided {@link EventExecutor} to notify the - * {@link ChannelGroupFuture}s. {@code stayClosed} defines whether or not, this group can be closed - * more than once. Adding channels to a closed group will immediately close them, too. This makes it - * easy, to shutdown server and child channels at once. - */ - public DefaultChannelGroup(EventExecutor executor, boolean stayClosed) { - this("group-0x" + Integer.toHexString(nextId.incrementAndGet()), executor, stayClosed); - } - - /** - * Creates a new group with the specified {@code name} and {@link EventExecutor} to notify the - * {@link ChannelGroupFuture}s. {@code stayClosed} defines whether or not, this group can be closed - * more than once. Adding channels to a closed group will immediately close them, too. This makes it - * easy, to shutdown server and child channels at once. Please note that different groups can have - * the same name, which means no duplicate check is done against group names. - */ - public DefaultChannelGroup(String name, EventExecutor executor, boolean stayClosed) { - if (name == null) { - throw new NullPointerException("name"); - } - this.name = name; - this.executor = executor; - this.stayClosed = stayClosed; - } - - @Override - public String name() { - return name; - } - - @Override - public boolean isEmpty() { - return nonServerChannels.isEmpty() && serverChannels.isEmpty(); - } - - @Override - public int size() { - return nonServerChannels.size() + serverChannels.size(); - } - - @Override - public boolean contains(Object o) { - if (o instanceof Channel) { - Channel c = (Channel) o; - if (o instanceof ServerChannel) { - return serverChannels.contains(c); - } else { - return nonServerChannels.contains(c); - } - } else { - return false; - } - } - - @Override - public boolean add(Channel channel) { - ConcurrentSet set = - channel instanceof ServerChannel? serverChannels : nonServerChannels; - - boolean added = set.add(channel); - if (added) { - channel.closeFuture().addListener(remover); - } - - if (stayClosed && closed) { - - // First add channel, than check if closed. - // Seems inefficient at first, but this way a volatile - // gives us enough synchronization to be thread-safe. - // - // If true: Close right away. - // (Might be closed a second time by ChannelGroup.close(), but this is ok) - // - // If false: Channel will definitely be closed by the ChannelGroup. - // (Because closed=true always happens-before ChannelGroup.close()) - // - // See https://github.com/netty/netty/issues/4020 - channel.close(); - } - - return added; - } - - @Override - public boolean remove(Object o) { - if (!(o instanceof Channel)) { - return false; - } - boolean removed; - Channel c = (Channel) o; - if (c instanceof ServerChannel) { - removed = serverChannels.remove(c); - } else { - removed = nonServerChannels.remove(c); - } - if (!removed) { - return false; - } - - c.closeFuture().removeListener(remover); - return true; - } - - @Override - public void clear() { - nonServerChannels.clear(); - serverChannels.clear(); - } - - @Override - public Iterator iterator() { - return new CombinedIterator( - serverChannels.iterator(), - nonServerChannels.iterator()); - } - - @Override - public Object[] toArray() { - Collection channels = new ArrayList(size()); - channels.addAll(serverChannels); - channels.addAll(nonServerChannels); - return channels.toArray(); - } - - @Override - public T[] toArray(T[] a) { - Collection channels = new ArrayList(size()); - channels.addAll(serverChannels); - channels.addAll(nonServerChannels); - return channels.toArray(a); - } - - @Override - public ChannelGroupFuture close() { - return close(ChannelMatchers.all()); - } - - @Override - public ChannelGroupFuture disconnect() { - return disconnect(ChannelMatchers.all()); - } - - @Override - public ChannelGroupFuture deregister() { - return deregister(ChannelMatchers.all()); - } - - @Override - public ChannelGroupFuture write(Object message) { - return write(message, ChannelMatchers.all()); - } - - // Create a safe duplicate of the message to write it to a channel but not affect other writes. - // See https://github.com/netty/netty/issues/1461 - private static Object safeDuplicate(Object message) { - if (message instanceof ByteBuf) { - return ((ByteBuf) message).duplicate().retain(); - } else if (message instanceof ByteBufHolder) { - return ((ByteBufHolder) message).duplicate().retain(); - } else { - return ReferenceCountUtil.retain(message); - } - } - - @Override - public ChannelGroupFuture write(Object message, ChannelMatcher matcher) { - if (message == null) { - throw new NullPointerException("message"); - } - if (matcher == null) { - throw new NullPointerException("matcher"); - } - - Map futures = new LinkedHashMap(size()); - for (Channel c: nonServerChannels) { - if (matcher.matches(c)) { - futures.put(c, c.write(safeDuplicate(message))); - } - } - - ReferenceCountUtil.release(message); - return new DefaultChannelGroupFuture(this, futures, executor); - } - - @Override - public ChannelGroup flush() { - return flush(ChannelMatchers.all()); - } - - @Override - public ChannelGroupFuture flushAndWrite(Object message) { - return writeAndFlush(message); - } - - @Override - public ChannelGroupFuture writeAndFlush(Object message) { - return writeAndFlush(message, ChannelMatchers.all()); - } - - @Override - public ChannelGroupFuture disconnect(ChannelMatcher matcher) { - if (matcher == null) { - throw new NullPointerException("matcher"); - } - - Map futures = - new LinkedHashMap(size()); - - for (Channel c: serverChannels) { - if (matcher.matches(c)) { - futures.put(c, c.disconnect()); - } - } - for (Channel c: nonServerChannels) { - if (matcher.matches(c)) { - futures.put(c, c.disconnect()); - } - } - - return new DefaultChannelGroupFuture(this, futures, executor); - } - - @Override - public ChannelGroupFuture close(ChannelMatcher matcher) { - if (matcher == null) { - throw new NullPointerException("matcher"); - } - - Map futures = - new LinkedHashMap(size()); - - if (stayClosed) { - // It is important to set the closed to true, before closing channels. - // Our invariants are: - // closed=true happens-before ChannelGroup.close() - // ChannelGroup.add() happens-before checking closed==true - // - // See https://github.com/netty/netty/issues/4020 - closed = true; - } - - for (Channel c: serverChannels) { - if (matcher.matches(c)) { - futures.put(c, c.close()); - } - } - for (Channel c: nonServerChannels) { - if (matcher.matches(c)) { - futures.put(c, c.close()); - } - } - - return new DefaultChannelGroupFuture(this, futures, executor); - } - - @Override - public ChannelGroupFuture deregister(ChannelMatcher matcher) { - if (matcher == null) { - throw new NullPointerException("matcher"); - } - - Map futures = - new LinkedHashMap(size()); - - for (Channel c: serverChannels) { - if (matcher.matches(c)) { - futures.put(c, c.deregister()); - } - } - for (Channel c: nonServerChannels) { - if (matcher.matches(c)) { - futures.put(c, c.deregister()); - } - } - - return new DefaultChannelGroupFuture(this, futures, executor); - } - - @Override - public ChannelGroup flush(ChannelMatcher matcher) { - for (Channel c: nonServerChannels) { - if (matcher.matches(c)) { - c.flush(); - } - } - return this; - } - - @Override - public ChannelGroupFuture flushAndWrite(Object message, ChannelMatcher matcher) { - return writeAndFlush(message, matcher); - } - - @Override - public ChannelGroupFuture writeAndFlush(Object message, ChannelMatcher matcher) { - if (message == null) { - throw new NullPointerException("message"); - } - - Map futures = new LinkedHashMap(size()); - - for (Channel c: nonServerChannels) { - if (matcher.matches(c)) { - futures.put(c, c.writeAndFlush(safeDuplicate(message))); - } - } - - ReferenceCountUtil.release(message); - - return new DefaultChannelGroupFuture(this, futures, executor); - } - - /** - * Returns the {@link ChannelGroupFuture} which will be notified when all {@link Channel}s that are part of this - * {@link ChannelGroup}, at the time of calling, are closed. - */ - public ChannelGroupFuture newCloseFuture() { - return newCloseFuture(ChannelMatchers.all()); - } - - /** - * Returns the {@link ChannelGroupFuture} which will be notified when all {@link Channel}s that are part of this - * {@link ChannelGroup}, at the time of calling, are closed. - */ - public ChannelGroupFuture newCloseFuture(ChannelMatcher matcher) { - Map futures = - new LinkedHashMap(size()); - - for (Channel c: serverChannels) { - if (matcher.matches(c)) { - futures.put(c, c.closeFuture()); - } - } - for (Channel c: nonServerChannels) { - if (matcher.matches(c)) { - futures.put(c, c.closeFuture()); - } - } - - return new DefaultChannelGroupFuture(this, futures, executor); - } - - @Override - public int hashCode() { - return System.identityHashCode(this); - } - - @Override - public boolean equals(Object o) { - return this == o; - } - - @Override - public int compareTo(ChannelGroup o) { - int v = name().compareTo(o.name()); - if (v != 0) { - return v; - } - - return System.identityHashCode(this) - System.identityHashCode(o); - } - - @Override - public String toString() { - return StringUtil.simpleClassName(this) + "(name: " + name() + ", size: " + size() + ')'; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/DefaultChannelGroupFuture.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/DefaultChannelGroupFuture.java deleted file mode 100755 index b918b09f3a..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/DefaultChannelGroupFuture.java +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.group; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelFuture; -import com.ai.cloud.io.netty.channel.ChannelFutureListener; -import com.ai.cloud.io.netty.util.concurrent.BlockingOperationException; -import com.ai.cloud.io.netty.util.concurrent.DefaultPromise; -import com.ai.cloud.io.netty.util.concurrent.EventExecutor; -import com.ai.cloud.io.netty.util.concurrent.Future; -import com.ai.cloud.io.netty.util.concurrent.GenericFutureListener; -import com.ai.cloud.io.netty.util.concurrent.ImmediateEventExecutor; - - -/** - * The default {@link ChannelGroupFuture} implementation. - */ -final class DefaultChannelGroupFuture extends DefaultPromise implements ChannelGroupFuture { - - private final ChannelGroup group; - private final Map futures; - private int successCount; - private int failureCount; - - private final ChannelFutureListener childListener = new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - boolean success = future.isSuccess(); - boolean callSetDone; - synchronized (DefaultChannelGroupFuture.this) { - if (success) { - successCount ++; - } else { - failureCount ++; - } - - callSetDone = successCount + failureCount == futures.size(); - assert successCount + failureCount <= futures.size(); - } - - if (callSetDone) { - if (failureCount > 0) { - List> failed = - new ArrayList>(failureCount); - for (ChannelFuture f: futures.values()) { - if (!f.isSuccess()) { - failed.add(new DefaultEntry(f.channel(), f.cause())); - } - } - setFailure0(new ChannelGroupException(failed)); - } else { - setSuccess0(); - } - } - } - }; - - /** - * Creates a new instance. - */ - DefaultChannelGroupFuture(ChannelGroup group, Collection futures, EventExecutor executor) { - super(executor); - if (group == null) { - throw new NullPointerException("group"); - } - if (futures == null) { - throw new NullPointerException("futures"); - } - - this.group = group; - - Map futureMap = new LinkedHashMap(); - for (ChannelFuture f: futures) { - futureMap.put(f.channel(), f); - } - - this.futures = Collections.unmodifiableMap(futureMap); - - for (ChannelFuture f: this.futures.values()) { - f.addListener(childListener); - } - - // Done on arrival? - if (this.futures.isEmpty()) { - setSuccess0(); - } - } - - DefaultChannelGroupFuture(ChannelGroup group, Map futures, EventExecutor executor) { - super(executor); - this.group = group; - this.futures = Collections.unmodifiableMap(futures); - for (ChannelFuture f: this.futures.values()) { - f.addListener(childListener); - } - - // Done on arrival? - if (this.futures.isEmpty()) { - setSuccess0(); - } - } - - @Override - public ChannelGroup group() { - return group; - } - - @Override - public ChannelFuture find(Channel channel) { - return futures.get(channel); - } - - @Override - public Iterator iterator() { - return futures.values().iterator(); - } - - @Override - public synchronized boolean isPartialSuccess() { - return successCount != 0 && successCount != futures.size(); - } - - @Override - public synchronized boolean isPartialFailure() { - return failureCount != 0 && failureCount != futures.size(); - } - - @Override - public DefaultChannelGroupFuture addListener(GenericFutureListener> listener) { - super.addListener(listener); - return this; - } - - @Override - public DefaultChannelGroupFuture addListeners(GenericFutureListener>... listeners) { - super.addListeners(listeners); - return this; - } - - @Override - public DefaultChannelGroupFuture removeListener(GenericFutureListener> listener) { - super.removeListener(listener); - return this; - } - - @Override - public DefaultChannelGroupFuture removeListeners( - GenericFutureListener>... listeners) { - super.removeListeners(listeners); - return this; - } - - @Override - public DefaultChannelGroupFuture await() throws InterruptedException { - super.await(); - return this; - } - - @Override - public DefaultChannelGroupFuture awaitUninterruptibly() { - super.awaitUninterruptibly(); - return this; - } - - @Override - public DefaultChannelGroupFuture syncUninterruptibly() { - super.syncUninterruptibly(); - return this; - } - - @Override - public DefaultChannelGroupFuture sync() throws InterruptedException { - super.sync(); - return this; - } - - @Override - public ChannelGroupException cause() { - return (ChannelGroupException) super.cause(); - } - - private void setSuccess0() { - super.setSuccess(null); - } - - private void setFailure0(ChannelGroupException cause) { - super.setFailure(cause); - } - - @Override - public DefaultChannelGroupFuture setSuccess(Void result) { - throw new IllegalStateException(); - } - - @Override - public boolean trySuccess(Void result) { - throw new IllegalStateException(); - } - - @Override - public DefaultChannelGroupFuture setFailure(Throwable cause) { - throw new IllegalStateException(); - } - - @Override - public boolean tryFailure(Throwable cause) { - throw new IllegalStateException(); - } - - @Override - protected void checkDeadLock() { - EventExecutor e = executor(); - if (e != null && e != ImmediateEventExecutor.INSTANCE && e.inEventLoop()) { - throw new BlockingOperationException(); - } - } - - private static final class DefaultEntry implements Map.Entry { - private final K key; - private final V value; - - DefaultEntry(K key, V value) { - this.key = key; - this.value = value; - } - - @Override - public K getKey() { - return key; - } - - @Override - public V getValue() { - return value; - } - - @Override - public V setValue(V value) { - throw new UnsupportedOperationException("read-only"); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/package-info.java deleted file mode 100755 index 2450a4caf7..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/group/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * A channel registry which helps a user maintain the list of open - * {@link com.ai.cloud.io.netty.channel.Channel}s and perform bulk operations on them. - */ -package com.ai.cloud.io.netty.channel.group; diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/local/LocalAddress.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/local/LocalAddress.java deleted file mode 100755 index 7501a8fb56..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/local/LocalAddress.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.local; - -import java.net.SocketAddress; - -import com.ai.cloud.io.netty.channel.Channel; - -/** - * An endpoint in the local transport. Each endpoint is identified by a unique - * case-insensitive string. - */ -public final class LocalAddress extends SocketAddress implements Comparable { - - private static final long serialVersionUID = 4644331421130916435L; - - public static final LocalAddress ANY = new LocalAddress("ANY"); - - private final String id; - private final String strVal; - - /** - * Creates a new ephemeral port based on the ID of the specified channel. - * Note that we prepend an upper-case character so that it never conflicts with - * the addresses created by a user, which are always lower-cased on construction time. - */ - LocalAddress(Channel channel) { - StringBuilder buf = new StringBuilder(16); - buf.append("local:E"); - buf.append(Long.toHexString(channel.hashCode() & 0xFFFFFFFFL | 0x100000000L)); - buf.setCharAt(7, ':'); - id = buf.substring(6); - strVal = buf.toString(); - } - - /** - * Creates a new instance with the specified ID. - */ - public LocalAddress(String id) { - if (id == null) { - throw new NullPointerException("id"); - } - id = id.trim().toLowerCase(); - if (id.isEmpty()) { - throw new IllegalArgumentException("empty id"); - } - this.id = id; - strVal = "local:" + id; - } - - /** - * Returns the ID of this address. - */ - public String id() { - return id; - } - - @Override - public int hashCode() { - return id.hashCode(); - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof LocalAddress)) { - return false; - } - - return id.equals(((LocalAddress) o).id); - } - - @Override - public int compareTo(LocalAddress o) { - return id.compareTo(o.id); - } - - @Override - public String toString() { - return strVal; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/local/LocalChannel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/local/LocalChannel.java deleted file mode 100755 index 59df953a59..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/local/LocalChannel.java +++ /dev/null @@ -1,484 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.local; - -import java.net.SocketAddress; -import java.nio.channels.AlreadyConnectedException; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.ConnectionPendingException; -import java.nio.channels.NotYetConnectedException; -import java.util.Queue; -import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; - -import com.ai.cloud.io.netty.channel.AbstractChannel; -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelConfig; -import com.ai.cloud.io.netty.channel.ChannelException; -import com.ai.cloud.io.netty.channel.ChannelMetadata; -import com.ai.cloud.io.netty.channel.ChannelOutboundBuffer; -import com.ai.cloud.io.netty.channel.ChannelPipeline; -import com.ai.cloud.io.netty.channel.ChannelPromise; -import com.ai.cloud.io.netty.channel.DefaultChannelConfig; -import com.ai.cloud.io.netty.channel.EventLoop; -import com.ai.cloud.io.netty.channel.SingleThreadEventLoop; -import com.ai.cloud.io.netty.util.ReferenceCountUtil; -import com.ai.cloud.io.netty.util.concurrent.Future; -import com.ai.cloud.io.netty.util.concurrent.SingleThreadEventExecutor; -import com.ai.cloud.io.netty.util.internal.EmptyArrays; -import com.ai.cloud.io.netty.util.internal.InternalThreadLocalMap; -import com.ai.cloud.io.netty.util.internal.OneTimeTask; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - -/** - * A {@link Channel} for the local transport. - */ -public class LocalChannel extends AbstractChannel { - - @SuppressWarnings({ "rawtypes" }) - private static final AtomicReferenceFieldUpdater FINISH_READ_FUTURE_UPDATER; - private static final ChannelMetadata METADATA = new ChannelMetadata(false); - private static final int MAX_READER_STACK_DEPTH = 8; - private static final ClosedChannelException CLOSED_CHANNEL_EXCEPTION = new ClosedChannelException(); - - private final ChannelConfig config = new DefaultChannelConfig(this); - // To further optimize this we could write our own SPSC queue. - private final Queue inboundBuffer = PlatformDependent.newMpscQueue(); - private final Runnable readTask = new Runnable() { - @Override - public void run() { - ChannelPipeline pipeline = pipeline(); - for (;;) { - Object m = inboundBuffer.poll(); - if (m == null) { - break; - } - pipeline.fireChannelRead(m); - } - pipeline.fireChannelReadComplete(); - } - }; - private final Runnable shutdownHook = new Runnable() { - @Override - public void run() { - unsafe().close(unsafe().voidPromise()); - } - }; - - private volatile int state; // 0 - open, 1 - bound, 2 - connected, 3 - closed - private volatile LocalChannel peer; - private volatile LocalAddress localAddress; - private volatile LocalAddress remoteAddress; - private volatile ChannelPromise connectPromise; - private volatile boolean readInProgress; - private volatile boolean registerInProgress; - private volatile boolean writeInProgress; - private volatile Future finishReadFuture; - - static { - @SuppressWarnings({ "rawtypes" }) - AtomicReferenceFieldUpdater finishReadFutureUpdater = - PlatformDependent.newAtomicReferenceFieldUpdater(LocalChannel.class, "finishReadFuture"); - if (finishReadFutureUpdater == null) { - finishReadFutureUpdater = - AtomicReferenceFieldUpdater.newUpdater(LocalChannel.class, Future.class, "finishReadFuture"); - } - FINISH_READ_FUTURE_UPDATER = finishReadFutureUpdater; - CLOSED_CHANNEL_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); - } - - public LocalChannel() { - super(null); - } - - LocalChannel(LocalServerChannel parent, LocalChannel peer) { - super(parent); - this.peer = peer; - localAddress = parent.localAddress(); - remoteAddress = peer.localAddress(); - } - - @Override - public ChannelMetadata metadata() { - return METADATA; - } - - @Override - public ChannelConfig config() { - return config; - } - - @Override - public LocalServerChannel parent() { - return (LocalServerChannel) super.parent(); - } - - @Override - public LocalAddress localAddress() { - return (LocalAddress) super.localAddress(); - } - - @Override - public LocalAddress remoteAddress() { - return (LocalAddress) super.remoteAddress(); - } - - @Override - public boolean isOpen() { - return state < 3; - } - - @Override - public boolean isActive() { - return state == 2; - } - - @Override - protected AbstractUnsafe newUnsafe() { - return new LocalUnsafe(); - } - - @Override - protected boolean isCompatible(EventLoop loop) { - return loop instanceof SingleThreadEventLoop; - } - - @Override - protected SocketAddress localAddress0() { - return localAddress; - } - - @Override - protected SocketAddress remoteAddress0() { - return remoteAddress; - } - - @Override - protected void doRegister() throws Exception { - // Check if both peer and parent are non-null because this channel was created by a LocalServerChannel. - // This is needed as a peer may not be null also if a LocalChannel was connected before and - // deregistered / registered later again. - // - // See https://github.com/netty/netty/issues/2400 - if (peer != null && parent() != null) { - // Store the peer in a local variable as it may be set to null if doClose() is called. - // Because of this we also set registerInProgress to true as we check for this in doClose() and make sure - // we delay the fireChannelInactive() to be fired after the fireChannelActive() and so keep the correct - // order of events. - // - // See https://github.com/netty/netty/issues/2144 - final LocalChannel peer = this.peer; - registerInProgress = true; - state = 2; - - peer.remoteAddress = parent().localAddress(); - peer.state = 2; - - // Always call peer.eventLoop().execute() even if peer.eventLoop().inEventLoop() is true. - // This ensures that if both channels are on the same event loop, the peer's channelActive - // event is triggered *after* this channel's channelRegistered event, so that this channel's - // pipeline is fully initialized by ChannelInitializer before any channelRead events. - peer.eventLoop().execute(new OneTimeTask() { - @Override - public void run() { - registerInProgress = false; - peer.pipeline().fireChannelActive(); - peer.connectPromise.setSuccess(); - } - }); - } - ((SingleThreadEventExecutor) eventLoop()).addShutdownHook(shutdownHook); - } - - @Override - protected void doBind(SocketAddress localAddress) throws Exception { - this.localAddress = - LocalChannelRegistry.register(this, this.localAddress, - localAddress); - state = 1; - } - - @Override - protected void doDisconnect() throws Exception { - doClose(); - } - - @Override - protected void doClose() throws Exception { - final LocalChannel peer = this.peer; - if (state <= 2) { - // Update all internal state before the closeFuture is notified. - if (localAddress != null) { - if (parent() == null) { - LocalChannelRegistry.unregister(localAddress); - } - localAddress = null; - } - - // State change must happen before finishPeerRead to ensure writes are released either in doWrite or - // channelRead. - state = 3; - - ChannelPromise promise = connectPromise; - if (promise != null) { - // Use tryFailure() instead of setFailure() to avoid the race against cancel(). - promise.tryFailure(CLOSED_CHANNEL_EXCEPTION); - connectPromise = null; - } - - // To preserve ordering of events we must process any pending reads - if (writeInProgress && peer != null) { - finishPeerRead(peer); - } - } - - if (peer != null && peer.isActive()) { - // Need to execute the close in the correct EventLoop (see https://github.com/netty/netty/issues/1777). - // Also check if the registration was not done yet. In this case we submit the close to the EventLoop - // to make sure its run after the registration completes (see https://github.com/netty/netty/issues/2144). - if (peer.eventLoop().inEventLoop() && !registerInProgress) { - doPeerClose(peer, peer.writeInProgress); - } else { - // This value may change, and so we should save it before executing the Runnable. - final boolean peerWriteInProgress = peer.writeInProgress; - try { - peer.eventLoop().execute(new OneTimeTask() { - @Override - public void run() { - doPeerClose(peer, peerWriteInProgress); - } - }); - } catch (RuntimeException e) { - // The peer close may attempt to drain this.inboundBuffers. If that fails make sure it is drained. - releaseInboundBuffers(); - throw e; - } - } - this.peer = null; - } - } - - private void doPeerClose(LocalChannel peer, boolean peerWriteInProgress) { - if (peerWriteInProgress) { - finishPeerRead0(this); - } - peer.unsafe().close(peer.unsafe().voidPromise()); - } - - @Override - protected void doDeregister() throws Exception { - // Just remove the shutdownHook as this Channel may be closed later or registered to another EventLoop - ((SingleThreadEventExecutor) eventLoop()).removeShutdownHook(shutdownHook); - } - - @Override - protected void doBeginRead() throws Exception { - if (readInProgress) { - return; - } - - ChannelPipeline pipeline = pipeline(); - Queue inboundBuffer = this.inboundBuffer; - if (inboundBuffer.isEmpty()) { - readInProgress = true; - return; - } - - final InternalThreadLocalMap threadLocals = InternalThreadLocalMap.get(); - final Integer stackDepth = threadLocals.localChannelReaderStackDepth(); - if (stackDepth < MAX_READER_STACK_DEPTH) { - threadLocals.setLocalChannelReaderStackDepth(stackDepth + 1); - try { - for (;;) { - Object received = inboundBuffer.poll(); - if (received == null) { - break; - } - pipeline.fireChannelRead(received); - } - pipeline.fireChannelReadComplete(); - } finally { - threadLocals.setLocalChannelReaderStackDepth(stackDepth); - } - } else { - try { - eventLoop().execute(readTask); - } catch (RuntimeException e) { - releaseInboundBuffers(); - throw e; - } - } - } - - @Override - protected void doWrite(ChannelOutboundBuffer in) throws Exception { - if (state < 2) { - throw new NotYetConnectedException(); - } - if (state > 2) { - throw CLOSED_CHANNEL_EXCEPTION; - } - - final LocalChannel peer = this.peer; - - writeInProgress = true; - try { - for (;;) { - Object msg = in.current(); - if (msg == null) { - break; - } - try { - // It is possible the peer could have closed while we are writing, and in this case we should - // simulate real socket behavior and ensure the write operation is failed. - if (peer.state == 2) { - peer.inboundBuffer.add(ReferenceCountUtil.retain(msg)); - in.remove(); - } else { - in.remove(CLOSED_CHANNEL_EXCEPTION); - } - } catch (Throwable cause) { - in.remove(cause); - } - } - } finally { - // The following situation may cause trouble: - // 1. Write (with promise X) - // 2. promise X is completed when in.remove() is called, and a listener on this promise calls close() - // 3. Then the close event will be executed for the peer before the write events, when the write events - // actually happened before the close event. - writeInProgress = false; - } - - finishPeerRead(peer); - } - - private void finishPeerRead(final LocalChannel peer) { - // If the peer is also writing, then we must schedule the event on the event loop to preserve read order. - if (peer.eventLoop() == eventLoop() && !peer.writeInProgress) { - finishPeerRead0(peer); - } else { - runFinishPeerReadTask(peer); - } - } - - private void runFinishPeerReadTask(final LocalChannel peer) { - // If the peer is writing, we must wait until after reads are completed for that peer before we can read. So - // we keep track of the task, and coordinate later that our read can't happen until the peer is done. - final Runnable finishPeerReadTask = new OneTimeTask() { - @Override - public void run() { - finishPeerRead0(peer); - } - }; - try { - if (peer.writeInProgress) { - peer.finishReadFuture = peer.eventLoop().submit(finishPeerReadTask); - } else { - peer.eventLoop().execute(finishPeerReadTask); - } - } catch (RuntimeException e) { - peer.releaseInboundBuffers(); - throw e; - } - } - - private void releaseInboundBuffers() { - for (;;) { - Object o = inboundBuffer.poll(); - if (o == null) { - break; - } - ReferenceCountUtil.release(o); - } - } - - private void finishPeerRead0(LocalChannel peer) { - Future peerFinishReadFuture = peer.finishReadFuture; - if (peerFinishReadFuture != null) { - if (!peerFinishReadFuture.isDone()) { - runFinishPeerReadTask(peer); - return; - } else { - // Lazy unset to make sure we don't prematurely unset it while scheduling a new task. - FINISH_READ_FUTURE_UPDATER.compareAndSet(peer, peerFinishReadFuture, null); - } - } - ChannelPipeline peerPipeline = peer.pipeline(); - if (peer.readInProgress) { - peer.readInProgress = false; - for (;;) { - Object received = peer.inboundBuffer.poll(); - if (received == null) { - break; - } - peerPipeline.fireChannelRead(received); - } - peerPipeline.fireChannelReadComplete(); - } - } - - private class LocalUnsafe extends AbstractUnsafe { - - @Override - public void connect(final SocketAddress remoteAddress, - SocketAddress localAddress, final ChannelPromise promise) { - if (!promise.setUncancellable() || !ensureOpen(promise)) { - return; - } - - if (state == 2) { - Exception cause = new AlreadyConnectedException(); - safeSetFailure(promise, cause); - pipeline().fireExceptionCaught(cause); - return; - } - - if (connectPromise != null) { - throw new ConnectionPendingException(); - } - - connectPromise = promise; - - if (state != 1) { - // Not bound yet and no localAddress specified - get one. - if (localAddress == null) { - localAddress = new LocalAddress(LocalChannel.this); - } - } - - if (localAddress != null) { - try { - doBind(localAddress); - } catch (Throwable t) { - safeSetFailure(promise, t); - close(voidPromise()); - return; - } - } - - Channel boundChannel = LocalChannelRegistry.get(remoteAddress); - if (!(boundChannel instanceof LocalServerChannel)) { - Exception cause = new ChannelException("connection refused"); - safeSetFailure(promise, cause); - close(voidPromise()); - return; - } - - LocalServerChannel serverChannel = (LocalServerChannel) boundChannel; - peer = serverChannel.serve(LocalChannel.this); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/local/LocalChannelRegistry.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/local/LocalChannelRegistry.java deleted file mode 100755 index 2b9fc2e450..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/local/LocalChannelRegistry.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.local; - -import java.net.SocketAddress; -import java.util.concurrent.ConcurrentMap; - -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelException; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; -import com.ai.cloud.io.netty.util.internal.StringUtil; - -final class LocalChannelRegistry { - - private static final ConcurrentMap boundChannels = PlatformDependent.newConcurrentHashMap(); - - static LocalAddress register( - Channel channel, LocalAddress oldLocalAddress, SocketAddress localAddress) { - if (oldLocalAddress != null) { - throw new ChannelException("already bound"); - } - if (!(localAddress instanceof LocalAddress)) { - throw new ChannelException("unsupported address type: " + StringUtil.simpleClassName(localAddress)); - } - - LocalAddress addr = (LocalAddress) localAddress; - if (LocalAddress.ANY.equals(addr)) { - addr = new LocalAddress(channel); - } - - Channel boundChannel = boundChannels.putIfAbsent(addr, channel); - if (boundChannel != null) { - throw new ChannelException("address already in use by: " + boundChannel); - } - return addr; - } - - static Channel get(SocketAddress localAddress) { - return boundChannels.get(localAddress); - } - - static void unregister(LocalAddress localAddress) { - boundChannels.remove(localAddress); - } - - private LocalChannelRegistry() { - // Unused - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/local/LocalEventLoop.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/local/LocalEventLoop.java deleted file mode 100755 index be1227e932..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/local/LocalEventLoop.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.local; - -import java.util.concurrent.ThreadFactory; - -import com.ai.cloud.io.netty.channel.SingleThreadEventLoop; - -final class LocalEventLoop extends SingleThreadEventLoop { - - LocalEventLoop(LocalEventLoopGroup parent, ThreadFactory threadFactory) { - super(parent, threadFactory, true); - } - - @Override - protected void run() { - for (;;) { - Runnable task = takeTask(); - if (task != null) { - task.run(); - updateLastExecutionTime(); - } - - if (confirmShutdown()) { - break; - } - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/local/LocalEventLoopGroup.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/local/LocalEventLoopGroup.java deleted file mode 100755 index c50e09a04a..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/local/LocalEventLoopGroup.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.local; - -import java.util.concurrent.ThreadFactory; - -import com.ai.cloud.io.netty.channel.MultithreadEventLoopGroup; -import com.ai.cloud.io.netty.util.concurrent.EventExecutor; - -/** - * {@link MultithreadEventLoopGroup} which must be used for the local transport. - */ -public class LocalEventLoopGroup extends MultithreadEventLoopGroup { - - /** - * Create a new instance with the default number of threads. - */ - public LocalEventLoopGroup() { - this(0); - } - - /** - * Create a new instance - * - * @param nThreads the number of threads to use - */ - public LocalEventLoopGroup(int nThreads) { - this(nThreads, null); - } - - /** - * Create a new instance - * - * @param nThreads the number of threads to use - * @param threadFactory the {@link ThreadFactory} or {@code null} to use the default - */ - public LocalEventLoopGroup(int nThreads, ThreadFactory threadFactory) { - super(nThreads, threadFactory); - } - - @Override - protected EventExecutor newChild( - ThreadFactory threadFactory, Object... args) throws Exception { - return new LocalEventLoop(this, threadFactory); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/local/LocalServerChannel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/local/LocalServerChannel.java deleted file mode 100755 index e934a1381f..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/local/LocalServerChannel.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.local; - -import java.net.SocketAddress; -import java.util.ArrayDeque; -import java.util.Queue; - -import com.ai.cloud.io.netty.channel.AbstractServerChannel; -import com.ai.cloud.io.netty.channel.ChannelConfig; -import com.ai.cloud.io.netty.channel.ChannelPipeline; -import com.ai.cloud.io.netty.channel.DefaultChannelConfig; -import com.ai.cloud.io.netty.channel.EventLoop; -import com.ai.cloud.io.netty.channel.ServerChannel; -import com.ai.cloud.io.netty.channel.SingleThreadEventLoop; -import com.ai.cloud.io.netty.util.concurrent.SingleThreadEventExecutor; - -/** - * A {@link ServerChannel} for the local transport which allows in VM communication. - */ -public class LocalServerChannel extends AbstractServerChannel { - - private final ChannelConfig config = new DefaultChannelConfig(this); - private final Queue inboundBuffer = new ArrayDeque(); - private final Runnable shutdownHook = new Runnable() { - @Override - public void run() { - unsafe().close(unsafe().voidPromise()); - } - }; - - private volatile int state; // 0 - open, 1 - active, 2 - closed - private volatile LocalAddress localAddress; - private volatile boolean acceptInProgress; - - @Override - public ChannelConfig config() { - return config; - } - - @Override - public LocalAddress localAddress() { - return (LocalAddress) super.localAddress(); - } - - @Override - public LocalAddress remoteAddress() { - return (LocalAddress) super.remoteAddress(); - } - - @Override - public boolean isOpen() { - return state < 2; - } - - @Override - public boolean isActive() { - return state == 1; - } - - @Override - protected boolean isCompatible(EventLoop loop) { - return loop instanceof SingleThreadEventLoop; - } - - @Override - protected SocketAddress localAddress0() { - return localAddress; - } - - @Override - protected void doRegister() throws Exception { - ((SingleThreadEventExecutor) eventLoop()).addShutdownHook(shutdownHook); - } - - @Override - protected void doBind(SocketAddress localAddress) throws Exception { - this.localAddress = LocalChannelRegistry.register(this, this.localAddress, localAddress); - state = 1; - } - - @Override - protected void doClose() throws Exception { - if (state <= 1) { - // Update all internal state before the closeFuture is notified. - if (localAddress != null) { - LocalChannelRegistry.unregister(localAddress); - localAddress = null; - } - state = 2; - } - } - - @Override - protected void doDeregister() throws Exception { - ((SingleThreadEventExecutor) eventLoop()).removeShutdownHook(shutdownHook); - } - - @Override - protected void doBeginRead() throws Exception { - if (acceptInProgress) { - return; - } - - Queue inboundBuffer = this.inboundBuffer; - if (inboundBuffer.isEmpty()) { - acceptInProgress = true; - return; - } - - ChannelPipeline pipeline = pipeline(); - for (;;) { - Object m = inboundBuffer.poll(); - if (m == null) { - break; - } - pipeline.fireChannelRead(m); - } - pipeline.fireChannelReadComplete(); - } - - LocalChannel serve(final LocalChannel peer) { - final LocalChannel child = new LocalChannel(this, peer); - if (eventLoop().inEventLoop()) { - serve0(child); - } else { - eventLoop().execute(new Runnable() { - @Override - public void run() { - serve0(child); - } - }); - } - return child; - } - - private void serve0(final LocalChannel child) { - inboundBuffer.add(child); - if (acceptInProgress) { - acceptInProgress = false; - ChannelPipeline pipeline = pipeline(); - for (;;) { - Object m = inboundBuffer.poll(); - if (m == null) { - break; - } - pipeline.fireChannelRead(m); - } - pipeline.fireChannelReadComplete(); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/local/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/local/package-info.java deleted file mode 100755 index a5caf2b30b..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/local/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * A virtual transport that enables the communication between the two - * parties in the same virtual machine. - */ -package com.ai.cloud.io.netty.channel.local; diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/nio/AbstractNioByteChannel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/nio/AbstractNioByteChannel.java deleted file mode 100755 index f72ddb52c7..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/nio/AbstractNioByteChannel.java +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.nio; - -import java.io.IOException; -import java.nio.channels.SelectableChannel; -import java.nio.channels.SelectionKey; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.ByteBufAllocator; -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelConfig; -import com.ai.cloud.io.netty.channel.ChannelOption; -import com.ai.cloud.io.netty.channel.ChannelOutboundBuffer; -import com.ai.cloud.io.netty.channel.ChannelPipeline; -import com.ai.cloud.io.netty.channel.FileRegion; -import com.ai.cloud.io.netty.channel.RecvByteBufAllocator; -import com.ai.cloud.io.netty.channel.socket.ChannelInputShutdownEvent; -import com.ai.cloud.io.netty.util.internal.StringUtil; - -/** - * {@link AbstractNioChannel} base class for {@link Channel}s that operate on bytes. - */ -public abstract class AbstractNioByteChannel extends AbstractNioChannel { - - private static final String EXPECTED_TYPES = - " (expected: " + StringUtil.simpleClassName(ByteBuf.class) + ", " + - StringUtil.simpleClassName(FileRegion.class) + ')'; - - private Runnable flushTask; - - /** - * Create a new instance - * - * @param parent the parent {@link Channel} by which this instance was created. May be {@code null} - * @param ch the underlying {@link SelectableChannel} on which it operates - */ - protected AbstractNioByteChannel(Channel parent, SelectableChannel ch) { - super(parent, ch, SelectionKey.OP_READ); - } - - @Override - protected AbstractNioUnsafe newUnsafe() { - return new NioByteUnsafe(); - } - - protected class NioByteUnsafe extends AbstractNioUnsafe { - private RecvByteBufAllocator.Handle allocHandle; - - private void closeOnRead(ChannelPipeline pipeline) { - SelectionKey key = selectionKey(); - setInputShutdown(); - if (isOpen()) { - if (Boolean.TRUE.equals(config().getOption(ChannelOption.ALLOW_HALF_CLOSURE))) { - key.interestOps(key.interestOps() & ~readInterestOp); - pipeline.fireUserEventTriggered(ChannelInputShutdownEvent.INSTANCE); - } else { - close(voidPromise()); - } - } - } - - private void handleReadException(ChannelPipeline pipeline, - ByteBuf byteBuf, Throwable cause, boolean close) { - if (byteBuf != null) { - if (byteBuf.isReadable()) { - setReadPending(false); - pipeline.fireChannelRead(byteBuf); - } else { - byteBuf.release(); - } - } - pipeline.fireChannelReadComplete(); - pipeline.fireExceptionCaught(cause); - if (close || cause instanceof IOException) { - closeOnRead(pipeline); - } - } - - @Override - public final void read() { - final ChannelConfig config = config(); - if (!config.isAutoRead() && !isReadPending()) { - // ChannelConfig.setAutoRead(false) was called in the meantime - removeReadOp(); - return; - } - - final ChannelPipeline pipeline = pipeline(); - final ByteBufAllocator allocator = config.getAllocator(); - final int maxMessagesPerRead = config.getMaxMessagesPerRead(); - RecvByteBufAllocator.Handle allocHandle = this.allocHandle; - if (allocHandle == null) { - this.allocHandle = allocHandle = config.getRecvByteBufAllocator().newHandle(); - } - - ByteBuf byteBuf = null; - int messages = 0; - boolean close = false; - try { - int totalReadAmount = 0; - boolean readPendingReset = false; - do { - byteBuf = allocHandle.allocate(allocator); - int writable = byteBuf.writableBytes(); - int localReadAmount = doReadBytes(byteBuf); - if (localReadAmount <= 0) { - // not was read release the buffer - byteBuf.release(); - byteBuf = null; - close = localReadAmount < 0; - break; - } - if (!readPendingReset) { - readPendingReset = true; - setReadPending(false); - } - pipeline.fireChannelRead(byteBuf); - byteBuf = null; - - if (totalReadAmount >= Integer.MAX_VALUE - localReadAmount) { - // Avoid overflow. - totalReadAmount = Integer.MAX_VALUE; - break; - } - - totalReadAmount += localReadAmount; - - // stop reading - if (!config.isAutoRead()) { - break; - } - - if (localReadAmount < writable) { - // Read less than what the buffer can hold, - // which might mean we drained the recv buffer completely. - break; - } - } while (++ messages < maxMessagesPerRead); - - pipeline.fireChannelReadComplete(); - allocHandle.record(totalReadAmount); - - if (close) { - closeOnRead(pipeline); - close = false; - } - } catch (Throwable t) { - handleReadException(pipeline, byteBuf, t, close); - } finally { - // Check if there is a readPending which was not processed yet. - // This could be for two reasons: - // * The user called Channel.read() or ChannelHandlerContext.read() in channelRead(...) method - // * The user called Channel.read() or ChannelHandlerContext.read() in channelReadComplete(...) method - // - // See https://github.com/netty/netty/issues/2254 - if (!config.isAutoRead() && !isReadPending()) { - removeReadOp(); - } - } - } - } - - @Override - protected void doWrite(ChannelOutboundBuffer in) throws Exception { - int writeSpinCount = -1; - - boolean setOpWrite = false; - for (;;) { - Object msg = in.current(); - if (msg == null) { - // Wrote all messages. - clearOpWrite(); - // Directly return here so incompleteWrite(...) is not called. - return; - } - - if (msg instanceof ByteBuf) { - ByteBuf buf = (ByteBuf) msg; - int readableBytes = buf.readableBytes(); - if (readableBytes == 0) { - in.remove(); - continue; - } - - boolean done = false; - long flushedAmount = 0; - if (writeSpinCount == -1) { - writeSpinCount = config().getWriteSpinCount(); - } - for (int i = writeSpinCount - 1; i >= 0; i --) { - int localFlushedAmount = doWriteBytes(buf); - if (localFlushedAmount == 0) { - setOpWrite = true; - break; - } - - flushedAmount += localFlushedAmount; - if (!buf.isReadable()) { - done = true; - break; - } - } - - in.progress(flushedAmount); - - if (done) { - in.remove(); - } else { - // Break the loop and so incompleteWrite(...) is called. - break; - } - } else if (msg instanceof FileRegion) { - FileRegion region = (FileRegion) msg; - boolean done = region.transfered() >= region.count(); - - if (!done) { - long flushedAmount = 0; - if (writeSpinCount == -1) { - writeSpinCount = config().getWriteSpinCount(); - } - - for (int i = writeSpinCount - 1; i >= 0; i--) { - long localFlushedAmount = doWriteFileRegion(region); - if (localFlushedAmount == 0) { - setOpWrite = true; - break; - } - - flushedAmount += localFlushedAmount; - if (region.transfered() >= region.count()) { - done = true; - break; - } - } - - in.progress(flushedAmount); - } - - if (done) { - in.remove(); - } else { - // Break the loop and so incompleteWrite(...) is called. - break; - } - } else { - // Should not reach here. - throw new Error(); - } - } - incompleteWrite(setOpWrite); - } - - @Override - protected final Object filterOutboundMessage(Object msg) { - if (msg instanceof ByteBuf) { - ByteBuf buf = (ByteBuf) msg; - if (buf.isDirect()) { - return msg; - } - - return newDirectBuffer(buf); - } - - if (msg instanceof FileRegion) { - return msg; - } - - throw new UnsupportedOperationException( - "unsupported message type: " + StringUtil.simpleClassName(msg) + EXPECTED_TYPES); - } - - protected final void incompleteWrite(boolean setOpWrite) { - // Did not write completely. - if (setOpWrite) { - setOpWrite(); - } else { - // Schedule flush again later so other tasks can be picked up in the meantime - Runnable flushTask = this.flushTask; - if (flushTask == null) { - flushTask = this.flushTask = new Runnable() { - @Override - public void run() { - flush(); - } - }; - } - eventLoop().execute(flushTask); - } - } - - /** - * Write a {@link FileRegion} - * - * @param region the {@link FileRegion} from which the bytes should be written - * @return amount the amount of written bytes - */ - protected abstract long doWriteFileRegion(FileRegion region) throws Exception; - - /** - * Read bytes into the given {@link ByteBuf} and return the amount. - */ - protected abstract int doReadBytes(ByteBuf buf) throws Exception; - - /** - * Write bytes form the given {@link ByteBuf} to the underlying {@link java.nio.channels.Channel}. - * @param buf the {@link ByteBuf} from which the bytes should be written - * @return amount the amount of written bytes - */ - protected abstract int doWriteBytes(ByteBuf buf) throws Exception; - - protected final void setOpWrite() { - final SelectionKey key = selectionKey(); - // Check first if the key is still valid as it may be canceled as part of the deregistration - // from the EventLoop - // See https://github.com/netty/netty/issues/2104 - if (!key.isValid()) { - return; - } - final int interestOps = key.interestOps(); - if ((interestOps & SelectionKey.OP_WRITE) == 0) { - key.interestOps(interestOps | SelectionKey.OP_WRITE); - } - } - - protected final void clearOpWrite() { - final SelectionKey key = selectionKey(); - // Check first if the key is still valid as it may be canceled as part of the deregistration - // from the EventLoop - // See https://github.com/netty/netty/issues/2104 - if (!key.isValid()) { - return; - } - final int interestOps = key.interestOps(); - if ((interestOps & SelectionKey.OP_WRITE) != 0) { - key.interestOps(interestOps & ~SelectionKey.OP_WRITE); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/nio/AbstractNioChannel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/nio/AbstractNioChannel.java deleted file mode 100755 index 9e9653d4f7..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/nio/AbstractNioChannel.java +++ /dev/null @@ -1,472 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.nio; - -import java.io.IOException; -import java.net.SocketAddress; -import java.nio.channels.CancelledKeyException; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.SelectableChannel; -import java.nio.channels.SelectionKey; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.ByteBufAllocator; -import com.ai.cloud.io.netty.buffer.ByteBufUtil; -import com.ai.cloud.io.netty.buffer.Unpooled; -import com.ai.cloud.io.netty.channel.AbstractChannel; -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelException; -import com.ai.cloud.io.netty.channel.ChannelFuture; -import com.ai.cloud.io.netty.channel.ChannelFutureListener; -import com.ai.cloud.io.netty.channel.ChannelPromise; -import com.ai.cloud.io.netty.channel.ConnectTimeoutException; -import com.ai.cloud.io.netty.channel.EventLoop; -import com.ai.cloud.io.netty.util.ReferenceCountUtil; -import com.ai.cloud.io.netty.util.ReferenceCounted; -import com.ai.cloud.io.netty.util.internal.EmptyArrays; -import com.ai.cloud.io.netty.util.internal.OneTimeTask; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * Abstract base class for {@link Channel} implementations which use a Selector based approach. - */ -public abstract class AbstractNioChannel extends AbstractChannel { - - private static final InternalLogger logger = - InternalLoggerFactory.getInstance(AbstractNioChannel.class); - - private static final ClosedChannelException CLOSED_CHANNEL_EXCEPTION = new ClosedChannelException(); - - static { - CLOSED_CHANNEL_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); - } - - private final SelectableChannel ch; - protected final int readInterestOp; - volatile SelectionKey selectionKey; - private volatile boolean inputShutdown; - private volatile boolean readPending; - - /** - * The future of the current connection attempt. If not null, subsequent - * connection attempts will fail. - */ - private ChannelPromise connectPromise; - private ScheduledFuture connectTimeoutFuture; - private SocketAddress requestedRemoteAddress; - - /** - * Create a new instance - * - * @param parent the parent {@link Channel} by which this instance was created. May be {@code null} - * @param ch the underlying {@link SelectableChannel} on which it operates - * @param readInterestOp the ops to set to receive data from the {@link SelectableChannel} - */ - protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) { - super(parent); - this.ch = ch; - this.readInterestOp = readInterestOp; - try { - ch.configureBlocking(false); - } catch (IOException e) { - try { - ch.close(); - } catch (IOException e2) { - if (logger.isWarnEnabled()) { - logger.warn( - "Failed to close a partially initialized socket.", e2); - } - } - - throw new ChannelException("Failed to enter non-blocking mode.", e); - } - } - - @Override - public boolean isOpen() { - return ch.isOpen(); - } - - @Override - public NioUnsafe unsafe() { - return (NioUnsafe) super.unsafe(); - } - - protected SelectableChannel javaChannel() { - return ch; - } - - @Override - public NioEventLoop eventLoop() { - return (NioEventLoop) super.eventLoop(); - } - - /** - * Return the current {@link SelectionKey} - */ - protected SelectionKey selectionKey() { - assert selectionKey != null; - return selectionKey; - } - - protected boolean isReadPending() { - return readPending; - } - - protected void setReadPending(boolean readPending) { - this.readPending = readPending; - } - - /** - * Return {@code true} if the input of this {@link Channel} is shutdown - */ - protected boolean isInputShutdown() { - return inputShutdown; - } - - /** - * Shutdown the input of this {@link Channel}. - */ - void setInputShutdown() { - inputShutdown = true; - } - - /** - * Special {@link Unsafe} sub-type which allows to access the underlying {@link SelectableChannel} - */ - public interface NioUnsafe extends Unsafe { - /** - * Return underlying {@link SelectableChannel} - */ - SelectableChannel ch(); - - /** - * Finish connect - */ - void finishConnect(); - - /** - * Read from underlying {@link SelectableChannel} - */ - void read(); - - void forceFlush(); - } - - protected abstract class AbstractNioUnsafe extends AbstractUnsafe implements NioUnsafe { - - protected final void removeReadOp() { - SelectionKey key = selectionKey(); - // Check first if the key is still valid as it may be canceled as part of the deregistration - // from the EventLoop - // See https://github.com/netty/netty/issues/2104 - if (!key.isValid()) { - return; - } - int interestOps = key.interestOps(); - if ((interestOps & readInterestOp) != 0) { - // only remove readInterestOp if needed - key.interestOps(interestOps & ~readInterestOp); - } - } - - @Override - public final SelectableChannel ch() { - return javaChannel(); - } - - @Override - public final void connect( - final SocketAddress remoteAddress, final SocketAddress localAddress, final ChannelPromise promise) { - if (!promise.setUncancellable() || !ensureOpen(promise)) { - return; - } - - try { - if (connectPromise != null) { - throw new IllegalStateException("connection attempt already made"); - } - - boolean wasActive = isActive(); - if (doConnect(remoteAddress, localAddress)) { - fulfillConnectPromise(promise, wasActive); - } else { - connectPromise = promise; - requestedRemoteAddress = remoteAddress; - - // Schedule connect timeout. - int connectTimeoutMillis = config().getConnectTimeoutMillis(); - if (connectTimeoutMillis > 0) { - connectTimeoutFuture = eventLoop().schedule(new OneTimeTask() { - @Override - public void run() { - ChannelPromise connectPromise = AbstractNioChannel.this.connectPromise; - ConnectTimeoutException cause = - new ConnectTimeoutException("connection timed out: " + remoteAddress); - if (connectPromise != null && connectPromise.tryFailure(cause)) { - close(voidPromise()); - } - } - }, connectTimeoutMillis, TimeUnit.MILLISECONDS); - } - - promise.addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - if (future.isCancelled()) { - if (connectTimeoutFuture != null) { - connectTimeoutFuture.cancel(false); - } - connectPromise = null; - close(voidPromise()); - } - } - }); - } - } catch (Throwable t) { - promise.tryFailure(annotateConnectException(t, remoteAddress)); - closeIfClosed(); - } - } - - private void fulfillConnectPromise(ChannelPromise promise, boolean wasActive) { - if (promise == null) { - // Closed via cancellation and the promise has been notified already. - return; - } - - // trySuccess() will return false if a user cancelled the connection attempt. - boolean promiseSet = promise.trySuccess(); - - // Regardless if the connection attempt was cancelled, channelActive() event should be triggered, - // because what happened is what happened. - if (!wasActive && isActive()) { - pipeline().fireChannelActive(); - } - - // If a user cancelled the connection attempt, close the channel, which is followed by channelInactive(). - if (!promiseSet) { - close(voidPromise()); - } - } - - private void fulfillConnectPromise(ChannelPromise promise, Throwable cause) { - if (promise == null) { - // Closed via cancellation and the promise has been notified already. - return; - } - - // Use tryFailure() instead of setFailure() to avoid the race against cancel(). - promise.tryFailure(cause); - closeIfClosed(); - } - - @Override - public final void finishConnect() { - // Note this method is invoked by the event loop only if the connection attempt was - // neither cancelled nor timed out. - - assert eventLoop().inEventLoop(); - - try { - boolean wasActive = isActive(); - doFinishConnect(); - fulfillConnectPromise(connectPromise, wasActive); - } catch (Throwable t) { - fulfillConnectPromise(connectPromise, annotateConnectException(t, requestedRemoteAddress)); - } finally { - // Check for null as the connectTimeoutFuture is only created if a connectTimeoutMillis > 0 is used - // See https://github.com/netty/netty/issues/1770 - if (connectTimeoutFuture != null) { - connectTimeoutFuture.cancel(false); - } - connectPromise = null; - } - } - - @Override - protected final void flush0() { - // Flush immediately only when there's no pending flush. - // If there's a pending flush operation, event loop will call forceFlush() later, - // and thus there's no need to call it now. - if (isFlushPending()) { - return; - } - super.flush0(); - } - - @Override - public final void forceFlush() { - // directly call super.flush0() to force a flush now - super.flush0(); - } - - private boolean isFlushPending() { - SelectionKey selectionKey = selectionKey(); - return selectionKey.isValid() && (selectionKey.interestOps() & SelectionKey.OP_WRITE) != 0; - } - } - - @Override - protected boolean isCompatible(EventLoop loop) { - return loop instanceof NioEventLoop; - } - - @Override - protected void doRegister() throws Exception { - boolean selected = false; - for (;;) { - try { - selectionKey = javaChannel().register(eventLoop().selector, 0, this); - return; - } catch (CancelledKeyException e) { - if (!selected) { - // Force the Selector to select now as the "canceled" SelectionKey may still be - // cached and not removed because no Select.select(..) operation was called yet. - eventLoop().selectNow(); - selected = true; - } else { - // We forced a select operation on the selector before but the SelectionKey is still cached - // for whatever reason. JDK bug ? - throw e; - } - } - } - } - - @Override - protected void doDeregister() throws Exception { - eventLoop().cancel(selectionKey()); - } - - @Override - protected void doBeginRead() throws Exception { - // Channel.read() or ChannelHandlerContext.read() was called - if (inputShutdown) { - return; - } - - final SelectionKey selectionKey = this.selectionKey; - if (!selectionKey.isValid()) { - return; - } - - readPending = true; - - final int interestOps = selectionKey.interestOps(); - if ((interestOps & readInterestOp) == 0) { - selectionKey.interestOps(interestOps | readInterestOp); - } - } - - /** - * Connect to the remote peer - */ - protected abstract boolean doConnect(SocketAddress remoteAddress, SocketAddress localAddress) throws Exception; - - /** - * Finish the connect - */ - protected abstract void doFinishConnect() throws Exception; - - /** - * Returns an off-heap copy of the specified {@link ByteBuf}, and releases the original one. - * Note that this method does not create an off-heap copy if the allocation / deallocation cost is too high, - * but just returns the original {@link ByteBuf}.. - */ - protected final ByteBuf newDirectBuffer(ByteBuf buf) { - final int readableBytes = buf.readableBytes(); - if (readableBytes == 0) { - ReferenceCountUtil.safeRelease(buf); - return Unpooled.EMPTY_BUFFER; - } - - final ByteBufAllocator alloc = alloc(); - if (alloc.isDirectBufferPooled()) { - ByteBuf directBuf = alloc.directBuffer(readableBytes); - directBuf.writeBytes(buf, buf.readerIndex(), readableBytes); - ReferenceCountUtil.safeRelease(buf); - return directBuf; - } - - final ByteBuf directBuf = ByteBufUtil.threadLocalDirectBuffer(); - if (directBuf != null) { - directBuf.writeBytes(buf, buf.readerIndex(), readableBytes); - ReferenceCountUtil.safeRelease(buf); - return directBuf; - } - - // Allocating and deallocating an unpooled direct buffer is very expensive; give up. - return buf; - } - - /** - * Returns an off-heap copy of the specified {@link ByteBuf}, and releases the specified holder. - * The caller must ensure that the holder releases the original {@link ByteBuf} when the holder is released by - * this method. Note that this method does not create an off-heap copy if the allocation / deallocation cost is - * too high, but just returns the original {@link ByteBuf}.. - */ - protected final ByteBuf newDirectBuffer(ReferenceCounted holder, ByteBuf buf) { - final int readableBytes = buf.readableBytes(); - if (readableBytes == 0) { - ReferenceCountUtil.safeRelease(holder); - return Unpooled.EMPTY_BUFFER; - } - - final ByteBufAllocator alloc = alloc(); - if (alloc.isDirectBufferPooled()) { - ByteBuf directBuf = alloc.directBuffer(readableBytes); - directBuf.writeBytes(buf, buf.readerIndex(), readableBytes); - ReferenceCountUtil.safeRelease(holder); - return directBuf; - } - - final ByteBuf directBuf = ByteBufUtil.threadLocalDirectBuffer(); - if (directBuf != null) { - directBuf.writeBytes(buf, buf.readerIndex(), readableBytes); - ReferenceCountUtil.safeRelease(holder); - return directBuf; - } - - // Allocating and deallocating an unpooled direct buffer is very expensive; give up. - if (holder != buf) { - // Ensure to call holder.release() to give the holder a chance to release other resources than its content. - buf.retain(); - ReferenceCountUtil.safeRelease(holder); - } - - return buf; - } - - @Override - protected void doClose() throws Exception { - ChannelPromise promise = connectPromise; - if (promise != null) { - // Use tryFailure() instead of setFailure() to avoid the race against cancel(). - promise.tryFailure(CLOSED_CHANNEL_EXCEPTION); - connectPromise = null; - } - - ScheduledFuture future = connectTimeoutFuture; - if (future != null) { - future.cancel(false); - connectTimeoutFuture = null; - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/nio/AbstractNioMessageChannel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/nio/AbstractNioMessageChannel.java deleted file mode 100755 index e70b72f509..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/nio/AbstractNioMessageChannel.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.nio; - -import java.io.IOException; -import java.net.PortUnreachableException; -import java.nio.channels.SelectableChannel; -import java.nio.channels.SelectionKey; -import java.util.ArrayList; -import java.util.List; - -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelConfig; -import com.ai.cloud.io.netty.channel.ChannelOutboundBuffer; -import com.ai.cloud.io.netty.channel.ChannelPipeline; -import com.ai.cloud.io.netty.channel.ServerChannel; - -/** - * {@link AbstractNioChannel} base class for {@link Channel}s that operate on messages. - */ -public abstract class AbstractNioMessageChannel extends AbstractNioChannel { - - /** - * @see {@link AbstractNioChannel#AbstractNioChannel(Channel, SelectableChannel, int)} - */ - protected AbstractNioMessageChannel(Channel parent, SelectableChannel ch, int readInterestOp) { - super(parent, ch, readInterestOp); - } - - @Override - protected AbstractNioUnsafe newUnsafe() { - return new NioMessageUnsafe(); - } - - private final class NioMessageUnsafe extends AbstractNioUnsafe { - - private final List readBuf = new ArrayList(); - - @Override - public void read() { - assert eventLoop().inEventLoop(); - final ChannelConfig config = config(); - if (!config.isAutoRead() && !isReadPending()) { - // ChannelConfig.setAutoRead(false) was called in the meantime - removeReadOp(); - return; - } - - final int maxMessagesPerRead = config.getMaxMessagesPerRead(); - final ChannelPipeline pipeline = pipeline(); - boolean closed = false; - Throwable exception = null; - try { - try { - for (;;) { - int localRead = doReadMessages(readBuf); - if (localRead == 0) { - break; - } - if (localRead < 0) { - closed = true; - break; - } - - // stop reading and remove op - if (!config.isAutoRead()) { - break; - } - - if (readBuf.size() >= maxMessagesPerRead) { - break; - } - } - } catch (Throwable t) { - exception = t; - } - setReadPending(false); - int size = readBuf.size(); - for (int i = 0; i < size; i ++) { - pipeline.fireChannelRead(readBuf.get(i)); - } - - readBuf.clear(); - pipeline.fireChannelReadComplete(); - - if (exception != null) { - if (exception instanceof IOException && !(exception instanceof PortUnreachableException)) { - // ServerChannel should not be closed even on IOException because it can often continue - // accepting incoming connections. (e.g. too many open files) - closed = !(AbstractNioMessageChannel.this instanceof ServerChannel); - } - - pipeline.fireExceptionCaught(exception); - } - - if (closed) { - if (isOpen()) { - close(voidPromise()); - } - } - } finally { - // Check if there is a readPending which was not processed yet. - // This could be for two reasons: - // * The user called Channel.read() or ChannelHandlerContext.read() in channelRead(...) method - // * The user called Channel.read() or ChannelHandlerContext.read() in channelReadComplete(...) method - // - // See https://github.com/netty/netty/issues/2254 - if (!config.isAutoRead() && !isReadPending()) { - removeReadOp(); - } - } - } - } - - @Override - protected void doWrite(ChannelOutboundBuffer in) throws Exception { - final SelectionKey key = selectionKey(); - final int interestOps = key.interestOps(); - - for (;;) { - Object msg = in.current(); - if (msg == null) { - // Wrote all messages. - if ((interestOps & SelectionKey.OP_WRITE) != 0) { - key.interestOps(interestOps & ~SelectionKey.OP_WRITE); - } - break; - } - try { - boolean done = false; - for (int i = config().getWriteSpinCount() - 1; i >= 0; i--) { - if (doWriteMessage(msg, in)) { - done = true; - break; - } - } - - if (done) { - in.remove(); - } else { - // Did not write all messages. - if ((interestOps & SelectionKey.OP_WRITE) == 0) { - key.interestOps(interestOps | SelectionKey.OP_WRITE); - } - break; - } - } catch (IOException e) { - if (continueOnWriteError()) { - in.remove(e); - } else { - throw e; - } - } - } - } - - /** - * Returns {@code true} if we should continue the write loop on a write error. - */ - protected boolean continueOnWriteError() { - return false; - } - - /** - * Read messages into the given array and return the amount which was read. - */ - protected abstract int doReadMessages(List buf) throws Exception; - - /** - * Write a message to the underlying {@link java.nio.channels.Channel}. - * - * @return {@code true} if and only if the message has been written - */ - protected abstract boolean doWriteMessage(Object msg, ChannelOutboundBuffer in) throws Exception; -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/nio/NioEventLoop.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/nio/NioEventLoop.java deleted file mode 100755 index 4a89f35bfb..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/nio/NioEventLoop.java +++ /dev/null @@ -1,692 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.nio; - - -import java.io.IOException; -import java.lang.reflect.Field; -import java.nio.channels.CancelledKeyException; -import java.nio.channels.SelectableChannel; -import java.nio.channels.SelectionKey; -import java.nio.channels.Selector; -import java.nio.channels.spi.SelectorProvider; -import java.util.ArrayList; -import java.util.Collection; -import java.util.ConcurrentModificationException; -import java.util.Iterator; -import java.util.Queue; -import java.util.Set; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelException; -import com.ai.cloud.io.netty.channel.EventLoopException; -import com.ai.cloud.io.netty.channel.SingleThreadEventLoop; -import com.ai.cloud.io.netty.channel.nio.AbstractNioChannel.NioUnsafe; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; -import com.ai.cloud.io.netty.util.internal.SystemPropertyUtil; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * {@link SingleThreadEventLoop} implementation which register the {@link Channel}'s to a - * {@link Selector} and so does the multi-plexing of these in the event loop. - * - */ -public final class NioEventLoop extends SingleThreadEventLoop { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(NioEventLoop.class); - - private static final int CLEANUP_INTERVAL = 256; // XXX Hard-coded value, but won't need customization. - - private static final boolean DISABLE_KEYSET_OPTIMIZATION = - SystemPropertyUtil.getBoolean("io.netty.noKeySetOptimization", false); - - private static final int MIN_PREMATURE_SELECTOR_RETURNS = 3; - private static final int SELECTOR_AUTO_REBUILD_THRESHOLD; - - // Workaround for JDK NIO bug. - // - // See: - // - http://bugs.sun.com/view_bug.do?bug_id=6427854 - // - https://github.com/netty/netty/issues/203 - static { - String key = "sun.nio.ch.bugLevel"; - try { - String buglevel = SystemPropertyUtil.get(key); - if (buglevel == null) { - System.setProperty(key, ""); - } - } catch (SecurityException e) { - if (logger.isDebugEnabled()) { - logger.debug("Unable to get/set System Property: {}", key, e); - } - } - - int selectorAutoRebuildThreshold = SystemPropertyUtil.getInt("io.netty.selectorAutoRebuildThreshold", 512); - if (selectorAutoRebuildThreshold < MIN_PREMATURE_SELECTOR_RETURNS) { - selectorAutoRebuildThreshold = 0; - } - - SELECTOR_AUTO_REBUILD_THRESHOLD = selectorAutoRebuildThreshold; - - if (logger.isDebugEnabled()) { - logger.debug("-Dio.netty.noKeySetOptimization: {}", DISABLE_KEYSET_OPTIMIZATION); - logger.debug("-Dio.netty.selectorAutoRebuildThreshold: {}", SELECTOR_AUTO_REBUILD_THRESHOLD); - } - } - - /** - * The NIO {@link Selector}. - */ - Selector selector; - private SelectedSelectionKeySet selectedKeys; - - private final SelectorProvider provider; - - /** - * Boolean that controls determines if a blocked Selector.select should - * break out of its selection process. In our case we use a timeout for - * the select method and the select method will block for that time unless - * waken up. - */ - private final AtomicBoolean wakenUp = new AtomicBoolean(); - - private volatile int ioRatio = 50; - private int cancelledKeys; - private boolean needsToSelectAgain; - - NioEventLoop(NioEventLoopGroup parent, ThreadFactory threadFactory, SelectorProvider selectorProvider) { - super(parent, threadFactory, false); - if (selectorProvider == null) { - throw new NullPointerException("selectorProvider"); - } - provider = selectorProvider; - selector = openSelector(); - } - - private Selector openSelector() { - final Selector selector; - try { - selector = provider.openSelector(); - } catch (IOException e) { - throw new ChannelException("failed to open a new selector", e); - } - - if (DISABLE_KEYSET_OPTIMIZATION) { - return selector; - } - - try { - SelectedSelectionKeySet selectedKeySet = new SelectedSelectionKeySet(); - - Class selectorImplClass = - Class.forName("sun.nio.ch.SelectorImpl", false, PlatformDependent.getSystemClassLoader()); - - // Ensure the current selector implementation is what we can instrument. - if (!selectorImplClass.isAssignableFrom(selector.getClass())) { - return selector; - } - - Field selectedKeysField = selectorImplClass.getDeclaredField("selectedKeys"); - Field publicSelectedKeysField = selectorImplClass.getDeclaredField("publicSelectedKeys"); - - selectedKeysField.setAccessible(true); - publicSelectedKeysField.setAccessible(true); - - selectedKeysField.set(selector, selectedKeySet); - publicSelectedKeysField.set(selector, selectedKeySet); - - selectedKeys = selectedKeySet; - logger.trace("Instrumented an optimized java.util.Set into: {}", selector); - } catch (Throwable t) { - selectedKeys = null; - logger.trace("Failed to instrument an optimized java.util.Set into: {}", selector, t); - } - - return selector; - } - - @Override - protected Queue newTaskQueue() { - // This event loop never calls takeTask() - return PlatformDependent.newMpscQueue(); - } - - /** - * Registers an arbitrary {@link SelectableChannel}, not necessarily created by Netty, to the {@link Selector} - * of this event loop. Once the specified {@link SelectableChannel} is registered, the specified {@code task} will - * be executed by this event loop when the {@link SelectableChannel} is ready. - */ - public void register(final SelectableChannel ch, final int interestOps, final NioTask task) { - if (ch == null) { - throw new NullPointerException("ch"); - } - if (interestOps == 0) { - throw new IllegalArgumentException("interestOps must be non-zero."); - } - if ((interestOps & ~ch.validOps()) != 0) { - throw new IllegalArgumentException( - "invalid interestOps: " + interestOps + "(validOps: " + ch.validOps() + ')'); - } - if (task == null) { - throw new NullPointerException("task"); - } - - if (isShutdown()) { - throw new IllegalStateException("event loop shut down"); - } - - try { - ch.register(selector, interestOps, task); - } catch (Exception e) { - throw new EventLoopException("failed to register a channel", e); - } - } - - /** - * Returns the percentage of the desired amount of time spent for I/O in the event loop. - */ - public int getIoRatio() { - return ioRatio; - } - - /** - * Sets the percentage of the desired amount of time spent for I/O in the event loop. The default value is - * {@code 50}, which means the event loop will try to spend the same amount of time for I/O as for non-I/O tasks. - */ - public void setIoRatio(int ioRatio) { - if (ioRatio <= 0 || ioRatio > 100) { - throw new IllegalArgumentException("ioRatio: " + ioRatio + " (expected: 0 < ioRatio <= 100)"); - } - this.ioRatio = ioRatio; - } - - /** - * Replaces the current {@link Selector} of this event loop with newly created {@link Selector}s to work - * around the infamous epoll 100% CPU bug. - */ - public void rebuildSelector() { - if (!inEventLoop()) { - execute(new Runnable() { - @Override - public void run() { - rebuildSelector(); - } - }); - return; - } - - final Selector oldSelector = selector; - final Selector newSelector; - - if (oldSelector == null) { - return; - } - - try { - newSelector = openSelector(); - } catch (Exception e) { - logger.warn("Failed to create a new Selector.", e); - return; - } - - // Register all channels to the new Selector. - int nChannels = 0; - for (;;) { - try { - for (SelectionKey key: oldSelector.keys()) { - Object a = key.attachment(); - try { - if (!key.isValid() || key.channel().keyFor(newSelector) != null) { - continue; - } - - int interestOps = key.interestOps(); - key.cancel(); - SelectionKey newKey = key.channel().register(newSelector, interestOps, a); - if (a instanceof AbstractNioChannel) { - // Update SelectionKey - ((AbstractNioChannel) a).selectionKey = newKey; - } - nChannels ++; - } catch (Exception e) { - logger.warn("Failed to re-register a Channel to the new Selector.", e); - if (a instanceof AbstractNioChannel) { - AbstractNioChannel ch = (AbstractNioChannel) a; - ch.unsafe().close(ch.unsafe().voidPromise()); - } else { - @SuppressWarnings("unchecked") - NioTask task = (NioTask) a; - invokeChannelUnregistered(task, key, e); - } - } - } - } catch (ConcurrentModificationException e) { - // Probably due to concurrent modification of the key set. - continue; - } - - break; - } - - selector = newSelector; - - try { - // time to close the old selector as everything else is registered to the new one - oldSelector.close(); - } catch (Throwable t) { - if (logger.isWarnEnabled()) { - logger.warn("Failed to close the old Selector.", t); - } - } - - logger.info("Migrated " + nChannels + " channel(s) to the new Selector."); - } - - @Override - protected void run() { - for (;;) { - boolean oldWakenUp = wakenUp.getAndSet(false); - try { - if (hasTasks()) { - selectNow(); - } else { - select(oldWakenUp); - - // 'wakenUp.compareAndSet(false, true)' is always evaluated - // before calling 'selector.wakeup()' to reduce the wake-up - // overhead. (Selector.wakeup() is an expensive operation.) - // - // However, there is a race condition in this approach. - // The race condition is triggered when 'wakenUp' is set to - // true too early. - // - // 'wakenUp' is set to true too early if: - // 1) Selector is waken up between 'wakenUp.set(false)' and - // 'selector.select(...)'. (BAD) - // 2) Selector is waken up between 'selector.select(...)' and - // 'if (wakenUp.get()) { ... }'. (OK) - // - // In the first case, 'wakenUp' is set to true and the - // following 'selector.select(...)' will wake up immediately. - // Until 'wakenUp' is set to false again in the next round, - // 'wakenUp.compareAndSet(false, true)' will fail, and therefore - // any attempt to wake up the Selector will fail, too, causing - // the following 'selector.select(...)' call to block - // unnecessarily. - // - // To fix this problem, we wake up the selector again if wakenUp - // is true immediately after selector.select(...). - // It is inefficient in that it wakes up the selector for both - // the first case (BAD - wake-up required) and the second case - // (OK - no wake-up required). - - if (wakenUp.get()) { - selector.wakeup(); - } - } - - cancelledKeys = 0; - needsToSelectAgain = false; - final int ioRatio = this.ioRatio; - if (ioRatio == 100) { - processSelectedKeys(); - runAllTasks(); - } else { - final long ioStartTime = System.nanoTime(); - - processSelectedKeys(); - - final long ioTime = System.nanoTime() - ioStartTime; - runAllTasks(ioTime * (100 - ioRatio) / ioRatio); - } - - if (isShuttingDown()) { - closeAll(); - if (confirmShutdown()) { - break; - } - } - } catch (Throwable t) { - logger.warn("Unexpected exception in the selector loop.", t); - - // Prevent possible consecutive immediate failures that lead to - // excessive CPU consumption. - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - // Ignore. - } - } - } - } - - private void processSelectedKeys() { - if (selectedKeys != null) { - processSelectedKeysOptimized(selectedKeys.flip()); - } else { - processSelectedKeysPlain(selector.selectedKeys()); - } - } - - @Override - protected void cleanup() { - try { - selector.close(); - } catch (IOException e) { - logger.warn("Failed to close a selector.", e); - } - } - - void cancel(SelectionKey key) { - key.cancel(); - cancelledKeys ++; - if (cancelledKeys >= CLEANUP_INTERVAL) { - cancelledKeys = 0; - needsToSelectAgain = true; - } - } - - @Override - protected Runnable pollTask() { - Runnable task = super.pollTask(); - if (needsToSelectAgain) { - selectAgain(); - } - return task; - } - - private void processSelectedKeysPlain(Set selectedKeys) { - // check if the set is empty and if so just return to not create garbage by - // creating a new Iterator every time even if there is nothing to process. - // See https://github.com/netty/netty/issues/597 - if (selectedKeys.isEmpty()) { - return; - } - - Iterator i = selectedKeys.iterator(); - for (;;) { - final SelectionKey k = i.next(); - final Object a = k.attachment(); - i.remove(); - - if (a instanceof AbstractNioChannel) { - processSelectedKey(k, (AbstractNioChannel) a); - } else { - @SuppressWarnings("unchecked") - NioTask task = (NioTask) a; - processSelectedKey(k, task); - } - - if (!i.hasNext()) { - break; - } - - if (needsToSelectAgain) { - selectAgain(); - selectedKeys = selector.selectedKeys(); - - // Create the iterator again to avoid ConcurrentModificationException - if (selectedKeys.isEmpty()) { - break; - } else { - i = selectedKeys.iterator(); - } - } - } - } - - private void processSelectedKeysOptimized(SelectionKey[] selectedKeys) { - for (int i = 0;; i ++) { - final SelectionKey k = selectedKeys[i]; - if (k == null) { - break; - } - // null out entry in the array to allow to have it GC'ed once the Channel close - // See https://github.com/netty/netty/issues/2363 - selectedKeys[i] = null; - - final Object a = k.attachment(); - - if (a instanceof AbstractNioChannel) { - processSelectedKey(k, (AbstractNioChannel) a); - } else { - @SuppressWarnings("unchecked") - NioTask task = (NioTask) a; - processSelectedKey(k, task); - } - - if (needsToSelectAgain) { - // null out entries in the array to allow to have it GC'ed once the Channel close - // See https://github.com/netty/netty/issues/2363 - for (;;) { - if (selectedKeys[i] == null) { - break; - } - selectedKeys[i] = null; - i++; - } - - selectAgain(); - // Need to flip the optimized selectedKeys to get the right reference to the array - // and reset the index to -1 which will then set to 0 on the for loop - // to start over again. - // - // See https://github.com/netty/netty/issues/1523 - selectedKeys = this.selectedKeys.flip(); - i = -1; - } - } - } - - private static void processSelectedKey(SelectionKey k, AbstractNioChannel ch) { - final NioUnsafe unsafe = ch.unsafe(); - if (!k.isValid()) { - // close the channel if the key is not valid anymore - unsafe.close(unsafe.voidPromise()); - return; - } - - try { - int readyOps = k.readyOps(); - // Also check for readOps of 0 to workaround possible JDK bug which may otherwise lead - // to a spin loop - if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) { - unsafe.read(); - if (!ch.isOpen()) { - // Connection already closed - no need to handle write. - return; - } - } - if ((readyOps & SelectionKey.OP_WRITE) != 0) { - // Call forceFlush which will also take care of clear the OP_WRITE once there is nothing left to write - ch.unsafe().forceFlush(); - } - if ((readyOps & SelectionKey.OP_CONNECT) != 0) { - // remove OP_CONNECT as otherwise Selector.select(..) will always return without blocking - // See https://github.com/netty/netty/issues/924 - int ops = k.interestOps(); - ops &= ~SelectionKey.OP_CONNECT; - k.interestOps(ops); - - unsafe.finishConnect(); - } - } catch (CancelledKeyException ignored) { - unsafe.close(unsafe.voidPromise()); - } - } - - private static void processSelectedKey(SelectionKey k, NioTask task) { - int state = 0; - try { - task.channelReady(k.channel(), k); - state = 1; - } catch (Exception e) { - k.cancel(); - invokeChannelUnregistered(task, k, e); - state = 2; - } finally { - switch (state) { - case 0: - k.cancel(); - invokeChannelUnregistered(task, k, null); - break; - case 1: - if (!k.isValid()) { // Cancelled by channelReady() - invokeChannelUnregistered(task, k, null); - } - break; - } - } - } - - private void closeAll() { - selectAgain(); - Set keys = selector.keys(); - Collection channels = new ArrayList(keys.size()); - for (SelectionKey k: keys) { - Object a = k.attachment(); - if (a instanceof AbstractNioChannel) { - channels.add((AbstractNioChannel) a); - } else { - k.cancel(); - @SuppressWarnings("unchecked") - NioTask task = (NioTask) a; - invokeChannelUnregistered(task, k, null); - } - } - - for (AbstractNioChannel ch: channels) { - ch.unsafe().close(ch.unsafe().voidPromise()); - } - } - - private static void invokeChannelUnregistered(NioTask task, SelectionKey k, Throwable cause) { - try { - task.channelUnregistered(k.channel(), cause); - } catch (Exception e) { - logger.warn("Unexpected exception while running NioTask.channelUnregistered()", e); - } - } - - @Override - protected void wakeup(boolean inEventLoop) { - if (!inEventLoop && wakenUp.compareAndSet(false, true)) { - selector.wakeup(); - } - } - - void selectNow() throws IOException { - try { - selector.selectNow(); - } finally { - // restore wakup state if needed - if (wakenUp.get()) { - selector.wakeup(); - } - } - } - - private void select(boolean oldWakenUp) throws IOException { - Selector selector = this.selector; - try { - int selectCnt = 0; - long currentTimeNanos = System.nanoTime(); - long selectDeadLineNanos = currentTimeNanos + delayNanos(currentTimeNanos); - for (;;) { - long timeoutMillis = (selectDeadLineNanos - currentTimeNanos + 500000L) / 1000000L; - if (timeoutMillis <= 0) { - if (selectCnt == 0) { - selector.selectNow(); - selectCnt = 1; - } - break; - } - - int selectedKeys = selector.select(timeoutMillis); - selectCnt ++; - - if (selectedKeys != 0 || oldWakenUp || wakenUp.get() || hasTasks() || hasScheduledTasks()) { - // - Selected something, - // - waken up by user, or - // - the task queue has a pending task. - // - a scheduled task is ready for processing - break; - } - if (Thread.interrupted()) { - // Thread was interrupted so reset selected keys and break so we not run into a busy loop. - // As this is most likely a bug in the handler of the user or it's client library we will - // also log it. - // - // See https://github.com/netty/netty/issues/2426 - if (logger.isDebugEnabled()) { - logger.debug("Selector.select() returned prematurely because " + - "Thread.currentThread().interrupt() was called. Use " + - "NioEventLoop.shutdownGracefully() to shutdown the NioEventLoop."); - } - selectCnt = 1; - break; - } - - long time = System.nanoTime(); - if (time - TimeUnit.MILLISECONDS.toNanos(timeoutMillis) >= currentTimeNanos) { - // timeoutMillis elapsed without anything selected. - selectCnt = 1; - } else if (SELECTOR_AUTO_REBUILD_THRESHOLD > 0 && - selectCnt >= SELECTOR_AUTO_REBUILD_THRESHOLD) { - // The selector returned prematurely many times in a row. - // Rebuild the selector to work around the problem. - logger.warn( - "Selector.select() returned prematurely {} times in a row; rebuilding selector.", - selectCnt); - - rebuildSelector(); - selector = this.selector; - - // Select again to populate selectedKeys. - selector.selectNow(); - selectCnt = 1; - break; - } - - currentTimeNanos = time; - } - - if (selectCnt > MIN_PREMATURE_SELECTOR_RETURNS) { - if (logger.isDebugEnabled()) { - logger.debug("Selector.select() returned prematurely {} times in a row.", selectCnt - 1); - } - } - } catch (CancelledKeyException e) { - if (logger.isDebugEnabled()) { - logger.debug(CancelledKeyException.class.getSimpleName() + " raised by a Selector - JDK bug?", e); - } - // Harmless exception - log anyway - } - } - - private void selectAgain() { - needsToSelectAgain = false; - try { - selector.selectNow(); - } catch (Throwable t) { - logger.warn("Failed to update SelectionKeys.", t); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/nio/NioEventLoopGroup.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/nio/NioEventLoopGroup.java deleted file mode 100755 index 0d43921612..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/nio/NioEventLoopGroup.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.nio; - -import java.nio.channels.Selector; -import java.nio.channels.spi.SelectorProvider; -import java.util.concurrent.ThreadFactory; - -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.MultithreadEventLoopGroup; -import com.ai.cloud.io.netty.util.concurrent.EventExecutor; - -/** - * {@link MultithreadEventLoopGroup} implementations which is used for NIO {@link Selector} based {@link Channel}s. - */ -public class NioEventLoopGroup extends MultithreadEventLoopGroup { - - /** - * Create a new instance using the default number of threads, the default {@link ThreadFactory} and - * the {@link SelectorProvider} which is returned by {@link SelectorProvider#provider()}. - */ - public NioEventLoopGroup() { - this(0); - } - - /** - * Create a new instance using the specified number of threads, {@link ThreadFactory} and the - * {@link SelectorProvider} which is returned by {@link SelectorProvider#provider()}. - */ - public NioEventLoopGroup(int nThreads) { - this(nThreads, null); - } - - /** - * Create a new instance using the specified number of threads, the given {@link ThreadFactory} and the - * {@link SelectorProvider} which is returned by {@link SelectorProvider#provider()}. - */ - public NioEventLoopGroup(int nThreads, ThreadFactory threadFactory) { - this(nThreads, threadFactory, SelectorProvider.provider()); - } - - /** - * Create a new instance using the specified number of threads, the given {@link ThreadFactory} and the given - * {@link SelectorProvider}. - */ - public NioEventLoopGroup( - int nThreads, ThreadFactory threadFactory, final SelectorProvider selectorProvider) { - super(nThreads, threadFactory, selectorProvider); - } - - /** - * Sets the percentage of the desired amount of time spent for I/O in the child event loops. The default value is - * {@code 50}, which means the event loop will try to spend the same amount of time for I/O as for non-I/O tasks. - */ - public void setIoRatio(int ioRatio) { - for (EventExecutor e: children()) { - ((NioEventLoop) e).setIoRatio(ioRatio); - } - } - - /** - * Replaces the current {@link Selector}s of the child event loops with newly created {@link Selector}s to work - * around the infamous epoll 100% CPU bug. - */ - public void rebuildSelectors() { - for (EventExecutor e: children()) { - ((NioEventLoop) e).rebuildSelector(); - } - } - - @Override - protected EventExecutor newChild( - ThreadFactory threadFactory, Object... args) throws Exception { - return new NioEventLoop(this, threadFactory, (SelectorProvider) args[0]); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/nio/NioTask.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/nio/NioTask.java deleted file mode 100755 index 171b6ddd5c..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/nio/NioTask.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.nio; - -import java.nio.channels.SelectableChannel; -import java.nio.channels.SelectionKey; -import java.nio.channels.Selector; - -/** - * An arbitrary task that can be executed by {@link NioEventLoop} when a {@link SelectableChannel} becomes ready. - * - * @see NioEventLoop#register(SelectableChannel, int, NioTask) - */ -public interface NioTask { - /** - * Invoked when the {@link SelectableChannel} has been selected by the {@link Selector}. - */ - void channelReady(C ch, SelectionKey key) throws Exception; - - /** - * Invoked when the {@link SelectionKey} of the specified {@link SelectableChannel} has been cancelled and thus - * this {@link NioTask} will not be notified anymore. - * - * @param cause the cause of the unregistration. {@code null} if a user called {@link SelectionKey#cancel()} or - * the event loop has been shut down. - */ - void channelUnregistered(C ch, Throwable cause) throws Exception; -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/nio/SelectedSelectionKeySet.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/nio/SelectedSelectionKeySet.java deleted file mode 100755 index 5a7115c73e..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/nio/SelectedSelectionKeySet.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.channel.nio; - -import java.nio.channels.SelectionKey; -import java.util.AbstractSet; -import java.util.Iterator; - -final class SelectedSelectionKeySet extends AbstractSet { - - private SelectionKey[] keysA; - private int keysASize; - private SelectionKey[] keysB; - private int keysBSize; - private boolean isA = true; - - SelectedSelectionKeySet() { - keysA = new SelectionKey[1024]; - keysB = keysA.clone(); - } - - @Override - public boolean add(SelectionKey o) { - if (o == null) { - return false; - } - - if (isA) { - int size = keysASize; - keysA[size ++] = o; - keysASize = size; - if (size == keysA.length) { - doubleCapacityA(); - } - } else { - int size = keysBSize; - keysB[size ++] = o; - keysBSize = size; - if (size == keysB.length) { - doubleCapacityB(); - } - } - - return true; - } - - private void doubleCapacityA() { - SelectionKey[] newKeysA = new SelectionKey[keysA.length << 1]; - System.arraycopy(keysA, 0, newKeysA, 0, keysASize); - keysA = newKeysA; - } - - private void doubleCapacityB() { - SelectionKey[] newKeysB = new SelectionKey[keysB.length << 1]; - System.arraycopy(keysB, 0, newKeysB, 0, keysBSize); - keysB = newKeysB; - } - - SelectionKey[] flip() { - if (isA) { - isA = false; - keysA[keysASize] = null; - keysBSize = 0; - return keysA; - } else { - isA = true; - keysB[keysBSize] = null; - keysASize = 0; - return keysB; - } - } - - @Override - public int size() { - if (isA) { - return keysASize; - } else { - return keysBSize; - } - } - - @Override - public boolean remove(Object o) { - return false; - } - - @Override - public boolean contains(Object o) { - return false; - } - - @Override - public Iterator iterator() { - throw new UnsupportedOperationException(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/nio/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/nio/package-info.java deleted file mode 100755 index 366cdbac38..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/nio/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * NIO-based channel - * API implementation - recommended for a large number of connections (>= 1000). - */ -package com.ai.cloud.io.netty.channel.nio; diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/oio/AbstractOioByteChannel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/oio/AbstractOioByteChannel.java deleted file mode 100755 index 5c6096fa32..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/oio/AbstractOioByteChannel.java +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.oio; - -import java.io.IOException; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelConfig; -import com.ai.cloud.io.netty.channel.ChannelMetadata; -import com.ai.cloud.io.netty.channel.ChannelOption; -import com.ai.cloud.io.netty.channel.ChannelOutboundBuffer; -import com.ai.cloud.io.netty.channel.ChannelPipeline; -import com.ai.cloud.io.netty.channel.FileRegion; -import com.ai.cloud.io.netty.channel.RecvByteBufAllocator; -import com.ai.cloud.io.netty.channel.socket.ChannelInputShutdownEvent; -import com.ai.cloud.io.netty.util.internal.StringUtil; - -/** - * Abstract base class for OIO which reads and writes bytes from/to a Socket - */ -public abstract class AbstractOioByteChannel extends AbstractOioChannel { - - private static final ChannelMetadata METADATA = new ChannelMetadata(false); - private static final String EXPECTED_TYPES = - " (expected: " + StringUtil.simpleClassName(ByteBuf.class) + ", " + - StringUtil.simpleClassName(FileRegion.class) + ')'; - - private RecvByteBufAllocator.Handle allocHandle; - private volatile boolean inputShutdown; - - /** - * @see AbstractOioByteChannel#AbstractOioByteChannel(Channel) - */ - protected AbstractOioByteChannel(Channel parent) { - super(parent); - } - - protected boolean isInputShutdown() { - return inputShutdown; - } - - @Override - public ChannelMetadata metadata() { - return METADATA; - } - - /** - * Check if the input was shutdown and if so return {@code true}. The default implementation sleeps also for - * {@link #SO_TIMEOUT} milliseconds to simulate some blocking. - */ - protected boolean checkInputShutdown() { - if (inputShutdown) { - try { - Thread.sleep(SO_TIMEOUT); - } catch (InterruptedException e) { - // ignore - } - return true; - } - return false; - } - - @Override - protected void doRead() { - if (checkInputShutdown()) { - return; - } - final ChannelConfig config = config(); - final ChannelPipeline pipeline = pipeline(); - - RecvByteBufAllocator.Handle allocHandle = this.allocHandle; - if (allocHandle == null) { - this.allocHandle = allocHandle = config.getRecvByteBufAllocator().newHandle(); - } - - ByteBuf byteBuf = allocHandle.allocate(alloc()); - - boolean closed = false; - boolean read = false; - Throwable exception = null; - int localReadAmount = 0; - try { - int totalReadAmount = 0; - - for (;;) { - localReadAmount = doReadBytes(byteBuf); - if (localReadAmount > 0) { - read = true; - } else if (localReadAmount < 0) { - closed = true; - } - - final int available = available(); - if (available <= 0) { - break; - } - - if (!byteBuf.isWritable()) { - final int capacity = byteBuf.capacity(); - final int maxCapacity = byteBuf.maxCapacity(); - if (capacity == maxCapacity) { - if (read) { - read = false; - pipeline.fireChannelRead(byteBuf); - byteBuf = alloc().buffer(); - } - } else { - final int writerIndex = byteBuf.writerIndex(); - if (writerIndex + available > maxCapacity) { - byteBuf.capacity(maxCapacity); - } else { - byteBuf.ensureWritable(available); - } - } - } - - if (totalReadAmount >= Integer.MAX_VALUE - localReadAmount) { - // Avoid overflow. - totalReadAmount = Integer.MAX_VALUE; - break; - } - - totalReadAmount += localReadAmount; - - if (!config.isAutoRead()) { - // stop reading until next Channel.read() call - // See https://github.com/netty/netty/issues/1363 - break; - } - } - allocHandle.record(totalReadAmount); - - } catch (Throwable t) { - exception = t; - } finally { - if (read) { - pipeline.fireChannelRead(byteBuf); - } else { - // nothing read into the buffer so release it - byteBuf.release(); - } - - pipeline.fireChannelReadComplete(); - if (exception != null) { - if (exception instanceof IOException) { - closed = true; - pipeline().fireExceptionCaught(exception); - } else { - pipeline.fireExceptionCaught(exception); - unsafe().close(voidPromise()); - } - } - - if (closed) { - inputShutdown = true; - if (isOpen()) { - if (Boolean.TRUE.equals(config().getOption(ChannelOption.ALLOW_HALF_CLOSURE))) { - pipeline.fireUserEventTriggered(ChannelInputShutdownEvent.INSTANCE); - } else { - unsafe().close(unsafe().voidPromise()); - } - } - } - if (localReadAmount == 0 && isActive()) { - // If the read amount was 0 and the channel is still active we need to trigger a new read() - // as otherwise we will never try to read again and the user will never know. - // Just call read() is ok here as it will be submitted to the EventLoop as a task and so we are - // able to process the rest of the tasks in the queue first. - // - // See https://github.com/netty/netty/issues/2404 - read(); - } - } - } - - @Override - protected void doWrite(ChannelOutboundBuffer in) throws Exception { - for (;;) { - Object msg = in.current(); - if (msg == null) { - // nothing left to write - break; - } - if (msg instanceof ByteBuf) { - ByteBuf buf = (ByteBuf) msg; - int readableBytes = buf.readableBytes(); - while (readableBytes > 0) { - doWriteBytes(buf); - int newReadableBytes = buf.readableBytes(); - in.progress(readableBytes - newReadableBytes); - readableBytes = newReadableBytes; - } - in.remove(); - } else if (msg instanceof FileRegion) { - FileRegion region = (FileRegion) msg; - long transfered = region.transfered(); - doWriteFileRegion(region); - in.progress(region.transfered() - transfered); - in.remove(); - } else { - in.remove(new UnsupportedOperationException( - "unsupported message type: " + StringUtil.simpleClassName(msg))); - } - } - } - - @Override - protected final Object filterOutboundMessage(Object msg) throws Exception { - if (msg instanceof ByteBuf || msg instanceof FileRegion) { - return msg; - } - - throw new UnsupportedOperationException( - "unsupported message type: " + StringUtil.simpleClassName(msg) + EXPECTED_TYPES); - } - - /** - * Return the number of bytes ready to read from the underlying Socket. - */ - protected abstract int available(); - - /** - * Read bytes from the underlying Socket. - * - * @param buf the {@link ByteBuf} into which the read bytes will be written - * @return amount the number of bytes read. This may return a negative amount if the underlying - * Socket was closed - * @throws Exception is thrown if an error occurred - */ - protected abstract int doReadBytes(ByteBuf buf) throws Exception; - - /** - * Write the data which is hold by the {@link ByteBuf} to the underlying Socket. - * - * @param buf the {@link ByteBuf} which holds the data to transfer - * @throws Exception is thrown if an error occurred - */ - protected abstract void doWriteBytes(ByteBuf buf) throws Exception; - - /** - * Write the data which is hold by the {@link FileRegion} to the underlying Socket. - * - * @param region the {@link FileRegion} which holds the data to transfer - * @throws Exception is thrown if an error occurred - */ - protected abstract void doWriteFileRegion(FileRegion region) throws Exception; -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/oio/AbstractOioChannel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/oio/AbstractOioChannel.java deleted file mode 100755 index 1a7ec87d5a..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/oio/AbstractOioChannel.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.oio; - -import java.net.SocketAddress; - -import com.ai.cloud.io.netty.channel.AbstractChannel; -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelPromise; -import com.ai.cloud.io.netty.channel.EventLoop; -import com.ai.cloud.io.netty.channel.ThreadPerChannelEventLoop; - -/** - * Abstract base class for {@link Channel} implementations that use Old-Blocking-IO - */ -public abstract class AbstractOioChannel extends AbstractChannel { - - protected static final int SO_TIMEOUT = 1000; - - private volatile boolean readPending; - - private final Runnable readTask = new Runnable() { - @Override - public void run() { - if (!isReadPending() && !config().isAutoRead()) { - // ChannelConfig.setAutoRead(false) was called in the meantime so just return - return; - } - - setReadPending(false); - doRead(); - } - }; - - /** - * @see AbstractChannel#AbstractChannel(Channel) - */ - protected AbstractOioChannel(Channel parent) { - super(parent); - } - - @Override - protected AbstractUnsafe newUnsafe() { - return new DefaultOioUnsafe(); - } - - private final class DefaultOioUnsafe extends AbstractUnsafe { - @Override - public void connect( - final SocketAddress remoteAddress, - final SocketAddress localAddress, final ChannelPromise promise) { - if (!promise.setUncancellable() || !ensureOpen(promise)) { - return; - } - - try { - boolean wasActive = isActive(); - doConnect(remoteAddress, localAddress); - safeSetSuccess(promise); - if (!wasActive && isActive()) { - pipeline().fireChannelActive(); - } - } catch (Throwable t) { - safeSetFailure(promise, annotateConnectException(t, remoteAddress)); - closeIfClosed(); - } - } - } - - @Override - protected boolean isCompatible(EventLoop loop) { - return loop instanceof ThreadPerChannelEventLoop; - } - - /** - * Connect to the remote peer using the given localAddress if one is specified or {@code null} otherwise. - */ - protected abstract void doConnect( - SocketAddress remoteAddress, SocketAddress localAddress) throws Exception; - - @Override - protected void doBeginRead() throws Exception { - if (isReadPending()) { - return; - } - - setReadPending(true); - eventLoop().execute(readTask); - } - - protected abstract void doRead(); - - protected boolean isReadPending() { - return readPending; - } - - protected void setReadPending(boolean readPending) { - this.readPending = readPending; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/oio/AbstractOioMessageChannel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/oio/AbstractOioMessageChannel.java deleted file mode 100755 index c4115f419a..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/oio/AbstractOioMessageChannel.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.oio; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelConfig; -import com.ai.cloud.io.netty.channel.ChannelPipeline; - -/** - * Abstract base class for OIO which reads and writes objects from/to a Socket - */ -public abstract class AbstractOioMessageChannel extends AbstractOioChannel { - - private final List readBuf = new ArrayList(); - - protected AbstractOioMessageChannel(Channel parent) { - super(parent); - } - - @Override - protected void doRead() { - final ChannelConfig config = config(); - final ChannelPipeline pipeline = pipeline(); - boolean closed = false; - final int maxMessagesPerRead = config.getMaxMessagesPerRead(); - - Throwable exception = null; - int localRead = 0; - int totalRead = 0; - try { - for (;;) { - // Perform a read. - localRead = doReadMessages(readBuf); - if (localRead == 0) { - break; - } - if (localRead < 0) { - closed = true; - break; - } - - // Notify with the received messages and clear the buffer. - int size = readBuf.size(); - for (int i = 0; i < size; i ++) { - pipeline.fireChannelRead(readBuf.get(i)); - } - readBuf.clear(); - - // Do not read beyond maxMessagesPerRead. - // Do not continue reading if autoRead has been turned off. - totalRead += localRead; - if (totalRead >= maxMessagesPerRead || !config.isAutoRead()) { - break; - } - } - } catch (Throwable t) { - exception = t; - } - - pipeline.fireChannelReadComplete(); - - if (exception != null) { - if (exception instanceof IOException) { - closed = true; - } - - pipeline().fireExceptionCaught(exception); - } - - if (closed) { - if (isOpen()) { - unsafe().close(unsafe().voidPromise()); - } - } else if (localRead == 0 && isActive()) { - // If the read amount was 0 and the channel is still active we need to trigger a new read() - // as otherwise we will never try to read again and the user will never know. - // Just call read() is ok here as it will be submitted to the EventLoop as a task and so we are - // able to process the rest of the tasks in the queue first. - // - // See https://github.com/netty/netty/issues/2404 - read(); - } - } - - /** - * Read messages into the given array and return the amount which was read. - */ - protected abstract int doReadMessages(List msgs) throws Exception; -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/oio/OioByteStreamChannel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/oio/OioByteStreamChannel.java deleted file mode 100755 index 48e32ff180..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/oio/OioByteStreamChannel.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.oio; - -import java.io.EOFException; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.channels.Channels; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.NotYetConnectedException; -import java.nio.channels.WritableByteChannel; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.FileRegion; - -/** - * Abstract base class for OIO Channels that are based on streams. - */ -public abstract class OioByteStreamChannel extends AbstractOioByteChannel { - - private static final InputStream CLOSED_IN = new InputStream() { - @Override - public int read() { - return -1; - } - }; - - private static final OutputStream CLOSED_OUT = new OutputStream() { - @Override - public void write(int b) throws IOException { - throw new ClosedChannelException(); - } - }; - - private InputStream is; - private OutputStream os; - private WritableByteChannel outChannel; - - /** - * Create a new instance - * - * @param parent the parent {@link Channel} which was used to create this instance. This can be null if the - * {@link} has no parent as it was created by your self. - */ - protected OioByteStreamChannel(Channel parent) { - super(parent); - } - - /** - * Activate this instance. After this call {@link #isActive()} will return {@code true}. - */ - protected final void activate(InputStream is, OutputStream os) { - if (this.is != null) { - throw new IllegalStateException("input was set already"); - } - if (this.os != null) { - throw new IllegalStateException("output was set already"); - } - if (is == null) { - throw new NullPointerException("is"); - } - if (os == null) { - throw new NullPointerException("os"); - } - this.is = is; - this.os = os; - } - - @Override - public boolean isActive() { - InputStream is = this.is; - if (is == null || is == CLOSED_IN) { - return false; - } - - OutputStream os = this.os; - return !(os == null || os == CLOSED_OUT); - } - - @Override - protected int available() { - try { - return is.available(); - } catch (IOException ignored) { - return 0; - } - } - - @Override - protected int doReadBytes(ByteBuf buf) throws Exception { - int length = Math.max(1, Math.min(available(), buf.maxWritableBytes())); - return buf.writeBytes(is, length); - } - - @Override - protected void doWriteBytes(ByteBuf buf) throws Exception { - OutputStream os = this.os; - if (os == null) { - throw new NotYetConnectedException(); - } - buf.readBytes(os, buf.readableBytes()); - } - - @Override - protected void doWriteFileRegion(FileRegion region) throws Exception { - OutputStream os = this.os; - if (os == null) { - throw new NotYetConnectedException(); - } - if (outChannel == null) { - outChannel = Channels.newChannel(os); - } - - long written = 0; - for (;;) { - long localWritten = region.transferTo(outChannel, written); - if (localWritten == -1) { - checkEOF(region); - return; - } - written += localWritten; - - if (written >= region.count()) { - return; - } - } - } - - private static void checkEOF(FileRegion region) throws IOException { - if (region.transfered() < region.count()) { - throw new EOFException("Expected to be able to write " + region.count() + " bytes, " + - "but only wrote " + region.transfered()); - } - } - - @Override - protected void doClose() throws Exception { - InputStream is = this.is; - OutputStream os = this.os; - this.is = CLOSED_IN; - this.os = CLOSED_OUT; - - try { - if (is != null) { - is.close(); - } - } finally { - if (os != null) { - os.close(); - } - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/oio/OioEventLoopGroup.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/oio/OioEventLoopGroup.java deleted file mode 100755 index 13105e53a6..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/oio/OioEventLoopGroup.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.oio; - - -import java.util.concurrent.Executors; -import java.util.concurrent.ThreadFactory; - -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelException; -import com.ai.cloud.io.netty.channel.ChannelPromise; -import com.ai.cloud.io.netty.channel.EventLoop; -import com.ai.cloud.io.netty.channel.EventLoopGroup; -import com.ai.cloud.io.netty.channel.ThreadPerChannelEventLoopGroup; - -/** - * {@link EventLoopGroup} which is used to handle OIO {@link Channel}'s. Each {@link Channel} will be handled by its - * own {@link EventLoop} to not block others. - */ -public class OioEventLoopGroup extends ThreadPerChannelEventLoopGroup { - - /** - * Create a new {@link OioEventLoopGroup} with no limit in place. - */ - public OioEventLoopGroup() { - this(0); - } - - /** - * Create a new {@link OioEventLoopGroup}. - * - * @param maxChannels the maximum number of channels to handle with this instance. Once you try to register - * a new {@link Channel} and the maximum is exceed it will throw an - * {@link ChannelException} on the {@link #register(Channel)} and - * {@link #register(Channel, ChannelPromise)} method. - * Use {@code 0} to use no limit - */ - public OioEventLoopGroup(int maxChannels) { - this(maxChannels, Executors.defaultThreadFactory()); - } - - /** - * Create a new {@link OioEventLoopGroup}. - * - * @param maxChannels the maximum number of channels to handle with this instance. Once you try to register - * a new {@link Channel} and the maximum is exceed it will throw an - * {@link ChannelException} on the {@link #register(Channel)} and - * {@link #register(Channel, ChannelPromise)} method. - * Use {@code 0} to use no limit - * @param threadFactory the {@link ThreadFactory} used to create new {@link Thread} instances that handle the - * registered {@link Channel}s - */ - public OioEventLoopGroup(int maxChannels, ThreadFactory threadFactory) { - super(maxChannels, threadFactory); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/oio/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/oio/package-info.java deleted file mode 100755 index 1724076af7..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/oio/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * Old blocking I/O based channel API implementation - recommended for - * a small number of connections (< 1000). - */ -package com.ai.cloud.io.netty.channel.oio; diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/package-info.java deleted file mode 100755 index 91b7314492..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/package-info.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * The core channel API which is asynchronous and event-driven abstraction of - * various transports such as a - * NIO Channel. - */ -package com.ai.cloud.io.netty.channel; diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/AbstractChannelPoolHandler.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/AbstractChannelPoolHandler.java deleted file mode 100755 index 04ae6bdfa9..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/AbstractChannelPoolHandler.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.pool; - -import com.ai.cloud.io.netty.channel.Channel; - -/** - * A skeletal {@link ChannelPoolHandler} implementation. - */ -public abstract class AbstractChannelPoolHandler implements ChannelPoolHandler { - - /** - * NOOP implementation, sub-classes may override this. - * - * {@inheritDoc} - */ - @Override - public void channelAcquired(@SuppressWarnings("unused") Channel ch) throws Exception { - // NOOP - } - - /** - * NOOP implementation, sub-classes may override this. - * - * {@inheritDoc} - */ - @Override - public void channelReleased(@SuppressWarnings("unused") Channel ch) throws Exception { - // NOOP - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/AbstractChannelPoolMap.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/AbstractChannelPoolMap.java deleted file mode 100755 index 9182f114e7..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/AbstractChannelPoolMap.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.pool; - -import java.io.Closeable; -import java.util.Iterator; -import java.util.Map.Entry; -import java.util.concurrent.ConcurrentMap; - -import com.ai.cloud.io.netty.util.internal.PlatformDependent; -import com.ai.cloud.io.netty.util.internal.ReadOnlyIterator; - -import static com.ai.cloud.io.netty.util.internal.ObjectUtil.checkNotNull; - -/** - * A skeletal {@link ChannelPoolMap} implementation. To find the right {@link ChannelPool} - * the {@link Object#hashCode()} and {@link Object#equals(Object)} is used. - */ -public abstract class AbstractChannelPoolMap - implements ChannelPoolMap, Iterable>, Closeable { - private final ConcurrentMap map = PlatformDependent.newConcurrentHashMap(); - - @Override - public final P get(K key) { - P pool = map.get(checkNotNull(key, "key")); - if (pool == null) { - pool = newPool(key); - P old = map.putIfAbsent(key, pool); - if (old != null) { - // We need to destroy the newly created pool as we not use it. - pool.close(); - pool = old; - } - } - return pool; - } - /** - * Remove the {@link ChannelPool} from this {@link AbstractChannelPoolMap}. Returns {@code true} if removed, - * {@code false} otherwise. - * - * Please note that {@code null} keys are not allowed. - */ - public final boolean remove(K key) { - P pool = map.remove(checkNotNull(key, "key")); - if (pool != null) { - pool.close(); - return true; - } - return false; - } - - @Override - public final Iterator> iterator() { - return new ReadOnlyIterator>(map.entrySet().iterator()); - } - - /** - * Returns the number of {@link ChannelPool}s currently in this {@link AbstractChannelPoolMap}. - */ - public final int size() { - return map.size(); - } - - /** - * Returns {@code true} if the {@link AbstractChannelPoolMap} is empty, otherwise {@code false}. - */ - public final boolean isEmpty() { - return map.isEmpty(); - } - - @Override - public final boolean contains(K key) { - return map.containsKey(checkNotNull(key, "key")); - } - - /** - * Called once a new {@link ChannelPool} needs to be created as non exists yet for the {@code key}. - */ - protected abstract P newPool(K key); - - @Override - public final void close() { - for (K key: map.keySet()) { - remove(key); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/ChannelHealthChecker.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/ChannelHealthChecker.java deleted file mode 100755 index a1794671ae..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/ChannelHealthChecker.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.pool; - -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.EventLoop; -import com.ai.cloud.io.netty.util.concurrent.Future; -import com.ai.cloud.io.netty.util.concurrent.Promise; - -/** - * Called before a {@link Channel} will be returned via {@link ChannelPool#acquire()} or - * {@link ChannelPool#acquire(Promise)}. - */ -public interface ChannelHealthChecker { - - /** - * {@link ChannelHealthChecker} implementation that checks if {@link Channel#isActive()} returns {@code true}. - */ - ChannelHealthChecker ACTIVE = new ChannelHealthChecker() { - @Override - public Future isHealthy(Channel channel) { - EventLoop loop = channel.eventLoop(); - return channel.isActive()? loop.newSucceededFuture(Boolean.TRUE) : loop.newSucceededFuture(Boolean.FALSE); - } - }; - - /** - * Check if the given channel is healthy which means it can be used. The returned {@link Future} is notified once - * the check is complete. If notified with {@link Boolean#TRUE} it can be used {@link Boolean#FALSE} otherwise. - * - * This method will be called by the {@link EventLoop} of the {@link Channel}. - */ - Future isHealthy(Channel channel); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/ChannelPool.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/ChannelPool.java deleted file mode 100755 index f429871660..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/ChannelPool.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.pool; - -import java.io.Closeable; -import java.io.IOException; - -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.util.concurrent.Future; -import com.ai.cloud.io.netty.util.concurrent.Promise; - -/** - * Allows to acquire and release {@link Channel} and so act as a pool of these. - */ -public interface ChannelPool extends Closeable { - - /** - * Acquire a {@link Channel} from this {@link ChannelPool}. The returned {@link Future} is notified once - * the acquire is successful and failed otherwise. - */ - Future acquire(); - - /** - * Acquire a {@link Channel} from this {@link ChannelPool}. The given {@link Promise} is notified once - * the acquire is successful and failed otherwise. - */ - Future acquire(Promise promise); - - /** - * Release a {@link Channel} back to this {@link ChannelPool}. The returned {@link Future} is notified once - * the release is successful and failed otherwise. When failed the {@link Channel} will automatically closed. - */ - Future release(Channel channel); - - /** - * Release a {@link Channel} back to this {@link ChannelPool}. The given {@link Promise} is notified once - * the release is successful and failed otherwise. When failed the {@link Channel} will automatically closed. - */ - Future release(Channel channel, Promise promise); - - @Override - void close(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/ChannelPoolHandler.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/ChannelPoolHandler.java deleted file mode 100755 index bc00a09ead..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/ChannelPoolHandler.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.pool; - -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.EventLoop; -import com.ai.cloud.io.netty.util.concurrent.Promise; - -/** - * Handler which is called for various actions done by the {@link ChannelPool}. - */ -public interface ChannelPoolHandler { - /** - * Called once a {@link Channel} was released by calling {@link ChannelPool#release(Channel)} or - * {@link ChannelPool#release(Channel, Promise)}. - * - * This method will be called by the {@link EventLoop} of the {@link Channel}. - */ - void channelReleased(Channel ch) throws Exception; - - /** - * Called once a {@link Channel} was acquired by calling {@link ChannelPool#acquire()} or - * {@link ChannelPool#acquire(Promise)}. - * - * This method will be called by the {@link EventLoop} of the {@link Channel}. - */ - void channelAcquired(Channel ch) throws Exception; - - /** - * Called once a new {@link Channel} is created in the {@link ChannelPool}. - * - * This method will be called by the {@link EventLoop} of the {@link Channel}. - */ - void channelCreated(Channel ch) throws Exception; -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/ChannelPoolMap.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/ChannelPoolMap.java deleted file mode 100755 index 8eb1833135..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/ChannelPoolMap.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.pool; - -/** - * Allows to map {@link ChannelPool} implementations to a specific key. - * - * @param the type of the key - * @param

the type of the {@link ChannelPool} - */ -public interface ChannelPoolMap { - /** - * Return the {@link ChannelPool} for the {@code code}. This will never return {@code null}, - * but create a new {@link ChannelPool} if non exists for they requested {@code key}. - * - * Please note that {@code null} keys are not allowed. - */ - P get(K key); - - /** - * Returns {@code true} if a {@link ChannelPool} exists for the given {@code key}. - * - * Please note that {@code null} keys are not allowed. - */ - boolean contains(K key); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/FixedChannelPool.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/FixedChannelPool.java deleted file mode 100755 index b3ba969515..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/FixedChannelPool.java +++ /dev/null @@ -1,424 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.pool; - -import java.nio.channels.ClosedChannelException; -import java.util.ArrayDeque; -import java.util.Queue; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import com.ai.cloud.io.netty.bootstrap.Bootstrap; -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.util.concurrent.EventExecutor; -import com.ai.cloud.io.netty.util.concurrent.Future; -import com.ai.cloud.io.netty.util.concurrent.FutureListener; -import com.ai.cloud.io.netty.util.concurrent.Promise; -import com.ai.cloud.io.netty.util.internal.EmptyArrays; -import com.ai.cloud.io.netty.util.internal.OneTimeTask; - -/** - * {@link ChannelPool} implementation that takes another {@link ChannelPool} implementation and enforce a maximum - * number of concurrent connections. - */ -public final class FixedChannelPool extends SimpleChannelPool { - private static final IllegalStateException FULL_EXCEPTION = - new IllegalStateException("Too many outstanding acquire operations"); - private static final TimeoutException TIMEOUT_EXCEPTION = - new TimeoutException("Acquire operation took longer then configured maximum time"); - - static { - FULL_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); - TIMEOUT_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); - } - - public enum AcquireTimeoutAction { - /** - * Create a new connection when the timeout is detected. - */ - NEW, - - /** - * Fail the {@link Future} of the acquire call with a {@link TimeoutException}. - */ - FAIL - } - - private final EventExecutor executor; - private final long acquireTimeoutNanos; - private final Runnable timeoutTask; - - // There is no need to worry about synchronization as everything that modified the queue or counts is done - // by the above EventExecutor. - private final Queue pendingAcquireQueue = new ArrayDeque(); - private final int maxConnections; - private final int maxPendingAcquires; - private int acquiredChannelCount; - private int pendingAcquireCount; - private boolean closed; - - /** - * Creates a new instance using the {@link ChannelHealthChecker#ACTIVE}. - * - * @param bootstrap the {@link Bootstrap} that is used for connections - * @param handler the {@link ChannelPoolHandler} that will be notified for the different pool actions - * @param maxConnections the numnber of maximal active connections, once this is reached new tries to acquire - * a {@link Channel} will be delayed until a connection is returned to the pool again. - */ - public FixedChannelPool(Bootstrap bootstrap, - ChannelPoolHandler handler, int maxConnections) { - this(bootstrap, handler, maxConnections, Integer.MAX_VALUE); - } - - /** - * Creates a new instance using the {@link ChannelHealthChecker#ACTIVE}. - * - * @param bootstrap the {@link Bootstrap} that is used for connections - * @param handler the {@link ChannelPoolHandler} that will be notified for the different pool actions - * @param maxConnections the numnber of maximal active connections, once this is reached new tries to - * acquire a {@link Channel} will be delayed until a connection is returned to the - * pool again. - * @param maxPendingAcquires the maximum number of pending acquires. Once this is exceed acquire tries will - * be failed. - */ - public FixedChannelPool(Bootstrap bootstrap, - ChannelPoolHandler handler, int maxConnections, int maxPendingAcquires) { - this(bootstrap, handler, ChannelHealthChecker.ACTIVE, null, -1, maxConnections, maxPendingAcquires); - } - - /** - * Creates a new instance. - * - * @param bootstrap the {@link Bootstrap} that is used for connections - * @param handler the {@link ChannelPoolHandler} that will be notified for the different pool actions - * @param healthCheck the {@link ChannelHealthChecker} that will be used to check if a {@link Channel} is - * still healty when obtain from the {@link ChannelPool} - * @param action the {@link AcquireTimeoutAction} to use or {@code null} if non should be used. - * In this case {@param acquireTimeoutMillis} must be {@code -1}. - * @param acquireTimeoutMillis the time (in milliseconds) after which an pending acquire must complete or - * the {@link AcquireTimeoutAction} takes place. - * @param maxConnections the numnber of maximal active connections, once this is reached new tries to - * acquire a {@link Channel} will be delayed until a connection is returned to the - * pool again. - * @param maxPendingAcquires the maximum number of pending acquires. Once this is exceed acquire tries will - * be failed. - */ - public FixedChannelPool(Bootstrap bootstrap, - ChannelPoolHandler handler, - ChannelHealthChecker healthCheck, AcquireTimeoutAction action, - final long acquireTimeoutMillis, - int maxConnections, int maxPendingAcquires) { - this(bootstrap, handler, healthCheck, action, acquireTimeoutMillis, maxConnections, maxPendingAcquires, true); - } - - /** - * Creates a new instance. - * - * @param bootstrap the {@link Bootstrap} that is used for connections - * @param handler the {@link ChannelPoolHandler} that will be notified for the different pool actions - * @param healthCheck the {@link ChannelHealthChecker} that will be used to check if a {@link Channel} is - * still healty when obtain from the {@link ChannelPool} - * @param action the {@link AcquireTimeoutAction} to use or {@code null} if non should be used. - * In this case {@param acquireTimeoutMillis} must be {@code -1}. - * @param acquireTimeoutMillis the time (in milliseconds) after which an pending acquire must complete or - * the {@link AcquireTimeoutAction} takes place. - * @param maxConnections the numnber of maximal active connections, once this is reached new tries to - * acquire a {@link Channel} will be delayed until a connection is returned to the - * pool again. - * @param maxPendingAcquires the maximum number of pending acquires. Once this is exceed acquire tries will - * be failed. - * @param releaseHealthCheck will check channel health before offering back if this parameter set to - * {@code true}. - */ - public FixedChannelPool(Bootstrap bootstrap, - ChannelPoolHandler handler, - ChannelHealthChecker healthCheck, AcquireTimeoutAction action, - final long acquireTimeoutMillis, - int maxConnections, int maxPendingAcquires, final boolean releaseHealthCheck) { - super(bootstrap, handler, healthCheck, releaseHealthCheck); - if (maxConnections < 1) { - throw new IllegalArgumentException("maxConnections: " + maxConnections + " (expected: >= 1)"); - } - if (maxPendingAcquires < 1) { - throw new IllegalArgumentException("maxPendingAcquires: " + maxPendingAcquires + " (expected: >= 1)"); - } - if (action == null && acquireTimeoutMillis == -1) { - timeoutTask = null; - acquireTimeoutNanos = -1; - } else if (action == null && acquireTimeoutMillis != -1) { - throw new NullPointerException("action"); - } else if (action != null && acquireTimeoutMillis < 0) { - throw new IllegalArgumentException("acquireTimeoutMillis: " + acquireTimeoutMillis + " (expected: >= 1)"); - } else { - acquireTimeoutNanos = TimeUnit.MILLISECONDS.toNanos(acquireTimeoutMillis); - switch (action) { - case FAIL: - timeoutTask = new TimeoutTask() { - @Override - public void onTimeout(AcquireTask task) { - // Fail the promise as we timed out. - task.promise.setFailure(TIMEOUT_EXCEPTION); - } - }; - break; - case NEW: - timeoutTask = new TimeoutTask() { - @Override - public void onTimeout(AcquireTask task) { - // Increment the acquire count and delegate to super to actually acquire a Channel which will - // create a new connetion. - task.acquired(); - - FixedChannelPool.super.acquire(task.promise); - } - }; - break; - default: - throw new Error(); - } - } - executor = bootstrap.group().next(); - this.maxConnections = maxConnections; - this.maxPendingAcquires = maxPendingAcquires; - } - - @Override - public Future acquire(final Promise promise) { - try { - if (executor.inEventLoop()) { - acquire0(promise); - } else { - executor.execute(new OneTimeTask() { - @Override - public void run() { - acquire0(promise); - } - }); - } - } catch (Throwable cause) { - promise.setFailure(cause); - } - return promise; - } - - private void acquire0(final Promise promise) { - assert executor.inEventLoop(); - - if (closed) { - promise.setFailure(new IllegalStateException("FixedChannelPooled was closed")); - return; - } - if (acquiredChannelCount < maxConnections) { - assert acquiredChannelCount >= 0; - - // We need to create a new promise as we need to ensure the AcquireListener runs in the correct - // EventLoop - Promise p = executor.newPromise(); - AcquireListener l = new AcquireListener(promise); - l.acquired(); - p.addListener(l); - super.acquire(p); - } else { - if (pendingAcquireCount >= maxPendingAcquires) { - promise.setFailure(FULL_EXCEPTION); - } else { - AcquireTask task = new AcquireTask(promise); - if (pendingAcquireQueue.offer(task)) { - ++pendingAcquireCount; - - if (timeoutTask != null) { - task.timeoutFuture = executor.schedule(timeoutTask, acquireTimeoutNanos, TimeUnit.NANOSECONDS); - } - } else { - promise.setFailure(FULL_EXCEPTION); - } - } - - assert pendingAcquireCount > 0; - } - } - - @Override - public Future release(final Channel channel, final Promise promise) { - final Promise p = executor.newPromise(); - super.release(channel, p.addListener(new FutureListener() { - - @Override - public void operationComplete(Future future) throws Exception { - assert executor.inEventLoop(); - - if (closed) { - promise.setFailure(new IllegalStateException("FixedChannelPooled was closed")); - return; - } - - if (future.isSuccess()) { - decrementAndRunTaskQueue(); - promise.setSuccess(null); - } else { - Throwable cause = future.cause(); - // Check if the exception was not because of we passed the Channel to the wrong pool. - if (!(cause instanceof IllegalArgumentException)) { - decrementAndRunTaskQueue(); - } - promise.setFailure(future.cause()); - } - } - })); - return p; - } - - private void decrementAndRunTaskQueue() { - --acquiredChannelCount; - - // We should never have a negative value. - assert acquiredChannelCount >= 0; - - // Run the pending acquire tasks before notify the original promise so if the user would - // try to acquire again from the ChannelFutureListener and the pendingAcquireCount is >= - // maxPendingAcquires we may be able to run some pending tasks first and so allow to add - // more. - runTaskQueue(); - } - - private void runTaskQueue() { - while (acquiredChannelCount < maxConnections) { - AcquireTask task = pendingAcquireQueue.poll(); - if (task == null) { - break; - } - - // Cancel the timeout if one was scheduled - ScheduledFuture timeoutFuture = task.timeoutFuture; - if (timeoutFuture != null) { - timeoutFuture.cancel(false); - } - - --pendingAcquireCount; - task.acquired(); - - super.acquire(task.promise); - } - - // We should never have a negative value. - assert pendingAcquireCount >= 0; - assert acquiredChannelCount >= 0; - } - - // AcquireTask extends AcquireListener to reduce object creations and so GC pressure - private final class AcquireTask extends AcquireListener { - final Promise promise; - final long expireNanoTime = System.nanoTime() + acquireTimeoutNanos; - ScheduledFuture timeoutFuture; - - public AcquireTask(Promise promise) { - super(promise); - // We need to create a new promise as we need to ensure the AcquireListener runs in the correct - // EventLoop. - this.promise = executor.newPromise().addListener(this); - } - } - - private abstract class TimeoutTask implements Runnable { - @Override - public final void run() { - assert executor.inEventLoop(); - long nanoTime = System.nanoTime(); - for (;;) { - AcquireTask task = pendingAcquireQueue.peek(); - // Compare nanoTime as descripted in the javadocs of System.nanoTime() - // - // See https://docs.oracle.com/javase/7/docs/api/java/lang/System.html#nanoTime() - // See https://github.com/netty/netty/issues/3705 - if (task == null || nanoTime - task.expireNanoTime < 0) { - break; - } - pendingAcquireQueue.remove(); - - --pendingAcquireCount; - onTimeout(task); - } - } - - public abstract void onTimeout(AcquireTask task); - } - - private class AcquireListener implements FutureListener { - private final Promise originalPromise; - protected boolean acquired; - - AcquireListener(Promise originalPromise) { - this.originalPromise = originalPromise; - } - - @Override - public void operationComplete(Future future) throws Exception { - assert executor.inEventLoop(); - - if (closed) { - originalPromise.setFailure(new IllegalStateException("FixedChannelPooled was closed")); - return; - } - - if (future.isSuccess()) { - originalPromise.setSuccess(future.getNow()); - } else { - if (acquired) { - decrementAndRunTaskQueue(); - } else { - runTaskQueue(); - } - - originalPromise.setFailure(future.cause()); - } - } - - public void acquired() { - if (acquired) { - return; - } - acquiredChannelCount++; - acquired = true; - } - } - - @Override - public void close() { - executor.execute(new OneTimeTask() { - @Override - public void run() { - if (!closed) { - closed = true; - for (;;) { - AcquireTask task = pendingAcquireQueue.poll(); - if (task == null) { - break; - } - ScheduledFuture f = task.timeoutFuture; - if (f != null) { - f.cancel(false); - } - task.promise.setFailure(new ClosedChannelException()); - } - acquiredChannelCount = 0; - pendingAcquireCount = 0; - FixedChannelPool.super.close(); - } - } - }); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/SimpleChannelPool.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/SimpleChannelPool.java deleted file mode 100755 index 5910b4249e..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/SimpleChannelPool.java +++ /dev/null @@ -1,346 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.pool; - -import java.util.Deque; - -import com.ai.cloud.io.netty.bootstrap.Bootstrap; -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelFuture; -import com.ai.cloud.io.netty.channel.ChannelFutureListener; -import com.ai.cloud.io.netty.channel.ChannelInitializer; -import com.ai.cloud.io.netty.channel.EventLoop; -import com.ai.cloud.io.netty.util.AttributeKey; -import com.ai.cloud.io.netty.util.concurrent.Future; -import com.ai.cloud.io.netty.util.concurrent.FutureListener; -import com.ai.cloud.io.netty.util.concurrent.Promise; -import com.ai.cloud.io.netty.util.internal.EmptyArrays; -import com.ai.cloud.io.netty.util.internal.OneTimeTask; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - -import static com.ai.cloud.io.netty.util.internal.ObjectUtil.*; - -/** - * Simple {@link ChannelPool} implementation which will create new {@link Channel}s if someone tries to acquire - * a {@link Channel} but none is in the pool atm. No limit on the maximal concurrent {@link Channel}s is enforced. - * - * This implementation uses LIFO order for {@link Channel}s in the {@link ChannelPool}. - * - */ -public class SimpleChannelPool implements ChannelPool { - private static final AttributeKey POOL_KEY = AttributeKey.newInstance("channelPool"); - private static final IllegalStateException FULL_EXCEPTION = new IllegalStateException("ChannelPool full"); - private static final IllegalStateException UNHEALTHY_NON_OFFERED_TO_POOL = - new IllegalStateException("Channel is unhealthy not offering it back to pool"); - static { - FULL_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); - UNHEALTHY_NON_OFFERED_TO_POOL.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); - } - private final Deque deque = PlatformDependent.newConcurrentDeque(); - private final ChannelPoolHandler handler; - private final ChannelHealthChecker healthCheck; - private final Bootstrap bootstrap; - private final boolean releaseHealthCheck; - - /** - * Creates a new instance using the {@link ChannelHealthChecker#ACTIVE}. - * - * @param bootstrap the {@link Bootstrap} that is used for connections - * @param handler the {@link ChannelPoolHandler} that will be notified for the different pool actions - */ - public SimpleChannelPool(Bootstrap bootstrap, final ChannelPoolHandler handler) { - this(bootstrap, handler, ChannelHealthChecker.ACTIVE); - } - - /** - * Creates a new instance. - * - * @param bootstrap the {@link Bootstrap} that is used for connections - * @param handler the {@link ChannelPoolHandler} that will be notified for the different pool actions - * @param healthCheck the {@link ChannelHealthChecker} that will be used to check if a {@link Channel} is - * still healthy when obtain from the {@link ChannelPool} - */ - public SimpleChannelPool(Bootstrap bootstrap, final ChannelPoolHandler handler, ChannelHealthChecker healthCheck) { - this(bootstrap, handler, healthCheck, true); - } - - /** - * Creates a new instance. - * - * @param bootstrap the {@link Bootstrap} that is used for connections - * @param handler the {@link ChannelPoolHandler} that will be notified for the different pool actions - * @param healthCheck the {@link ChannelHealthChecker} that will be used to check if a {@link Channel} is - * still healthy when obtain from the {@link ChannelPool} - * @param releaseHealthCheck will offercheck channel health before offering back if this parameter set to - * {@code true}. - */ - public SimpleChannelPool(Bootstrap bootstrap, final ChannelPoolHandler handler, ChannelHealthChecker healthCheck, - boolean releaseHealthCheck) { - this.handler = checkNotNull(handler, "handler"); - this.healthCheck = checkNotNull(healthCheck, "healthCheck"); - this.releaseHealthCheck = releaseHealthCheck; - // Clone the original Bootstrap as we want to set our own handler - this.bootstrap = checkNotNull(bootstrap, "bootstrap").clone(); - this.bootstrap.handler(new ChannelInitializer() { - @Override - protected void initChannel(Channel ch) throws Exception { - assert ch.eventLoop().inEventLoop(); - handler.channelCreated(ch); - } - }); - } - - @Override - public final Future acquire() { - return acquire(bootstrap.group().next().newPromise()); - } - - @Override - public Future acquire(final Promise promise) { - checkNotNull(promise, "promise"); - return acquireHealthyFromPoolOrNew(promise); - } - - /** - * Tries to retrieve healthy channel from the pool if any or creates a new channel otherwise. - * @param promise the promise to provide acquire result. - * @return future for acquiring a channel. - */ - private Future acquireHealthyFromPoolOrNew(final Promise promise) { - try { - final Channel ch = pollChannel(); - if (ch == null) { - // No Channel left in the pool bootstrap a new Channel - Bootstrap bs = bootstrap.clone(); - bs.attr(POOL_KEY, this); - ChannelFuture f = connectChannel(bs); - if (f.isDone()) { - notifyConnect(f, promise); - } else { - f.addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - notifyConnect(future, promise); - } - }); - } - return promise; - } - EventLoop loop = ch.eventLoop(); - if (loop.inEventLoop()) { - doHealthCheck(ch, promise); - } else { - loop.execute(new OneTimeTask() { - @Override - public void run() { - doHealthCheck(ch, promise); - } - }); - } - } catch (Throwable cause) { - promise.setFailure(cause); - } - return promise; - } - - private static void notifyConnect(ChannelFuture future, Promise promise) { - if (future.isSuccess()) { - promise.setSuccess(future.channel()); - } else { - promise.setFailure(future.cause()); - } - } - - private void doHealthCheck(final Channel ch, final Promise promise) { - assert ch.eventLoop().inEventLoop(); - - Future f = healthCheck.isHealthy(ch); - if (f.isDone()) { - notifyHealthCheck(f, ch, promise); - } else { - f.addListener(new FutureListener() { - @Override - public void operationComplete(Future future) throws Exception { - notifyHealthCheck(future, ch, promise); - } - }); - } - } - - private void notifyHealthCheck(Future future, Channel ch, Promise promise) { - assert ch.eventLoop().inEventLoop(); - - if (future.isSuccess()) { - if (future.getNow() == Boolean.TRUE) { - try { - ch.attr(POOL_KEY).set(this); - handler.channelAcquired(ch); - promise.setSuccess(ch); - } catch (Throwable cause) { - closeAndFail(ch, cause, promise); - } - } else { - closeChannel(ch); - acquireHealthyFromPoolOrNew(promise); - } - } else { - closeChannel(ch); - acquireHealthyFromPoolOrNew(promise); - } - } - - /** - * Bootstrap a new {@link Channel}. The default implementation uses {@link Bootstrap#connect()}, sub-classes may - * override this. - *

- * The {@link Bootstrap} that is passed in here is cloned via {@link Bootstrap#clone()}, so it is safe to modify. - */ - protected ChannelFuture connectChannel(Bootstrap bs) { - return bs.connect(); - } - - @Override - public final Future release(Channel channel) { - return release(channel, channel.eventLoop().newPromise()); - } - - @Override - public Future release(final Channel channel, final Promise promise) { - checkNotNull(channel, "channel"); - checkNotNull(promise, "promise"); - try { - EventLoop loop = channel.eventLoop(); - if (loop.inEventLoop()) { - doReleaseChannel(channel, promise); - } else { - loop.execute(new OneTimeTask() { - @Override - public void run() { - doReleaseChannel(channel, promise); - } - }); - } - } catch (Throwable cause) { - closeAndFail(channel, cause, promise); - } - return promise; - } - - private void doReleaseChannel(Channel channel, Promise promise) { - assert channel.eventLoop().inEventLoop(); - // Remove the POOL_KEY attribute from the Channel and check if it was acquired from this pool, if not fail. - if (channel.attr(POOL_KEY).getAndSet(null) != this) { - closeAndFail(channel, - // Better include a stracktrace here as this is an user error. - new IllegalArgumentException( - "Channel " + channel + " was not acquired from this ChannelPool"), - promise); - } else { - try { - if (releaseHealthCheck) { - doHealthCheckOnRelease(channel, promise); - } else { - releaseAndOffer(channel, promise); - } - } catch (Throwable cause) { - closeAndFail(channel, cause, promise); - } - } - } - - private void doHealthCheckOnRelease(final Channel channel, final Promise promise) throws Exception { - final Future f = healthCheck.isHealthy(channel); - if (f.isDone()) { - releaseAndOfferIfHealthy(channel, promise, f); - } else { - f.addListener(new FutureListener() { - @Override - public void operationComplete(Future future) throws Exception { - releaseAndOfferIfHealthy(channel, promise, f); - } - }); - } - } - - /** - * Adds the channel back to the pool only if the channel is healty. - * @param channel the channel to put back to the pool - * @param promise offer operation promise. - * @param future the future that contains information fif channel is healthy or not. - * @throws Exception in case when failed to notify handler about release operation. - */ - private void releaseAndOfferIfHealthy(Channel channel, Promise promise, Future future) - throws Exception { - if (future.getNow()) { //channel turns out to be healthy, offering and releasing it. - releaseAndOffer(channel, promise); - } else { //channel ont healthy, just releasing it. - handler.channelReleased(channel); - closeAndFail(channel, UNHEALTHY_NON_OFFERED_TO_POOL, promise); - } - } - - private void releaseAndOffer(Channel channel, Promise promise) throws Exception { - if (offerChannel(channel)) { - handler.channelReleased(channel); - promise.setSuccess(null); - } else { - closeAndFail(channel, FULL_EXCEPTION, promise); - } - } - - private static void closeChannel(Channel channel) { - channel.attr(POOL_KEY).getAndSet(null); - channel.close(); - } - - private static void closeAndFail(Channel channel, Throwable cause, Promise promise) { - closeChannel(channel); - promise.setFailure(cause); - } - - /** - * Poll a {@link Channel} out of the internal storage to reuse it. This will return {@code null} if no - * {@link Channel} is ready to be reused. - * - * Sub-classes may override {@link #pollChannel()} and {@link #offerChannel(Channel)}. Be aware that - * implementations of these methods needs to be thread-safe! - */ - protected Channel pollChannel() { - return deque.pollLast(); - } - - /** - * Offer a {@link Channel} back to the internal storage. This will return {@code true} if the {@link Channel} - * could be added, {@code false} otherwise. - * - * Sub-classes may override {@link #pollChannel()} and {@link #offerChannel(Channel)}. Be aware that - * implementations of these methods needs to be thread-safe! - */ - protected boolean offerChannel(Channel channel) { - return deque.offer(channel); - } - - @Override - public void close() { - for (;;) { - Channel channel = pollChannel(); - if (channel == null) { - break; - } - channel.close(); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/package-info.java deleted file mode 100755 index 5558bc87ff..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/pool/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * Implementations and API for {@link com.ai.cloud.io.netty.channel.Channel} pools. - */ -package com.ai.cloud.io.netty.channel.pool; diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/ChannelInputShutdownEvent.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/ChannelInputShutdownEvent.java deleted file mode 100755 index e9edd3c22a..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/ChannelInputShutdownEvent.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.socket; - -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelInboundHandler; - -/** - * Special event which will be fired and passed to the - * {@link ChannelInboundHandler#userEventTriggered(ChannelHandlerContext, Object)} methods once the input of - * a {@link SocketChannel} was shutdown and the {@link SocketChannelConfig#isAllowHalfClosure()} method returns - * {@code true}. - */ -public final class ChannelInputShutdownEvent { - - /** - * Instance to use - */ - @SuppressWarnings("InstantiationOfUtilityClass") - public static final ChannelInputShutdownEvent INSTANCE = new ChannelInputShutdownEvent(); - - private ChannelInputShutdownEvent() { } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/DatagramChannel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/DatagramChannel.java deleted file mode 100755 index b226b600e3..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/DatagramChannel.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.socket; - -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.NetworkInterface; - -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelFuture; -import com.ai.cloud.io.netty.channel.ChannelPromise; - -/** - * A UDP/IP {@link Channel}. - */ -public interface DatagramChannel extends Channel { - @Override - DatagramChannelConfig config(); - @Override - InetSocketAddress localAddress(); - @Override - InetSocketAddress remoteAddress(); - - /** - * Return {@code true} if the {@link DatagramChannel} is connected to the remote peer. - */ - boolean isConnected(); - - /** - * Joins a multicast group and notifies the {@link ChannelFuture} once the operation completes. - */ - ChannelFuture joinGroup(InetAddress multicastAddress); - - /** - * Joins a multicast group and notifies the {@link ChannelFuture} once the operation completes. - * - * The given {@link ChannelFuture} will be notified and also returned. - */ - ChannelFuture joinGroup(InetAddress multicastAddress, ChannelPromise future); - - /** - * Joins the specified multicast group at the specified interface and notifies the {@link ChannelFuture} - * once the operation completes. - */ - ChannelFuture joinGroup(InetSocketAddress multicastAddress, NetworkInterface networkInterface); - - /** - * Joins the specified multicast group at the specified interface and notifies the {@link ChannelFuture} - * once the operation completes. - * - * The given {@link ChannelFuture} will be notified and also returned. - */ - ChannelFuture joinGroup( - InetSocketAddress multicastAddress, NetworkInterface networkInterface, ChannelPromise future); - - /** - * Joins the specified multicast group at the specified interface and notifies the {@link ChannelFuture} - * once the operation completes. - */ - ChannelFuture joinGroup(InetAddress multicastAddress, NetworkInterface networkInterface, InetAddress source); - - /** - * Joins the specified multicast group at the specified interface and notifies the {@link ChannelFuture} - * once the operation completes. - * - * The given {@link ChannelFuture} will be notified and also returned. - */ - ChannelFuture joinGroup( - InetAddress multicastAddress, NetworkInterface networkInterface, InetAddress source, ChannelPromise future); - - /** - * Leaves a multicast group and notifies the {@link ChannelFuture} once the operation completes. - */ - ChannelFuture leaveGroup(InetAddress multicastAddress); - - /** - * Leaves a multicast group and notifies the {@link ChannelFuture} once the operation completes. - * - * The given {@link ChannelFuture} will be notified and also returned. - */ - ChannelFuture leaveGroup(InetAddress multicastAddress, ChannelPromise future); - - /** - * Leaves a multicast group on a specified local interface and notifies the {@link ChannelFuture} once the - * operation completes. - */ - ChannelFuture leaveGroup(InetSocketAddress multicastAddress, NetworkInterface networkInterface); - - /** - * Leaves a multicast group on a specified local interface and notifies the {@link ChannelFuture} once the - * operation completes. - * - * The given {@link ChannelFuture} will be notified and also returned. - */ - ChannelFuture leaveGroup( - InetSocketAddress multicastAddress, NetworkInterface networkInterface, ChannelPromise future); - - /** - * Leave the specified multicast group at the specified interface using the specified source and notifies - * the {@link ChannelFuture} once the operation completes. - * - */ - ChannelFuture leaveGroup( - InetAddress multicastAddress, NetworkInterface networkInterface, InetAddress source); - - /** - * Leave the specified multicast group at the specified interface using the specified source and notifies - * the {@link ChannelFuture} once the operation completes. - * - * The given {@link ChannelFuture} will be notified and also returned. - */ - ChannelFuture leaveGroup( - InetAddress multicastAddress, NetworkInterface networkInterface, InetAddress source, - ChannelPromise future); - - /** - * Block the given sourceToBlock address for the given multicastAddress on the given networkInterface and notifies - * the {@link ChannelFuture} once the operation completes. - * - * The given {@link ChannelFuture} will be notified and also returned. - */ - ChannelFuture block( - InetAddress multicastAddress, NetworkInterface networkInterface, - InetAddress sourceToBlock); - - /** - * Block the given sourceToBlock address for the given multicastAddress on the given networkInterface and notifies - * the {@link ChannelFuture} once the operation completes. - * - * The given {@link ChannelFuture} will be notified and also returned. - */ - ChannelFuture block( - InetAddress multicastAddress, NetworkInterface networkInterface, - InetAddress sourceToBlock, ChannelPromise future); - - /** - * Block the given sourceToBlock address for the given multicastAddress and notifies the {@link ChannelFuture} once - * the operation completes. - * - * The given {@link ChannelFuture} will be notified and also returned. - */ - ChannelFuture block(InetAddress multicastAddress, InetAddress sourceToBlock); - - /** - * Block the given sourceToBlock address for the given multicastAddress and notifies the {@link ChannelFuture} once - * the operation completes. - * - * The given {@link ChannelFuture} will be notified and also returned. - */ - ChannelFuture block( - InetAddress multicastAddress, InetAddress sourceToBlock, ChannelPromise future); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/DatagramChannelConfig.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/DatagramChannelConfig.java deleted file mode 100755 index eb9c04164a..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/DatagramChannelConfig.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.socket; - -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.net.StandardSocketOptions; - -import com.ai.cloud.io.netty.buffer.ByteBufAllocator; -import com.ai.cloud.io.netty.channel.ChannelConfig; -import com.ai.cloud.io.netty.channel.ChannelOption; -import com.ai.cloud.io.netty.channel.MessageSizeEstimator; -import com.ai.cloud.io.netty.channel.RecvByteBufAllocator; - -/** - * A {@link ChannelConfig} for a {@link DatagramChannel}. - * - *

Available options

- * - * In addition to the options provided by {@link ChannelConfig}, - * {@link DatagramChannelConfig} allows the following options in the option map: - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
NameAssociated setter method
{@link ChannelOption#SO_BROADCAST}{@link #setBroadcast(boolean)}
{@link ChannelOption#IP_MULTICAST_ADDR}{@link #setInterface(InetAddress)}
{@link ChannelOption#IP_MULTICAST_LOOP_DISABLED}{@link #setLoopbackModeDisabled(boolean)}
{@link ChannelOption#IP_MULTICAST_IF}{@link #setNetworkInterface(NetworkInterface)}
{@link ChannelOption#SO_REUSEADDR}{@link #setReuseAddress(boolean)}
{@link ChannelOption#SO_RCVBUF}{@link #setReceiveBufferSize(int)}
{@link ChannelOption#SO_SNDBUF}{@link #setSendBufferSize(int)}
{@link ChannelOption#IP_MULTICAST_TTL}{@link #setTimeToLive(int)}
{@link ChannelOption#IP_TOS}{@link #setTrafficClass(int)}
- */ -public interface DatagramChannelConfig extends ChannelConfig { - - /** - * Gets the {@link StandardSocketOptions#SO_SNDBUF} option. - */ - int getSendBufferSize(); - - /** - * Sets the {@link StandardSocketOptions#SO_SNDBUF} option. - */ - DatagramChannelConfig setSendBufferSize(int sendBufferSize); - - /** - * Gets the {@link StandardSocketOptions#SO_RCVBUF} option. - */ - int getReceiveBufferSize(); - - /** - * Sets the {@link StandardSocketOptions#SO_RCVBUF} option. - */ - DatagramChannelConfig setReceiveBufferSize(int receiveBufferSize); - - /** - * Gets the {@link StandardSocketOptions#IP_TOS} option. - */ - int getTrafficClass(); - - /** - * Sets the {@link StandardSocketOptions#IP_TOS} option. - */ - DatagramChannelConfig setTrafficClass(int trafficClass); - - /** - * Gets the {@link StandardSocketOptions#SO_REUSEADDR} option. - */ - boolean isReuseAddress(); - - /** - * Gets the {@link StandardSocketOptions#SO_REUSEADDR} option. - */ - DatagramChannelConfig setReuseAddress(boolean reuseAddress); - - /** - * Gets the {@link StandardSocketOptions#SO_BROADCAST} option. - */ - boolean isBroadcast(); - - /** - * Sets the {@link StandardSocketOptions#SO_BROADCAST} option. - */ - DatagramChannelConfig setBroadcast(boolean broadcast); - - /** - * Gets the {@link StandardSocketOptions#IP_MULTICAST_LOOP} option. - * - * @return {@code true} if and only if the loopback mode has been disabled - */ - boolean isLoopbackModeDisabled(); - - /** - * Sets the {@link StandardSocketOptions#IP_MULTICAST_LOOP} option. - * - * @param loopbackModeDisabled - * {@code true} if and only if the loopback mode has been disabled - */ - DatagramChannelConfig setLoopbackModeDisabled(boolean loopbackModeDisabled); - - /** - * Gets the {@link StandardSocketOptions#IP_MULTICAST_TTL} option. - */ - int getTimeToLive(); - - /** - * Sets the {@link StandardSocketOptions#IP_MULTICAST_TTL} option. - */ - DatagramChannelConfig setTimeToLive(int ttl); - - /** - * Gets the address of the network interface used for multicast packets. - */ - InetAddress getInterface(); - - /** - * Sets the address of the network interface used for multicast packets. - */ - DatagramChannelConfig setInterface(InetAddress interfaceAddress); - - /** - * Gets the {@link StandardSocketOptions#IP_MULTICAST_IF} option. - */ - NetworkInterface getNetworkInterface(); - - /** - * Sets the {@link StandardSocketOptions#IP_MULTICAST_IF} option. - */ - DatagramChannelConfig setNetworkInterface(NetworkInterface networkInterface); - - @Override - DatagramChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead); - - @Override - DatagramChannelConfig setWriteSpinCount(int writeSpinCount); - - @Override - DatagramChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis); - - @Override - DatagramChannelConfig setAllocator(ByteBufAllocator allocator); - - @Override - DatagramChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator); - - @Override - DatagramChannelConfig setAutoRead(boolean autoRead); - - @Override - DatagramChannelConfig setAutoClose(boolean autoClose); - - @Override - DatagramChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/DatagramPacket.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/DatagramPacket.java deleted file mode 100755 index 18002e4163..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/DatagramPacket.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.socket; - -import java.net.InetSocketAddress; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.ByteBufHolder; -import com.ai.cloud.io.netty.channel.DefaultAddressedEnvelope; - -/** - * The message container that is used for {@link DatagramChannel} to communicate with the remote peer. - */ -public final class DatagramPacket - extends DefaultAddressedEnvelope implements ByteBufHolder { - - /** - * Create a new instance with the specified packet {@code data} and {@code recipient} address. - */ - public DatagramPacket(ByteBuf data, InetSocketAddress recipient) { - super(data, recipient); - } - - /** - * Create a new instance with the specified packet {@code data}, {@code recipient} address, and {@code sender} - * address. - */ - public DatagramPacket(ByteBuf data, InetSocketAddress recipient, InetSocketAddress sender) { - super(data, recipient, sender); - } - - @Override - public DatagramPacket copy() { - return new DatagramPacket(content().copy(), recipient(), sender()); - } - - @Override - public DatagramPacket duplicate() { - return new DatagramPacket(content().duplicate(), recipient(), sender()); - } - - @Override - public DatagramPacket retain() { - super.retain(); - return this; - } - - @Override - public DatagramPacket retain(int increment) { - super.retain(increment); - return this; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/DefaultDatagramChannelConfig.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/DefaultDatagramChannelConfig.java deleted file mode 100755 index 830cdac86f..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/DefaultDatagramChannelConfig.java +++ /dev/null @@ -1,421 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.socket; - -import java.io.IOException; -import java.net.DatagramSocket; -import java.net.InetAddress; -import java.net.MulticastSocket; -import java.net.NetworkInterface; -import java.net.SocketException; -import java.util.Map; - -import com.ai.cloud.io.netty.buffer.ByteBufAllocator; -import com.ai.cloud.io.netty.channel.ChannelException; -import com.ai.cloud.io.netty.channel.ChannelOption; -import com.ai.cloud.io.netty.channel.DefaultChannelConfig; -import com.ai.cloud.io.netty.channel.FixedRecvByteBufAllocator; -import com.ai.cloud.io.netty.channel.MessageSizeEstimator; -import com.ai.cloud.io.netty.channel.RecvByteBufAllocator; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -import static com.ai.cloud.io.netty.channel.ChannelOption.*; - -/** - * The default {@link DatagramChannelConfig} implementation. - */ -public class DefaultDatagramChannelConfig extends DefaultChannelConfig implements DatagramChannelConfig { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(DefaultDatagramChannelConfig.class); - - private static final RecvByteBufAllocator DEFAULT_RCVBUF_ALLOCATOR = new FixedRecvByteBufAllocator(2048); - - private final DatagramSocket javaSocket; - private volatile boolean activeOnOpen; - - /** - * Creates a new instance. - */ - public DefaultDatagramChannelConfig(DatagramChannel channel, DatagramSocket javaSocket) { - super(channel); - if (javaSocket == null) { - throw new NullPointerException("javaSocket"); - } - this.javaSocket = javaSocket; - setRecvByteBufAllocator(DEFAULT_RCVBUF_ALLOCATOR); - } - - @Override - @SuppressWarnings("deprecation") - public Map, Object> getOptions() { - return getOptions( - super.getOptions(), - SO_BROADCAST, SO_RCVBUF, SO_SNDBUF, SO_REUSEADDR, IP_MULTICAST_LOOP_DISABLED, - IP_MULTICAST_ADDR, IP_MULTICAST_IF, IP_MULTICAST_TTL, IP_TOS, DATAGRAM_CHANNEL_ACTIVE_ON_REGISTRATION); - } - - @Override - @SuppressWarnings({ "unchecked", "deprecation" }) - public T getOption(ChannelOption option) { - if (option == SO_BROADCAST) { - return (T) Boolean.valueOf(isBroadcast()); - } - if (option == SO_RCVBUF) { - return (T) Integer.valueOf(getReceiveBufferSize()); - } - if (option == SO_SNDBUF) { - return (T) Integer.valueOf(getSendBufferSize()); - } - if (option == SO_REUSEADDR) { - return (T) Boolean.valueOf(isReuseAddress()); - } - if (option == IP_MULTICAST_LOOP_DISABLED) { - return (T) Boolean.valueOf(isLoopbackModeDisabled()); - } - if (option == IP_MULTICAST_ADDR) { - return (T) getInterface(); - } - if (option == IP_MULTICAST_IF) { - return (T) getNetworkInterface(); - } - if (option == IP_MULTICAST_TTL) { - return (T) Integer.valueOf(getTimeToLive()); - } - if (option == IP_TOS) { - return (T) Integer.valueOf(getTrafficClass()); - } - if (option == DATAGRAM_CHANNEL_ACTIVE_ON_REGISTRATION) { - return (T) Boolean.valueOf(activeOnOpen); - } - return super.getOption(option); - } - - @Override - @SuppressWarnings("deprecation") - public boolean setOption(ChannelOption option, T value) { - validate(option, value); - - if (option == SO_BROADCAST) { - setBroadcast((Boolean) value); - } else if (option == SO_RCVBUF) { - setReceiveBufferSize((Integer) value); - } else if (option == SO_SNDBUF) { - setSendBufferSize((Integer) value); - } else if (option == SO_REUSEADDR) { - setReuseAddress((Boolean) value); - } else if (option == IP_MULTICAST_LOOP_DISABLED) { - setLoopbackModeDisabled((Boolean) value); - } else if (option == IP_MULTICAST_ADDR) { - setInterface((InetAddress) value); - } else if (option == IP_MULTICAST_IF) { - setNetworkInterface((NetworkInterface) value); - } else if (option == IP_MULTICAST_TTL) { - setTimeToLive((Integer) value); - } else if (option == IP_TOS) { - setTrafficClass((Integer) value); - } else if (option == DATAGRAM_CHANNEL_ACTIVE_ON_REGISTRATION) { - setActiveOnOpen((Boolean) value); - } else { - return super.setOption(option, value); - } - - return true; - } - - private void setActiveOnOpen(boolean activeOnOpen) { - if (channel.isRegistered()) { - throw new IllegalStateException("Can only changed before channel was registered"); - } - this.activeOnOpen = activeOnOpen; - } - @Override - public boolean isBroadcast() { - try { - return javaSocket.getBroadcast(); - } catch (SocketException e) { - throw new ChannelException(e); - } - } - - @Override - public DatagramChannelConfig setBroadcast(boolean broadcast) { - try { - // See: https://github.com/netty/netty/issues/576 - if (broadcast && - !javaSocket.getLocalAddress().isAnyLocalAddress() && - !PlatformDependent.isWindows() && !PlatformDependent.isRoot()) { - // Warn a user about the fact that a non-root user can't receive a - // broadcast packet on *nix if the socket is bound on non-wildcard address. - logger.warn( - "A non-root user can't receive a broadcast packet if the socket " + - "is not bound to a wildcard address; setting the SO_BROADCAST flag " + - "anyway as requested on the socket which is bound to " + - javaSocket.getLocalSocketAddress() + '.'); - } - - javaSocket.setBroadcast(broadcast); - } catch (SocketException e) { - throw new ChannelException(e); - } - return this; - } - - @Override - public InetAddress getInterface() { - if (javaSocket instanceof MulticastSocket) { - try { - return ((MulticastSocket) javaSocket).getInterface(); - } catch (SocketException e) { - throw new ChannelException(e); - } - } else { - throw new UnsupportedOperationException(); - } - } - - @Override - public DatagramChannelConfig setInterface(InetAddress interfaceAddress) { - if (javaSocket instanceof MulticastSocket) { - try { - ((MulticastSocket) javaSocket).setInterface(interfaceAddress); - } catch (SocketException e) { - throw new ChannelException(e); - } - } else { - throw new UnsupportedOperationException(); - } - return this; - } - - @Override - public boolean isLoopbackModeDisabled() { - if (javaSocket instanceof MulticastSocket) { - try { - return ((MulticastSocket) javaSocket).getLoopbackMode(); - } catch (SocketException e) { - throw new ChannelException(e); - } - } else { - throw new UnsupportedOperationException(); - } - } - - @Override - public DatagramChannelConfig setLoopbackModeDisabled(boolean loopbackModeDisabled) { - if (javaSocket instanceof MulticastSocket) { - try { - ((MulticastSocket) javaSocket).setLoopbackMode(loopbackModeDisabled); - } catch (SocketException e) { - throw new ChannelException(e); - } - } else { - throw new UnsupportedOperationException(); - } - return this; - } - - @Override - public NetworkInterface getNetworkInterface() { - if (javaSocket instanceof MulticastSocket) { - try { - return ((MulticastSocket) javaSocket).getNetworkInterface(); - } catch (SocketException e) { - throw new ChannelException(e); - } - } else { - throw new UnsupportedOperationException(); - } - } - - @Override - public DatagramChannelConfig setNetworkInterface(NetworkInterface networkInterface) { - if (javaSocket instanceof MulticastSocket) { - try { - ((MulticastSocket) javaSocket).setNetworkInterface(networkInterface); - } catch (SocketException e) { - throw new ChannelException(e); - } - } else { - throw new UnsupportedOperationException(); - } - return this; - } - - @Override - public boolean isReuseAddress() { - try { - return javaSocket.getReuseAddress(); - } catch (SocketException e) { - throw new ChannelException(e); - } - } - - @Override - public DatagramChannelConfig setReuseAddress(boolean reuseAddress) { - try { - javaSocket.setReuseAddress(reuseAddress); - } catch (SocketException e) { - throw new ChannelException(e); - } - return this; - } - - @Override - public int getReceiveBufferSize() { - try { - return javaSocket.getReceiveBufferSize(); - } catch (SocketException e) { - throw new ChannelException(e); - } - } - - @Override - public DatagramChannelConfig setReceiveBufferSize(int receiveBufferSize) { - try { - javaSocket.setReceiveBufferSize(receiveBufferSize); - } catch (SocketException e) { - throw new ChannelException(e); - } - return this; - } - - @Override - public int getSendBufferSize() { - try { - return javaSocket.getSendBufferSize(); - } catch (SocketException e) { - throw new ChannelException(e); - } - } - - @Override - public DatagramChannelConfig setSendBufferSize(int sendBufferSize) { - try { - javaSocket.setSendBufferSize(sendBufferSize); - } catch (SocketException e) { - throw new ChannelException(e); - } - return this; - } - - @Override - public int getTimeToLive() { - if (javaSocket instanceof MulticastSocket) { - try { - return ((MulticastSocket) javaSocket).getTimeToLive(); - } catch (IOException e) { - throw new ChannelException(e); - } - } else { - throw new UnsupportedOperationException(); - } - } - - @Override - public DatagramChannelConfig setTimeToLive(int ttl) { - if (javaSocket instanceof MulticastSocket) { - try { - ((MulticastSocket) javaSocket).setTimeToLive(ttl); - } catch (IOException e) { - throw new ChannelException(e); - } - } else { - throw new UnsupportedOperationException(); - } - return this; - } - - @Override - public int getTrafficClass() { - try { - return javaSocket.getTrafficClass(); - } catch (SocketException e) { - throw new ChannelException(e); - } - } - - @Override - public DatagramChannelConfig setTrafficClass(int trafficClass) { - try { - javaSocket.setTrafficClass(trafficClass); - } catch (SocketException e) { - throw new ChannelException(e); - } - return this; - } - - @Override - public DatagramChannelConfig setWriteSpinCount(int writeSpinCount) { - super.setWriteSpinCount(writeSpinCount); - return this; - } - - @Override - public DatagramChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis) { - super.setConnectTimeoutMillis(connectTimeoutMillis); - return this; - } - - @Override - public DatagramChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead) { - super.setMaxMessagesPerRead(maxMessagesPerRead); - return this; - } - - @Override - public DatagramChannelConfig setAllocator(ByteBufAllocator allocator) { - super.setAllocator(allocator); - return this; - } - - @Override - public DatagramChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator) { - super.setRecvByteBufAllocator(allocator); - return this; - } - - @Override - public DatagramChannelConfig setAutoRead(boolean autoRead) { - super.setAutoRead(autoRead); - return this; - } - - @Override - public DatagramChannelConfig setAutoClose(boolean autoClose) { - super.setAutoClose(autoClose); - return this; - } - - @Override - public DatagramChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) { - super.setWriteBufferHighWaterMark(writeBufferHighWaterMark); - return this; - } - - @Override - public DatagramChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark) { - super.setWriteBufferLowWaterMark(writeBufferLowWaterMark); - return this; - } - - @Override - public DatagramChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator) { - super.setMessageSizeEstimator(estimator); - return this; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/DefaultServerSocketChannelConfig.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/DefaultServerSocketChannelConfig.java deleted file mode 100755 index 0aef3ccf35..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/DefaultServerSocketChannelConfig.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.socket; - -import java.net.ServerSocket; -import java.net.SocketException; -import java.util.Map; - -import com.ai.cloud.io.netty.buffer.ByteBufAllocator; -import com.ai.cloud.io.netty.channel.ChannelException; -import com.ai.cloud.io.netty.channel.ChannelOption; -import com.ai.cloud.io.netty.channel.DefaultChannelConfig; -import com.ai.cloud.io.netty.channel.MessageSizeEstimator; -import com.ai.cloud.io.netty.channel.RecvByteBufAllocator; -import com.ai.cloud.io.netty.util.NetUtil; - -import static com.ai.cloud.io.netty.channel.ChannelOption.*; - -/** - * The default {@link ServerSocketChannelConfig} implementation. - */ -public class DefaultServerSocketChannelConfig extends DefaultChannelConfig - implements ServerSocketChannelConfig { - - protected final ServerSocket javaSocket; - private volatile int backlog = NetUtil.SOMAXCONN; - - /** - * Creates a new instance. - */ - public DefaultServerSocketChannelConfig(ServerSocketChannel channel, ServerSocket javaSocket) { - super(channel); - if (javaSocket == null) { - throw new NullPointerException("javaSocket"); - } - this.javaSocket = javaSocket; - } - - @Override - public Map, Object> getOptions() { - return getOptions(super.getOptions(), SO_RCVBUF, SO_REUSEADDR, SO_BACKLOG); - } - - @SuppressWarnings("unchecked") - @Override - public T getOption(ChannelOption option) { - if (option == SO_RCVBUF) { - return (T) Integer.valueOf(getReceiveBufferSize()); - } - if (option == SO_REUSEADDR) { - return (T) Boolean.valueOf(isReuseAddress()); - } - if (option == SO_BACKLOG) { - return (T) Integer.valueOf(getBacklog()); - } - - return super.getOption(option); - } - - @Override - public boolean setOption(ChannelOption option, T value) { - validate(option, value); - - if (option == SO_RCVBUF) { - setReceiveBufferSize((Integer) value); - } else if (option == SO_REUSEADDR) { - setReuseAddress((Boolean) value); - } else if (option == SO_BACKLOG) { - setBacklog((Integer) value); - } else { - return super.setOption(option, value); - } - - return true; - } - - @Override - public boolean isReuseAddress() { - try { - return javaSocket.getReuseAddress(); - } catch (SocketException e) { - throw new ChannelException(e); - } - } - - @Override - public ServerSocketChannelConfig setReuseAddress(boolean reuseAddress) { - try { - javaSocket.setReuseAddress(reuseAddress); - } catch (SocketException e) { - throw new ChannelException(e); - } - return this; - } - - @Override - public int getReceiveBufferSize() { - try { - return javaSocket.getReceiveBufferSize(); - } catch (SocketException e) { - throw new ChannelException(e); - } - } - - @Override - public ServerSocketChannelConfig setReceiveBufferSize(int receiveBufferSize) { - try { - javaSocket.setReceiveBufferSize(receiveBufferSize); - } catch (SocketException e) { - throw new ChannelException(e); - } - return this; - } - - @Override - public ServerSocketChannelConfig setPerformancePreferences(int connectionTime, int latency, int bandwidth) { - javaSocket.setPerformancePreferences(connectionTime, latency, bandwidth); - return this; - } - - @Override - public int getBacklog() { - return backlog; - } - - @Override - public ServerSocketChannelConfig setBacklog(int backlog) { - if (backlog < 0) { - throw new IllegalArgumentException("backlog: " + backlog); - } - this.backlog = backlog; - return this; - } - - @Override - public ServerSocketChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis) { - super.setConnectTimeoutMillis(connectTimeoutMillis); - return this; - } - - @Override - public ServerSocketChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead) { - super.setMaxMessagesPerRead(maxMessagesPerRead); - return this; - } - - @Override - public ServerSocketChannelConfig setWriteSpinCount(int writeSpinCount) { - super.setWriteSpinCount(writeSpinCount); - return this; - } - - @Override - public ServerSocketChannelConfig setAllocator(ByteBufAllocator allocator) { - super.setAllocator(allocator); - return this; - } - - @Override - public ServerSocketChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator) { - super.setRecvByteBufAllocator(allocator); - return this; - } - - @Override - public ServerSocketChannelConfig setAutoRead(boolean autoRead) { - super.setAutoRead(autoRead); - return this; - } - - @Override - public ServerSocketChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) { - super.setWriteBufferHighWaterMark(writeBufferHighWaterMark); - return this; - } - - @Override - public ServerSocketChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark) { - super.setWriteBufferLowWaterMark(writeBufferLowWaterMark); - return this; - } - - @Override - public ServerSocketChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator) { - super.setMessageSizeEstimator(estimator); - return this; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/DefaultSocketChannelConfig.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/DefaultSocketChannelConfig.java deleted file mode 100755 index a98ec11668..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/DefaultSocketChannelConfig.java +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.socket; - -import java.net.Socket; -import java.net.SocketException; -import java.util.Map; - -import com.ai.cloud.io.netty.buffer.ByteBufAllocator; -import com.ai.cloud.io.netty.channel.ChannelException; -import com.ai.cloud.io.netty.channel.ChannelOption; -import com.ai.cloud.io.netty.channel.DefaultChannelConfig; -import com.ai.cloud.io.netty.channel.MessageSizeEstimator; -import com.ai.cloud.io.netty.channel.RecvByteBufAllocator; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - -import static com.ai.cloud.io.netty.channel.ChannelOption.*; - -/** - * The default {@link SocketChannelConfig} implementation. - */ -public class DefaultSocketChannelConfig extends DefaultChannelConfig - implements SocketChannelConfig { - - protected final Socket javaSocket; - private volatile boolean allowHalfClosure; - - /** - * Creates a new instance. - */ - public DefaultSocketChannelConfig(SocketChannel channel, Socket javaSocket) { - super(channel); - if (javaSocket == null) { - throw new NullPointerException("javaSocket"); - } - this.javaSocket = javaSocket; - - // Enable TCP_NODELAY by default if possible. - if (PlatformDependent.canEnableTcpNoDelayByDefault()) { - try { - setTcpNoDelay(true); - } catch (Exception e) { - // Ignore. - } - } - } - - @Override - public Map, Object> getOptions() { - return getOptions( - super.getOptions(), - SO_RCVBUF, SO_SNDBUF, TCP_NODELAY, SO_KEEPALIVE, SO_REUSEADDR, SO_LINGER, IP_TOS, - ALLOW_HALF_CLOSURE); - } - - @SuppressWarnings("unchecked") - @Override - public T getOption(ChannelOption option) { - if (option == SO_RCVBUF) { - return (T) Integer.valueOf(getReceiveBufferSize()); - } - if (option == SO_SNDBUF) { - return (T) Integer.valueOf(getSendBufferSize()); - } - if (option == TCP_NODELAY) { - return (T) Boolean.valueOf(isTcpNoDelay()); - } - if (option == SO_KEEPALIVE) { - return (T) Boolean.valueOf(isKeepAlive()); - } - if (option == SO_REUSEADDR) { - return (T) Boolean.valueOf(isReuseAddress()); - } - if (option == SO_LINGER) { - return (T) Integer.valueOf(getSoLinger()); - } - if (option == IP_TOS) { - return (T) Integer.valueOf(getTrafficClass()); - } - if (option == ALLOW_HALF_CLOSURE) { - return (T) Boolean.valueOf(isAllowHalfClosure()); - } - - return super.getOption(option); - } - - @Override - public boolean setOption(ChannelOption option, T value) { - validate(option, value); - - if (option == SO_RCVBUF) { - setReceiveBufferSize((Integer) value); - } else if (option == SO_SNDBUF) { - setSendBufferSize((Integer) value); - } else if (option == TCP_NODELAY) { - setTcpNoDelay((Boolean) value); - } else if (option == SO_KEEPALIVE) { - setKeepAlive((Boolean) value); - } else if (option == SO_REUSEADDR) { - setReuseAddress((Boolean) value); - } else if (option == SO_LINGER) { - setSoLinger((Integer) value); - } else if (option == IP_TOS) { - setTrafficClass((Integer) value); - } else if (option == ALLOW_HALF_CLOSURE) { - setAllowHalfClosure((Boolean) value); - } else { - return super.setOption(option, value); - } - - return true; - } - - @Override - public int getReceiveBufferSize() { - try { - return javaSocket.getReceiveBufferSize(); - } catch (SocketException e) { - throw new ChannelException(e); - } - } - - @Override - public int getSendBufferSize() { - try { - return javaSocket.getSendBufferSize(); - } catch (SocketException e) { - throw new ChannelException(e); - } - } - - @Override - public int getSoLinger() { - try { - return javaSocket.getSoLinger(); - } catch (SocketException e) { - throw new ChannelException(e); - } - } - - @Override - public int getTrafficClass() { - try { - return javaSocket.getTrafficClass(); - } catch (SocketException e) { - throw new ChannelException(e); - } - } - - @Override - public boolean isKeepAlive() { - try { - return javaSocket.getKeepAlive(); - } catch (SocketException e) { - throw new ChannelException(e); - } - } - - @Override - public boolean isReuseAddress() { - try { - return javaSocket.getReuseAddress(); - } catch (SocketException e) { - throw new ChannelException(e); - } - } - - @Override - public boolean isTcpNoDelay() { - try { - return javaSocket.getTcpNoDelay(); - } catch (SocketException e) { - throw new ChannelException(e); - } - } - - @Override - public SocketChannelConfig setKeepAlive(boolean keepAlive) { - try { - javaSocket.setKeepAlive(keepAlive); - } catch (SocketException e) { - throw new ChannelException(e); - } - return this; - } - - @Override - public SocketChannelConfig setPerformancePreferences( - int connectionTime, int latency, int bandwidth) { - javaSocket.setPerformancePreferences(connectionTime, latency, bandwidth); - return this; - } - - @Override - public SocketChannelConfig setReceiveBufferSize(int receiveBufferSize) { - try { - javaSocket.setReceiveBufferSize(receiveBufferSize); - } catch (SocketException e) { - throw new ChannelException(e); - } - return this; - } - - @Override - public SocketChannelConfig setReuseAddress(boolean reuseAddress) { - try { - javaSocket.setReuseAddress(reuseAddress); - } catch (SocketException e) { - throw new ChannelException(e); - } - return this; - } - - @Override - public SocketChannelConfig setSendBufferSize(int sendBufferSize) { - try { - javaSocket.setSendBufferSize(sendBufferSize); - } catch (SocketException e) { - throw new ChannelException(e); - } - return this; - } - - @Override - public SocketChannelConfig setSoLinger(int soLinger) { - try { - if (soLinger < 0) { - javaSocket.setSoLinger(false, 0); - } else { - javaSocket.setSoLinger(true, soLinger); - } - } catch (SocketException e) { - throw new ChannelException(e); - } - return this; - } - - @Override - public SocketChannelConfig setTcpNoDelay(boolean tcpNoDelay) { - try { - javaSocket.setTcpNoDelay(tcpNoDelay); - } catch (SocketException e) { - throw new ChannelException(e); - } - return this; - } - - @Override - public SocketChannelConfig setTrafficClass(int trafficClass) { - try { - javaSocket.setTrafficClass(trafficClass); - } catch (SocketException e) { - throw new ChannelException(e); - } - return this; - } - - @Override - public boolean isAllowHalfClosure() { - return allowHalfClosure; - } - - @Override - public SocketChannelConfig setAllowHalfClosure(boolean allowHalfClosure) { - this.allowHalfClosure = allowHalfClosure; - return this; - } - - @Override - public SocketChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis) { - super.setConnectTimeoutMillis(connectTimeoutMillis); - return this; - } - - @Override - public SocketChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead) { - super.setMaxMessagesPerRead(maxMessagesPerRead); - return this; - } - - @Override - public SocketChannelConfig setWriteSpinCount(int writeSpinCount) { - super.setWriteSpinCount(writeSpinCount); - return this; - } - - @Override - public SocketChannelConfig setAllocator(ByteBufAllocator allocator) { - super.setAllocator(allocator); - return this; - } - - @Override - public SocketChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator) { - super.setRecvByteBufAllocator(allocator); - return this; - } - - @Override - public SocketChannelConfig setAutoRead(boolean autoRead) { - super.setAutoRead(autoRead); - return this; - } - - @Override - public SocketChannelConfig setAutoClose(boolean autoClose) { - super.setAutoClose(autoClose); - return this; - } - - @Override - public SocketChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) { - super.setWriteBufferHighWaterMark(writeBufferHighWaterMark); - return this; - } - - @Override - public SocketChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark) { - super.setWriteBufferLowWaterMark(writeBufferLowWaterMark); - return this; - } - - @Override - public SocketChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator) { - super.setMessageSizeEstimator(estimator); - return this; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/InternetProtocolFamily.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/InternetProtocolFamily.java deleted file mode 100755 index b37c1c60b5..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/InternetProtocolFamily.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.socket; - -/** - * Internet Protocol (IP) families used byte the {@link DatagramChannel} - */ -public enum InternetProtocolFamily { - IPv4, - IPv6 -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/ServerSocketChannel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/ServerSocketChannel.java deleted file mode 100755 index 5ae619e768..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/ServerSocketChannel.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.socket; - -import java.net.InetSocketAddress; - -import com.ai.cloud.io.netty.channel.ServerChannel; - -/** - * A TCP/IP {@link ServerChannel} which accepts incoming TCP/IP connections. - */ -public interface ServerSocketChannel extends ServerChannel { - @Override - ServerSocketChannelConfig config(); - @Override - InetSocketAddress localAddress(); - @Override - InetSocketAddress remoteAddress(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/ServerSocketChannelConfig.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/ServerSocketChannelConfig.java deleted file mode 100755 index f9c3229dae..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/ServerSocketChannelConfig.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.socket; - -import java.net.ServerSocket; -import java.net.StandardSocketOptions; - -import com.ai.cloud.io.netty.buffer.ByteBufAllocator; -import com.ai.cloud.io.netty.channel.ChannelConfig; -import com.ai.cloud.io.netty.channel.MessageSizeEstimator; -import com.ai.cloud.io.netty.channel.RecvByteBufAllocator; - -/** - * A {@link ChannelConfig} for a {@link ServerSocketChannel}. - * - *

Available options

- * - * In addition to the options provided by {@link ChannelConfig}, - * {@link ServerSocketChannelConfig} allows the following options in the - * option map: - * - * - * - * - * - * - * - * - * - * - * - *
NameAssociated setter method
{@code "backlog"}{@link #setBacklog(int)}
{@code "reuseAddress"}{@link #setReuseAddress(boolean)}
{@code "receiveBufferSize"}{@link #setReceiveBufferSize(int)}
- */ -public interface ServerSocketChannelConfig extends ChannelConfig { - - /** - * Gets the backlog value to specify when the channel binds to a local - * address. - */ - int getBacklog(); - - /** - * Sets the backlog value to specify when the channel binds to a local - * address. - */ - ServerSocketChannelConfig setBacklog(int backlog); - - /** - * Gets the {@link StandardSocketOptions#SO_REUSEADDR} option. - */ - boolean isReuseAddress(); - - /** - * Sets the {@link StandardSocketOptions#SO_REUSEADDR} option. - */ - ServerSocketChannelConfig setReuseAddress(boolean reuseAddress); - - /** - * Gets the {@link StandardSocketOptions#SO_RCVBUF} option. - */ - int getReceiveBufferSize(); - - /** - * Gets the {@link StandardSocketOptions#SO_SNDBUF} option. - */ - ServerSocketChannelConfig setReceiveBufferSize(int receiveBufferSize); - - /** - * Sets the performance preferences as specified in - * {@link ServerSocket#setPerformancePreferences(int, int, int)}. - */ - ServerSocketChannelConfig setPerformancePreferences(int connectionTime, int latency, int bandwidth); - - @Override - ServerSocketChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis); - - @Override - ServerSocketChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead); - - @Override - ServerSocketChannelConfig setWriteSpinCount(int writeSpinCount); - - @Override - ServerSocketChannelConfig setAllocator(ByteBufAllocator allocator); - - @Override - ServerSocketChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator); - - @Override - ServerSocketChannelConfig setAutoRead(boolean autoRead); - - @Override - ServerSocketChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/SocketChannel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/SocketChannel.java deleted file mode 100755 index 2d81228d5a..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/SocketChannel.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.socket; - -import java.net.InetSocketAddress; -import java.net.Socket; - -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelFuture; -import com.ai.cloud.io.netty.channel.ChannelPromise; - -/** - * A TCP/IP socket {@link Channel}. - */ -public interface SocketChannel extends Channel { - @Override - ServerSocketChannel parent(); - - @Override - SocketChannelConfig config(); - @Override - InetSocketAddress localAddress(); - @Override - InetSocketAddress remoteAddress(); - - /** - * Returns {@code true} if and only if the remote peer shut down its output so that no more - * data is received from this channel. Note that the semantic of this method is different from - * that of {@link Socket#shutdownInput()} and {@link Socket#isInputShutdown()}. - */ - boolean isInputShutdown(); - - /** - * @see Socket#isOutputShutdown() - */ - boolean isOutputShutdown(); - - /** - * @see Socket#shutdownOutput() - */ - ChannelFuture shutdownOutput(); - - /** - * @see Socket#shutdownOutput() - * - * Will notify the given {@link ChannelPromise} - */ - ChannelFuture shutdownOutput(ChannelPromise future); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/SocketChannelConfig.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/SocketChannelConfig.java deleted file mode 100755 index 80787fa216..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/SocketChannelConfig.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.socket; - -import java.net.Socket; -import java.net.StandardSocketOptions; - -import com.ai.cloud.io.netty.buffer.ByteBufAllocator; -import com.ai.cloud.io.netty.channel.ChannelConfig; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelInboundHandler; -import com.ai.cloud.io.netty.channel.ChannelOption; -import com.ai.cloud.io.netty.channel.MessageSizeEstimator; -import com.ai.cloud.io.netty.channel.RecvByteBufAllocator; - -/** - * A {@link ChannelConfig} for a {@link SocketChannel}. - * - *

Available options

- * - * In addition to the options provided by {@link ChannelConfig}, - * {@link SocketChannelConfig} allows the following options in the option map: - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
NameAssociated setter method
{@link ChannelOption#SO_KEEPALIVE}{@link #setKeepAlive(boolean)}
{@link ChannelOption#SO_REUSEADDR}{@link #setReuseAddress(boolean)}
{@link ChannelOption#SO_LINGER}{@link #setSoLinger(int)}
{@link ChannelOption#TCP_NODELAY}{@link #setTcpNoDelay(boolean)}
{@link ChannelOption#SO_RCVBUF}{@link #setReceiveBufferSize(int)}
{@link ChannelOption#SO_SNDBUF}{@link #setSendBufferSize(int)}
{@link ChannelOption#IP_TOS}{@link #setTrafficClass(int)}
{@link ChannelOption#ALLOW_HALF_CLOSURE}{@link #setAllowHalfClosure(boolean)}
- */ -public interface SocketChannelConfig extends ChannelConfig { - - /** - * Gets the {@link StandardSocketOptions#TCP_NODELAY} option. Please note that the default value of this option - * is {@code true} unlike the operating system default ({@code false}). However, for some buggy platforms, such as - * Android, that shows erratic behavior with Nagle's algorithm disabled, the default value remains to be - * {@code false}. - */ - boolean isTcpNoDelay(); - - /** - * Sets the {@link StandardSocketOptions#TCP_NODELAY} option. Please note that the default value of this option - * is {@code true} unlike the operating system default ({@code false}). However, for some buggy platforms, such as - * Android, that shows erratic behavior with Nagle's algorithm disabled, the default value remains to be - * {@code false}. - */ - SocketChannelConfig setTcpNoDelay(boolean tcpNoDelay); - - /** - * Gets the {@link StandardSocketOptions#SO_LINGER} option. - */ - int getSoLinger(); - - /** - * Sets the {@link StandardSocketOptions#SO_LINGER} option. - */ - SocketChannelConfig setSoLinger(int soLinger); - - /** - * Gets the {@link StandardSocketOptions#SO_SNDBUF} option. - */ - int getSendBufferSize(); - - /** - * Sets the {@link StandardSocketOptions#SO_SNDBUF} option. - */ - SocketChannelConfig setSendBufferSize(int sendBufferSize); - - /** - * Gets the {@link StandardSocketOptions#SO_RCVBUF} option. - */ - int getReceiveBufferSize(); - - /** - * Sets the {@link StandardSocketOptions#SO_RCVBUF} option. - */ - SocketChannelConfig setReceiveBufferSize(int receiveBufferSize); - - /** - * Gets the {@link StandardSocketOptions#SO_KEEPALIVE} option. - */ - boolean isKeepAlive(); - - /** - * Sets the {@link StandardSocketOptions#SO_KEEPALIVE} option. - */ - SocketChannelConfig setKeepAlive(boolean keepAlive); - - /** - * Gets the {@link StandardSocketOptions#IP_TOS} option. - */ - int getTrafficClass(); - - /** - * Sets the {@link StandardSocketOptions#IP_TOS} option. - */ - SocketChannelConfig setTrafficClass(int trafficClass); - - /** - * Gets the {@link StandardSocketOptions#SO_REUSEADDR} option. - */ - boolean isReuseAddress(); - - /** - * Sets the {@link StandardSocketOptions#SO_REUSEADDR} option. - */ - SocketChannelConfig setReuseAddress(boolean reuseAddress); - - /** - * Sets the performance preferences as specified in - * {@link Socket#setPerformancePreferences(int, int, int)}. - */ - SocketChannelConfig setPerformancePreferences(int connectionTime, int latency, int bandwidth); - - /** - * Returns {@code true} if and only if the channel should not close itself when its remote - * peer shuts down output to make the connection half-closed. If {@code false}, the connection - * is closed automatically when the remote peer shuts down output. - */ - boolean isAllowHalfClosure(); - - /** - * Sets whether the channel should not close itself when its remote peer shuts down output to - * make the connection half-closed. If {@code true} the connection is not closed when the - * remote peer shuts down output. Instead, - * {@link ChannelInboundHandler#userEventTriggered(ChannelHandlerContext, Object)} - * is invoked with a {@link ChannelInputShutdownEvent} object. If {@code false}, the connection - * is closed automatically. - */ - SocketChannelConfig setAllowHalfClosure(boolean allowHalfClosure); - - @Override - SocketChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis); - - @Override - SocketChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead); - - @Override - SocketChannelConfig setWriteSpinCount(int writeSpinCount); - - @Override - SocketChannelConfig setAllocator(ByteBufAllocator allocator); - - @Override - SocketChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator); - - @Override - SocketChannelConfig setAutoRead(boolean autoRead); - - @Override - SocketChannelConfig setAutoClose(boolean autoClose); - - @Override - SocketChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/nio/NioDatagramChannel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/nio/NioDatagramChannel.java deleted file mode 100755 index e18bb1bf26..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/nio/NioDatagramChannel.java +++ /dev/null @@ -1,589 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.socket.nio; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.NetworkInterface; -import java.net.SocketAddress; -import java.net.SocketException; -import java.nio.ByteBuffer; -import java.nio.channels.DatagramChannel; -import java.nio.channels.MembershipKey; -import java.nio.channels.SelectionKey; -import java.nio.channels.spi.SelectorProvider; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.AddressedEnvelope; -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelException; -import com.ai.cloud.io.netty.channel.ChannelFuture; -import com.ai.cloud.io.netty.channel.ChannelMetadata; -import com.ai.cloud.io.netty.channel.ChannelOption; -import com.ai.cloud.io.netty.channel.ChannelOutboundBuffer; -import com.ai.cloud.io.netty.channel.ChannelPromise; -import com.ai.cloud.io.netty.channel.DefaultAddressedEnvelope; -import com.ai.cloud.io.netty.channel.RecvByteBufAllocator; -import com.ai.cloud.io.netty.channel.nio.AbstractNioMessageChannel; -import com.ai.cloud.io.netty.channel.socket.DatagramChannelConfig; -import com.ai.cloud.io.netty.channel.socket.DatagramPacket; -import com.ai.cloud.io.netty.channel.socket.InternetProtocolFamily; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; -import com.ai.cloud.io.netty.util.internal.StringUtil; - -/** - * An NIO datagram {@link Channel} that sends and receives an - * {@link AddressedEnvelope AddressedEnvelope}. - * - * @see AddressedEnvelope - * @see DatagramPacket - */ -public final class NioDatagramChannel - extends AbstractNioMessageChannel implements com.ai.cloud.io.netty.channel.socket.DatagramChannel { - - private static final ChannelMetadata METADATA = new ChannelMetadata(true); - private static final SelectorProvider DEFAULT_SELECTOR_PROVIDER = SelectorProvider.provider(); - private static final String EXPECTED_TYPES = - " (expected: " + StringUtil.simpleClassName(DatagramPacket.class) + ", " + - StringUtil.simpleClassName(AddressedEnvelope.class) + '<' + - StringUtil.simpleClassName(ByteBuf.class) + ", " + - StringUtil.simpleClassName(SocketAddress.class) + ">, " + - StringUtil.simpleClassName(ByteBuf.class) + ')'; - - private final DatagramChannelConfig config; - - private Map> memberships; - private RecvByteBufAllocator.Handle allocHandle; - - private static DatagramChannel newSocket(SelectorProvider provider) { - try { - /** - * Use the {@link SelectorProvider} to open {@link SocketChannel} and so remove condition in - * {@link SelectorProvider#provider()} which is called by each DatagramChannel.open() otherwise. - * - * See #2308. - */ - return provider.openDatagramChannel(); - } catch (IOException e) { - throw new ChannelException("Failed to open a socket.", e); - } - } - - private static DatagramChannel newSocket(SelectorProvider provider, InternetProtocolFamily ipFamily) { - if (ipFamily == null) { - return newSocket(provider); - } - - checkJavaVersion(); - - try { - return provider.openDatagramChannel(ProtocolFamilyConverter.convert(ipFamily)); - } catch (IOException e) { - throw new ChannelException("Failed to open a socket.", e); - } - } - - private static void checkJavaVersion() { - if (PlatformDependent.javaVersion() < 7) { - throw new UnsupportedOperationException("Only supported on java 7+."); - } - } - - /** - * Create a new instance which will use the Operation Systems default {@link InternetProtocolFamily}. - */ - public NioDatagramChannel() { - this(newSocket(DEFAULT_SELECTOR_PROVIDER)); - } - - /** - * Create a new instance using the given {@link SelectorProvider} - * which will use the Operation Systems default {@link InternetProtocolFamily}. - */ - public NioDatagramChannel(SelectorProvider provider) { - this(newSocket(provider)); - } - - /** - * Create a new instance using the given {@link InternetProtocolFamily}. If {@code null} is used it will depend - * on the Operation Systems default which will be chosen. - */ - public NioDatagramChannel(InternetProtocolFamily ipFamily) { - this(newSocket(DEFAULT_SELECTOR_PROVIDER, ipFamily)); - } - - /** - * Create a new instance using the given {@link SelectorProvider} and {@link InternetProtocolFamily}. - * If {@link InternetProtocolFamily} is {@code null} it will depend on the Operation Systems default - * which will be chosen. - */ - public NioDatagramChannel(SelectorProvider provider, InternetProtocolFamily ipFamily) { - this(newSocket(provider, ipFamily)); - } - - /** - * Create a new instance from the given {@link DatagramChannel}. - */ - public NioDatagramChannel(DatagramChannel socket) { - super(null, socket, SelectionKey.OP_READ); - config = new NioDatagramChannelConfig(this, socket); - } - - @Override - public ChannelMetadata metadata() { - return METADATA; - } - - @Override - public DatagramChannelConfig config() { - return config; - } - - @Override - @SuppressWarnings("deprecation") - public boolean isActive() { - DatagramChannel ch = javaChannel(); - return ch.isOpen() && ( - config.getOption(ChannelOption.DATAGRAM_CHANNEL_ACTIVE_ON_REGISTRATION) && isRegistered() - || ch.socket().isBound()); - } - - @Override - public boolean isConnected() { - return javaChannel().isConnected(); - } - - @Override - protected DatagramChannel javaChannel() { - return (DatagramChannel) super.javaChannel(); - } - - @Override - protected SocketAddress localAddress0() { - return javaChannel().socket().getLocalSocketAddress(); - } - - @Override - protected SocketAddress remoteAddress0() { - return javaChannel().socket().getRemoteSocketAddress(); - } - - @Override - protected void doBind(SocketAddress localAddress) throws Exception { - javaChannel().socket().bind(localAddress); - } - - @Override - protected boolean doConnect(SocketAddress remoteAddress, - SocketAddress localAddress) throws Exception { - if (localAddress != null) { - javaChannel().socket().bind(localAddress); - } - - boolean success = false; - try { - javaChannel().connect(remoteAddress); - success = true; - return true; - } finally { - if (!success) { - doClose(); - } - } - } - - @Override - protected void doFinishConnect() throws Exception { - throw new Error(); - } - - @Override - protected void doDisconnect() throws Exception { - javaChannel().disconnect(); - } - - @Override - protected void doClose() throws Exception { - javaChannel().close(); - } - - @Override - protected int doReadMessages(List buf) throws Exception { - DatagramChannel ch = javaChannel(); - DatagramChannelConfig config = config(); - RecvByteBufAllocator.Handle allocHandle = this.allocHandle; - if (allocHandle == null) { - this.allocHandle = allocHandle = config.getRecvByteBufAllocator().newHandle(); - } - ByteBuf data = allocHandle.allocate(config.getAllocator()); - boolean free = true; - try { - ByteBuffer nioData = data.internalNioBuffer(data.writerIndex(), data.writableBytes()); - int pos = nioData.position(); - InetSocketAddress remoteAddress = (InetSocketAddress) ch.receive(nioData); - if (remoteAddress == null) { - return 0; - } - - int readBytes = nioData.position() - pos; - data.writerIndex(data.writerIndex() + readBytes); - allocHandle.record(readBytes); - - buf.add(new DatagramPacket(data, localAddress(), remoteAddress)); - free = false; - return 1; - } catch (Throwable cause) { - PlatformDependent.throwException(cause); - return -1; - } finally { - if (free) { - data.release(); - } - } - } - - @Override - protected boolean doWriteMessage(Object msg, ChannelOutboundBuffer in) throws Exception { - final SocketAddress remoteAddress; - final ByteBuf data; - if (msg instanceof AddressedEnvelope) { - @SuppressWarnings("unchecked") - AddressedEnvelope envelope = (AddressedEnvelope) msg; - remoteAddress = envelope.recipient(); - data = envelope.content(); - } else { - data = (ByteBuf) msg; - remoteAddress = null; - } - - final int dataLen = data.readableBytes(); - if (dataLen == 0) { - return true; - } - - final ByteBuffer nioData = data.internalNioBuffer(data.readerIndex(), dataLen); - final int writtenBytes; - if (remoteAddress != null) { - writtenBytes = javaChannel().send(nioData, remoteAddress); - } else { - writtenBytes = javaChannel().write(nioData); - } - return writtenBytes > 0; - } - - @Override - protected Object filterOutboundMessage(Object msg) { - if (msg instanceof DatagramPacket) { - DatagramPacket p = (DatagramPacket) msg; - ByteBuf content = p.content(); - if (isSingleDirectBuffer(content)) { - return p; - } - return new DatagramPacket(newDirectBuffer(p, content), p.recipient()); - } - - if (msg instanceof ByteBuf) { - ByteBuf buf = (ByteBuf) msg; - if (isSingleDirectBuffer(buf)) { - return buf; - } - return newDirectBuffer(buf); - } - - if (msg instanceof AddressedEnvelope) { - @SuppressWarnings("unchecked") - AddressedEnvelope e = (AddressedEnvelope) msg; - if (e.content() instanceof ByteBuf) { - ByteBuf content = (ByteBuf) e.content(); - if (isSingleDirectBuffer(content)) { - return e; - } - return new DefaultAddressedEnvelope(newDirectBuffer(e, content), e.recipient()); - } - } - - throw new UnsupportedOperationException( - "unsupported message type: " + StringUtil.simpleClassName(msg) + EXPECTED_TYPES); - } - - /** - * Checks if the specified buffer is a direct buffer and is composed of a single NIO buffer. - * (We check this because otherwise we need to make it a non-composite buffer.) - */ - private static boolean isSingleDirectBuffer(ByteBuf buf) { - return buf.isDirect() && buf.nioBufferCount() == 1; - } - - @Override - protected boolean continueOnWriteError() { - // Continue on write error as a DatagramChannel can write to multiple remote peers - // - // See https://github.com/netty/netty/issues/2665 - return true; - } - - @Override - public InetSocketAddress localAddress() { - return (InetSocketAddress) super.localAddress(); - } - - @Override - public InetSocketAddress remoteAddress() { - return (InetSocketAddress) super.remoteAddress(); - } - - @Override - public ChannelFuture joinGroup(InetAddress multicastAddress) { - return joinGroup(multicastAddress, newPromise()); - } - - @Override - public ChannelFuture joinGroup(InetAddress multicastAddress, ChannelPromise promise) { - try { - return joinGroup( - multicastAddress, - NetworkInterface.getByInetAddress(localAddress().getAddress()), - null, promise); - } catch (SocketException e) { - promise.setFailure(e); - } - return promise; - } - - @Override - public ChannelFuture joinGroup( - InetSocketAddress multicastAddress, NetworkInterface networkInterface) { - return joinGroup(multicastAddress, networkInterface, newPromise()); - } - - @Override - public ChannelFuture joinGroup( - InetSocketAddress multicastAddress, NetworkInterface networkInterface, - ChannelPromise promise) { - return joinGroup(multicastAddress.getAddress(), networkInterface, null, promise); - } - - @Override - public ChannelFuture joinGroup( - InetAddress multicastAddress, NetworkInterface networkInterface, InetAddress source) { - return joinGroup(multicastAddress, networkInterface, source, newPromise()); - } - - @Override - public ChannelFuture joinGroup( - InetAddress multicastAddress, NetworkInterface networkInterface, - InetAddress source, ChannelPromise promise) { - - checkJavaVersion(); - - if (multicastAddress == null) { - throw new NullPointerException("multicastAddress"); - } - - if (networkInterface == null) { - throw new NullPointerException("networkInterface"); - } - - try { - MembershipKey key; - if (source == null) { - key = javaChannel().join(multicastAddress, networkInterface); - } else { - key = javaChannel().join(multicastAddress, networkInterface, source); - } - - synchronized (this) { - List keys = null; - if (memberships == null) { - memberships = new HashMap>(); - } else { - keys = memberships.get(multicastAddress); - } - if (keys == null) { - keys = new ArrayList(); - memberships.put(multicastAddress, keys); - } - keys.add(key); - } - - promise.setSuccess(); - } catch (Throwable e) { - promise.setFailure(e); - } - - return promise; - } - - @Override - public ChannelFuture leaveGroup(InetAddress multicastAddress) { - return leaveGroup(multicastAddress, newPromise()); - } - - @Override - public ChannelFuture leaveGroup(InetAddress multicastAddress, ChannelPromise promise) { - try { - return leaveGroup( - multicastAddress, NetworkInterface.getByInetAddress(localAddress().getAddress()), null, promise); - } catch (SocketException e) { - promise.setFailure(e); - } - return promise; - } - - @Override - public ChannelFuture leaveGroup( - InetSocketAddress multicastAddress, NetworkInterface networkInterface) { - return leaveGroup(multicastAddress, networkInterface, newPromise()); - } - - @Override - public ChannelFuture leaveGroup( - InetSocketAddress multicastAddress, - NetworkInterface networkInterface, ChannelPromise promise) { - return leaveGroup(multicastAddress.getAddress(), networkInterface, null, promise); - } - - @Override - public ChannelFuture leaveGroup( - InetAddress multicastAddress, NetworkInterface networkInterface, InetAddress source) { - return leaveGroup(multicastAddress, networkInterface, source, newPromise()); - } - - @Override - public ChannelFuture leaveGroup( - InetAddress multicastAddress, NetworkInterface networkInterface, InetAddress source, - ChannelPromise promise) { - checkJavaVersion(); - - if (multicastAddress == null) { - throw new NullPointerException("multicastAddress"); - } - if (networkInterface == null) { - throw new NullPointerException("networkInterface"); - } - - synchronized (this) { - if (memberships != null) { - List keys = memberships.get(multicastAddress); - if (keys != null) { - Iterator keyIt = keys.iterator(); - - while (keyIt.hasNext()) { - MembershipKey key = keyIt.next(); - if (networkInterface.equals(key.networkInterface())) { - if (source == null && key.sourceAddress() == null || - source != null && source.equals(key.sourceAddress())) { - key.drop(); - keyIt.remove(); - } - } - } - if (keys.isEmpty()) { - memberships.remove(multicastAddress); - } - } - } - } - - promise.setSuccess(); - return promise; - } - - /** - * Block the given sourceToBlock address for the given multicastAddress on the given networkInterface - */ - @Override - public ChannelFuture block( - InetAddress multicastAddress, NetworkInterface networkInterface, - InetAddress sourceToBlock) { - return block(multicastAddress, networkInterface, sourceToBlock, newPromise()); - } - - /** - * Block the given sourceToBlock address for the given multicastAddress on the given networkInterface - */ - @Override - public ChannelFuture block( - InetAddress multicastAddress, NetworkInterface networkInterface, - InetAddress sourceToBlock, ChannelPromise promise) { - checkJavaVersion(); - - if (multicastAddress == null) { - throw new NullPointerException("multicastAddress"); - } - if (sourceToBlock == null) { - throw new NullPointerException("sourceToBlock"); - } - - if (networkInterface == null) { - throw new NullPointerException("networkInterface"); - } - synchronized (this) { - if (memberships != null) { - List keys = memberships.get(multicastAddress); - for (MembershipKey key: keys) { - if (networkInterface.equals(key.networkInterface())) { - try { - key.block(sourceToBlock); - } catch (IOException e) { - promise.setFailure(e); - } - } - } - } - } - promise.setSuccess(); - return promise; - } - - /** - * Block the given sourceToBlock address for the given multicastAddress - * - */ - @Override - public ChannelFuture block(InetAddress multicastAddress, InetAddress sourceToBlock) { - return block(multicastAddress, sourceToBlock, newPromise()); - } - - /** - * Block the given sourceToBlock address for the given multicastAddress - * - */ - @Override - public ChannelFuture block( - InetAddress multicastAddress, InetAddress sourceToBlock, ChannelPromise promise) { - try { - return block( - multicastAddress, - NetworkInterface.getByInetAddress(localAddress().getAddress()), - sourceToBlock, promise); - } catch (SocketException e) { - promise.setFailure(e); - } - return promise; - } - - @Override - protected void setReadPending(boolean readPending) { - super.setReadPending(readPending); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/nio/NioDatagramChannelConfig.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/nio/NioDatagramChannelConfig.java deleted file mode 100755 index f04134d830..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/nio/NioDatagramChannelConfig.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.socket.nio; - -import java.lang.reflect.Method; -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.net.SocketException; -import java.nio.channels.DatagramChannel; -import java.nio.channels.NetworkChannel; -import java.util.Enumeration; - -import com.ai.cloud.io.netty.channel.ChannelException; -import com.ai.cloud.io.netty.channel.socket.DatagramChannelConfig; -import com.ai.cloud.io.netty.channel.socket.DefaultDatagramChannelConfig; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - -/** - * The default {@link NioDatagramChannelConfig} implementation. - */ -class NioDatagramChannelConfig extends DefaultDatagramChannelConfig { - - private static final Object IP_MULTICAST_TTL; - private static final Object IP_MULTICAST_IF; - private static final Object IP_MULTICAST_LOOP; - private static final Method GET_OPTION; - private static final Method SET_OPTION; - - static { - ClassLoader classLoader = PlatformDependent.getClassLoader(DatagramChannel.class); - Class socketOptionType = null; - try { - socketOptionType = Class.forName("java.net.SocketOption", true, classLoader); - } catch (Exception e) { - // Not Java 7+ - } - Class stdSocketOptionType = null; - try { - stdSocketOptionType = Class.forName("java.net.StandardSocketOptions", true, classLoader); - } catch (Exception e) { - // Not Java 7+ - } - - Object ipMulticastTtl = null; - Object ipMulticastIf = null; - Object ipMulticastLoop = null; - Method getOption = null; - Method setOption = null; - if (socketOptionType != null) { - try { - ipMulticastTtl = stdSocketOptionType.getDeclaredField("IP_MULTICAST_TTL").get(null); - } catch (Exception e) { - throw new Error("cannot locate the IP_MULTICAST_TTL field", e); - } - - try { - ipMulticastIf = stdSocketOptionType.getDeclaredField("IP_MULTICAST_IF").get(null); - } catch (Exception e) { - throw new Error("cannot locate the IP_MULTICAST_IF field", e); - } - - try { - ipMulticastLoop = stdSocketOptionType.getDeclaredField("IP_MULTICAST_LOOP").get(null); - } catch (Exception e) { - throw new Error("cannot locate the IP_MULTICAST_LOOP field", e); - } - - try { - getOption = NetworkChannel.class.getDeclaredMethod("getOption", socketOptionType); - } catch (Exception e) { - throw new Error("cannot locate the getOption() method", e); - } - - try { - setOption = NetworkChannel.class.getDeclaredMethod("setOption", socketOptionType, Object.class); - } catch (Exception e) { - throw new Error("cannot locate the setOption() method", e); - } - } - IP_MULTICAST_TTL = ipMulticastTtl; - IP_MULTICAST_IF = ipMulticastIf; - IP_MULTICAST_LOOP = ipMulticastLoop; - GET_OPTION = getOption; - SET_OPTION = setOption; - } - - private final DatagramChannel javaChannel; - - NioDatagramChannelConfig(NioDatagramChannel channel, DatagramChannel javaChannel) { - super(channel, javaChannel.socket()); - this.javaChannel = javaChannel; - } - - @Override - public int getTimeToLive() { - return (Integer) getOption0(IP_MULTICAST_TTL); - } - - @Override - public DatagramChannelConfig setTimeToLive(int ttl) { - setOption0(IP_MULTICAST_TTL, ttl); - return this; - } - - @Override - public InetAddress getInterface() { - NetworkInterface inf = getNetworkInterface(); - if (inf == null) { - return null; - } else { - Enumeration addresses = inf.getInetAddresses(); - if (addresses.hasMoreElements()) { - return addresses.nextElement(); - } - return null; - } - } - - @Override - public DatagramChannelConfig setInterface(InetAddress interfaceAddress) { - try { - setNetworkInterface(NetworkInterface.getByInetAddress(interfaceAddress)); - } catch (SocketException e) { - throw new ChannelException(e); - } - return this; - } - - @Override - public NetworkInterface getNetworkInterface() { - return (NetworkInterface) getOption0(IP_MULTICAST_IF); - } - - @Override - public DatagramChannelConfig setNetworkInterface(NetworkInterface networkInterface) { - setOption0(IP_MULTICAST_IF, networkInterface); - return this; - } - - @Override - public boolean isLoopbackModeDisabled() { - return (Boolean) getOption0(IP_MULTICAST_LOOP); - } - - @Override - public DatagramChannelConfig setLoopbackModeDisabled(boolean loopbackModeDisabled) { - setOption0(IP_MULTICAST_LOOP, loopbackModeDisabled); - return this; - } - - @Override - public DatagramChannelConfig setAutoRead(boolean autoRead) { - super.setAutoRead(autoRead); - return this; - } - - @Override - protected void autoReadCleared() { - ((NioDatagramChannel) channel).setReadPending(false); - } - - private Object getOption0(Object option) { - if (PlatformDependent.javaVersion() < 7) { - throw new UnsupportedOperationException(); - } else { - try { - return GET_OPTION.invoke(javaChannel, option); - } catch (Exception e) { - throw new ChannelException(e); - } - } - } - - private void setOption0(Object option, Object value) { - if (PlatformDependent.javaVersion() < 7) { - throw new UnsupportedOperationException(); - } else { - try { - SET_OPTION.invoke(javaChannel, option, value); - } catch (Exception e) { - throw new ChannelException(e); - } - } - } - -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/nio/NioServerSocketChannel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/nio/NioServerSocketChannel.java deleted file mode 100755 index 4371244c47..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/nio/NioServerSocketChannel.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.socket.nio; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.ServerSocket; -import java.net.SocketAddress; -import java.nio.channels.SelectionKey; -import java.nio.channels.ServerSocketChannel; -import java.nio.channels.SocketChannel; -import java.nio.channels.spi.SelectorProvider; -import java.util.List; - -import com.ai.cloud.io.netty.channel.ChannelException; -import com.ai.cloud.io.netty.channel.ChannelMetadata; -import com.ai.cloud.io.netty.channel.ChannelOutboundBuffer; -import com.ai.cloud.io.netty.channel.nio.AbstractNioMessageChannel; -import com.ai.cloud.io.netty.channel.socket.DefaultServerSocketChannelConfig; -import com.ai.cloud.io.netty.channel.socket.ServerSocketChannelConfig; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * A {@link com.ai.cloud.io.netty.channel.socket.ServerSocketChannel} implementation which uses - * NIO selector based implementation to accept new connections. - */ -public class NioServerSocketChannel extends AbstractNioMessageChannel - implements com.ai.cloud.io.netty.channel.socket.ServerSocketChannel { - - private static final ChannelMetadata METADATA = new ChannelMetadata(false); - private static final SelectorProvider DEFAULT_SELECTOR_PROVIDER = SelectorProvider.provider(); - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(NioServerSocketChannel.class); - - private static ServerSocketChannel newSocket(SelectorProvider provider) { - try { - /** - * Use the {@link SelectorProvider} to open {@link SocketChannel} and so remove condition in - * {@link SelectorProvider#provider()} which is called by each ServerSocketChannel.open() otherwise. - * - * See #2308. - */ - return provider.openServerSocketChannel(); - } catch (IOException e) { - throw new ChannelException( - "Failed to open a server socket.", e); - } - } - - private final ServerSocketChannelConfig config; - - /** - * Create a new instance - */ - public NioServerSocketChannel() { - this(newSocket(DEFAULT_SELECTOR_PROVIDER)); - } - - /** - * Create a new instance using the given {@link SelectorProvider}. - */ - public NioServerSocketChannel(SelectorProvider provider) { - this(newSocket(provider)); - } - - /** - * Create a new instance using the given {@link ServerSocketChannel}. - */ - public NioServerSocketChannel(ServerSocketChannel channel) { - super(null, channel, SelectionKey.OP_ACCEPT); - config = new NioServerSocketChannelConfig(this, javaChannel().socket()); - } - - @Override - public InetSocketAddress localAddress() { - return (InetSocketAddress) super.localAddress(); - } - - @Override - public ChannelMetadata metadata() { - return METADATA; - } - - @Override - public ServerSocketChannelConfig config() { - return config; - } - - @Override - public boolean isActive() { - return javaChannel().socket().isBound(); - } - - @Override - public InetSocketAddress remoteAddress() { - return null; - } - - @Override - protected ServerSocketChannel javaChannel() { - return (ServerSocketChannel) super.javaChannel(); - } - - @Override - protected SocketAddress localAddress0() { - return javaChannel().socket().getLocalSocketAddress(); - } - - @Override - protected void doBind(SocketAddress localAddress) throws Exception { - javaChannel().socket().bind(localAddress, config.getBacklog()); - } - - @Override - protected void doClose() throws Exception { - javaChannel().close(); - } - - @Override - protected int doReadMessages(List buf) throws Exception { - SocketChannel ch = javaChannel().accept(); - - try { - if (ch != null) { - buf.add(new NioSocketChannel(this, ch)); - return 1; - } - } catch (Throwable t) { - logger.warn("Failed to create a new channel from an accepted socket.", t); - - try { - ch.close(); - } catch (Throwable t2) { - logger.warn("Failed to close a socket.", t2); - } - } - - return 0; - } - - // Unnecessary stuff - @Override - protected boolean doConnect( - SocketAddress remoteAddress, SocketAddress localAddress) throws Exception { - throw new UnsupportedOperationException(); - } - - @Override - protected void doFinishConnect() throws Exception { - throw new UnsupportedOperationException(); - } - - @Override - protected SocketAddress remoteAddress0() { - return null; - } - - @Override - protected void doDisconnect() throws Exception { - throw new UnsupportedOperationException(); - } - - @Override - protected boolean doWriteMessage(Object msg, ChannelOutboundBuffer in) throws Exception { - throw new UnsupportedOperationException(); - } - - @Override - protected final Object filterOutboundMessage(Object msg) throws Exception { - throw new UnsupportedOperationException(); - } - - private final class NioServerSocketChannelConfig extends DefaultServerSocketChannelConfig { - private NioServerSocketChannelConfig(NioServerSocketChannel channel, ServerSocket javaSocket) { - super(channel, javaSocket); - } - - @Override - protected void autoReadCleared() { - setReadPending(false); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/nio/NioSocketChannel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/nio/NioSocketChannel.java deleted file mode 100755 index f278c3c535..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/nio/NioSocketChannel.java +++ /dev/null @@ -1,353 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.socket.nio; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.net.SocketAddress; -import java.nio.ByteBuffer; -import java.nio.channels.SelectionKey; -import java.nio.channels.SocketChannel; -import java.nio.channels.spi.SelectorProvider; -import java.util.concurrent.Executor; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelException; -import com.ai.cloud.io.netty.channel.ChannelFuture; -import com.ai.cloud.io.netty.channel.ChannelMetadata; -import com.ai.cloud.io.netty.channel.ChannelOutboundBuffer; -import com.ai.cloud.io.netty.channel.ChannelPromise; -import com.ai.cloud.io.netty.channel.EventLoop; -import com.ai.cloud.io.netty.channel.FileRegion; -import com.ai.cloud.io.netty.channel.nio.AbstractNioByteChannel; -import com.ai.cloud.io.netty.channel.socket.DefaultSocketChannelConfig; -import com.ai.cloud.io.netty.channel.socket.ServerSocketChannel; -import com.ai.cloud.io.netty.channel.socket.SocketChannelConfig; -import com.ai.cloud.io.netty.util.concurrent.GlobalEventExecutor; -import com.ai.cloud.io.netty.util.internal.OneTimeTask; - -/** - * {@link com.ai.cloud.io.netty.channel.socket.SocketChannel} which uses NIO selector based implementation. - */ -public class NioSocketChannel extends AbstractNioByteChannel implements com.ai.cloud.io.netty.channel.socket.SocketChannel { - - private static final ChannelMetadata METADATA = new ChannelMetadata(false); - private static final SelectorProvider DEFAULT_SELECTOR_PROVIDER = SelectorProvider.provider(); - - private static SocketChannel newSocket(SelectorProvider provider) { - try { - /** - * Use the {@link SelectorProvider} to open {@link SocketChannel} and so remove condition in - * {@link SelectorProvider#provider()} which is called by each SocketChannel.open() otherwise. - * - * See #2308. - */ - return provider.openSocketChannel(); - } catch (IOException e) { - throw new ChannelException("Failed to open a socket.", e); - } - } - - private final SocketChannelConfig config; - - /** - * Create a new instance - */ - public NioSocketChannel() { - this(newSocket(DEFAULT_SELECTOR_PROVIDER)); - } - - /** - * Create a new instance using the given {@link SelectorProvider}. - */ - public NioSocketChannel(SelectorProvider provider) { - this(newSocket(provider)); - } - - /** - * Create a new instance using the given {@link SocketChannel}. - */ - public NioSocketChannel(SocketChannel socket) { - this(null, socket); - } - - /** - * Create a new instance - * - * @param parent the {@link Channel} which created this instance or {@code null} if it was created by the user - * @param socket the {@link SocketChannel} which will be used - */ - public NioSocketChannel(Channel parent, SocketChannel socket) { - super(parent, socket); - config = new NioSocketChannelConfig(this, socket.socket()); - } - - @Override - public ServerSocketChannel parent() { - return (ServerSocketChannel) super.parent(); - } - - @Override - public ChannelMetadata metadata() { - return METADATA; - } - - @Override - public SocketChannelConfig config() { - return config; - } - - @Override - protected SocketChannel javaChannel() { - return (SocketChannel) super.javaChannel(); - } - - @Override - public boolean isActive() { - SocketChannel ch = javaChannel(); - return ch.isOpen() && ch.isConnected(); - } - - @Override - public boolean isInputShutdown() { - return super.isInputShutdown(); - } - - @Override - public InetSocketAddress localAddress() { - return (InetSocketAddress) super.localAddress(); - } - - @Override - public InetSocketAddress remoteAddress() { - return (InetSocketAddress) super.remoteAddress(); - } - - @Override - public boolean isOutputShutdown() { - return javaChannel().socket().isOutputShutdown() || !isActive(); - } - - @Override - public ChannelFuture shutdownOutput() { - return shutdownOutput(newPromise()); - } - - @Override - public ChannelFuture shutdownOutput(final ChannelPromise promise) { - Executor closeExecutor = ((NioSocketChannelUnsafe) unsafe()).closeExecutor(); - if (closeExecutor != null) { - closeExecutor.execute(new OneTimeTask() { - @Override - public void run() { - shutdownOutput0(promise); - } - }); - } else { - EventLoop loop = eventLoop(); - if (loop.inEventLoop()) { - shutdownOutput0(promise); - } else { - loop.execute(new OneTimeTask() { - @Override - public void run() { - shutdownOutput0(promise); - } - }); - } - } - return promise; - } - - private void shutdownOutput0(final ChannelPromise promise) { - try { - javaChannel().socket().shutdownOutput(); - promise.setSuccess(); - } catch (Throwable t) { - promise.setFailure(t); - } - } - - @Override - protected SocketAddress localAddress0() { - return javaChannel().socket().getLocalSocketAddress(); - } - - @Override - protected SocketAddress remoteAddress0() { - return javaChannel().socket().getRemoteSocketAddress(); - } - - @Override - protected void doBind(SocketAddress localAddress) throws Exception { - javaChannel().socket().bind(localAddress); - } - - @Override - protected boolean doConnect(SocketAddress remoteAddress, SocketAddress localAddress) throws Exception { - if (localAddress != null) { - javaChannel().socket().bind(localAddress); - } - - boolean success = false; - try { - boolean connected = javaChannel().connect(remoteAddress); - if (!connected) { - selectionKey().interestOps(SelectionKey.OP_CONNECT); - } - success = true; - return connected; - } finally { - if (!success) { - doClose(); - } - } - } - - @Override - protected void doFinishConnect() throws Exception { - if (!javaChannel().finishConnect()) { - throw new Error(); - } - } - - @Override - protected void doDisconnect() throws Exception { - doClose(); - } - - @Override - protected void doClose() throws Exception { - super.doClose(); - javaChannel().close(); - } - - @Override - protected int doReadBytes(ByteBuf byteBuf) throws Exception { - return byteBuf.writeBytes(javaChannel(), byteBuf.writableBytes()); - } - - @Override - protected int doWriteBytes(ByteBuf buf) throws Exception { - final int expectedWrittenBytes = buf.readableBytes(); - return buf.readBytes(javaChannel(), expectedWrittenBytes); - } - - @Override - protected long doWriteFileRegion(FileRegion region) throws Exception { - final long position = region.transfered(); - return region.transferTo(javaChannel(), position); - } - - @Override - protected void doWrite(ChannelOutboundBuffer in) throws Exception { - for (;;) { - int size = in.size(); - if (size == 0) { - // All written so clear OP_WRITE - clearOpWrite(); - break; - } - long writtenBytes = 0; - boolean done = false; - boolean setOpWrite = false; - - // Ensure the pending writes are made of ByteBufs only. - ByteBuffer[] nioBuffers = in.nioBuffers(); - int nioBufferCnt = in.nioBufferCount(); - long expectedWrittenBytes = in.nioBufferSize(); - SocketChannel ch = javaChannel(); - - // Always us nioBuffers() to workaround data-corruption. - // See https://github.com/netty/netty/issues/2761 - switch (nioBufferCnt) { - case 0: - // We have something else beside ByteBuffers to write so fallback to normal writes. - super.doWrite(in); - return; - case 1: - // Only one ByteBuf so use non-gathering write - ByteBuffer nioBuffer = nioBuffers[0]; - for (int i = config().getWriteSpinCount() - 1; i >= 0; i --) { - final int localWrittenBytes = ch.write(nioBuffer); - if (localWrittenBytes == 0) { - setOpWrite = true; - break; - } - expectedWrittenBytes -= localWrittenBytes; - writtenBytes += localWrittenBytes; - if (expectedWrittenBytes == 0) { - done = true; - break; - } - } - break; - default: - for (int i = config().getWriteSpinCount() - 1; i >= 0; i --) { - final long localWrittenBytes = ch.write(nioBuffers, 0, nioBufferCnt); - if (localWrittenBytes == 0) { - setOpWrite = true; - break; - } - expectedWrittenBytes -= localWrittenBytes; - writtenBytes += localWrittenBytes; - if (expectedWrittenBytes == 0) { - done = true; - break; - } - } - break; - } - - // Release the fully written buffers, and update the indexes of the partially written buffer. - in.removeBytes(writtenBytes); - - if (!done) { - // Did not write all buffers completely. - incompleteWrite(setOpWrite); - break; - } - } - } - - @Override - protected AbstractNioUnsafe newUnsafe() { - return new NioSocketChannelUnsafe(); - } - - private final class NioSocketChannelUnsafe extends NioByteUnsafe { - @Override - protected Executor closeExecutor() { - if (javaChannel().isOpen() && config().getSoLinger() > 0) { - return GlobalEventExecutor.INSTANCE; - } - return null; - } - } - - private final class NioSocketChannelConfig extends DefaultSocketChannelConfig { - private NioSocketChannelConfig(NioSocketChannel channel, Socket javaSocket) { - super(channel, javaSocket); - } - - @Override - protected void autoReadCleared() { - setReadPending(false); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/nio/ProtocolFamilyConverter.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/nio/ProtocolFamilyConverter.java deleted file mode 100755 index 2cd91191cd..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/nio/ProtocolFamilyConverter.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.socket.nio; - -import java.net.ProtocolFamily; -import java.net.StandardProtocolFamily; - -import com.ai.cloud.io.netty.channel.socket.InternetProtocolFamily; - -/** - * Helper class which convert the {@link InternetProtocolFamily}. - */ -final class ProtocolFamilyConverter { - - private ProtocolFamilyConverter() { - // Utility class - } - - /** - * Convert the {@link InternetProtocolFamily}. This MUST only be called on jdk version >= 7. - */ - public static ProtocolFamily convert(InternetProtocolFamily family) { - switch (family) { - case IPv4: - return StandardProtocolFamily.INET; - case IPv6: - return StandardProtocolFamily.INET6; - default: - throw new IllegalArgumentException(); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/nio/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/nio/package-info.java deleted file mode 100755 index fbe471647f..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/nio/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * NIO-based socket channel - * API implementation - recommended for a large number of connections (>= 1000). - */ -package com.ai.cloud.io.netty.channel.socket.nio; diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/oio/DefaultOioServerSocketChannelConfig.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/oio/DefaultOioServerSocketChannelConfig.java deleted file mode 100755 index 72594eb191..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/oio/DefaultOioServerSocketChannelConfig.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.socket.oio; - -import java.io.IOException; -import java.net.ServerSocket; -import java.util.Map; - -import com.ai.cloud.io.netty.buffer.ByteBufAllocator; -import com.ai.cloud.io.netty.channel.ChannelException; -import com.ai.cloud.io.netty.channel.ChannelOption; -import com.ai.cloud.io.netty.channel.MessageSizeEstimator; -import com.ai.cloud.io.netty.channel.RecvByteBufAllocator; -import com.ai.cloud.io.netty.channel.socket.DefaultServerSocketChannelConfig; -import com.ai.cloud.io.netty.channel.socket.ServerSocketChannel; - -import static com.ai.cloud.io.netty.channel.ChannelOption.*; - -/** - * Default {@link OioServerSocketChannelConfig} implementation - */ -public class DefaultOioServerSocketChannelConfig extends DefaultServerSocketChannelConfig implements - OioServerSocketChannelConfig { - - @Deprecated - public DefaultOioServerSocketChannelConfig(ServerSocketChannel channel, ServerSocket javaSocket) { - super(channel, javaSocket); - } - - DefaultOioServerSocketChannelConfig(OioServerSocketChannel channel, ServerSocket javaSocket) { - super(channel, javaSocket); - } - - @Override - public Map, Object> getOptions() { - return getOptions( - super.getOptions(), SO_TIMEOUT); - } - - @SuppressWarnings("unchecked") - @Override - public T getOption(ChannelOption option) { - if (option == SO_TIMEOUT) { - return (T) Integer.valueOf(getSoTimeout()); - } - return super.getOption(option); - } - - @Override - public boolean setOption(ChannelOption option, T value) { - validate(option, value); - - if (option == SO_TIMEOUT) { - setSoTimeout((Integer) value); - } else { - return super.setOption(option, value); - } - return true; - } - - @Override - public OioServerSocketChannelConfig setSoTimeout(int timeout) { - try { - javaSocket.setSoTimeout(timeout); - } catch (IOException e) { - throw new ChannelException(e); - } - return this; - } - - @Override - public int getSoTimeout() { - try { - return javaSocket.getSoTimeout(); - } catch (IOException e) { - throw new ChannelException(e); - } - } - - @Override - public OioServerSocketChannelConfig setBacklog(int backlog) { - super.setBacklog(backlog); - return this; - } - - @Override - public OioServerSocketChannelConfig setReuseAddress(boolean reuseAddress) { - super.setReuseAddress(reuseAddress); - return this; - } - - @Override - public OioServerSocketChannelConfig setReceiveBufferSize(int receiveBufferSize) { - super.setReceiveBufferSize(receiveBufferSize); - return this; - } - - @Override - public OioServerSocketChannelConfig setPerformancePreferences(int connectionTime, int latency, int bandwidth) { - super.setPerformancePreferences(connectionTime, latency, bandwidth); - return this; - } - - @Override - public OioServerSocketChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis) { - super.setConnectTimeoutMillis(connectTimeoutMillis); - return this; - } - - @Override - public OioServerSocketChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead) { - super.setMaxMessagesPerRead(maxMessagesPerRead); - return this; - } - - @Override - public OioServerSocketChannelConfig setWriteSpinCount(int writeSpinCount) { - super.setWriteSpinCount(writeSpinCount); - return this; - } - - @Override - public OioServerSocketChannelConfig setAllocator(ByteBufAllocator allocator) { - super.setAllocator(allocator); - return this; - } - - @Override - public OioServerSocketChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator) { - super.setRecvByteBufAllocator(allocator); - return this; - } - - @Override - public OioServerSocketChannelConfig setAutoRead(boolean autoRead) { - super.setAutoRead(autoRead); - return this; - } - - @Override - protected void autoReadCleared() { - if (channel instanceof OioServerSocketChannel) { - ((OioServerSocketChannel) channel).setReadPending(false); - } - } - - @Override - public OioServerSocketChannelConfig setAutoClose(boolean autoClose) { - super.setAutoClose(autoClose); - return this; - } - - @Override - public OioServerSocketChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) { - super.setWriteBufferHighWaterMark(writeBufferHighWaterMark); - return this; - } - - @Override - public OioServerSocketChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark) { - super.setWriteBufferLowWaterMark(writeBufferLowWaterMark); - return this; - } - - @Override - public OioServerSocketChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator) { - super.setMessageSizeEstimator(estimator); - return this; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/oio/DefaultOioSocketChannelConfig.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/oio/DefaultOioSocketChannelConfig.java deleted file mode 100755 index cf086e7a77..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/oio/DefaultOioSocketChannelConfig.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.socket.oio; - -import java.io.IOException; -import java.net.Socket; -import java.util.Map; - -import com.ai.cloud.io.netty.buffer.ByteBufAllocator; -import com.ai.cloud.io.netty.channel.ChannelException; -import com.ai.cloud.io.netty.channel.ChannelOption; -import com.ai.cloud.io.netty.channel.MessageSizeEstimator; -import com.ai.cloud.io.netty.channel.RecvByteBufAllocator; -import com.ai.cloud.io.netty.channel.socket.DefaultSocketChannelConfig; -import com.ai.cloud.io.netty.channel.socket.SocketChannel; - -import static com.ai.cloud.io.netty.channel.ChannelOption.*; - -/** - * Default {@link OioSocketChannelConfig} implementation - */ -public class DefaultOioSocketChannelConfig extends DefaultSocketChannelConfig implements OioSocketChannelConfig { - @Deprecated - public DefaultOioSocketChannelConfig(SocketChannel channel, Socket javaSocket) { - super(channel, javaSocket); - } - - DefaultOioSocketChannelConfig(OioSocketChannel channel, Socket javaSocket) { - super(channel, javaSocket); - } - - @Override - public Map, Object> getOptions() { - return getOptions( - super.getOptions(), SO_TIMEOUT); - } - - @SuppressWarnings("unchecked") - @Override - public T getOption(ChannelOption option) { - if (option == SO_TIMEOUT) { - return (T) Integer.valueOf(getSoTimeout()); - } - return super.getOption(option); - } - - @Override - public boolean setOption(ChannelOption option, T value) { - validate(option, value); - - if (option == SO_TIMEOUT) { - setSoTimeout((Integer) value); - } else { - return super.setOption(option, value); - } - return true; - } - - @Override - public OioSocketChannelConfig setSoTimeout(int timeout) { - try { - javaSocket.setSoTimeout(timeout); - } catch (IOException e) { - throw new ChannelException(e); - } - return this; - } - - @Override - public int getSoTimeout() { - try { - return javaSocket.getSoTimeout(); - } catch (IOException e) { - throw new ChannelException(e); - } - } - - @Override - public OioSocketChannelConfig setTcpNoDelay(boolean tcpNoDelay) { - super.setTcpNoDelay(tcpNoDelay); - return this; - } - - @Override - public OioSocketChannelConfig setSoLinger(int soLinger) { - super.setSoLinger(soLinger); - return this; - } - - @Override - public OioSocketChannelConfig setSendBufferSize(int sendBufferSize) { - super.setSendBufferSize(sendBufferSize); - return this; - } - - @Override - public OioSocketChannelConfig setReceiveBufferSize(int receiveBufferSize) { - super.setReceiveBufferSize(receiveBufferSize); - return this; - } - - @Override - public OioSocketChannelConfig setKeepAlive(boolean keepAlive) { - super.setKeepAlive(keepAlive); - return this; - } - - @Override - public OioSocketChannelConfig setTrafficClass(int trafficClass) { - super.setTrafficClass(trafficClass); - return this; - } - - @Override - public OioSocketChannelConfig setReuseAddress(boolean reuseAddress) { - super.setReuseAddress(reuseAddress); - return this; - } - - @Override - public OioSocketChannelConfig setPerformancePreferences(int connectionTime, int latency, int bandwidth) { - super.setPerformancePreferences(connectionTime, latency, bandwidth); - return this; - } - - @Override - public OioSocketChannelConfig setAllowHalfClosure(boolean allowHalfClosure) { - super.setAllowHalfClosure(allowHalfClosure); - return this; - } - - @Override - public OioSocketChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis) { - super.setConnectTimeoutMillis(connectTimeoutMillis); - return this; - } - - @Override - public OioSocketChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead) { - super.setMaxMessagesPerRead(maxMessagesPerRead); - return this; - } - - @Override - public OioSocketChannelConfig setWriteSpinCount(int writeSpinCount) { - super.setWriteSpinCount(writeSpinCount); - return this; - } - - @Override - public OioSocketChannelConfig setAllocator(ByteBufAllocator allocator) { - super.setAllocator(allocator); - return this; - } - - @Override - public OioSocketChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator) { - super.setRecvByteBufAllocator(allocator); - return this; - } - - @Override - public OioSocketChannelConfig setAutoRead(boolean autoRead) { - super.setAutoRead(autoRead); - return this; - } - - @Override - protected void autoReadCleared() { - if (channel instanceof OioSocketChannel) { - ((OioSocketChannel) channel).setReadPending(false); - } - } - - @Override - public OioSocketChannelConfig setAutoClose(boolean autoClose) { - super.setAutoClose(autoClose); - return this; - } - - @Override - public OioSocketChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) { - super.setWriteBufferHighWaterMark(writeBufferHighWaterMark); - return this; - } - - @Override - public OioSocketChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark) { - super.setWriteBufferLowWaterMark(writeBufferLowWaterMark); - return this; - } - - @Override - public OioSocketChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator) { - super.setMessageSizeEstimator(estimator); - return this; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/oio/OioDatagramChannel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/oio/OioDatagramChannel.java deleted file mode 100755 index 22c213737f..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/oio/OioDatagramChannel.java +++ /dev/null @@ -1,435 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.socket.oio; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.MulticastSocket; -import java.net.NetworkInterface; -import java.net.SocketAddress; -import java.net.SocketException; -import java.net.SocketTimeoutException; -import java.util.List; -import java.util.Locale; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.AddressedEnvelope; -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelException; -import com.ai.cloud.io.netty.channel.ChannelFuture; -import com.ai.cloud.io.netty.channel.ChannelMetadata; -import com.ai.cloud.io.netty.channel.ChannelOption; -import com.ai.cloud.io.netty.channel.ChannelOutboundBuffer; -import com.ai.cloud.io.netty.channel.ChannelPromise; -import com.ai.cloud.io.netty.channel.RecvByteBufAllocator; -import com.ai.cloud.io.netty.channel.oio.AbstractOioMessageChannel; -import com.ai.cloud.io.netty.channel.socket.DatagramChannel; -import com.ai.cloud.io.netty.channel.socket.DatagramChannelConfig; -import com.ai.cloud.io.netty.channel.socket.DatagramPacket; -import com.ai.cloud.io.netty.channel.socket.DefaultDatagramChannelConfig; -import com.ai.cloud.io.netty.util.internal.EmptyArrays; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; -import com.ai.cloud.io.netty.util.internal.StringUtil; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * An OIO datagram {@link Channel} that sends and receives an - * {@link AddressedEnvelope AddressedEnvelope}. - * - * @see AddressedEnvelope - * @see DatagramPacket - */ -public class OioDatagramChannel extends AbstractOioMessageChannel - implements DatagramChannel { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(OioDatagramChannel.class); - - private static final ChannelMetadata METADATA = new ChannelMetadata(true); - private static final String EXPECTED_TYPES = - " (expected: " + StringUtil.simpleClassName(DatagramPacket.class) + ", " + - StringUtil.simpleClassName(AddressedEnvelope.class) + '<' + - StringUtil.simpleClassName(ByteBuf.class) + ", " + - StringUtil.simpleClassName(SocketAddress.class) + ">, " + - StringUtil.simpleClassName(ByteBuf.class) + ')'; - - private final MulticastSocket socket; - private final DatagramChannelConfig config; - private final java.net.DatagramPacket tmpPacket = new java.net.DatagramPacket(EmptyArrays.EMPTY_BYTES, 0); - - private RecvByteBufAllocator.Handle allocHandle; - - private static MulticastSocket newSocket() { - try { - return new MulticastSocket(null); - } catch (Exception e) { - throw new ChannelException("failed to create a new socket", e); - } - } - - /** - * Create a new instance with an new {@link MulticastSocket}. - */ - public OioDatagramChannel() { - this(newSocket()); - } - - /** - * Create a new instance from the given {@link MulticastSocket}. - * - * @param socket the {@link MulticastSocket} which is used by this instance - */ - public OioDatagramChannel(MulticastSocket socket) { - super(null); - - boolean success = false; - try { - socket.setSoTimeout(SO_TIMEOUT); - socket.setBroadcast(false); - success = true; - } catch (SocketException e) { - throw new ChannelException( - "Failed to configure the datagram socket timeout.", e); - } finally { - if (!success) { - socket.close(); - } - } - - this.socket = socket; - config = new DefaultDatagramChannelConfig(this, socket); - } - - @Override - public ChannelMetadata metadata() { - return METADATA; - } - - @Override - public DatagramChannelConfig config() { - return config; - } - - @Override - public boolean isOpen() { - return !socket.isClosed(); - } - - @Override - @SuppressWarnings("deprecation") - public boolean isActive() { - return isOpen() - && (config.getOption(ChannelOption.DATAGRAM_CHANNEL_ACTIVE_ON_REGISTRATION) && isRegistered() - || socket.isBound()); - } - - @Override - public boolean isConnected() { - return socket.isConnected(); - } - - @Override - protected SocketAddress localAddress0() { - return socket.getLocalSocketAddress(); - } - - @Override - protected SocketAddress remoteAddress0() { - return socket.getRemoteSocketAddress(); - } - - @Override - protected void doBind(SocketAddress localAddress) throws Exception { - socket.bind(localAddress); - } - - @Override - public InetSocketAddress localAddress() { - return (InetSocketAddress) super.localAddress(); - } - - @Override - public InetSocketAddress remoteAddress() { - return (InetSocketAddress) super.remoteAddress(); - } - - @Override - protected void doConnect(SocketAddress remoteAddress, - SocketAddress localAddress) throws Exception { - if (localAddress != null) { - socket.bind(localAddress); - } - - boolean success = false; - try { - socket.connect(remoteAddress); - success = true; - } finally { - if (!success) { - try { - socket.close(); - } catch (Throwable t) { - logger.warn("Failed to close a socket.", t); - } - } - } - } - - @Override - protected void doDisconnect() throws Exception { - socket.disconnect(); - } - - @Override - protected void doClose() throws Exception { - socket.close(); - } - - @Override - protected int doReadMessages(List buf) throws Exception { - DatagramChannelConfig config = config(); - RecvByteBufAllocator.Handle allocHandle = this.allocHandle; - if (allocHandle == null) { - this.allocHandle = allocHandle = config.getRecvByteBufAllocator().newHandle(); - } - - ByteBuf data = config.getAllocator().heapBuffer(allocHandle.guess()); - boolean free = true; - try { - tmpPacket.setData(data.array(), data.arrayOffset(), data.capacity()); - socket.receive(tmpPacket); - - InetSocketAddress remoteAddr = (InetSocketAddress) tmpPacket.getSocketAddress(); - - int readBytes = tmpPacket.getLength(); - allocHandle.record(readBytes); - buf.add(new DatagramPacket(data.writerIndex(readBytes), localAddress(), remoteAddr)); - free = false; - return 1; - } catch (SocketTimeoutException e) { - // Expected - return 0; - } catch (SocketException e) { - if (!e.getMessage().toLowerCase(Locale.US).contains("socket closed")) { - throw e; - } - return -1; - } catch (Throwable cause) { - PlatformDependent.throwException(cause); - return -1; - } finally { - if (free) { - data.release(); - } - } - } - - @Override - protected void doWrite(ChannelOutboundBuffer in) throws Exception { - for (;;) { - final Object o = in.current(); - if (o == null) { - break; - } - - final ByteBuf data; - final SocketAddress remoteAddress; - if (o instanceof AddressedEnvelope) { - @SuppressWarnings("unchecked") - AddressedEnvelope envelope = (AddressedEnvelope) o; - remoteAddress = envelope.recipient(); - data = envelope.content(); - } else { - data = (ByteBuf) o; - remoteAddress = null; - } - - final int length = data.readableBytes(); - if (remoteAddress != null) { - tmpPacket.setSocketAddress(remoteAddress); - } - if (data.hasArray()) { - tmpPacket.setData(data.array(), data.arrayOffset() + data.readerIndex(), length); - } else { - byte[] tmp = new byte[length]; - data.getBytes(data.readerIndex(), tmp); - tmpPacket.setData(tmp); - } - try { - socket.send(tmpPacket); - in.remove(); - } catch (IOException e) { - // Continue on write error as a DatagramChannel can write to multiple remote peers - // - // See https://github.com/netty/netty/issues/2665 - in.remove(e); - } - } - } - - @Override - protected Object filterOutboundMessage(Object msg) { - if (msg instanceof DatagramPacket || msg instanceof ByteBuf) { - return msg; - } - - if (msg instanceof AddressedEnvelope) { - @SuppressWarnings("unchecked") - AddressedEnvelope e = (AddressedEnvelope) msg; - if (e.content() instanceof ByteBuf) { - return msg; - } - } - - throw new UnsupportedOperationException( - "unsupported message type: " + StringUtil.simpleClassName(msg) + EXPECTED_TYPES); - } - - @Override - public ChannelFuture joinGroup(InetAddress multicastAddress) { - return joinGroup(multicastAddress, newPromise()); - } - - @Override - public ChannelFuture joinGroup(InetAddress multicastAddress, ChannelPromise promise) { - ensureBound(); - try { - socket.joinGroup(multicastAddress); - promise.setSuccess(); - } catch (IOException e) { - promise.setFailure(e); - } - return promise; - } - - @Override - public ChannelFuture joinGroup(InetSocketAddress multicastAddress, NetworkInterface networkInterface) { - return joinGroup(multicastAddress, networkInterface, newPromise()); - } - - @Override - public ChannelFuture joinGroup( - InetSocketAddress multicastAddress, NetworkInterface networkInterface, - ChannelPromise promise) { - ensureBound(); - try { - socket.joinGroup(multicastAddress, networkInterface); - promise.setSuccess(); - } catch (IOException e) { - promise.setFailure(e); - } - return promise; - } - - @Override - public ChannelFuture joinGroup( - InetAddress multicastAddress, NetworkInterface networkInterface, InetAddress source) { - return newFailedFuture(new UnsupportedOperationException()); - } - - @Override - public ChannelFuture joinGroup( - InetAddress multicastAddress, NetworkInterface networkInterface, InetAddress source, - ChannelPromise promise) { - promise.setFailure(new UnsupportedOperationException()); - return promise; - } - - private void ensureBound() { - if (!isActive()) { - throw new IllegalStateException( - DatagramChannel.class.getName() + - " must be bound to join a group."); - } - } - - @Override - public ChannelFuture leaveGroup(InetAddress multicastAddress) { - return leaveGroup(multicastAddress, newPromise()); - } - - @Override - public ChannelFuture leaveGroup(InetAddress multicastAddress, ChannelPromise promise) { - try { - socket.leaveGroup(multicastAddress); - promise.setSuccess(); - } catch (IOException e) { - promise.setFailure(e); - } - return promise; - } - - @Override - public ChannelFuture leaveGroup( - InetSocketAddress multicastAddress, NetworkInterface networkInterface) { - return leaveGroup(multicastAddress, networkInterface, newPromise()); - } - - @Override - public ChannelFuture leaveGroup( - InetSocketAddress multicastAddress, NetworkInterface networkInterface, - ChannelPromise promise) { - try { - socket.leaveGroup(multicastAddress, networkInterface); - promise.setSuccess(); - } catch (IOException e) { - promise.setFailure(e); - } - return promise; - } - - @Override - public ChannelFuture leaveGroup( - InetAddress multicastAddress, NetworkInterface networkInterface, InetAddress source) { - return newFailedFuture(new UnsupportedOperationException()); - } - - @Override - public ChannelFuture leaveGroup( - InetAddress multicastAddress, NetworkInterface networkInterface, InetAddress source, - ChannelPromise promise) { - promise.setFailure(new UnsupportedOperationException()); - return promise; - } - - @Override - public ChannelFuture block(InetAddress multicastAddress, - NetworkInterface networkInterface, InetAddress sourceToBlock) { - return newFailedFuture(new UnsupportedOperationException()); - } - - @Override - public ChannelFuture block(InetAddress multicastAddress, - NetworkInterface networkInterface, InetAddress sourceToBlock, - ChannelPromise promise) { - promise.setFailure(new UnsupportedOperationException()); - return promise; - } - - @Override - public ChannelFuture block(InetAddress multicastAddress, - InetAddress sourceToBlock) { - return newFailedFuture(new UnsupportedOperationException()); - } - - @Override - public ChannelFuture block(InetAddress multicastAddress, - InetAddress sourceToBlock, ChannelPromise promise) { - promise.setFailure(new UnsupportedOperationException()); - return promise; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/oio/OioServerSocketChannel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/oio/OioServerSocketChannel.java deleted file mode 100755 index 6d2b7cceaf..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/oio/OioServerSocketChannel.java +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.socket.oio; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.SocketAddress; -import java.net.SocketTimeoutException; -import java.util.List; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -import com.ai.cloud.io.netty.channel.ChannelException; -import com.ai.cloud.io.netty.channel.ChannelMetadata; -import com.ai.cloud.io.netty.channel.ChannelOutboundBuffer; -import com.ai.cloud.io.netty.channel.oio.AbstractOioMessageChannel; -import com.ai.cloud.io.netty.channel.socket.ServerSocketChannel; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * {@link ServerSocketChannel} which accepts new connections and create the {@link OioSocketChannel}'s for them. - * - * This implementation use Old-Blocking-IO. - */ -public class OioServerSocketChannel extends AbstractOioMessageChannel - implements ServerSocketChannel { - - private static final InternalLogger logger = - InternalLoggerFactory.getInstance(OioServerSocketChannel.class); - - private static final ChannelMetadata METADATA = new ChannelMetadata(false); - - private static ServerSocket newServerSocket() { - try { - return new ServerSocket(); - } catch (IOException e) { - throw new ChannelException("failed to create a server socket", e); - } - } - - final ServerSocket socket; - final Lock shutdownLock = new ReentrantLock(); - private final OioServerSocketChannelConfig config; - - /** - * Create a new instance with an new {@link Socket} - */ - public OioServerSocketChannel() { - this(newServerSocket()); - } - - /** - * Create a new instance from the given {@link ServerSocket} - * - * @param socket the {@link ServerSocket} which is used by this instance - */ - public OioServerSocketChannel(ServerSocket socket) { - super(null); - if (socket == null) { - throw new NullPointerException("socket"); - } - - boolean success = false; - try { - socket.setSoTimeout(SO_TIMEOUT); - success = true; - } catch (IOException e) { - throw new ChannelException( - "Failed to set the server socket timeout.", e); - } finally { - if (!success) { - try { - socket.close(); - } catch (IOException e) { - if (logger.isWarnEnabled()) { - logger.warn( - "Failed to close a partially initialized socket.", e); - } - } - } - } - this.socket = socket; - config = new DefaultOioServerSocketChannelConfig(this, socket); - } - - @Override - public InetSocketAddress localAddress() { - return (InetSocketAddress) super.localAddress(); - } - - @Override - public ChannelMetadata metadata() { - return METADATA; - } - - @Override - public OioServerSocketChannelConfig config() { - return config; - } - - @Override - public InetSocketAddress remoteAddress() { - return null; - } - - @Override - public boolean isOpen() { - return !socket.isClosed(); - } - - @Override - public boolean isActive() { - return isOpen() && socket.isBound(); - } - - @Override - protected SocketAddress localAddress0() { - return socket.getLocalSocketAddress(); - } - - @Override - protected void doBind(SocketAddress localAddress) throws Exception { - socket.bind(localAddress, config.getBacklog()); - } - - @Override - protected void doClose() throws Exception { - socket.close(); - } - - @Override - protected int doReadMessages(List buf) throws Exception { - if (socket.isClosed()) { - return -1; - } - - try { - Socket s = socket.accept(); - try { - buf.add(new OioSocketChannel(this, s)); - return 1; - } catch (Throwable t) { - logger.warn("Failed to create a new channel from an accepted socket.", t); - try { - s.close(); - } catch (Throwable t2) { - logger.warn("Failed to close a socket.", t2); - } - } - } catch (SocketTimeoutException e) { - // Expected - } - return 0; - } - - @Override - protected void doWrite(ChannelOutboundBuffer in) throws Exception { - throw new UnsupportedOperationException(); - } - - @Override - protected Object filterOutboundMessage(Object msg) throws Exception { - throw new UnsupportedOperationException(); - } - - @Override - protected void doConnect( - SocketAddress remoteAddress, SocketAddress localAddress) throws Exception { - throw new UnsupportedOperationException(); - } - - @Override - protected SocketAddress remoteAddress0() { - return null; - } - - @Override - protected void doDisconnect() throws Exception { - throw new UnsupportedOperationException(); - } - - @Override - protected void setReadPending(boolean readPending) { - super.setReadPending(readPending); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/oio/OioServerSocketChannelConfig.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/oio/OioServerSocketChannelConfig.java deleted file mode 100755 index 094f996600..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/oio/OioServerSocketChannelConfig.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.socket.oio; - -import com.ai.cloud.io.netty.buffer.ByteBufAllocator; -import com.ai.cloud.io.netty.channel.ChannelOption; -import com.ai.cloud.io.netty.channel.MessageSizeEstimator; -import com.ai.cloud.io.netty.channel.RecvByteBufAllocator; -import com.ai.cloud.io.netty.channel.socket.ServerSocketChannelConfig; - - -/** - * A {@link ServerSocketChannelConfig} for a {@link OioServerSocketChannel}. - * - *

Available options

- * - * In addition to the options provided by {@link ServerSocketChannelConfig}, - * {@link OioServerSocketChannelConfig} allows the following options in the - * option map: - * - * - * - * - * - * - * - *
NameAssociated setter method
{@link ChannelOption#SO_TIMEOUT}{@link #setSoTimeout(int)}
- */ -public interface OioServerSocketChannelConfig extends ServerSocketChannelConfig { - - /** - * Sets the maximal time a operation on the underlying socket may block. - */ - OioServerSocketChannelConfig setSoTimeout(int timeout); - - /** - * Returns the maximal time a operation on the underlying socket may block. - */ - int getSoTimeout(); - - @Override - OioServerSocketChannelConfig setBacklog(int backlog); - - @Override - OioServerSocketChannelConfig setReuseAddress(boolean reuseAddress); - - @Override - OioServerSocketChannelConfig setReceiveBufferSize(int receiveBufferSize); - - @Override - OioServerSocketChannelConfig setPerformancePreferences(int connectionTime, int latency, int bandwidth); - - @Override - OioServerSocketChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis); - - @Override - OioServerSocketChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead); - - @Override - OioServerSocketChannelConfig setWriteSpinCount(int writeSpinCount); - - @Override - OioServerSocketChannelConfig setAllocator(ByteBufAllocator allocator); - - @Override - OioServerSocketChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator); - - @Override - OioServerSocketChannelConfig setAutoRead(boolean autoRead); - - @Override - OioServerSocketChannelConfig setAutoClose(boolean autoClose); - - @Override - OioServerSocketChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark); - - @Override - OioServerSocketChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark); - - @Override - OioServerSocketChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/oio/OioSocketChannel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/oio/OioSocketChannel.java deleted file mode 100755 index f240666674..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/oio/OioSocketChannel.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.socket.oio; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.net.SocketAddress; -import java.net.SocketTimeoutException; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelException; -import com.ai.cloud.io.netty.channel.ChannelFuture; -import com.ai.cloud.io.netty.channel.ChannelPromise; -import com.ai.cloud.io.netty.channel.ConnectTimeoutException; -import com.ai.cloud.io.netty.channel.EventLoop; -import com.ai.cloud.io.netty.channel.oio.OioByteStreamChannel; -import com.ai.cloud.io.netty.channel.socket.ServerSocketChannel; -import com.ai.cloud.io.netty.channel.socket.SocketChannel; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * A {@link SocketChannel} which is using Old-Blocking-IO - */ -public class OioSocketChannel extends OioByteStreamChannel - implements SocketChannel { - - private static final InternalLogger logger = - InternalLoggerFactory.getInstance(OioSocketChannel.class); - - private final Socket socket; - private final OioSocketChannelConfig config; - - /** - * Create a new instance with an new {@link Socket} - */ - public OioSocketChannel() { - this(new Socket()); - } - - /** - * Create a new instance from the given {@link Socket} - * - * @param socket the {@link Socket} which is used by this instance - */ - public OioSocketChannel(Socket socket) { - this(null, socket); - } - - /** - * Create a new instance from the given {@link Socket} - * - * @param parent the parent {@link Channel} which was used to create this instance. This can be null if the - * {@link} has no parent as it was created by your self. - * @param socket the {@link Socket} which is used by this instance - */ - public OioSocketChannel(Channel parent, Socket socket) { - super(parent); - this.socket = socket; - config = new DefaultOioSocketChannelConfig(this, socket); - - boolean success = false; - try { - if (socket.isConnected()) { - activate(socket.getInputStream(), socket.getOutputStream()); - } - socket.setSoTimeout(SO_TIMEOUT); - success = true; - } catch (Exception e) { - throw new ChannelException("failed to initialize a socket", e); - } finally { - if (!success) { - try { - socket.close(); - } catch (IOException e) { - logger.warn("Failed to close a socket.", e); - } - } - } - } - - @Override - public ServerSocketChannel parent() { - return (ServerSocketChannel) super.parent(); - } - - @Override - public OioSocketChannelConfig config() { - return config; - } - - @Override - public boolean isOpen() { - return !socket.isClosed(); - } - - @Override - public boolean isActive() { - return !socket.isClosed() && socket.isConnected(); - } - - @Override - public boolean isInputShutdown() { - return super.isInputShutdown(); - } - - @Override - public boolean isOutputShutdown() { - return socket.isOutputShutdown() || !isActive(); - } - - @Override - public ChannelFuture shutdownOutput() { - return shutdownOutput(newPromise()); - } - - @Override - protected int doReadBytes(ByteBuf buf) throws Exception { - if (socket.isClosed()) { - return -1; - } - try { - return super.doReadBytes(buf); - } catch (SocketTimeoutException ignored) { - return 0; - } - } - - @Override - public ChannelFuture shutdownOutput(final ChannelPromise future) { - EventLoop loop = eventLoop(); - if (loop.inEventLoop()) { - try { - socket.shutdownOutput(); - future.setSuccess(); - } catch (Throwable t) { - future.setFailure(t); - } - } else { - loop.execute(new Runnable() { - @Override - public void run() { - shutdownOutput(future); - } - }); - } - return future; - } - - @Override - public InetSocketAddress localAddress() { - return (InetSocketAddress) super.localAddress(); - } - - @Override - public InetSocketAddress remoteAddress() { - return (InetSocketAddress) super.remoteAddress(); - } - - @Override - protected SocketAddress localAddress0() { - return socket.getLocalSocketAddress(); - } - - @Override - protected SocketAddress remoteAddress0() { - return socket.getRemoteSocketAddress(); - } - - @Override - protected void doBind(SocketAddress localAddress) throws Exception { - socket.bind(localAddress); - } - - @Override - protected void doConnect(SocketAddress remoteAddress, - SocketAddress localAddress) throws Exception { - if (localAddress != null) { - socket.bind(localAddress); - } - - boolean success = false; - try { - socket.connect(remoteAddress, config().getConnectTimeoutMillis()); - activate(socket.getInputStream(), socket.getOutputStream()); - success = true; - } catch (SocketTimeoutException e) { - ConnectTimeoutException cause = new ConnectTimeoutException("connection timed out: " + remoteAddress); - cause.setStackTrace(e.getStackTrace()); - throw cause; - } finally { - if (!success) { - doClose(); - } - } - } - - @Override - protected void doDisconnect() throws Exception { - doClose(); - } - - @Override - protected void doClose() throws Exception { - socket.close(); - } - - @Override - protected boolean checkInputShutdown() { - if (isInputShutdown()) { - try { - Thread.sleep(config().getSoTimeout()); - } catch (Throwable e) { - // ignore - } - return true; - } - return false; - } - - @Override - protected void setReadPending(boolean readPending) { - super.setReadPending(readPending); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/oio/OioSocketChannelConfig.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/oio/OioSocketChannelConfig.java deleted file mode 100755 index c5af7a39c4..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/oio/OioSocketChannelConfig.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.socket.oio; - -import com.ai.cloud.io.netty.buffer.ByteBufAllocator; -import com.ai.cloud.io.netty.channel.ChannelConfig; -import com.ai.cloud.io.netty.channel.ChannelOption; -import com.ai.cloud.io.netty.channel.MessageSizeEstimator; -import com.ai.cloud.io.netty.channel.RecvByteBufAllocator; -import com.ai.cloud.io.netty.channel.socket.SocketChannelConfig; - -/** - * A {@link ChannelConfig} for a {@link OioSocketChannel}. - * - *

Available options

- * - * In addition to the options provided by {@link SocketChannelConfig}, - * {@link OioSocketChannelConfig} allows the following options in the - * option map: - * - * - * - * - * - * - * - *
NameAssociated setter method
{@link ChannelOption#SO_TIMEOUT}{@link #setSoTimeout(int)}
- */ -public interface OioSocketChannelConfig extends SocketChannelConfig { - - /** - * Sets the maximal time a operation on the underlying socket may block. - */ - OioSocketChannelConfig setSoTimeout(int timeout); - - /** - * Returns the maximal time a operation on the underlying socket may block. - */ - int getSoTimeout(); - - @Override - OioSocketChannelConfig setTcpNoDelay(boolean tcpNoDelay); - - @Override - OioSocketChannelConfig setSoLinger(int soLinger); - - @Override - OioSocketChannelConfig setSendBufferSize(int sendBufferSize); - - @Override - OioSocketChannelConfig setReceiveBufferSize(int receiveBufferSize); - - @Override - OioSocketChannelConfig setKeepAlive(boolean keepAlive); - - @Override - OioSocketChannelConfig setTrafficClass(int trafficClass); - - @Override - OioSocketChannelConfig setReuseAddress(boolean reuseAddress); - - @Override - OioSocketChannelConfig setPerformancePreferences(int connectionTime, int latency, int bandwidth); - - @Override - OioSocketChannelConfig setAllowHalfClosure(boolean allowHalfClosure); - - @Override - OioSocketChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis); - - @Override - OioSocketChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead); - - @Override - OioSocketChannelConfig setWriteSpinCount(int writeSpinCount); - - @Override - OioSocketChannelConfig setAllocator(ByteBufAllocator allocator); - - @Override - OioSocketChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator); - - @Override - OioSocketChannelConfig setAutoRead(boolean autoRead); - - @Override - OioSocketChannelConfig setAutoClose(boolean autoClose); - - @Override - OioSocketChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark); - - @Override - OioSocketChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark); - - @Override - OioSocketChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/oio/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/oio/package-info.java deleted file mode 100755 index c0415d8c59..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/oio/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * Old blocking I/O based socket channel API implementation - recommended for - * a small number of connections (< 1000). - */ -package com.ai.cloud.io.netty.channel.socket.oio; diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/package-info.java deleted file mode 100755 index 3259852f23..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/socket/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * Abstract TCP and UDP socket interfaces which extend the core channel API. - */ -package com.ai.cloud.io.netty.channel.socket; diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/DatagramSocketAddress.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/DatagramSocketAddress.java deleted file mode 100755 index 9a1a0898cc..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/DatagramSocketAddress.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.unix; - -import java.net.InetSocketAddress; - -/** - * Act as special {@link InetSocketAddress} to be able to easily pass all needed data from JNI without the need - * to create more objects then needed. - *

- * Internal usage only! - */ -public final class DatagramSocketAddress extends InetSocketAddress { - private static final long serialVersionUID = 3094819287843178401L; - - // holds the amount of received bytes - private final int receivedAmount; - - DatagramSocketAddress(String addr, int port, int receivedAmount) { - super(addr, port); - this.receivedAmount = receivedAmount; - } - - public int receivedAmount() { - return receivedAmount; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/DomainSocketAddress.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/DomainSocketAddress.java deleted file mode 100755 index a69d9756b3..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/DomainSocketAddress.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.unix; - -import java.io.File; -import java.net.SocketAddress; - -/** - * A address for a - * Unix Domain Socket. - */ -public final class DomainSocketAddress extends SocketAddress { - private final String socketPath; - - public DomainSocketAddress(String socketPath) { - if (socketPath == null) { - throw new NullPointerException("socketPath"); - } - this.socketPath = socketPath; - } - - public DomainSocketAddress(File file) { - this(file.getPath()); - } - - /** - * The path to the domain socket. - */ - public String path() { - return socketPath; - } - - @Override - public String toString() { - return path(); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof DomainSocketAddress)) { - return false; - } - - return ((DomainSocketAddress) o).socketPath.equals(socketPath); - } - - @Override - public int hashCode() { - return socketPath.hashCode(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/DomainSocketChannel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/DomainSocketChannel.java deleted file mode 100755 index 7bbe1a5c20..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/DomainSocketChannel.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.unix; - -/** - * A {@link UnixChannel} that supports communication via - * Unix Domain Socket. - */ -public interface DomainSocketChannel extends UnixChannel { - @Override - DomainSocketAddress remoteAddress(); - - @Override - DomainSocketAddress localAddress(); - - @Override - DomainSocketChannelConfig config(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/DomainSocketChannelConfig.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/DomainSocketChannelConfig.java deleted file mode 100755 index 57a84227ca..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/DomainSocketChannelConfig.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.unix; - -import com.ai.cloud.io.netty.buffer.ByteBufAllocator; -import com.ai.cloud.io.netty.channel.ChannelConfig; -import com.ai.cloud.io.netty.channel.MessageSizeEstimator; -import com.ai.cloud.io.netty.channel.RecvByteBufAllocator; - -/** - * Special {@link ChannelConfig} for {@link DomainSocketChannel}s. - */ -public interface DomainSocketChannelConfig extends ChannelConfig { - - @Override - DomainSocketChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead); - - @Override - DomainSocketChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis); - - @Override - DomainSocketChannelConfig setWriteSpinCount(int writeSpinCount); - - @Override - DomainSocketChannelConfig setAllocator(ByteBufAllocator allocator); - - @Override - DomainSocketChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator); - - @Override - DomainSocketChannelConfig setAutoRead(boolean autoRead); - - @Override - DomainSocketChannelConfig setAutoClose(boolean autoClose); - - @Override - DomainSocketChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark); - - @Override - DomainSocketChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark); - - @Override - DomainSocketChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator); - - /** - * Change the {@link DomainSocketReadMode} for the channel. The default is - * {@link DomainSocketReadMode#BYTES} which means bytes will be read from the - * {@link com.ai.cloud.io.netty.channel.Channel} and passed through the pipeline. If - * {@link DomainSocketReadMode#FILE_DESCRIPTORS} is used - * {@link FileDescriptor}s will be passed through the {@link com.ai.cloud.io.netty.channel.ChannelPipeline}. - * - * This setting can be modified on the fly if needed. - */ - DomainSocketChannelConfig setReadMode(DomainSocketReadMode mode); - - /** - * Return the {@link DomainSocketReadMode} for the channel. - */ - DomainSocketReadMode getReadMode(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/DomainSocketReadMode.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/DomainSocketReadMode.java deleted file mode 100755 index 96146c21c4..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/DomainSocketReadMode.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.unix; - -/** - * Different modes of reading from a {@link DomainSocketChannel}. - */ -public enum DomainSocketReadMode { - - /** - * Read (@link ByteBuf)s from the {@link DomainSocketChannel}. - */ - BYTES, - - /** - * Read (@link FileDscriptor)s from the {@link DomainSocketChannel}. - */ - FILE_DESCRIPTORS -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/Errors.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/Errors.java deleted file mode 100755 index 6955986103..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/Errors.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.unix; - -import java.io.IOException; -import java.net.ConnectException; -import java.nio.channels.ClosedChannelException; - -import com.ai.cloud.io.netty.util.internal.EmptyArrays; - -/** - * Internal usage only! - */ -public final class Errors { - // As all our JNI methods return -errno on error we need to compare with the negative errno codes. - public static final int ERRNO_ENOTCONN_NEGATIVE = -errnoENOTCONN(); - public static final int ERRNO_EBADF_NEGATIVE = -errnoEBADF(); - public static final int ERRNO_EPIPE_NEGATIVE = -errnoEPIPE(); - public static final int ERRNO_ECONNRESET_NEGATIVE = -errnoECONNRESET(); - public static final int ERRNO_EAGAIN_NEGATIVE = -errnoEAGAIN(); - public static final int ERRNO_EWOULDBLOCK_NEGATIVE = -errnoEWOULDBLOCK(); - public static final int ERRNO_EINPROGRESS_NEGATIVE = -errnoEINPROGRESS(); - - /** - * Holds the mappings for errno codes to String messages. - * This eliminates the need to call back into JNI to get the right String message on an exception - * and thus is faster. - * - * The array length of 512 should be more then enough because errno.h only holds < 200 codes. - */ - private static final String[] ERRORS = new String[512]; - - // Pre-instantiated exceptions which does not need any stacktrace and - // can be thrown multiple times for performance reasons. - static final ClosedChannelException CLOSED_CHANNEL_EXCEPTION; - static final NativeIoException CONNECTION_NOT_CONNECTED_SHUTDOWN_EXCEPTION; - static final NativeIoException CONNECTION_RESET_EXCEPTION_WRITE; - static final NativeIoException CONNECTION_RESET_EXCEPTION_WRITEV; - static final NativeIoException CONNECTION_RESET_EXCEPTION_READ; - static final NativeIoException CONNECTION_RESET_EXCEPTION_SENDTO; - static final NativeIoException CONNECTION_RESET_EXCEPTION_SENDMSG; - - /** - * Internal usage only! - */ - public static final class NativeIoException extends IOException { - private static final long serialVersionUID = 8222160204268655526L; - private final int expectedErr; - public NativeIoException(String method, int expectedErr) { - super(method); - this.expectedErr = expectedErr; - } - - public int expectedErr() { - return expectedErr; - } - } - - static { - for (int i = 0; i < ERRORS.length; i++) { - // This is ok as strerror returns 'Unknown error i' when the message is not known. - ERRORS[i] = strError(i); - } - - CONNECTION_RESET_EXCEPTION_READ = newConnectionResetException("syscall:read(...)", - ERRNO_ECONNRESET_NEGATIVE); - CONNECTION_RESET_EXCEPTION_WRITE = newConnectionResetException("syscall:write(...)", - ERRNO_EPIPE_NEGATIVE); - CONNECTION_RESET_EXCEPTION_WRITEV = newConnectionResetException("syscall:writev(...)", - ERRNO_EPIPE_NEGATIVE); - CONNECTION_RESET_EXCEPTION_SENDTO = newConnectionResetException("syscall:sendto(...)", - ERRNO_EPIPE_NEGATIVE); - CONNECTION_RESET_EXCEPTION_SENDMSG = newConnectionResetException("syscall:sendmsg(...)", - ERRNO_EPIPE_NEGATIVE); - CONNECTION_NOT_CONNECTED_SHUTDOWN_EXCEPTION = newConnectionResetException("syscall:shutdown(...)", - ERRNO_ENOTCONN_NEGATIVE); - CLOSED_CHANNEL_EXCEPTION = new ClosedChannelException(); - CLOSED_CHANNEL_EXCEPTION.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); - } - - static ConnectException newConnectException(String method, int err) { - return new ConnectException(method + "() failed: " + ERRORS[-err]); - } - - public static NativeIoException newConnectionResetException(String method, int errnoNegative) { - NativeIoException exception = newIOException(method, errnoNegative); - exception.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); - return exception; - } - - public static NativeIoException newIOException(String method, int err) { - return new NativeIoException(method + "() failed: " + ERRORS[-err], err); - } - - public static int ioResult(String method, int err, NativeIoException resetCause) throws IOException { - // network stack saturated... try again later - if (err == ERRNO_EAGAIN_NEGATIVE || err == ERRNO_EWOULDBLOCK_NEGATIVE) { - return 0; - } - if (err == resetCause.expectedErr()) { - throw resetCause; - } - if (err == ERRNO_EBADF_NEGATIVE || err == ERRNO_ENOTCONN_NEGATIVE) { - throw CLOSED_CHANNEL_EXCEPTION; - } - // TODO: We could even go further and use a pre-instantiated IOException for the other error codes, but for - // all other errors it may be better to just include a stack trace. - throw newIOException(method, err); - } - - private static native int errnoEBADF(); - private static native int errnoEPIPE(); - private static native int errnoECONNRESET(); - private static native int errnoENOTCONN(); - private static native int errnoEAGAIN(); - private static native int errnoEWOULDBLOCK(); - private static native int errnoEINPROGRESS(); - private static native String strError(int err); - - private Errors() { } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/FileDescriptor.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/FileDescriptor.java deleted file mode 100755 index 8cae114870..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/FileDescriptor.java +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.unix; - -import java.io.File; -import java.io.IOException; -import java.nio.ByteBuffer; - -import static com.ai.cloud.io.netty.channel.unix.Errors.CONNECTION_RESET_EXCEPTION_READ; -import static com.ai.cloud.io.netty.channel.unix.Errors.CONNECTION_RESET_EXCEPTION_WRITE; -import static com.ai.cloud.io.netty.channel.unix.Errors.CONNECTION_RESET_EXCEPTION_WRITEV; -import static com.ai.cloud.io.netty.channel.unix.Errors.ioResult; -import static com.ai.cloud.io.netty.channel.unix.Errors.newIOException; -import static com.ai.cloud.io.netty.util.internal.ObjectUtil.checkNotNull; - -/** - * Native {@link FileDescriptor} implementation which allows to wrap an {@code int} and provide a - * {@link FileDescriptor} for it. - */ -public class FileDescriptor { - private final int fd; - private volatile boolean open = true; - - public FileDescriptor(int fd) { - if (fd < 0) { - throw new IllegalArgumentException("fd must be >= 0"); - } - this.fd = fd; - } - - /** - * Return the int value of the filedescriptor. - */ - public int intValue() { - return fd; - } - - /** - * Close the file descriptor. - */ - public void close() throws IOException { - open = false; - int res = close(fd); - if (res < 0) { - throw newIOException("close", res); - } - } - - /** - * Returns {@code true} if the file descriptor is open. - */ - public boolean isOpen() { - return open; - } - - public final int write(ByteBuffer buf, int pos, int limit) throws IOException { - int res = write(fd, buf, pos, limit); - if (res >= 0) { - return res; - } - return ioResult("write", res, CONNECTION_RESET_EXCEPTION_WRITE); - } - - public final int writeAddress(long address, int pos, int limit) throws IOException { - int res = writeAddress(fd, address, pos, limit); - if (res >= 0) { - return res; - } - return ioResult("writeAddress", res, CONNECTION_RESET_EXCEPTION_WRITE); - } - - public final long writev(ByteBuffer[] buffers, int offset, int length) throws IOException { - long res = writev(fd, buffers, offset, length); - if (res >= 0) { - return res; - } - return ioResult("writev", (int) res, CONNECTION_RESET_EXCEPTION_WRITEV); - } - - public final long writevAddresses(long memoryAddress, int length) throws IOException { - long res = writevAddresses(fd, memoryAddress, length); - if (res >= 0) { - return res; - } - return ioResult("writevAddresses", (int) res, CONNECTION_RESET_EXCEPTION_WRITEV); - } - - public final int read(ByteBuffer buf, int pos, int limit) throws IOException { - int res = read(fd, buf, pos, limit); - if (res > 0) { - return res; - } - if (res == 0) { - return -1; - } - return ioResult("read", res, CONNECTION_RESET_EXCEPTION_READ); - } - - public final int readAddress(long address, int pos, int limit) throws IOException { - int res = readAddress(fd, address, pos, limit); - if (res > 0) { - return res; - } - if (res == 0) { - return -1; - } - return ioResult("readAddress", res, CONNECTION_RESET_EXCEPTION_READ); - } - - @Override - public String toString() { - return "FileDescriptor{" + - "fd=" + fd + - '}'; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof FileDescriptor)) { - return false; - } - - return fd == ((FileDescriptor) o).fd; - } - - @Override - public int hashCode() { - return fd; - } - - /** - * Open a new {@link FileDescriptor} for the given path. - */ - public static FileDescriptor from(String path) throws IOException { - checkNotNull(path, "path"); - int res = open(path); - if (res < 0) { - throw newIOException("open", res); - } - return new FileDescriptor(res); - } - - /** - * Open a new {@link FileDescriptor} for the given {@link File}. - */ - public static FileDescriptor from(File file) throws IOException { - return from(checkNotNull(file, "file").getPath()); - } - - /** - * @return [0] = read end, [1] = write end - */ - public static FileDescriptor[] pipe() throws IOException { - long res = newPipe(); - if (res < 0) { - throw newIOException("newPipe", (int) res); - } - return new FileDescriptor[]{new FileDescriptor((int) (res >>> 32)), new FileDescriptor((int) res)}; - } - - private static native int open(String path); - private static native int close(int fd); - - private static native int write(int fd, ByteBuffer buf, int pos, int limit); - private static native int writeAddress(int fd, long address, int pos, int limit); - private static native long writev(int fd, ByteBuffer[] buffers, int offset, int length); - private static native long writevAddresses(int fd, long memoryAddress, int length); - - private static native int read(int fd, ByteBuffer buf, int pos, int limit); - private static native int readAddress(int fd, long address, int pos, int limit); - - private static native long newPipe(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/NativeInetAddress.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/NativeInetAddress.java deleted file mode 100755 index 6f6fe284cf..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/NativeInetAddress.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.unix; - -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.UnknownHostException; - -/** - * Internal usage only! - */ -public final class NativeInetAddress { - private static final byte[] IPV4_MAPPED_IPV6_PREFIX = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0xff, (byte) 0xff }; - final byte[] address; - final int scopeId; - - public static NativeInetAddress newInstance(InetAddress addr) { - byte[] bytes = addr.getAddress(); - if (addr instanceof Inet6Address) { - return new NativeInetAddress(bytes, ((Inet6Address) addr).getScopeId()); - } else { - // convert to ipv4 mapped ipv6 address; - return new NativeInetAddress(ipv4MappedIpv6Address(bytes)); - } - } - - public NativeInetAddress(byte[] address, int scopeId) { - this.address = address; - this.scopeId = scopeId; - } - - public NativeInetAddress(byte[] address) { - this(address, 0); - } - - public byte[] address() { - return address; - } - - public int scopeId() { - return scopeId; - } - - public static byte[] ipv4MappedIpv6Address(byte[] ipv4) { - byte[] address = new byte[16]; - System.arraycopy(IPV4_MAPPED_IPV6_PREFIX, 0, address, 0, IPV4_MAPPED_IPV6_PREFIX.length); - System.arraycopy(ipv4, 0, address, 12, ipv4.length); - return address; - } - - public static InetSocketAddress address(byte[] addr, int offset, int len) { - // The last 4 bytes are always the port - final int port = decodeInt(addr, offset + len - 4); - final InetAddress address; - - try { - switch (len) { - // 8 bytes: - // - 4 == ipaddress - // - 4 == port - case 8: - byte[] ipv4 = new byte[4]; - System.arraycopy(addr, offset, ipv4, 0, 4); - address = InetAddress.getByAddress(ipv4); - break; - - // 24 bytes: - // - 16 == ipaddress - // - 4 == scopeId - // - 4 == port - case 24: - byte[] ipv6 = new byte[16]; - System.arraycopy(addr, offset, ipv6, 0, 16); - int scopeId = decodeInt(addr, offset + len - 8); - address = Inet6Address.getByAddress(null, ipv6, scopeId); - break; - default: - throw new Error(); - } - return new InetSocketAddress(address, port); - } catch (UnknownHostException e) { - throw new Error("Should never happen", e); - } - } - - static int decodeInt(byte[] addr, int index) { - return (addr[index] & 0xff) << 24 | - (addr[index + 1] & 0xff) << 16 | - (addr[index + 2] & 0xff) << 8 | - addr[index + 3] & 0xff; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/ServerDomainSocketChannel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/ServerDomainSocketChannel.java deleted file mode 100755 index f04b519f17..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/ServerDomainSocketChannel.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.unix; - -import com.ai.cloud.io.netty.channel.ServerChannel; - -/** - * {@link ServerChannel} that accepts {@link DomainSocketChannel}'s via - * Unix Domain Socket. - */ -public interface ServerDomainSocketChannel extends ServerChannel, UnixChannel { - @Override - DomainSocketAddress remoteAddress(); - - @Override - DomainSocketAddress localAddress(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/Socket.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/Socket.java deleted file mode 100755 index 433987fe18..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/Socket.java +++ /dev/null @@ -1,363 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.unix; - -import java.io.IOException; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.nio.ByteBuffer; - -import com.ai.cloud.io.netty.channel.ChannelException; -import com.ai.cloud.io.netty.util.CharsetUtil; - -import static com.ai.cloud.io.netty.channel.unix.Errors.CONNECTION_NOT_CONNECTED_SHUTDOWN_EXCEPTION; -import static com.ai.cloud.io.netty.channel.unix.Errors.CONNECTION_RESET_EXCEPTION_SENDMSG; -import static com.ai.cloud.io.netty.channel.unix.Errors.CONNECTION_RESET_EXCEPTION_SENDTO; -import static com.ai.cloud.io.netty.channel.unix.Errors.ERRNO_EAGAIN_NEGATIVE; -import static com.ai.cloud.io.netty.channel.unix.Errors.ERRNO_EINPROGRESS_NEGATIVE; -import static com.ai.cloud.io.netty.channel.unix.Errors.ERRNO_EWOULDBLOCK_NEGATIVE; -import static com.ai.cloud.io.netty.channel.unix.Errors.ioResult; -import static com.ai.cloud.io.netty.channel.unix.Errors.newConnectException; -import static com.ai.cloud.io.netty.channel.unix.Errors.newIOException; -import static com.ai.cloud.io.netty.channel.unix.NativeInetAddress.address; -import static com.ai.cloud.io.netty.channel.unix.NativeInetAddress.ipv4MappedIpv6Address; - -/** - * Provides a JNI bridge to native socket operations. - * Internal usage only! - */ -public final class Socket extends FileDescriptor { - private volatile boolean inputShutdown; - private volatile boolean outputShutdown; - - public Socket(int fd) { - super(fd); - } - - public void shutdown(boolean read, boolean write) throws IOException { - inputShutdown = read || inputShutdown; - outputShutdown = write || outputShutdown; - int res = shutdown(intValue(), read, write); - if (res < 0) { - ioResult("shutdown", res, CONNECTION_NOT_CONNECTED_SHUTDOWN_EXCEPTION); - } - } - - public void shutdown() throws IOException { - shutdown(true, true); - } - - public boolean isShutdown() { - return isInputShutdown() && isOutputShutdown(); - } - - public boolean isInputShutdown() { - return inputShutdown; - } - - public boolean isOutputShutdown() { - return outputShutdown; - } - - public int sendTo(ByteBuffer buf, int pos, int limit, InetAddress addr, int port) throws IOException { - // just duplicate the toNativeInetAddress code here to minimize object creation as this method is expected - // to be called frequently - byte[] address; - int scopeId; - if (addr instanceof Inet6Address) { - address = addr.getAddress(); - scopeId = ((Inet6Address) addr).getScopeId(); - } else { - // convert to ipv4 mapped ipv6 address; - scopeId = 0; - address = ipv4MappedIpv6Address(addr.getAddress()); - } - int res = sendTo(intValue(), buf, pos, limit, address, scopeId, port); - if (res >= 0) { - return res; - } - return ioResult("sendTo", res, CONNECTION_RESET_EXCEPTION_SENDTO); - } - - public int sendToAddress(long memoryAddress, int pos, int limit, InetAddress addr, int port) - throws IOException { - // just duplicate the toNativeInetAddress code here to minimize object creation as this method is expected - // to be called frequently - byte[] address; - int scopeId; - if (addr instanceof Inet6Address) { - address = addr.getAddress(); - scopeId = ((Inet6Address) addr).getScopeId(); - } else { - // convert to ipv4 mapped ipv6 address; - scopeId = 0; - address = ipv4MappedIpv6Address(addr.getAddress()); - } - int res = sendToAddress(intValue(), memoryAddress, pos, limit, address, scopeId, port); - if (res >= 0) { - return res; - } - return ioResult("sendToAddress", res, CONNECTION_RESET_EXCEPTION_SENDTO); - } - - public int sendToAddresses(long memoryAddress, int length, InetAddress addr, int port) throws IOException { - // just duplicate the toNativeInetAddress code here to minimize object creation as this method is expected - // to be called frequently - byte[] address; - int scopeId; - if (addr instanceof Inet6Address) { - address = addr.getAddress(); - scopeId = ((Inet6Address) addr).getScopeId(); - } else { - // convert to ipv4 mapped ipv6 address; - scopeId = 0; - address = ipv4MappedIpv6Address(addr.getAddress()); - } - int res = sendToAddresses(intValue(), memoryAddress, length, address, scopeId, port); - if (res >= 0) { - return res; - } - return ioResult("sendToAddresses", res, CONNECTION_RESET_EXCEPTION_SENDMSG); - } - - public DatagramSocketAddress recvFrom(ByteBuffer buf, int pos, int limit) throws IOException { - return recvFrom(intValue(), buf, pos, limit); - } - - public DatagramSocketAddress recvFromAddress(long memoryAddress, int pos, int limit) throws IOException { - return recvFromAddress(intValue(), memoryAddress, pos, limit); - } - - public boolean connect(SocketAddress socketAddress) throws IOException { - int res; - if (socketAddress instanceof InetSocketAddress) { - InetSocketAddress inetSocketAddress = (InetSocketAddress) socketAddress; - NativeInetAddress address = NativeInetAddress.newInstance(inetSocketAddress.getAddress()); - res = connect(intValue(), address.address, address.scopeId, inetSocketAddress.getPort()); - } else if (socketAddress instanceof DomainSocketAddress) { - DomainSocketAddress unixDomainSocketAddress = (DomainSocketAddress) socketAddress; - res = connectDomainSocket(intValue(), unixDomainSocketAddress.path().getBytes(CharsetUtil.UTF_8)); - } else { - throw new Error("Unexpected SocketAddress implementation " + socketAddress); - } - if (res < 0) { - if (res == ERRNO_EINPROGRESS_NEGATIVE) { - // connect not complete yet need to wait for EPOLLOUT event - return false; - } - throw newConnectException("connect", res); - } - return true; - } - - public boolean finishConnect() throws IOException { - int res = finishConnect(intValue()); - if (res < 0) { - if (res == ERRNO_EINPROGRESS_NEGATIVE) { - // connect still in progress - return false; - } - throw newConnectException("finishConnect", res); - } - return true; - } - - public void bind(SocketAddress socketAddress) throws IOException { - if (socketAddress instanceof InetSocketAddress) { - InetSocketAddress addr = (InetSocketAddress) socketAddress; - NativeInetAddress address = NativeInetAddress.newInstance(addr.getAddress()); - int res = bind(intValue(), address.address, address.scopeId, addr.getPort()); - if (res < 0) { - throw newIOException("bind", res); - } - } else if (socketAddress instanceof DomainSocketAddress) { - DomainSocketAddress addr = (DomainSocketAddress) socketAddress; - int res = bindDomainSocket(intValue(), addr.path().getBytes(CharsetUtil.UTF_8)); - if (res < 0) { - throw newIOException("bind", res); - } - } else { - throw new Error("Unexpected SocketAddress implementation " + socketAddress); - } - } - - public void listen(int backlog) throws IOException { - int res = listen(intValue(), backlog); - if (res < 0) { - throw newIOException("listen", res); - } - } - - public int accept(byte[] addr) throws IOException { - int res = accept(intValue(), addr); - if (res >= 0) { - return res; - } - if (res == ERRNO_EAGAIN_NEGATIVE || res == ERRNO_EWOULDBLOCK_NEGATIVE) { - // Everything consumed so just return -1 here. - return -1; - } - throw newIOException("accept", res); - } - - public InetSocketAddress remoteAddress() { - byte[] addr = remoteAddress(intValue()); - // addr may be null if getpeername failed. - // See https://github.com/netty/netty/issues/3328 - if (addr == null) { - return null; - } - return address(addr, 0, addr.length); - } - - public InetSocketAddress localAddress() { - byte[] addr = localAddress(intValue()); - // addr may be null if getpeername failed. - // See https://github.com/netty/netty/issues/3328 - if (addr == null) { - return null; - } - return address(addr, 0, addr.length); - } - - public int getReceiveBufferSize() { - return getReceiveBufferSize(intValue()); - } - - public int getSendBufferSize() { - return getSendBufferSize(intValue()); - } - - public boolean isKeepAlive() { - return isKeepAlive(intValue()) != 0; - } - - public boolean isTcpNoDelay() { - return isTcpNoDelay(intValue()) != 0; - } - - public boolean isTcpCork() { - return isTcpCork(intValue()) != 0; - } - - public int getSoLinger() { - return getSoLinger(intValue()); - } - - public int getSoError() { - return getSoError(intValue()); - } - - public void setKeepAlive(boolean keepAlive) { - setKeepAlive(intValue(), keepAlive ? 1 : 0); - } - - public void setReceiveBufferSize(int receiveBufferSize) { - setReceiveBufferSize(intValue(), receiveBufferSize); - } - - public void setSendBufferSize(int sendBufferSize) { - setSendBufferSize(intValue(), sendBufferSize); - } - - public void setTcpNoDelay(boolean tcpNoDelay) { - setTcpNoDelay(intValue(), tcpNoDelay ? 1 : 0); - } - - public void setTcpCork(boolean tcpCork) { - setTcpCork(intValue(), tcpCork ? 1 : 0); - } - - public void setSoLinger(int soLinger) { - setSoLinger(intValue(), soLinger); - } - - @Override - public String toString() { - return "Socket{" + - "fd=" + intValue() + - '}'; - } - - public static Socket newSocketStream() { - int res = newSocketStreamFd(); - if (res < 0) { - throw new ChannelException(newIOException("newSocketStream", res)); - } - return new Socket(res); - } - - public static Socket newSocketDgram() { - int res = newSocketDgramFd(); - if (res < 0) { - throw new ChannelException(newIOException("newSocketDgram", res)); - } - return new Socket(res); - } - - public static Socket newSocketDomain() { - int res = newSocketDomainFd(); - if (res < 0) { - throw new ChannelException(newIOException("newSocketDomain", res)); - } - return new Socket(res); - } - - private static native int shutdown(int fd, boolean read, boolean write); - private static native int connect(int fd, byte[] address, int scopeId, int port); - private static native int connectDomainSocket(int fd, byte[] path); - private static native int finishConnect(int fd); - private static native int bind(int fd, byte[] address, int scopeId, int port); - private static native int bindDomainSocket(int fd, byte[] path); - private static native int listen(int fd, int backlog); - private static native int accept(int fd, byte[] addr); - - private static native byte[] remoteAddress(int fd); - private static native byte[] localAddress(int fd); - - private static native int sendTo( - int fd, ByteBuffer buf, int pos, int limit, byte[] address, int scopeId, int port); - private static native int sendToAddress( - int fd, long memoryAddress, int pos, int limit, byte[] address, int scopeId, int port); - private static native int sendToAddresses( - int fd, long memoryAddress, int length, byte[] address, int scopeId, int port); - - private static native DatagramSocketAddress recvFrom( - int fd, ByteBuffer buf, int pos, int limit) throws IOException; - private static native DatagramSocketAddress recvFromAddress( - int fd, long memoryAddress, int pos, int limit) throws IOException; - - private static native int newSocketStreamFd(); - private static native int newSocketDgramFd(); - private static native int newSocketDomainFd(); - - private static native int getReceiveBufferSize(int fd); - private static native int getSendBufferSize(int fd); - private static native int isKeepAlive(int fd); - private static native int isTcpNoDelay(int fd); - private static native int isTcpCork(int fd); - private static native int getSoLinger(int fd); - private static native int getSoError(int fd); - - private static native void setKeepAlive(int fd, int keepAlive); - private static native void setReceiveBufferSize(int fd, int receiveBufferSize); - private static native void setSendBufferSize(int fd, int sendBufferSize); - private static native void setTcpNoDelay(int fd, int tcpNoDelay); - private static native void setTcpCork(int fd, int tcpCork); - private static native void setSoLinger(int fd, int soLinger); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/UnixChannel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/UnixChannel.java deleted file mode 100755 index 1706f47176..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/UnixChannel.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.channel.unix; - -import com.ai.cloud.io.netty.channel.Channel; - -/** - * {@link Channel} that expose operations that are only present on {@code UNIX} like systems. - */ -public interface UnixChannel extends Channel { - /** - * Returns the {@link FileDescriptor} that is used by this {@link Channel}. - */ - FileDescriptor fd(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/package-info.java deleted file mode 100755 index 0f9127be73..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/channel/unix/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * Unix specific transport. - */ -package com.ai.cloud.io.netty.channel.unix; diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/ByteToMessageCodec.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/ByteToMessageCodec.java deleted file mode 100755 index 158429fd95..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/ByteToMessageCodec.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec; - -import java.util.List; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelDuplexHandler; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelPromise; -import com.ai.cloud.io.netty.util.internal.TypeParameterMatcher; - -/** - * A Codec for on-the-fly encoding/decoding of bytes to messages and vise-versa. - * - * This can be thought of as a combination of {@link ByteToMessageDecoder} and {@link MessageToByteEncoder}. - * - * Be aware that sub-classes of {@link ByteToMessageCodec} MUST NOT - * annotated with {@link @Sharable}. - */ -public abstract class ByteToMessageCodec extends ChannelDuplexHandler { - - private final TypeParameterMatcher outboundMsgMatcher; - private final MessageToByteEncoder encoder; - - private final ByteToMessageDecoder decoder = new ByteToMessageDecoder() { - @Override - public void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { - ByteToMessageCodec.this.decode(ctx, in, out); - } - - @Override - protected void decodeLast(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { - ByteToMessageCodec.this.decodeLast(ctx, in, out); - } - }; - - /** - * @see {@link #ByteToMessageCodec(boolean)} with {@code true} as boolean parameter. - */ - protected ByteToMessageCodec() { - this(true); - } - - /** - * @see {@link #ByteToMessageCodec(Class, boolean)} with {@code true} as boolean value. - */ - protected ByteToMessageCodec(Class outboundMessageType) { - this(outboundMessageType, true); - } - - /** - * Create a new instance which will try to detect the types to match out of the type parameter of the class. - * - * @param preferDirect {@code true} if a direct {@link ByteBuf} should be tried to be used as target for - * the encoded messages. If {@code false} is used it will allocate a heap - * {@link ByteBuf}, which is backed by an byte array. - */ - protected ByteToMessageCodec(boolean preferDirect) { - CodecUtil.ensureNotSharable(this); - outboundMsgMatcher = TypeParameterMatcher.find(this, ByteToMessageCodec.class, "I"); - encoder = new Encoder(preferDirect); - } - - /** - * Create a new instance - * - * @param outboundMessageType The type of messages to match - * @param preferDirect {@code true} if a direct {@link ByteBuf} should be tried to be used as target for - * the encoded messages. If {@code false} is used it will allocate a heap - * {@link ByteBuf}, which is backed by an byte array. - */ - protected ByteToMessageCodec(Class outboundMessageType, boolean preferDirect) { - CodecUtil.ensureNotSharable(this); - outboundMsgMatcher = TypeParameterMatcher.get(outboundMessageType); - encoder = new Encoder(preferDirect); - } - - /** - * Returns {@code true} if and only if the specified message can be encoded by this codec. - * - * @param msg the message - */ - public boolean acceptOutboundMessage(Object msg) throws Exception { - return outboundMsgMatcher.match(msg); - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - decoder.channelRead(ctx, msg); - } - - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - encoder.write(ctx, msg, promise); - } - - @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { - decoder.channelReadComplete(ctx); - } - - @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { - decoder.channelInactive(ctx); - } - - @Override - public void handlerAdded(ChannelHandlerContext ctx) throws Exception { - try { - decoder.handlerAdded(ctx); - } finally { - encoder.handlerAdded(ctx); - } - } - - @Override - public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { - try { - decoder.handlerRemoved(ctx); - } finally { - encoder.handlerRemoved(ctx); - } - } - - /** - * @see MessageToByteEncoder#encode(ChannelHandlerContext, Object, ByteBuf) - */ - protected abstract void encode(ChannelHandlerContext ctx, I msg, ByteBuf out) throws Exception; - - /** - * @see ByteToMessageDecoder#decode(ChannelHandlerContext, ByteBuf, List) - */ - protected abstract void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception; - - /** - * @see ByteToMessageDecoder#decodeLast(ChannelHandlerContext, ByteBuf, List) - */ - protected void decodeLast(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { - decode(ctx, in, out); - } - - private final class Encoder extends MessageToByteEncoder { - Encoder(boolean preferDirect) { - super(preferDirect); - } - - @Override - public boolean acceptOutboundMessage(Object msg) throws Exception { - return ByteToMessageCodec.this.acceptOutboundMessage(msg); - } - - @Override - protected void encode(ChannelHandlerContext ctx, I msg, ByteBuf out) throws Exception { - ByteToMessageCodec.this.encode(ctx, msg, out); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/ByteToMessageDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/ByteToMessageDecoder.java deleted file mode 100755 index 10d240fc91..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/ByteToMessageDecoder.java +++ /dev/null @@ -1,437 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec; - -import java.util.List; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.ByteBufAllocator; -import com.ai.cloud.io.netty.buffer.CompositeByteBuf; -import com.ai.cloud.io.netty.buffer.Unpooled; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelInboundHandlerAdapter; -import com.ai.cloud.io.netty.util.internal.RecyclableArrayList; -import com.ai.cloud.io.netty.util.internal.StringUtil; - -/** - * {@link ChannelInboundHandlerAdapter} which decodes bytes in a stream-like fashion from one {@link ByteBuf} to an - * other Message type. - * - * For example here is an implementation which reads all readable bytes from - * the input {@link ByteBuf} and create a new {@link ByteBuf}. - * - *
- *     public class SquareDecoder extends {@link ByteToMessageDecoder} {
- *         {@code @Override}
- *         public void decode({@link ChannelHandlerContext} ctx, {@link ByteBuf} in, List<Object> out)
- *                 throws {@link Exception} {
- *             out.add(in.readBytes(in.readableBytes()));
- *         }
- *     }
- * 
- * - *

Frame detection

- *

- * Generally frame detection should be handled earlier in the pipeline by adding a - * {@link DelimiterBasedFrameDecoder}, {@link FixedLengthFrameDecoder}, {@link LengthFieldBasedFrameDecoder}, - * or {@link LineBasedFrameDecoder}. - *

- * If a custom frame decoder is required, then one needs to be careful when implementing - * one with {@link ByteToMessageDecoder}. Ensure there are enough bytes in the buffer for a - * complete frame by checking {@link ByteBuf#readableBytes()}. If there are not enough bytes - * for a complete frame, return without modifying the reader index to allow more bytes to arrive. - *

- * To check for complete frames without modifying the reader index, use methods like {@link ByteBuf#getInt(int)}. - * One MUST use the reader index when using methods like {@link ByteBuf#getInt(int)}. - * For example calling in.getInt(0) is assuming the frame starts at the beginning of the buffer, which - * is not always the case. Use in.getInt(in.readerIndex()) instead. - *

Pitfalls

- *

- * Be aware that sub-classes of {@link ByteToMessageDecoder} MUST NOT - * annotated with {@link @Sharable}. - *

- * Some methods such as {@link ByteBuf#readBytes(int)} will cause a memory leak if the returned buffer - * is not released or added to the out {@link List}. Use derived buffers like {@link ByteBuf#readSlice(int)} - * to avoid leaking memory. - */ -public abstract class ByteToMessageDecoder extends ChannelInboundHandlerAdapter { - - /** - * Cumulate {@link ByteBuf}s by merge them into one {@link ByteBuf}'s, using memory copies. - */ - public static final Cumulator MERGE_CUMULATOR = new Cumulator() { - @Override - public ByteBuf cumulate(ByteBufAllocator alloc, ByteBuf cumulation, ByteBuf in) { - ByteBuf buffer; - if (cumulation.writerIndex() > cumulation.maxCapacity() - in.readableBytes() - || cumulation.refCnt() > 1) { - // Expand cumulation (by replace it) when either there is not more room in the buffer - // or if the refCnt is greater then 1 which may happen when the user use slice().retain() or - // duplicate().retain(). - // - // See: - // - https://github.com/netty/netty/issues/2327 - // - https://github.com/netty/netty/issues/1764 - buffer = expandCumulation(alloc, cumulation, in.readableBytes()); - } else { - buffer = cumulation; - } - buffer.writeBytes(in); - in.release(); - return buffer; - } - }; - - /** - * Cumulate {@link ByteBuf}s by add them to a {@link CompositeByteBuf} and so do no memory copy whenever possible. - * Be aware that {@link CompositeByteBuf} use a more complex indexing implementation so depending on your use-case - * and the decoder implementation this may be slower then just use the {@link #MERGE_CUMULATOR}. - */ - public static final Cumulator COMPOSITE_CUMULATOR = new Cumulator() { - @Override - public ByteBuf cumulate(ByteBufAllocator alloc, ByteBuf cumulation, ByteBuf in) { - ByteBuf buffer; - if (cumulation.refCnt() > 1) { - // Expand cumulation (by replace it) when the refCnt is greater then 1 which may happen when the user - // use slice().retain() or duplicate().retain(). - // - // See: - // - https://github.com/netty/netty/issues/2327 - // - https://github.com/netty/netty/issues/1764 - buffer = expandCumulation(alloc, cumulation, in.readableBytes()); - buffer.writeBytes(in); - in.release(); - } else { - CompositeByteBuf composite; - if (cumulation instanceof CompositeByteBuf) { - composite = (CompositeByteBuf) cumulation; - } else { - int readable = cumulation.readableBytes(); - composite = alloc.compositeBuffer(); - composite.addComponent(cumulation).writerIndex(readable); - } - composite.addComponent(in).writerIndex(composite.writerIndex() + in.readableBytes()); - buffer = composite; - } - return buffer; - } - }; - - ByteBuf cumulation; - private Cumulator cumulator = MERGE_CUMULATOR; - private boolean singleDecode; - private boolean decodeWasNull; - private boolean first; - private int discardAfterReads = 16; - private int numReads; - - protected ByteToMessageDecoder() { - CodecUtil.ensureNotSharable(this); - } - - /** - * If set then only one message is decoded on each {@link #channelRead(ChannelHandlerContext, Object)} - * call. This may be useful if you need to do some protocol upgrade and want to make sure nothing is mixed up. - * - * Default is {@code false} as this has performance impacts. - */ - public void setSingleDecode(boolean singleDecode) { - this.singleDecode = singleDecode; - } - - /** - * If {@code true} then only one message is decoded on each - * {@link #channelRead(ChannelHandlerContext, Object)} call. - * - * Default is {@code false} as this has performance impacts. - */ - public boolean isSingleDecode() { - return singleDecode; - } - - /** - * Set the {@link Cumulator} to use for cumulate the received {@link ByteBuf}s. - */ - public void setCumulator(Cumulator cumulator) { - if (cumulator == null) { - throw new NullPointerException("cumulator"); - } - this.cumulator = cumulator; - } - - /** - * Set the number of reads after which {@link ByteBuf#discardSomeReadBytes()} are called and so free up memory. - * The default is {@code 16}. - */ - public void setDiscardAfterReads(int discardAfterReads) { - if (discardAfterReads <= 0) { - throw new IllegalArgumentException("discardAfterReads must be > 0"); - } - this.discardAfterReads = discardAfterReads; - } - - /** - * Returns the actual number of readable bytes in the internal cumulative - * buffer of this decoder. You usually do not need to rely on this value - * to write a decoder. Use it only when you must use it at your own risk. - * This method is a shortcut to {@link #internalBuffer() internalBuffer().readableBytes()}. - */ - protected int actualReadableBytes() { - return internalBuffer().readableBytes(); - } - - /** - * Returns the internal cumulative buffer of this decoder. You usually - * do not need to access the internal buffer directly to write a decoder. - * Use it only when you must use it at your own risk. - */ - protected ByteBuf internalBuffer() { - if (cumulation != null) { - return cumulation; - } else { - return Unpooled.EMPTY_BUFFER; - } - } - - @Override - public final void handlerRemoved(ChannelHandlerContext ctx) throws Exception { - ByteBuf buf = internalBuffer(); - int readable = buf.readableBytes(); - if (readable > 0) { - ByteBuf bytes = buf.readBytes(readable); - buf.release(); - ctx.fireChannelRead(bytes); - } else { - buf.release(); - } - cumulation = null; - numReads = 0; - ctx.fireChannelReadComplete(); - handlerRemoved0(ctx); - } - - /** - * Gets called after the {@link ByteToMessageDecoder} was removed from the actual context and it doesn't handle - * events anymore. - */ - protected void handlerRemoved0(ChannelHandlerContext ctx) throws Exception { } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - if (msg instanceof ByteBuf) { - RecyclableArrayList out = RecyclableArrayList.newInstance(); - try { - ByteBuf data = (ByteBuf) msg; - first = cumulation == null; - if (first) { - cumulation = data; - } else { - cumulation = cumulator.cumulate(ctx.alloc(), cumulation, data); - } - callDecode(ctx, cumulation, out); - } catch (DecoderException e) { - throw e; - } catch (Throwable t) { - throw new DecoderException(t); - } finally { - if (cumulation != null && !cumulation.isReadable()) { - numReads = 0; - cumulation.release(); - cumulation = null; - } else if (++ numReads >= discardAfterReads) { - // We did enough reads already try to discard some bytes so we not risk to see a OOME. - // See https://github.com/netty/netty/issues/4275 - numReads = 0; - discardSomeReadBytes(); - } - - int size = out.size(); - decodeWasNull = !out.insertSinceRecycled(); - fireChannelRead(ctx, out, size); - out.recycle(); - } - } else { - ctx.fireChannelRead(msg); - } - } - - /** - * Get {@code numElements} out of the {@link List} and forward these through the pipeline. - */ - static void fireChannelRead(ChannelHandlerContext ctx, List msgs, int numElements) { - for (int i = 0; i < numElements; i ++) { - ctx.fireChannelRead(msgs.get(i)); - } - } - - @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { - numReads = 0; - discardSomeReadBytes(); - if (decodeWasNull) { - decodeWasNull = false; - if (!ctx.channel().config().isAutoRead()) { - ctx.read(); - } - } - ctx.fireChannelReadComplete(); - } - - protected final void discardSomeReadBytes() { - if (cumulation != null && !first && cumulation.refCnt() == 1) { - // discard some bytes if possible to make more room in the - // buffer but only if the refCnt == 1 as otherwise the user may have - // used slice().retain() or duplicate().retain(). - // - // See: - // - https://github.com/netty/netty/issues/2327 - // - https://github.com/netty/netty/issues/1764 - cumulation.discardSomeReadBytes(); - } - } - - @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { - RecyclableArrayList out = RecyclableArrayList.newInstance(); - try { - if (cumulation != null) { - callDecode(ctx, cumulation, out); - decodeLast(ctx, cumulation, out); - } else { - decodeLast(ctx, Unpooled.EMPTY_BUFFER, out); - } - } catch (DecoderException e) { - throw e; - } catch (Exception e) { - throw new DecoderException(e); - } finally { - try { - if (cumulation != null) { - cumulation.release(); - cumulation = null; - } - int size = out.size(); - fireChannelRead(ctx, out, size); - if (size > 0) { - // Something was read, call fireChannelReadComplete() - ctx.fireChannelReadComplete(); - } - ctx.fireChannelInactive(); - } finally { - // recycle in all cases - out.recycle(); - } - } - } - - /** - * Called once data should be decoded from the given {@link ByteBuf}. This method will call - * {@link #decode(ChannelHandlerContext, ByteBuf, List)} as long as decoding should take place. - * - * @param ctx the {@link ChannelHandlerContext} which this {@link ByteToMessageDecoder} belongs to - * @param in the {@link ByteBuf} from which to read data - * @param out the {@link List} to which decoded messages should be added - */ - protected void callDecode(ChannelHandlerContext ctx, ByteBuf in, List out) { - try { - while (in.isReadable()) { - int outSize = out.size(); - - if (outSize > 0) { - fireChannelRead(ctx, out, outSize); - out.clear(); - outSize = 0; - } - - int oldInputLength = in.readableBytes(); - decode(ctx, in, out); - - // Check if this handler was removed before continuing the loop. - // If it was removed, it is not safe to continue to operate on the buffer. - // - // See https://github.com/netty/netty/issues/1664 - if (ctx.isRemoved()) { - break; - } - - if (outSize == out.size()) { - if (oldInputLength == in.readableBytes()) { - break; - } else { - continue; - } - } - - if (oldInputLength == in.readableBytes()) { - throw new DecoderException( - StringUtil.simpleClassName(getClass()) + - ".decode() did not read anything but decoded a message."); - } - - if (isSingleDecode()) { - break; - } - } - } catch (DecoderException e) { - throw e; - } catch (Throwable cause) { - throw new DecoderException(cause); - } - } - - /** - * Decode the from one {@link ByteBuf} to an other. This method will be called till either the input - * {@link ByteBuf} has nothing to read when return from this method or till nothing was read from the input - * {@link ByteBuf}. - * - * @param ctx the {@link ChannelHandlerContext} which this {@link ByteToMessageDecoder} belongs to - * @param in the {@link ByteBuf} from which to read data - * @param out the {@link List} to which decoded messages should be added - * @throws Exception is thrown if an error accour - */ - protected abstract void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception; - - /** - * Is called one last time when the {@link ChannelHandlerContext} goes in-active. Which means the - * {@link #channelInactive(ChannelHandlerContext)} was triggered. - * - * By default this will just call {@link #decode(ChannelHandlerContext, ByteBuf, List)} but sub-classes may - * override this for some special cleanup operation. - */ - protected void decodeLast(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { - decode(ctx, in, out); - } - - static ByteBuf expandCumulation(ByteBufAllocator alloc, ByteBuf cumulation, int readable) { - ByteBuf oldCumulation = cumulation; - cumulation = alloc.buffer(oldCumulation.readableBytes() + readable); - cumulation.writeBytes(oldCumulation); - oldCumulation.release(); - return cumulation; - } - - /** - * Cumulate {@link ByteBuf}s. - */ - public interface Cumulator { - /** - * Cumulate the given {@link ByteBuf}s and return the {@link ByteBuf} that holds the cumulated bytes. - * The implementation is responsible to correctly handle the life-cycle of the given {@link ByteBuf}s and so - * call {@link ByteBuf#release()} if a {@link ByteBuf} is fully consumed. - */ - ByteBuf cumulate(ByteBufAllocator alloc, ByteBuf cumulation, ByteBuf in); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/CodecException.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/CodecException.java deleted file mode 100755 index 4b2a389839..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/CodecException.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec; - -/** - * An {@link Exception} which is thrown by a codec. - */ -public class CodecException extends RuntimeException { - - private static final long serialVersionUID = -1464830400709348473L; - - /** - * Creates a new instance. - */ - public CodecException() { - } - - /** - * Creates a new instance. - */ - public CodecException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Creates a new instance. - */ - public CodecException(String message) { - super(message); - } - - /** - * Creates a new instance. - */ - public CodecException(Throwable cause) { - super(cause); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/CodecUtil.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/CodecUtil.java deleted file mode 100755 index 6ded45fc28..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/CodecUtil.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec; - -import com.ai.cloud.io.netty.channel.ChannelHandlerAdapter; - -final class CodecUtil { - - /** - * Throws {@link IllegalStateException} if {@link ChannelHandlerAdapter#isSharable()} returns {@code true} - */ - static void ensureNotSharable(ChannelHandlerAdapter handler) { - if (handler.isSharable()) { - throw new IllegalStateException("@Sharable annotation is not allowed"); - } - } - - private CodecUtil() { } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/CorruptedFrameException.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/CorruptedFrameException.java deleted file mode 100755 index 80d0f6053b..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/CorruptedFrameException.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec; - -/** - * An {@link DecoderException} which is thrown when the received frame data could not be decoded by - * an inbound handler. - */ -public class CorruptedFrameException extends DecoderException { - - private static final long serialVersionUID = 3918052232492988408L; - - /** - * Creates a new instance. - */ - public CorruptedFrameException() { - } - - /** - * Creates a new instance. - */ - public CorruptedFrameException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Creates a new instance. - */ - public CorruptedFrameException(String message) { - super(message); - } - - /** - * Creates a new instance. - */ - public CorruptedFrameException(Throwable cause) { - super(cause); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/DecoderException.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/DecoderException.java deleted file mode 100755 index 0efb777fa3..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/DecoderException.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec; - -/** - * An {@link CodecException} which is thrown by a dencoder. - */ -public class DecoderException extends CodecException { - - private static final long serialVersionUID = 6926716840699621852L; - - /** - * Creates a new instance. - */ - public DecoderException() { - } - - /** - * Creates a new instance. - */ - public DecoderException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Creates a new instance. - */ - public DecoderException(String message) { - super(message); - } - - /** - * Creates a new instance. - */ - public DecoderException(Throwable cause) { - super(cause); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/DecoderResult.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/DecoderResult.java deleted file mode 100755 index 36d1212bb8..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/DecoderResult.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec; - -import com.ai.cloud.io.netty.util.Signal; - -public class DecoderResult { - - protected static final Signal SIGNAL_UNFINISHED = Signal.valueOf(DecoderResult.class.getName() + ".UNFINISHED"); - protected static final Signal SIGNAL_SUCCESS = Signal.valueOf(DecoderResult.class.getName() + ".SUCCESS"); - - public static final DecoderResult UNFINISHED = new DecoderResult(SIGNAL_UNFINISHED); - public static final DecoderResult SUCCESS = new DecoderResult(SIGNAL_SUCCESS); - - public static DecoderResult failure(Throwable cause) { - if (cause == null) { - throw new NullPointerException("cause"); - } - return new DecoderResult(cause); - } - - private final Throwable cause; - - protected DecoderResult(Throwable cause) { - if (cause == null) { - throw new NullPointerException("cause"); - } - this.cause = cause; - } - - public boolean isFinished() { - return cause != SIGNAL_UNFINISHED; - } - - public boolean isSuccess() { - return cause == SIGNAL_SUCCESS; - } - - public boolean isFailure() { - return cause != SIGNAL_SUCCESS && cause != SIGNAL_UNFINISHED; - } - - public Throwable cause() { - if (isFailure()) { - return cause; - } else { - return null; - } - } - - @Override - public String toString() { - if (isFinished()) { - if (isSuccess()) { - return "success"; - } - - String cause = cause().toString(); - return new StringBuilder(cause.length() + 17) - .append("failure(") - .append(cause) - .append(')') - .toString(); - } else { - return "unfinished"; - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/DelimiterBasedFrameDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/DelimiterBasedFrameDecoder.java deleted file mode 100755 index 475468b5ae..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/DelimiterBasedFrameDecoder.java +++ /dev/null @@ -1,355 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec; - -import java.util.List; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; - -/** - * A decoder that splits the received {@link ByteBuf}s by one or more - * delimiters. It is particularly useful for decoding the frames which ends - * with a delimiter such as {@link Delimiters#nulDelimiter() NUL} or - * {@linkplain Delimiters#lineDelimiter() newline characters}. - * - *

Predefined delimiters

- *

- * {@link Delimiters} defines frequently used delimiters for convenience' sake. - * - *

Specifying more than one delimiter

- *

- * {@link DelimiterBasedFrameDecoder} allows you to specify more than one - * delimiter. If more than one delimiter is found in the buffer, it chooses - * the delimiter which produces the shortest frame. For example, if you have - * the following data in the buffer: - *

- * +--------------+
- * | ABC\nDEF\r\n |
- * +--------------+
- * 
- * a {@link DelimiterBasedFrameDecoder}({@link Delimiters#lineDelimiter() Delimiters.lineDelimiter()}) - * will choose {@code '\n'} as the first delimiter and produce two frames: - *
- * +-----+-----+
- * | ABC | DEF |
- * +-----+-----+
- * 
- * rather than incorrectly choosing {@code '\r\n'} as the first delimiter: - *
- * +----------+
- * | ABC\nDEF |
- * +----------+
- * 
- */ -public class DelimiterBasedFrameDecoder extends ByteToMessageDecoder { - - private final ByteBuf[] delimiters; - private final int maxFrameLength; - private final boolean stripDelimiter; - private final boolean failFast; - private boolean discardingTooLongFrame; - private int tooLongFrameLength; - /** Set only when decoding with "\n" and "\r\n" as the delimiter. */ - private final LineBasedFrameDecoder lineBasedDecoder; - - /** - * Creates a new instance. - * - * @param maxFrameLength the maximum length of the decoded frame. - * A {@link TooLongFrameException} is thrown if - * the length of the frame exceeds this value. - * @param delimiter the delimiter - */ - public DelimiterBasedFrameDecoder(int maxFrameLength, ByteBuf delimiter) { - this(maxFrameLength, true, delimiter); - } - - /** - * Creates a new instance. - * - * @param maxFrameLength the maximum length of the decoded frame. - * A {@link TooLongFrameException} is thrown if - * the length of the frame exceeds this value. - * @param stripDelimiter whether the decoded frame should strip out the - * delimiter or not - * @param delimiter the delimiter - */ - public DelimiterBasedFrameDecoder( - int maxFrameLength, boolean stripDelimiter, ByteBuf delimiter) { - this(maxFrameLength, stripDelimiter, true, delimiter); - } - - /** - * Creates a new instance. - * - * @param maxFrameLength the maximum length of the decoded frame. - * A {@link TooLongFrameException} is thrown if - * the length of the frame exceeds this value. - * @param stripDelimiter whether the decoded frame should strip out the - * delimiter or not - * @param failFast If true, a {@link TooLongFrameException} is - * thrown as soon as the decoder notices the length of the - * frame will exceed maxFrameLength regardless of - * whether the entire frame has been read. - * If false, a {@link TooLongFrameException} is - * thrown after the entire frame that exceeds - * maxFrameLength has been read. - * @param delimiter the delimiter - */ - public DelimiterBasedFrameDecoder( - int maxFrameLength, boolean stripDelimiter, boolean failFast, - ByteBuf delimiter) { - this(maxFrameLength, stripDelimiter, failFast, new ByteBuf[] { - delimiter.slice(delimiter.readerIndex(), delimiter.readableBytes())}); - } - - /** - * Creates a new instance. - * - * @param maxFrameLength the maximum length of the decoded frame. - * A {@link TooLongFrameException} is thrown if - * the length of the frame exceeds this value. - * @param delimiters the delimiters - */ - public DelimiterBasedFrameDecoder(int maxFrameLength, ByteBuf... delimiters) { - this(maxFrameLength, true, delimiters); - } - - /** - * Creates a new instance. - * - * @param maxFrameLength the maximum length of the decoded frame. - * A {@link TooLongFrameException} is thrown if - * the length of the frame exceeds this value. - * @param stripDelimiter whether the decoded frame should strip out the - * delimiter or not - * @param delimiters the delimiters - */ - public DelimiterBasedFrameDecoder( - int maxFrameLength, boolean stripDelimiter, ByteBuf... delimiters) { - this(maxFrameLength, stripDelimiter, true, delimiters); - } - - /** - * Creates a new instance. - * - * @param maxFrameLength the maximum length of the decoded frame. - * A {@link TooLongFrameException} is thrown if - * the length of the frame exceeds this value. - * @param stripDelimiter whether the decoded frame should strip out the - * delimiter or not - * @param failFast If true, a {@link TooLongFrameException} is - * thrown as soon as the decoder notices the length of the - * frame will exceed maxFrameLength regardless of - * whether the entire frame has been read. - * If false, a {@link TooLongFrameException} is - * thrown after the entire frame that exceeds - * maxFrameLength has been read. - * @param delimiters the delimiters - */ - public DelimiterBasedFrameDecoder( - int maxFrameLength, boolean stripDelimiter, boolean failFast, ByteBuf... delimiters) { - validateMaxFrameLength(maxFrameLength); - if (delimiters == null) { - throw new NullPointerException("delimiters"); - } - if (delimiters.length == 0) { - throw new IllegalArgumentException("empty delimiters"); - } - - if (isLineBased(delimiters) && !isSubclass()) { - lineBasedDecoder = new LineBasedFrameDecoder(maxFrameLength, stripDelimiter, failFast); - this.delimiters = null; - } else { - this.delimiters = new ByteBuf[delimiters.length]; - for (int i = 0; i < delimiters.length; i ++) { - ByteBuf d = delimiters[i]; - validateDelimiter(d); - this.delimiters[i] = d.slice(d.readerIndex(), d.readableBytes()); - } - lineBasedDecoder = null; - } - this.maxFrameLength = maxFrameLength; - this.stripDelimiter = stripDelimiter; - this.failFast = failFast; - } - - /** Returns true if the delimiters are "\n" and "\r\n". */ - private static boolean isLineBased(final ByteBuf[] delimiters) { - if (delimiters.length != 2) { - return false; - } - ByteBuf a = delimiters[0]; - ByteBuf b = delimiters[1]; - if (a.capacity() < b.capacity()) { - a = delimiters[1]; - b = delimiters[0]; - } - return a.capacity() == 2 && b.capacity() == 1 - && a.getByte(0) == '\r' && a.getByte(1) == '\n' - && b.getByte(0) == '\n'; - } - - /** - * Return {@code true} if the current instance is a subclass of DelimiterBasedFrameDecoder - */ - private boolean isSubclass() { - return getClass() != DelimiterBasedFrameDecoder.class; - } - - @Override - protected final void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { - Object decoded = decode(ctx, in); - if (decoded != null) { - out.add(decoded); - } - } - - /** - * Create a frame out of the {@link ByteBuf} and return it. - * - * @param ctx the {@link ChannelHandlerContext} which this {@link ByteToMessageDecoder} belongs to - * @param buffer the {@link ByteBuf} from which to read data - * @return frame the {@link ByteBuf} which represent the frame or {@code null} if no frame could - * be created. - */ - protected Object decode(ChannelHandlerContext ctx, ByteBuf buffer) throws Exception { - if (lineBasedDecoder != null) { - return lineBasedDecoder.decode(ctx, buffer); - } - // Try all delimiters and choose the delimiter which yields the shortest frame. - int minFrameLength = Integer.MAX_VALUE; - ByteBuf minDelim = null; - for (ByteBuf delim: delimiters) { - int frameLength = indexOf(buffer, delim); - if (frameLength >= 0 && frameLength < minFrameLength) { - minFrameLength = frameLength; - minDelim = delim; - } - } - - if (minDelim != null) { - int minDelimLength = minDelim.capacity(); - ByteBuf frame; - - if (discardingTooLongFrame) { - // We've just finished discarding a very large frame. - // Go back to the initial state. - discardingTooLongFrame = false; - buffer.skipBytes(minFrameLength + minDelimLength); - - int tooLongFrameLength = this.tooLongFrameLength; - this.tooLongFrameLength = 0; - if (!failFast) { - fail(tooLongFrameLength); - } - return null; - } - - if (minFrameLength > maxFrameLength) { - // Discard read frame. - buffer.skipBytes(minFrameLength + minDelimLength); - fail(minFrameLength); - return null; - } - - if (stripDelimiter) { - frame = buffer.readSlice(minFrameLength); - buffer.skipBytes(minDelimLength); - } else { - frame = buffer.readSlice(minFrameLength + minDelimLength); - } - - return frame.retain(); - } else { - if (!discardingTooLongFrame) { - if (buffer.readableBytes() > maxFrameLength) { - // Discard the content of the buffer until a delimiter is found. - tooLongFrameLength = buffer.readableBytes(); - buffer.skipBytes(buffer.readableBytes()); - discardingTooLongFrame = true; - if (failFast) { - fail(tooLongFrameLength); - } - } - } else { - // Still discarding the buffer since a delimiter is not found. - tooLongFrameLength += buffer.readableBytes(); - buffer.skipBytes(buffer.readableBytes()); - } - return null; - } - } - - private void fail(long frameLength) { - if (frameLength > 0) { - throw new TooLongFrameException( - "frame length exceeds " + maxFrameLength + - ": " + frameLength + " - discarded"); - } else { - throw new TooLongFrameException( - "frame length exceeds " + maxFrameLength + - " - discarding"); - } - } - - /** - * Returns the number of bytes between the readerIndex of the haystack and - * the first needle found in the haystack. -1 is returned if no needle is - * found in the haystack. - */ - private static int indexOf(ByteBuf haystack, ByteBuf needle) { - for (int i = haystack.readerIndex(); i < haystack.writerIndex(); i ++) { - int haystackIndex = i; - int needleIndex; - for (needleIndex = 0; needleIndex < needle.capacity(); needleIndex ++) { - if (haystack.getByte(haystackIndex) != needle.getByte(needleIndex)) { - break; - } else { - haystackIndex ++; - if (haystackIndex == haystack.writerIndex() && - needleIndex != needle.capacity() - 1) { - return -1; - } - } - } - - if (needleIndex == needle.capacity()) { - // Found the needle from the haystack! - return i - haystack.readerIndex(); - } - } - return -1; - } - - private static void validateDelimiter(ByteBuf delimiter) { - if (delimiter == null) { - throw new NullPointerException("delimiter"); - } - if (!delimiter.isReadable()) { - throw new IllegalArgumentException("empty delimiter"); - } - } - - private static void validateMaxFrameLength(int maxFrameLength) { - if (maxFrameLength <= 0) { - throw new IllegalArgumentException( - "maxFrameLength must be a positive integer: " + - maxFrameLength); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/Delimiters.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/Delimiters.java deleted file mode 100755 index 9db83e0f37..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/Delimiters.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.Unpooled; - -/** - * A set of commonly used delimiters for {@link DelimiterBasedFrameDecoder}. - */ -public final class Delimiters { - - /** - * Returns a {@code NUL (0x00)} delimiter, which could be used for - * Flash XML socket or any similar protocols. - */ - public static ByteBuf[] nulDelimiter() { - return new ByteBuf[] { - Unpooled.wrappedBuffer(new byte[] { 0 }) }; - } - - /** - * Returns {@code CR ('\r')} and {@code LF ('\n')} delimiters, which could - * be used for text-based line protocols. - */ - public static ByteBuf[] lineDelimiter() { - return new ByteBuf[] { - Unpooled.wrappedBuffer(new byte[] { '\r', '\n' }), - Unpooled.wrappedBuffer(new byte[] { '\n' }), - }; - } - - private Delimiters() { - // Unused - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/EncoderException.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/EncoderException.java deleted file mode 100755 index fdf2b6f089..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/EncoderException.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec; - -/** - * An {@link CodecException} which is thrown by an encoder. - */ -public class EncoderException extends CodecException { - - private static final long serialVersionUID = -5086121160476476774L; - - /** - * Creates a new instance. - */ - public EncoderException() { - } - - /** - * Creates a new instance. - */ - public EncoderException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Creates a new instance. - */ - public EncoderException(String message) { - super(message); - } - - /** - * Creates a new instance. - */ - public EncoderException(Throwable cause) { - super(cause); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/FixedLengthFrameDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/FixedLengthFrameDecoder.java deleted file mode 100755 index 96e9cdc604..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/FixedLengthFrameDecoder.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec; - -import java.util.List; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; - -/** - * A decoder that splits the received {@link ByteBuf}s by the fixed number - * of bytes. For example, if you received the following four fragmented packets: - *
- * +---+----+------+----+
- * | A | BC | DEFG | HI |
- * +---+----+------+----+
- * 
- * A {@link FixedLengthFrameDecoder}{@code (3)} will decode them into the - * following three packets with the fixed length: - *
- * +-----+-----+-----+
- * | ABC | DEF | GHI |
- * +-----+-----+-----+
- * 
- */ -public class FixedLengthFrameDecoder extends ByteToMessageDecoder { - - private final int frameLength; - - /** - * Creates a new instance. - * - * @param frameLength the length of the frame - */ - public FixedLengthFrameDecoder(int frameLength) { - if (frameLength <= 0) { - throw new IllegalArgumentException( - "frameLength must be a positive integer: " + frameLength); - } - this.frameLength = frameLength; - } - - @Override - protected final void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { - Object decoded = decode(ctx, in); - if (decoded != null) { - out.add(decoded); - } - } - - /** - * Create a frame out of the {@link ByteBuf} and return it. - * - * @param ctx the {@link ChannelHandlerContext} which this {@link ByteToMessageDecoder} belongs to - * @param in the {@link ByteBuf} from which to read data - * @return frame the {@link ByteBuf} which represent the frame or {@code null} if no frame could - * be created. - */ - protected Object decode( - @SuppressWarnings("UnusedParameters") ChannelHandlerContext ctx, ByteBuf in) throws Exception { - if (in.readableBytes() < frameLength) { - return null; - } else { - return in.readSlice(frameLength).retain(); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/LengthFieldBasedFrameDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/LengthFieldBasedFrameDecoder.java deleted file mode 100755 index b7bdba8fde..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/LengthFieldBasedFrameDecoder.java +++ /dev/null @@ -1,508 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec; - -import java.nio.ByteOrder; -import java.util.List; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.handler.codec.serialization.ObjectDecoder; - -/** - * A decoder that splits the received {@link ByteBuf}s dynamically by the - * value of the length field in the message. It is particularly useful when you - * decode a binary message which has an integer header field that represents the - * length of the message body or the whole message. - *

- * {@link LengthFieldBasedFrameDecoder} has many configuration parameters so - * that it can decode any message with a length field, which is often seen in - * proprietary client-server protocols. Here are some example that will give - * you the basic idea on which option does what. - * - *

2 bytes length field at offset 0, do not strip header

- * - * The value of the length field in this example is 12 (0x0C) which - * represents the length of "HELLO, WORLD". By default, the decoder assumes - * that the length field represents the number of the bytes that follows the - * length field. Therefore, it can be decoded with the simplistic parameter - * combination. - *
- * lengthFieldOffset   = 0
- * lengthFieldLength   = 2
- * lengthAdjustment    = 0
- * initialBytesToStrip = 0 (= do not strip header)
- *
- * BEFORE DECODE (14 bytes)         AFTER DECODE (14 bytes)
- * +--------+----------------+      +--------+----------------+
- * | Length | Actual Content |----->| Length | Actual Content |
- * | 0x000C | "HELLO, WORLD" |      | 0x000C | "HELLO, WORLD" |
- * +--------+----------------+      +--------+----------------+
- * 
- * - *

2 bytes length field at offset 0, strip header

- * - * Because we can get the length of the content by calling - * {@link ByteBuf#readableBytes()}, you might want to strip the length - * field by specifying initialBytesToStrip. In this example, we - * specified 2, that is same with the length of the length field, to - * strip the first two bytes. - *
- * lengthFieldOffset   = 0
- * lengthFieldLength   = 2
- * lengthAdjustment    = 0
- * initialBytesToStrip = 2 (= the length of the Length field)
- *
- * BEFORE DECODE (14 bytes)         AFTER DECODE (12 bytes)
- * +--------+----------------+      +----------------+
- * | Length | Actual Content |----->| Actual Content |
- * | 0x000C | "HELLO, WORLD" |      | "HELLO, WORLD" |
- * +--------+----------------+      +----------------+
- * 
- * - *

2 bytes length field at offset 0, do not strip header, the length field - * represents the length of the whole message

- * - * In most cases, the length field represents the length of the message body - * only, as shown in the previous examples. However, in some protocols, the - * length field represents the length of the whole message, including the - * message header. In such a case, we specify a non-zero - * lengthAdjustment. Because the length value in this example message - * is always greater than the body length by 2, we specify -2 - * as lengthAdjustment for compensation. - *
- * lengthFieldOffset   =  0
- * lengthFieldLength   =  2
- * lengthAdjustment    = -2 (= the length of the Length field)
- * initialBytesToStrip =  0
- *
- * BEFORE DECODE (14 bytes)         AFTER DECODE (14 bytes)
- * +--------+----------------+      +--------+----------------+
- * | Length | Actual Content |----->| Length | Actual Content |
- * | 0x000E | "HELLO, WORLD" |      | 0x000E | "HELLO, WORLD" |
- * +--------+----------------+      +--------+----------------+
- * 
- * - *

3 bytes length field at the end of 5 bytes header, do not strip header

- * - * The following message is a simple variation of the first example. An extra - * header value is prepended to the message. lengthAdjustment is zero - * again because the decoder always takes the length of the prepended data into - * account during frame length calculation. - *
- * lengthFieldOffset   = 2 (= the length of Header 1)
- * lengthFieldLength   = 3
- * lengthAdjustment    = 0
- * initialBytesToStrip = 0
- *
- * BEFORE DECODE (17 bytes)                      AFTER DECODE (17 bytes)
- * +----------+----------+----------------+      +----------+----------+----------------+
- * | Header 1 |  Length  | Actual Content |----->| Header 1 |  Length  | Actual Content |
- * |  0xCAFE  | 0x00000C | "HELLO, WORLD" |      |  0xCAFE  | 0x00000C | "HELLO, WORLD" |
- * +----------+----------+----------------+      +----------+----------+----------------+
- * 
- * - *

3 bytes length field at the beginning of 5 bytes header, do not strip header

- * - * This is an advanced example that shows the case where there is an extra - * header between the length field and the message body. You have to specify a - * positive lengthAdjustment so that the decoder counts the extra - * header into the frame length calculation. - *
- * lengthFieldOffset   = 0
- * lengthFieldLength   = 3
- * lengthAdjustment    = 2 (= the length of Header 1)
- * initialBytesToStrip = 0
- *
- * BEFORE DECODE (17 bytes)                      AFTER DECODE (17 bytes)
- * +----------+----------+----------------+      +----------+----------+----------------+
- * |  Length  | Header 1 | Actual Content |----->|  Length  | Header 1 | Actual Content |
- * | 0x00000C |  0xCAFE  | "HELLO, WORLD" |      | 0x00000C |  0xCAFE  | "HELLO, WORLD" |
- * +----------+----------+----------------+      +----------+----------+----------------+
- * 
- * - *

2 bytes length field at offset 1 in the middle of 4 bytes header, - * strip the first header field and the length field

- * - * This is a combination of all the examples above. There are the prepended - * header before the length field and the extra header after the length field. - * The prepended header affects the lengthFieldOffset and the extra - * header affects the lengthAdjustment. We also specified a non-zero - * initialBytesToStrip to strip the length field and the prepended - * header from the frame. If you don't want to strip the prepended header, you - * could specify 0 for initialBytesToSkip. - *
- * lengthFieldOffset   = 1 (= the length of HDR1)
- * lengthFieldLength   = 2
- * lengthAdjustment    = 1 (= the length of HDR2)
- * initialBytesToStrip = 3 (= the length of HDR1 + LEN)
- *
- * BEFORE DECODE (16 bytes)                       AFTER DECODE (13 bytes)
- * +------+--------+------+----------------+      +------+----------------+
- * | HDR1 | Length | HDR2 | Actual Content |----->| HDR2 | Actual Content |
- * | 0xCA | 0x000C | 0xFE | "HELLO, WORLD" |      | 0xFE | "HELLO, WORLD" |
- * +------+--------+------+----------------+      +------+----------------+
- * 
- * - *

2 bytes length field at offset 1 in the middle of 4 bytes header, - * strip the first header field and the length field, the length field - * represents the length of the whole message

- * - * Let's give another twist to the previous example. The only difference from - * the previous example is that the length field represents the length of the - * whole message instead of the message body, just like the third example. - * We have to count the length of HDR1 and Length into lengthAdjustment. - * Please note that we don't need to take the length of HDR2 into account - * because the length field already includes the whole header length. - *
- * lengthFieldOffset   =  1
- * lengthFieldLength   =  2
- * lengthAdjustment    = -3 (= the length of HDR1 + LEN, negative)
- * initialBytesToStrip =  3
- *
- * BEFORE DECODE (16 bytes)                       AFTER DECODE (13 bytes)
- * +------+--------+------+----------------+      +------+----------------+
- * | HDR1 | Length | HDR2 | Actual Content |----->| HDR2 | Actual Content |
- * | 0xCA | 0x0010 | 0xFE | "HELLO, WORLD" |      | 0xFE | "HELLO, WORLD" |
- * +------+--------+------+----------------+      +------+----------------+
- * 
- * @see LengthFieldPrepender - */ -public class LengthFieldBasedFrameDecoder extends ByteToMessageDecoder { - - private final ByteOrder byteOrder; - private final int maxFrameLength; - private final int lengthFieldOffset; - private final int lengthFieldLength; - private final int lengthFieldEndOffset; - private final int lengthAdjustment; - private final int initialBytesToStrip; - private final boolean failFast; - private boolean discardingTooLongFrame; - private long tooLongFrameLength; - private long bytesToDiscard; - - /** - * Creates a new instance. - * - * @param maxFrameLength - * the maximum length of the frame. If the length of the frame is - * greater than this value, {@link TooLongFrameException} will be - * thrown. - * @param lengthFieldOffset - * the offset of the length field - * @param lengthFieldLength - * the length of the length field - */ - public LengthFieldBasedFrameDecoder( - int maxFrameLength, - int lengthFieldOffset, int lengthFieldLength) { - this(maxFrameLength, lengthFieldOffset, lengthFieldLength, 0, 0); - } - - /** - * Creates a new instance. - * - * @param maxFrameLength - * the maximum length of the frame. If the length of the frame is - * greater than this value, {@link TooLongFrameException} will be - * thrown. - * @param lengthFieldOffset - * the offset of the length field - * @param lengthFieldLength - * the length of the length field - * @param lengthAdjustment - * the compensation value to add to the value of the length field - * @param initialBytesToStrip - * the number of first bytes to strip out from the decoded frame - */ - public LengthFieldBasedFrameDecoder( - int maxFrameLength, - int lengthFieldOffset, int lengthFieldLength, - int lengthAdjustment, int initialBytesToStrip) { - this( - maxFrameLength, - lengthFieldOffset, lengthFieldLength, lengthAdjustment, - initialBytesToStrip, true); - } - - /** - * Creates a new instance. - * - * @param maxFrameLength - * the maximum length of the frame. If the length of the frame is - * greater than this value, {@link TooLongFrameException} will be - * thrown. - * @param lengthFieldOffset - * the offset of the length field - * @param lengthFieldLength - * the length of the length field - * @param lengthAdjustment - * the compensation value to add to the value of the length field - * @param initialBytesToStrip - * the number of first bytes to strip out from the decoded frame - * @param failFast - * If true, a {@link TooLongFrameException} is thrown as - * soon as the decoder notices the length of the frame will exceed - * maxFrameLength regardless of whether the entire frame - * has been read. If false, a {@link TooLongFrameException} - * is thrown after the entire frame that exceeds maxFrameLength - * has been read. - */ - public LengthFieldBasedFrameDecoder( - int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, - int lengthAdjustment, int initialBytesToStrip, boolean failFast) { - this( - ByteOrder.BIG_ENDIAN, maxFrameLength, lengthFieldOffset, lengthFieldLength, - lengthAdjustment, initialBytesToStrip, failFast); - } - - /** - * Creates a new instance. - * - * @param byteOrder - * the {@link ByteOrder} of the length field - * @param maxFrameLength - * the maximum length of the frame. If the length of the frame is - * greater than this value, {@link TooLongFrameException} will be - * thrown. - * @param lengthFieldOffset - * the offset of the length field - * @param lengthFieldLength - * the length of the length field - * @param lengthAdjustment - * the compensation value to add to the value of the length field - * @param initialBytesToStrip - * the number of first bytes to strip out from the decoded frame - * @param failFast - * If true, a {@link TooLongFrameException} is thrown as - * soon as the decoder notices the length of the frame will exceed - * maxFrameLength regardless of whether the entire frame - * has been read. If false, a {@link TooLongFrameException} - * is thrown after the entire frame that exceeds maxFrameLength - * has been read. - */ - public LengthFieldBasedFrameDecoder( - ByteOrder byteOrder, int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, - int lengthAdjustment, int initialBytesToStrip, boolean failFast) { - if (byteOrder == null) { - throw new NullPointerException("byteOrder"); - } - - if (maxFrameLength <= 0) { - throw new IllegalArgumentException( - "maxFrameLength must be a positive integer: " + - maxFrameLength); - } - - if (lengthFieldOffset < 0) { - throw new IllegalArgumentException( - "lengthFieldOffset must be a non-negative integer: " + - lengthFieldOffset); - } - - if (initialBytesToStrip < 0) { - throw new IllegalArgumentException( - "initialBytesToStrip must be a non-negative integer: " + - initialBytesToStrip); - } - - if (lengthFieldOffset > maxFrameLength - lengthFieldLength) { - throw new IllegalArgumentException( - "maxFrameLength (" + maxFrameLength + ") " + - "must be equal to or greater than " + - "lengthFieldOffset (" + lengthFieldOffset + ") + " + - "lengthFieldLength (" + lengthFieldLength + ")."); - } - - this.byteOrder = byteOrder; - this.maxFrameLength = maxFrameLength; - this.lengthFieldOffset = lengthFieldOffset; - this.lengthFieldLength = lengthFieldLength; - this.lengthAdjustment = lengthAdjustment; - lengthFieldEndOffset = lengthFieldOffset + lengthFieldLength; - this.initialBytesToStrip = initialBytesToStrip; - this.failFast = failFast; - } - - @Override - protected final void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { - Object decoded = decode(ctx, in); - if (decoded != null) { - out.add(decoded); - } - } - - /** - * Create a frame out of the {@link ByteBuf} and return it. - * - * @param ctx the {@link ChannelHandlerContext} which this {@link ByteToMessageDecoder} belongs to - * @param in the {@link ByteBuf} from which to read data - * @return frame the {@link ByteBuf} which represent the frame or {@code null} if no frame could - * be created. - */ - protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception { - if (discardingTooLongFrame) { - long bytesToDiscard = this.bytesToDiscard; - int localBytesToDiscard = (int) Math.min(bytesToDiscard, in.readableBytes()); - in.skipBytes(localBytesToDiscard); - bytesToDiscard -= localBytesToDiscard; - this.bytesToDiscard = bytesToDiscard; - - failIfNecessary(false); - } - - if (in.readableBytes() < lengthFieldEndOffset) { - return null; - } - - int actualLengthFieldOffset = in.readerIndex() + lengthFieldOffset; - long frameLength = getUnadjustedFrameLength(in, actualLengthFieldOffset, lengthFieldLength, byteOrder); - - if (frameLength < 0) { - in.skipBytes(lengthFieldEndOffset); - throw new CorruptedFrameException( - "negative pre-adjustment length field: " + frameLength); - } - - frameLength += lengthAdjustment + lengthFieldEndOffset; - - if (frameLength < lengthFieldEndOffset) { - in.skipBytes(lengthFieldEndOffset); - throw new CorruptedFrameException( - "Adjusted frame length (" + frameLength + ") is less " + - "than lengthFieldEndOffset: " + lengthFieldEndOffset); - } - - if (frameLength > maxFrameLength) { - long discard = frameLength - in.readableBytes(); - tooLongFrameLength = frameLength; - - if (discard < 0) { - // buffer contains more bytes then the frameLength so we can discard all now - in.skipBytes((int) frameLength); - } else { - // Enter the discard mode and discard everything received so far. - discardingTooLongFrame = true; - bytesToDiscard = discard; - in.skipBytes(in.readableBytes()); - } - failIfNecessary(true); - return null; - } - - // never overflows because it's less than maxFrameLength - int frameLengthInt = (int) frameLength; - if (in.readableBytes() < frameLengthInt) { - return null; - } - - if (initialBytesToStrip > frameLengthInt) { - in.skipBytes(frameLengthInt); - throw new CorruptedFrameException( - "Adjusted frame length (" + frameLength + ") is less " + - "than initialBytesToStrip: " + initialBytesToStrip); - } - in.skipBytes(initialBytesToStrip); - - // extract frame - int readerIndex = in.readerIndex(); - int actualFrameLength = frameLengthInt - initialBytesToStrip; - ByteBuf frame = extractFrame(ctx, in, readerIndex, actualFrameLength); - in.readerIndex(readerIndex + actualFrameLength); - return frame; - } - - /** - * Decodes the specified region of the buffer into an unadjusted frame length. The default implementation is - * capable of decoding the specified region into an unsigned 8/16/24/32/64 bit integer. Override this method to - * decode the length field encoded differently. Note that this method must not modify the state of the specified - * buffer (e.g. {@code readerIndex}, {@code writerIndex}, and the content of the buffer.) - * - * @throws DecoderException if failed to decode the specified region - */ - protected long getUnadjustedFrameLength(ByteBuf buf, int offset, int length, ByteOrder order) { - buf = buf.order(order); - long frameLength; - switch (length) { - case 1: - frameLength = buf.getUnsignedByte(offset); - break; - case 2: - frameLength = buf.getUnsignedShort(offset); - break; - case 3: - frameLength = buf.getUnsignedMedium(offset); - break; - case 4: - frameLength = buf.getUnsignedInt(offset); - break; - case 8: - frameLength = buf.getLong(offset); - break; - default: - throw new DecoderException( - "unsupported lengthFieldLength: " + lengthFieldLength + " (expected: 1, 2, 3, 4, or 8)"); - } - return frameLength; - } - - private void failIfNecessary(boolean firstDetectionOfTooLongFrame) { - if (bytesToDiscard == 0) { - // Reset to the initial state and tell the handlers that - // the frame was too large. - long tooLongFrameLength = this.tooLongFrameLength; - this.tooLongFrameLength = 0; - discardingTooLongFrame = false; - if (!failFast || - failFast && firstDetectionOfTooLongFrame) { - fail(tooLongFrameLength); - } - } else { - // Keep discarding and notify handlers if necessary. - if (failFast && firstDetectionOfTooLongFrame) { - fail(tooLongFrameLength); - } - } - } - - /** - * Extract the sub-region of the specified buffer. - *

- * If you are sure that the frame and its content are not accessed after - * the current {@link #decode(ChannelHandlerContext, ByteBuf)} - * call returns, you can even avoid memory copy by returning the sliced - * sub-region (i.e. return buffer.slice(index, length)). - * It's often useful when you convert the extracted frame into an object. - * Refer to the source code of {@link ObjectDecoder} to see how this method - * is overridden to avoid memory copy. - */ - protected ByteBuf extractFrame(ChannelHandlerContext ctx, ByteBuf buffer, int index, int length) { - return buffer.slice(index, length).retain(); - } - - private void fail(long frameLength) { - if (frameLength > 0) { - throw new TooLongFrameException( - "Adjusted frame length exceeds " + maxFrameLength + - ": " + frameLength + " - discarded"); - } else { - throw new TooLongFrameException( - "Adjusted frame length exceeds " + maxFrameLength + - " - discarding"); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/LengthFieldPrepender.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/LengthFieldPrepender.java deleted file mode 100755 index 66ef27d167..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/LengthFieldPrepender.java +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec; - -import java.nio.ByteOrder; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelHandler.Sharable; -import com.ai.cloud.io.netty.util.internal.ObjectUtil; - -/** - * An encoder that prepends the length of the message. The length value is - * prepended as a binary form. - *

- * For example, {@link LengthFieldPrepender}(2) will encode the - * following 12-bytes string: - *

- * +----------------+
- * | "HELLO, WORLD" |
- * +----------------+
- * 
- * into the following: - *
- * +--------+----------------+
- * + 0x000C | "HELLO, WORLD" |
- * +--------+----------------+
- * 
- * If you turned on the {@code lengthIncludesLengthFieldLength} flag in the - * constructor, the encoded data would look like the following - * (12 (original data) + 2 (prepended data) = 14 (0xE)): - *
- * +--------+----------------+
- * + 0x000E | "HELLO, WORLD" |
- * +--------+----------------+
- * 
- */ -@Sharable -public class LengthFieldPrepender extends MessageToByteEncoder { - - private final ByteOrder byteOrder; - private final int lengthFieldLength; - private final boolean lengthIncludesLengthFieldLength; - private final int lengthAdjustment; - - /** - * Creates a new instance. - * - * @param lengthFieldLength the length of the prepended length field. - * Only 1, 2, 3, 4, and 8 are allowed. - * - * @throws IllegalArgumentException - * if {@code lengthFieldLength} is not 1, 2, 3, 4, or 8 - */ - public LengthFieldPrepender(int lengthFieldLength) { - this(lengthFieldLength, false); - } - - /** - * Creates a new instance. - * - * @param lengthFieldLength the length of the prepended length field. - * Only 1, 2, 3, 4, and 8 are allowed. - * @param lengthIncludesLengthFieldLength - * if {@code true}, the length of the prepended - * length field is added to the value of the - * prepended length field. - * - * @throws IllegalArgumentException - * if {@code lengthFieldLength} is not 1, 2, 3, 4, or 8 - */ - public LengthFieldPrepender(int lengthFieldLength, boolean lengthIncludesLengthFieldLength) { - this(lengthFieldLength, 0, lengthIncludesLengthFieldLength); - } - - /** - * Creates a new instance. - * - * @param lengthFieldLength the length of the prepended length field. - * Only 1, 2, 3, 4, and 8 are allowed. - * @param lengthAdjustment the compensation value to add to the value - * of the length field - * - * @throws IllegalArgumentException - * if {@code lengthFieldLength} is not 1, 2, 3, 4, or 8 - */ - public LengthFieldPrepender(int lengthFieldLength, int lengthAdjustment) { - this(lengthFieldLength, lengthAdjustment, false); - } - - /** - * Creates a new instance. - * - * @param lengthFieldLength the length of the prepended length field. - * Only 1, 2, 3, 4, and 8 are allowed. - * @param lengthAdjustment the compensation value to add to the value - * of the length field - * @param lengthIncludesLengthFieldLength - * if {@code true}, the length of the prepended - * length field is added to the value of the - * prepended length field. - * - * @throws IllegalArgumentException - * if {@code lengthFieldLength} is not 1, 2, 3, 4, or 8 - */ - public LengthFieldPrepender(int lengthFieldLength, int lengthAdjustment, boolean lengthIncludesLengthFieldLength) { - this(ByteOrder.BIG_ENDIAN, lengthFieldLength, lengthAdjustment, lengthIncludesLengthFieldLength); - } - - /** - * Creates a new instance. - * - * @param byteOrder the {@link ByteOrder} of the length field - * @param lengthFieldLength the length of the prepended length field. - * Only 1, 2, 3, 4, and 8 are allowed. - * @param lengthAdjustment the compensation value to add to the value - * of the length field - * @param lengthIncludesLengthFieldLength - * if {@code true}, the length of the prepended - * length field is added to the value of the - * prepended length field. - * - * @throws IllegalArgumentException - * if {@code lengthFieldLength} is not 1, 2, 3, 4, or 8 - */ - public LengthFieldPrepender( - ByteOrder byteOrder, int lengthFieldLength, - int lengthAdjustment, boolean lengthIncludesLengthFieldLength) { - if (lengthFieldLength != 1 && lengthFieldLength != 2 && - lengthFieldLength != 3 && lengthFieldLength != 4 && - lengthFieldLength != 8) { - throw new IllegalArgumentException( - "lengthFieldLength must be either 1, 2, 3, 4, or 8: " + - lengthFieldLength); - } - ObjectUtil.checkNotNull(byteOrder, "byteOrder"); - - this.byteOrder = byteOrder; - this.lengthFieldLength = lengthFieldLength; - this.lengthIncludesLengthFieldLength = lengthIncludesLengthFieldLength; - this.lengthAdjustment = lengthAdjustment; - } - - @Override - protected void encode(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out) throws Exception { - int length = msg.readableBytes() + lengthAdjustment; - if (lengthIncludesLengthFieldLength) { - length += lengthFieldLength; - } - - if (length < 0) { - throw new IllegalArgumentException( - "Adjusted frame length (" + length + ") is less than zero"); - } - - switch (lengthFieldLength) { - case 1: - if (length >= 256) { - throw new IllegalArgumentException( - "length does not fit into a byte: " + length); - } - out.writeByte((byte) length); - break; - case 2: - if (length >= 65536) { - throw new IllegalArgumentException( - "length does not fit into a short integer: " + length); - } - out.writeShort((short) length); - break; - case 3: - if (length >= 16777216) { - throw new IllegalArgumentException( - "length does not fit into a medium integer: " + length); - } - out.writeMedium(length); - break; - case 4: - out.writeInt(length); - break; - case 8: - out.writeLong(length); - break; - default: - throw new Error("should not reach here"); - } - - out.writeBytes(msg, msg.readerIndex(), msg.readableBytes()); - } - - @Override - protected ByteBuf allocateBuffer(ChannelHandlerContext ctx, ByteBuf msg, boolean preferDirect) throws Exception { - return super.allocateBuffer(ctx, msg, preferDirect).order(byteOrder); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/LineBasedFrameDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/LineBasedFrameDecoder.java deleted file mode 100755 index 4e1912f545..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/LineBasedFrameDecoder.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec; - -import java.util.List; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; - -/** - * A decoder that splits the received {@link ByteBuf}s on line endings. - *

- * Both {@code "\n"} and {@code "\r\n"} are handled. - * For a more general delimiter-based decoder, see {@link DelimiterBasedFrameDecoder}. - */ -public class LineBasedFrameDecoder extends ByteToMessageDecoder { - - /** Maximum length of a frame we're willing to decode. */ - private final int maxLength; - /** Whether or not to throw an exception as soon as we exceed maxLength. */ - private final boolean failFast; - private final boolean stripDelimiter; - - /** True if we're discarding input because we're already over maxLength. */ - private boolean discarding; - private int discardedBytes; - - /** - * Creates a new decoder. - * @param maxLength the maximum length of the decoded frame. - * A {@link TooLongFrameException} is thrown if - * the length of the frame exceeds this value. - */ - public LineBasedFrameDecoder(final int maxLength) { - this(maxLength, true, false); - } - - /** - * Creates a new decoder. - * @param maxLength the maximum length of the decoded frame. - * A {@link TooLongFrameException} is thrown if - * the length of the frame exceeds this value. - * @param stripDelimiter whether the decoded frame should strip out the - * delimiter or not - * @param failFast If true, a {@link TooLongFrameException} is - * thrown as soon as the decoder notices the length of the - * frame will exceed maxFrameLength regardless of - * whether the entire frame has been read. - * If false, a {@link TooLongFrameException} is - * thrown after the entire frame that exceeds - * maxFrameLength has been read. - */ - public LineBasedFrameDecoder(final int maxLength, final boolean stripDelimiter, final boolean failFast) { - this.maxLength = maxLength; - this.failFast = failFast; - this.stripDelimiter = stripDelimiter; - } - - @Override - protected final void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { - Object decoded = decode(ctx, in); - if (decoded != null) { - out.add(decoded); - } - } - - /** - * Create a frame out of the {@link ByteBuf} and return it. - * - * @param ctx the {@link ChannelHandlerContext} which this {@link ByteToMessageDecoder} belongs to - * @param buffer the {@link ByteBuf} from which to read data - * @return frame the {@link ByteBuf} which represent the frame or {@code null} if no frame could - * be created. - */ - protected Object decode(ChannelHandlerContext ctx, ByteBuf buffer) throws Exception { - final int eol = findEndOfLine(buffer); - if (!discarding) { - if (eol >= 0) { - final ByteBuf frame; - final int length = eol - buffer.readerIndex(); - final int delimLength = buffer.getByte(eol) == '\r'? 2 : 1; - - if (length > maxLength) { - buffer.readerIndex(eol + delimLength); - fail(ctx, length); - return null; - } - - if (stripDelimiter) { - frame = buffer.readSlice(length); - buffer.skipBytes(delimLength); - } else { - frame = buffer.readSlice(length + delimLength); - } - - return frame.retain(); - } else { - final int length = buffer.readableBytes(); - if (length > maxLength) { - discardedBytes = length; - buffer.readerIndex(buffer.writerIndex()); - discarding = true; - if (failFast) { - fail(ctx, "over " + discardedBytes); - } - } - return null; - } - } else { - if (eol >= 0) { - final int length = discardedBytes + eol - buffer.readerIndex(); - final int delimLength = buffer.getByte(eol) == '\r'? 2 : 1; - buffer.readerIndex(eol + delimLength); - discardedBytes = 0; - discarding = false; - if (!failFast) { - fail(ctx, length); - } - } else { - discardedBytes += buffer.readableBytes(); - buffer.readerIndex(buffer.writerIndex()); - } - return null; - } - } - - private void fail(final ChannelHandlerContext ctx, int length) { - fail(ctx, String.valueOf(length)); - } - - private void fail(final ChannelHandlerContext ctx, String length) { - ctx.fireExceptionCaught( - new TooLongFrameException( - "frame length (" + length + ") exceeds the allowed maximum (" + maxLength + ')')); - } - - /** - * Returns the index in the buffer of the end of line found. - * Returns -1 if no end of line was found in the buffer. - */ - private static int findEndOfLine(final ByteBuf buffer) { - final int n = buffer.writerIndex(); - for (int i = buffer.readerIndex(); i < n; i ++) { - final byte b = buffer.getByte(i); - if (b == '\n') { - return i; - } else if (b == '\r' && i < n - 1 && buffer.getByte(i + 1) == '\n') { - return i; // \r\n - } - } - return -1; // Not found. - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/MessageToByteEncoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/MessageToByteEncoder.java deleted file mode 100755 index 8588b5f0e2..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/MessageToByteEncoder.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.Unpooled; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelOutboundHandler; -import com.ai.cloud.io.netty.channel.ChannelOutboundHandlerAdapter; -import com.ai.cloud.io.netty.channel.ChannelPipeline; -import com.ai.cloud.io.netty.channel.ChannelPromise; -import com.ai.cloud.io.netty.util.ReferenceCountUtil; -import com.ai.cloud.io.netty.util.internal.TypeParameterMatcher; - - -/** - * {@link ChannelOutboundHandlerAdapter} which encodes message in a stream-like fashion from one message to an - * {@link ByteBuf}. - * - * - * Example implementation which encodes {@link Integer}s to a {@link ByteBuf}. - * - *
- *     public class IntegerEncoder extends {@link MessageToByteEncoder}<{@link Integer}> {
- *         {@code @Override}
- *         public void encode({@link ChannelHandlerContext} ctx, {@link Integer} msg, {@link ByteBuf} out)
- *                 throws {@link Exception} {
- *             out.writeInt(msg);
- *         }
- *     }
- * 
- */ -public abstract class MessageToByteEncoder extends ChannelOutboundHandlerAdapter { - - private final TypeParameterMatcher matcher; - private final boolean preferDirect; - - /** - * @see {@link #MessageToByteEncoder(boolean)} with {@code true} as boolean parameter. - */ - protected MessageToByteEncoder() { - this(true); - } - - /** - * @see {@link #MessageToByteEncoder(Class, boolean)} with {@code true} as boolean value. - */ - protected MessageToByteEncoder(Class outboundMessageType) { - this(outboundMessageType, true); - } - - /** - * Create a new instance which will try to detect the types to match out of the type parameter of the class. - * - * @param preferDirect {@code true} if a direct {@link ByteBuf} should be tried to be used as target for - * the encoded messages. If {@code false} is used it will allocate a heap - * {@link ByteBuf}, which is backed by an byte array. - */ - protected MessageToByteEncoder(boolean preferDirect) { - matcher = TypeParameterMatcher.find(this, MessageToByteEncoder.class, "I"); - this.preferDirect = preferDirect; - } - - /** - * Create a new instance - * - * @param outboundMessageType The tpye of messages to match - * @param preferDirect {@code true} if a direct {@link ByteBuf} should be tried to be used as target for - * the encoded messages. If {@code false} is used it will allocate a heap - * {@link ByteBuf}, which is backed by an byte array. - */ - protected MessageToByteEncoder(Class outboundMessageType, boolean preferDirect) { - matcher = TypeParameterMatcher.get(outboundMessageType); - this.preferDirect = preferDirect; - } - - /** - * Returns {@code true} if the given message should be handled. If {@code false} it will be passed to the next - * {@link ChannelOutboundHandler} in the {@link ChannelPipeline}. - */ - public boolean acceptOutboundMessage(Object msg) throws Exception { - return matcher.match(msg); - } - - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - ByteBuf buf = null; - try { - if (acceptOutboundMessage(msg)) { - @SuppressWarnings("unchecked") - I cast = (I) msg; - buf = allocateBuffer(ctx, cast, preferDirect); - try { - encode(ctx, cast, buf); - } finally { - ReferenceCountUtil.release(cast); - } - - if (buf.isReadable()) { - ctx.write(buf, promise); - } else { - buf.release(); - ctx.write(Unpooled.EMPTY_BUFFER, promise); - } - buf = null; - } else { - ctx.write(msg, promise); - } - } catch (EncoderException e) { - throw e; - } catch (Throwable e) { - throw new EncoderException(e); - } finally { - if (buf != null) { - buf.release(); - } - } - } - - /** - * Allocate a {@link ByteBuf} which will be used as argument of {@link #encode(ChannelHandlerContext, I, ByteBuf)}. - * Sub-classes may override this method to returna {@link ByteBuf} with a perfect matching {@code initialCapacity}. - */ - protected ByteBuf allocateBuffer(ChannelHandlerContext ctx, @SuppressWarnings("unused") I msg, - boolean preferDirect) throws Exception { - if (preferDirect) { - return ctx.alloc().ioBuffer(); - } else { - return ctx.alloc().heapBuffer(); - } - } - - /** - * Encode a message into a {@link ByteBuf}. This method will be called for each written message that can be handled - * by this encoder. - * - * @param ctx the {@link ChannelHandlerContext} which this {@link MessageToByteEncoder} belongs to - * @param msg the message to encode - * @param out the {@link ByteBuf} into which the encoded message will be written - * @throws Exception is thrown if an error accour - */ - protected abstract void encode(ChannelHandlerContext ctx, I msg, ByteBuf out) throws Exception; -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/MessageToMessageCodec.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/MessageToMessageCodec.java deleted file mode 100755 index 4eaebbcfa9..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/MessageToMessageCodec.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec; - -import java.util.List; - -import com.ai.cloud.io.netty.channel.ChannelDuplexHandler; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelPromise; -import com.ai.cloud.io.netty.util.ReferenceCounted; -import com.ai.cloud.io.netty.util.internal.TypeParameterMatcher; - -/** - * A Codec for on-the-fly encoding/decoding of message. - * - * This can be thought of as a combination of {@link MessageToMessageDecoder} and {@link MessageToMessageEncoder}. - * - * Here is an example of a {@link MessageToMessageCodec} which just decode from {@link Integer} to {@link Long} - * and encode from {@link Long} to {@link Integer}. - * - *
- *     public class NumberCodec extends
- *             {@link MessageToMessageCodec}<{@link Integer}, {@link Long}> {
- *         {@code @Override}
- *         public {@link Long} decode({@link ChannelHandlerContext} ctx, {@link Integer} msg, List<Object> out)
- *                 throws {@link Exception} {
- *             out.add(msg.longValue());
- *         }
- *
- *         {@code @Overrride}
- *         public {@link Integer} encode({@link ChannelHandlerContext} ctx, {@link Long} msg, List<Object> out)
- *                 throws {@link Exception} {
- *             out.add(msg.intValue());
- *         }
- *     }
- * 
- * - * Be aware that you need to call {@link ReferenceCounted#retain()} on messages that are just passed through if they - * are of type {@link ReferenceCounted}. This is needed as the {@link MessageToMessageCodec} will call - * {@link ReferenceCounted#release()} on encoded / decoded messages. - */ -public abstract class MessageToMessageCodec extends ChannelDuplexHandler { - - private final MessageToMessageEncoder encoder = new MessageToMessageEncoder() { - - @Override - public boolean acceptOutboundMessage(Object msg) throws Exception { - return MessageToMessageCodec.this.acceptOutboundMessage(msg); - } - - @Override - @SuppressWarnings("unchecked") - protected void encode(ChannelHandlerContext ctx, Object msg, List out) throws Exception { - MessageToMessageCodec.this.encode(ctx, (OUTBOUND_IN) msg, out); - } - }; - - private final MessageToMessageDecoder decoder = new MessageToMessageDecoder() { - - @Override - public boolean acceptInboundMessage(Object msg) throws Exception { - return MessageToMessageCodec.this.acceptInboundMessage(msg); - } - - @Override - @SuppressWarnings("unchecked") - protected void decode(ChannelHandlerContext ctx, Object msg, List out) throws Exception { - MessageToMessageCodec.this.decode(ctx, (INBOUND_IN) msg, out); - } - }; - - private final TypeParameterMatcher inboundMsgMatcher; - private final TypeParameterMatcher outboundMsgMatcher; - - /** - * Create a new instance which will try to detect the types to decode and encode out of the type parameter - * of the class. - */ - protected MessageToMessageCodec() { - inboundMsgMatcher = TypeParameterMatcher.find(this, MessageToMessageCodec.class, "INBOUND_IN"); - outboundMsgMatcher = TypeParameterMatcher.find(this, MessageToMessageCodec.class, "OUTBOUND_IN"); - } - - /** - * Create a new instance. - * - * @param inboundMessageType The type of messages to decode - * @param outboundMessageType The type of messages to encode - */ - protected MessageToMessageCodec( - Class inboundMessageType, Class outboundMessageType) { - inboundMsgMatcher = TypeParameterMatcher.get(inboundMessageType); - outboundMsgMatcher = TypeParameterMatcher.get(outboundMessageType); - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - decoder.channelRead(ctx, msg); - } - - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - encoder.write(ctx, msg, promise); - } - - /** - * Returns {@code true} if and only if the specified message can be decoded by this codec. - * - * @param msg the message - */ - public boolean acceptInboundMessage(Object msg) throws Exception { - return inboundMsgMatcher.match(msg); - } - - /** - * Returns {@code true} if and only if the specified message can be encoded by this codec. - * - * @param msg the message - */ - public boolean acceptOutboundMessage(Object msg) throws Exception { - return outboundMsgMatcher.match(msg); - } - - /** - * @see MessageToMessageEncoder#encode(ChannelHandlerContext, Object, List) - */ - protected abstract void encode(ChannelHandlerContext ctx, OUTBOUND_IN msg, List out) - throws Exception; - - /** - * @see MessageToMessageDecoder#decode(ChannelHandlerContext, Object, List) - */ - protected abstract void decode(ChannelHandlerContext ctx, INBOUND_IN msg, List out) - throws Exception; -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/MessageToMessageDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/MessageToMessageDecoder.java deleted file mode 100755 index 026ef222a4..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/MessageToMessageDecoder.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec; - -import java.util.List; - -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelInboundHandler; -import com.ai.cloud.io.netty.channel.ChannelInboundHandlerAdapter; -import com.ai.cloud.io.netty.channel.ChannelPipeline; -import com.ai.cloud.io.netty.util.ReferenceCountUtil; -import com.ai.cloud.io.netty.util.ReferenceCounted; -import com.ai.cloud.io.netty.util.internal.RecyclableArrayList; -import com.ai.cloud.io.netty.util.internal.TypeParameterMatcher; - -/** - * {@link ChannelInboundHandlerAdapter} which decodes from one message to an other message. - * - * - * For example here is an implementation which decodes a {@link String} to an {@link Integer} which represent - * the length of the {@link String}. - * - *
- *     public class StringToIntegerDecoder extends
- *             {@link MessageToMessageDecoder}<{@link String}> {
- *
- *         {@code @Override}
- *         public void decode({@link ChannelHandlerContext} ctx, {@link String} message,
- *                            List<Object> out) throws {@link Exception} {
- *             out.add(message.length());
- *         }
- *     }
- * 
- * - * Be aware that you need to call {@link ReferenceCounted#retain()} on messages that are just passed through if they - * are of type {@link ReferenceCounted}. This is needed as the {@link MessageToMessageDecoder} will call - * {@link ReferenceCounted#release()} on decoded messages. - * - */ -public abstract class MessageToMessageDecoder extends ChannelInboundHandlerAdapter { - - private final TypeParameterMatcher matcher; - - /** - * Create a new instance which will try to detect the types to match out of the type parameter of the class. - */ - protected MessageToMessageDecoder() { - matcher = TypeParameterMatcher.find(this, MessageToMessageDecoder.class, "I"); - } - - /** - * Create a new instance - * - * @param inboundMessageType The type of messages to match and so decode - */ - protected MessageToMessageDecoder(Class inboundMessageType) { - matcher = TypeParameterMatcher.get(inboundMessageType); - } - - /** - * Returns {@code true} if the given message should be handled. If {@code false} it will be passed to the next - * {@link ChannelInboundHandler} in the {@link ChannelPipeline}. - */ - public boolean acceptInboundMessage(Object msg) throws Exception { - return matcher.match(msg); - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - RecyclableArrayList out = RecyclableArrayList.newInstance(); - try { - if (acceptInboundMessage(msg)) { - @SuppressWarnings("unchecked") - I cast = (I) msg; - try { - decode(ctx, cast, out); - } finally { - ReferenceCountUtil.release(cast); - } - } else { - out.add(msg); - } - } catch (DecoderException e) { - throw e; - } catch (Exception e) { - throw new DecoderException(e); - } finally { - int size = out.size(); - for (int i = 0; i < size; i ++) { - ctx.fireChannelRead(out.get(i)); - } - out.recycle(); - } - } - - /** - * Decode from one message to an other. This method will be called for each written message that can be handled - * by this encoder. - * - * @param ctx the {@link ChannelHandlerContext} which this {@link MessageToMessageDecoder} belongs to - * @param msg the message to decode to an other one - * @param out the {@link List} to which decoded messages should be added - * @throws Exception is thrown if an error accour - */ - protected abstract void decode(ChannelHandlerContext ctx, I msg, List out) throws Exception; -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/MessageToMessageEncoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/MessageToMessageEncoder.java deleted file mode 100755 index fcf4b63605..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/MessageToMessageEncoder.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec; - -import java.util.List; - -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelOutboundHandler; -import com.ai.cloud.io.netty.channel.ChannelOutboundHandlerAdapter; -import com.ai.cloud.io.netty.channel.ChannelPipeline; -import com.ai.cloud.io.netty.channel.ChannelPromise; -import com.ai.cloud.io.netty.util.ReferenceCountUtil; -import com.ai.cloud.io.netty.util.ReferenceCounted; -import com.ai.cloud.io.netty.util.internal.RecyclableArrayList; -import com.ai.cloud.io.netty.util.internal.StringUtil; -import com.ai.cloud.io.netty.util.internal.TypeParameterMatcher; - -/** - * {@link ChannelOutboundHandlerAdapter} which encodes from one message to an other message - * - * For example here is an implementation which decodes an {@link Integer} to an {@link String}. - * - *
- *     public class IntegerToStringEncoder extends
- *             {@link MessageToMessageEncoder}<{@link Integer}> {
- *
- *         {@code @Override}
- *         public void encode({@link ChannelHandlerContext} ctx, {@link Integer} message, List<Object> out)
- *                 throws {@link Exception} {
- *             out.add(message.toString());
- *         }
- *     }
- * 
- * - * Be aware that you need to call {@link ReferenceCounted#retain()} on messages that are just passed through if they - * are of type {@link ReferenceCounted}. This is needed as the {@link MessageToMessageEncoder} will call - * {@link ReferenceCounted#release()} on encoded messages. - */ -public abstract class MessageToMessageEncoder extends ChannelOutboundHandlerAdapter { - - private final TypeParameterMatcher matcher; - - /** - * Create a new instance which will try to detect the types to match out of the type parameter of the class. - */ - protected MessageToMessageEncoder() { - matcher = TypeParameterMatcher.find(this, MessageToMessageEncoder.class, "I"); - } - - /** - * Create a new instance - * - * @param outboundMessageType The type of messages to match and so encode - */ - protected MessageToMessageEncoder(Class outboundMessageType) { - matcher = TypeParameterMatcher.get(outboundMessageType); - } - - /** - * Returns {@code true} if the given message should be handled. If {@code false} it will be passed to the next - * {@link ChannelOutboundHandler} in the {@link ChannelPipeline}. - */ - public boolean acceptOutboundMessage(Object msg) throws Exception { - return matcher.match(msg); - } - - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - RecyclableArrayList out = null; - try { - if (acceptOutboundMessage(msg)) { - out = RecyclableArrayList.newInstance(); - @SuppressWarnings("unchecked") - I cast = (I) msg; - try { - encode(ctx, cast, out); - } finally { - ReferenceCountUtil.release(cast); - } - - if (out.isEmpty()) { - out.recycle(); - out = null; - - throw new EncoderException( - StringUtil.simpleClassName(this) + " must produce at least one message."); - } - } else { - ctx.write(msg, promise); - } - } catch (EncoderException e) { - throw e; - } catch (Throwable t) { - throw new EncoderException(t); - } finally { - if (out != null) { - final int sizeMinusOne = out.size() - 1; - if (sizeMinusOne == 0) { - ctx.write(out.get(0), promise); - } else if (sizeMinusOne > 0) { - // Check if we can use a voidPromise for our extra writes to reduce GC-Pressure - // See https://github.com/netty/netty/issues/2525 - ChannelPromise voidPromise = ctx.voidPromise(); - boolean isVoidPromise = promise == voidPromise; - for (int i = 0; i < sizeMinusOne; i ++) { - ChannelPromise p; - if (isVoidPromise) { - p = voidPromise; - } else { - p = ctx.newPromise(); - } - ctx.write(out.get(i), p); - } - ctx.write(out.get(sizeMinusOne), promise); - } - out.recycle(); - } - } - } - - /** - * Encode from one message to an other. This method will be called for each written message that can be handled - * by this encoder. - * - * @param ctx the {@link ChannelHandlerContext} which this {@link MessageToMessageEncoder} belongs to - * @param msg the message to encode to an other one - * @param out the {@link List} into which the encoded msg should be added - * needs to do some kind of aggragation - * @throws Exception is thrown if an error accour - */ - protected abstract void encode(ChannelHandlerContext ctx, I msg, List out) throws Exception; -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/PrematureChannelClosureException.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/PrematureChannelClosureException.java deleted file mode 100755 index cb46ccf75f..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/PrematureChannelClosureException.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec; - -import com.ai.cloud.io.netty.channel.Channel; - -/** - * A {@link CodecException} which is thrown when a {@link Channel} is closed unexpectedly before - * the codec finishes handling the current message, such as missing response while waiting for a - * request. - */ -public class PrematureChannelClosureException extends CodecException { - - private static final long serialVersionUID = 4907642202594703094L; - - /** - * Creates a new instance. - */ - public PrematureChannelClosureException() { } - - /** - * Creates a new instance. - */ - public PrematureChannelClosureException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Creates a new instance. - */ - public PrematureChannelClosureException(String message) { - super(message); - } - - /** - * Creates a new instance. - */ - public PrematureChannelClosureException(Throwable cause) { - super(cause); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/ProtocolDetectionResult.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/ProtocolDetectionResult.java deleted file mode 100755 index a89f6040df..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/ProtocolDetectionResult.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec; - -import static com.ai.cloud.io.netty.util.internal.ObjectUtil.checkNotNull; - -/** - * Result of detecting a protocol. - * - * @param the type of the protocol - */ -public final class ProtocolDetectionResult { - - @SuppressWarnings({ "rawtypes", "unchecked" }) - private static final ProtocolDetectionResult NEEDS_MORE_DATE = - new ProtocolDetectionResult(ProtocolDetectionState.NEEDS_MORE_DATA, null); - @SuppressWarnings({ "rawtypes", "unchecked" }) - private static final ProtocolDetectionResult INVALID = - new ProtocolDetectionResult(ProtocolDetectionState.INVALID, null); - - private final ProtocolDetectionState state; - private final T result; - - /** - * Returns a {@link ProtocolDetectionResult} that signals that more data is needed to detect the protocol. - */ - @SuppressWarnings("unchecked") - public static ProtocolDetectionResult needsMoreData() { - return NEEDS_MORE_DATE; - } - - /** - * Returns a {@link ProtocolDetectionResult} that signals the data was invalid for the protocol. - */ - @SuppressWarnings("unchecked") - public static ProtocolDetectionResult invalid() { - return INVALID; - } - - /** - * Returns a {@link ProtocolDetectionResult} which holds the detected protocol. - */ - @SuppressWarnings("unchecked") - public static ProtocolDetectionResult detected(T protocol) { - return new ProtocolDetectionResult(ProtocolDetectionState.DETECTED, checkNotNull(protocol, "protocol")); - } - - private ProtocolDetectionResult(ProtocolDetectionState state, T result) { - this.state = state; - this.result = result; - } - - /** - * Return the {@link ProtocolDetectionState}. If the state is {@link ProtocolDetectionState#DETECTED} you - * can retrieve the protocol via {@link #detectedProtocol()}. - */ - public ProtocolDetectionState state() { - return state; - } - - /** - * Returns the protocol if {@link #state()} returns {@link ProtocolDetectionState#DETECTED}, otherwise {@code null}. - */ - public T detectedProtocol() { - return result; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/ProtocolDetectionState.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/ProtocolDetectionState.java deleted file mode 100755 index c0c7be3057..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/ProtocolDetectionState.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec; - -/** - * The state of the current detection. - */ -public enum ProtocolDetectionState { - /** - * Need more data to detect the protocol. - */ - NEEDS_MORE_DATA, - - /** - * The data was invalid. - */ - INVALID, - - /** - * Protocol was detected, - */ - DETECTED -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/ReplayingDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/ReplayingDecoder.java deleted file mode 100755 index 2c7d4cf139..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/ReplayingDecoder.java +++ /dev/null @@ -1,434 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec; - -import java.util.List; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelHandler; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelPipeline; -import com.ai.cloud.io.netty.util.Signal; -import com.ai.cloud.io.netty.util.internal.RecyclableArrayList; -import com.ai.cloud.io.netty.util.internal.StringUtil; - -/** - * A specialized variation of {@link ByteToMessageDecoder} which enables implementation - * of a non-blocking decoder in the blocking I/O paradigm. - *

- * The biggest difference between {@link ReplayingDecoder} and - * {@link ByteToMessageDecoder} is that {@link ReplayingDecoder} allows you to - * implement the {@code decode()} and {@code decodeLast()} methods just like - * all required bytes were received already, rather than checking the - * availability of the required bytes. For example, the following - * {@link ByteToMessageDecoder} implementation: - *

- * public class IntegerHeaderFrameDecoder extends {@link ByteToMessageDecoder} {
- *
- *   {@code @Override}
- *   protected void decode({@link ChannelHandlerContext} ctx,
- *                           {@link ByteBuf} buf, List<Object> out) throws Exception {
- *
- *     if (buf.readableBytes() < 4) {
- *        return;
- *     }
- *
- *     buf.markReaderIndex();
- *     int length = buf.readInt();
- *
- *     if (buf.readableBytes() < length) {
- *        buf.resetReaderIndex();
- *        return;
- *     }
- *
- *     out.add(buf.readBytes(length));
- *   }
- * }
- * 
- * is simplified like the following with {@link ReplayingDecoder}: - *
- * public class IntegerHeaderFrameDecoder
- *      extends {@link ReplayingDecoder}<{@link Void}> {
- *
- *   protected void decode({@link ChannelHandlerContext} ctx,
- *                           {@link ByteBuf} buf) throws Exception {
- *
- *     out.add(buf.readBytes(buf.readInt()));
- *   }
- * }
- * 
- * - *

How does this work?

- *

- * {@link ReplayingDecoder} passes a specialized {@link ByteBuf} - * implementation which throws an {@link Error} of certain type when there's not - * enough data in the buffer. In the {@code IntegerHeaderFrameDecoder} above, - * you just assumed that there will be 4 or more bytes in the buffer when - * you call {@code buf.readInt()}. If there's really 4 bytes in the buffer, - * it will return the integer header as you expected. Otherwise, the - * {@link Error} will be raised and the control will be returned to - * {@link ReplayingDecoder}. If {@link ReplayingDecoder} catches the - * {@link Error}, then it will rewind the {@code readerIndex} of the buffer - * back to the 'initial' position (i.e. the beginning of the buffer) and call - * the {@code decode(..)} method again when more data is received into the - * buffer. - *

- * Please note that {@link ReplayingDecoder} always throws the same cached - * {@link Error} instance to avoid the overhead of creating a new {@link Error} - * and filling its stack trace for every throw. - * - *

Limitations

- *

- * At the cost of the simplicity, {@link ReplayingDecoder} enforces you a few - * limitations: - *

    - *
  • Some buffer operations are prohibited.
  • - *
  • Performance can be worse if the network is slow and the message - * format is complicated unlike the example above. In this case, your - * decoder might have to decode the same part of the message over and over - * again.
  • - *
  • You must keep in mind that {@code decode(..)} method can be called many - * times to decode a single message. For example, the following code will - * not work: - *
     public class MyDecoder extends {@link ReplayingDecoder}<{@link Void}> {
    - *
    - *   private final Queue<Integer> values = new LinkedList<Integer>();
    - *
    - *   {@code @Override}
    - *   public void decode(.., {@link ByteBuf} buf, List<Object> out) throws Exception {
    - *
    - *     // A message contains 2 integers.
    - *     values.offer(buf.readInt());
    - *     values.offer(buf.readInt());
    - *
    - *     // This assertion will fail intermittently since values.offer()
    - *     // can be called more than two times!
    - *     assert values.size() == 2;
    - *     out.add(values.poll() + values.poll());
    - *   }
    - * }
    - * The correct implementation looks like the following, and you can also - * utilize the 'checkpoint' feature which is explained in detail in the - * next section. - *
     public class MyDecoder extends {@link ReplayingDecoder}<{@link Void}> {
    - *
    - *   private final Queue<Integer> values = new LinkedList<Integer>();
    - *
    - *   {@code @Override}
    - *   public void decode(.., {@link ByteBuf} buf, List<Object> out) throws Exception {
    - *
    - *     // Revert the state of the variable that might have been changed
    - *     // since the last partial decode.
    - *     values.clear();
    - *
    - *     // A message contains 2 integers.
    - *     values.offer(buf.readInt());
    - *     values.offer(buf.readInt());
    - *
    - *     // Now we know this assertion will never fail.
    - *     assert values.size() == 2;
    - *     out.add(values.poll() + values.poll());
    - *   }
    - * }
    - *
  • - *
- * - *

Improving the performance

- *

- * Fortunately, the performance of a complex decoder implementation can be - * improved significantly with the {@code checkpoint()} method. The - * {@code checkpoint()} method updates the 'initial' position of the buffer so - * that {@link ReplayingDecoder} rewinds the {@code readerIndex} of the buffer - * to the last position where you called the {@code checkpoint()} method. - * - *

Calling {@code checkpoint(T)} with an {@link Enum}

- *

- * Although you can just use {@code checkpoint()} method and manage the state - * of the decoder by yourself, the easiest way to manage the state of the - * decoder is to create an {@link Enum} type which represents the current state - * of the decoder and to call {@code checkpoint(T)} method whenever the state - * changes. You can have as many states as you want depending on the - * complexity of the message you want to decode: - * - *

- * public enum MyDecoderState {
- *   READ_LENGTH,
- *   READ_CONTENT;
- * }
- *
- * public class IntegerHeaderFrameDecoder
- *      extends {@link ReplayingDecoder}<MyDecoderState> {
- *
- *   private int length;
- *
- *   public IntegerHeaderFrameDecoder() {
- *     // Set the initial state.
- *     super(MyDecoderState.READ_LENGTH);
- *   }
- *
- *   {@code @Override}
- *   protected void decode({@link ChannelHandlerContext} ctx,
- *                           {@link ByteBuf} buf, List<Object> out) throws Exception {
- *     switch (state()) {
- *     case READ_LENGTH:
- *       length = buf.readInt();
- *       checkpoint(MyDecoderState.READ_CONTENT);
- *     case READ_CONTENT:
- *       ByteBuf frame = buf.readBytes(length);
- *       checkpoint(MyDecoderState.READ_LENGTH);
- *       out.add(frame);
- *       break;
- *     default:
- *       throw new Error("Shouldn't reach here.");
- *     }
- *   }
- * }
- * 
- * - *

Calling {@code checkpoint()} with no parameter

- *

- * An alternative way to manage the decoder state is to manage it by yourself. - *

- * public class IntegerHeaderFrameDecoder
- *      extends {@link ReplayingDecoder}<{@link Void}> {
- *
- *   private boolean readLength;
- *   private int length;
- *
- *   {@code @Override}
- *   protected void decode({@link ChannelHandlerContext} ctx,
- *                           {@link ByteBuf} buf, List<Object> out) throws Exception {
- *     if (!readLength) {
- *       length = buf.readInt();
- *       readLength = true;
- *       checkpoint();
- *     }
- *
- *     if (readLength) {
- *       ByteBuf frame = buf.readBytes(length);
- *       readLength = false;
- *       checkpoint();
- *       out.add(frame);
- *     }
- *   }
- * }
- * 
- * - *

Replacing a decoder with another decoder in a pipeline

- *

- * If you are going to write a protocol multiplexer, you will probably want to - * replace a {@link ReplayingDecoder} (protocol detector) with another - * {@link ReplayingDecoder}, {@link ByteToMessageDecoder} or {@link MessageToMessageDecoder} - * (actual protocol decoder). - * It is not possible to achieve this simply by calling - * {@link ChannelPipeline#replace(ChannelHandler, String, ChannelHandler)}, but - * some additional steps are required: - *

- * public class FirstDecoder extends {@link ReplayingDecoder}<{@link Void}> {
- *
- *     {@code @Override}
- *     protected void decode({@link ChannelHandlerContext} ctx,
- *                             {@link ByteBuf} buf, List<Object> out) {
- *         ...
- *         // Decode the first message
- *         Object firstMessage = ...;
- *
- *         // Add the second decoder
- *         ctx.pipeline().addLast("second", new SecondDecoder());
- *
- *         if (buf.isReadable()) {
- *             // Hand off the remaining data to the second decoder
- *             out.add(firstMessage);
- *             out.add(buf.readBytes(super.actualReadableBytes()));
- *         } else {
- *             // Nothing to hand off
- *             out.add(firstMessage);
- *         }
- *         // Remove the first decoder (me)
- *         ctx.pipeline().remove(this);
- *     }
- * 
- * @param - * the state type which is usually an {@link Enum}; use {@link Void} if state management is - * unused - */ -public abstract class ReplayingDecoder extends ByteToMessageDecoder { - - static final Signal REPLAY = Signal.valueOf(ReplayingDecoder.class.getName() + ".REPLAY"); - - private final ReplayingDecoderByteBuf replayable = new ReplayingDecoderByteBuf(); - private S state; - private int checkpoint = -1; - - /** - * Creates a new instance with no initial state (i.e: {@code null}). - */ - protected ReplayingDecoder() { - this(null); - } - - /** - * Creates a new instance with the specified initial state. - */ - protected ReplayingDecoder(S initialState) { - state = initialState; - } - - /** - * Stores the internal cumulative buffer's reader position. - */ - protected void checkpoint() { - checkpoint = internalBuffer().readerIndex(); - } - - /** - * Stores the internal cumulative buffer's reader position and updates - * the current decoder state. - */ - protected void checkpoint(S state) { - checkpoint(); - state(state); - } - - /** - * Returns the current state of this decoder. - * @return the current state of this decoder - */ - protected S state() { - return state; - } - - /** - * Sets the current state of this decoder. - * @return the old state of this decoder - */ - protected S state(S newState) { - S oldState = state; - state = newState; - return oldState; - } - - @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { - RecyclableArrayList out = RecyclableArrayList.newInstance(); - try { - replayable.terminate(); - callDecode(ctx, internalBuffer(), out); - decodeLast(ctx, replayable, out); - } catch (Signal replay) { - // Ignore - replay.expect(REPLAY); - } catch (DecoderException e) { - throw e; - } catch (Exception e) { - throw new DecoderException(e); - } finally { - try { - if (cumulation != null) { - cumulation.release(); - cumulation = null; - } - - int size = out.size(); - if (size > 0) { - fireChannelRead(ctx, out, size); - // Something was read, call fireChannelReadComplete() - ctx.fireChannelReadComplete(); - } - ctx.fireChannelInactive(); - } finally { - // recycle in all cases - out.recycle(); - } - } - } - - @Override - protected void callDecode(ChannelHandlerContext ctx, ByteBuf in, List out) { - replayable.setCumulation(in); - try { - while (in.isReadable()) { - int oldReaderIndex = checkpoint = in.readerIndex(); - int outSize = out.size(); - - if (outSize > 0) { - fireChannelRead(ctx, out, outSize); - out.clear(); - outSize = 0; - } - - S oldState = state; - int oldInputLength = in.readableBytes(); - try { - decode(ctx, replayable, out); - - // Check if this handler was removed before continuing the loop. - // If it was removed, it is not safe to continue to operate on the buffer. - // - // See https://github.com/netty/netty/issues/1664 - if (ctx.isRemoved()) { - break; - } - - if (outSize == out.size()) { - if (oldInputLength == in.readableBytes() && oldState == state) { - throw new DecoderException( - StringUtil.simpleClassName(getClass()) + ".decode() must consume the inbound " + - "data or change its state if it did not decode anything."); - } else { - // Previous data has been discarded or caused state transition. - // Probably it is reading on. - continue; - } - } - } catch (Signal replay) { - replay.expect(REPLAY); - - // Check if this handler was removed before continuing the loop. - // If it was removed, it is not safe to continue to operate on the buffer. - // - // See https://github.com/netty/netty/issues/1664 - if (ctx.isRemoved()) { - break; - } - - // Return to the checkpoint (or oldPosition) and retry. - int checkpoint = this.checkpoint; - if (checkpoint >= 0) { - in.readerIndex(checkpoint); - } else { - // Called by cleanup() - no need to maintain the readerIndex - // anymore because the buffer has been released already. - } - break; - } - - if (oldReaderIndex == in.readerIndex() && oldState == state) { - throw new DecoderException( - StringUtil.simpleClassName(getClass()) + ".decode() method must consume the inbound data " + - "or change its state if it decoded something."); - } - if (isSingleDecode()) { - break; - } - } - } catch (DecoderException e) { - throw e; - } catch (Throwable cause) { - throw new DecoderException(cause); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/ReplayingDecoderByteBuf.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/ReplayingDecoderByteBuf.java deleted file mode 100755 index 2cd02dc178..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/ReplayingDecoderByteBuf.java +++ /dev/null @@ -1,1006 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec; - -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; -import java.nio.charset.Charset; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.ByteBufAllocator; -import com.ai.cloud.io.netty.buffer.ByteBufProcessor; -import com.ai.cloud.io.netty.buffer.SwappedByteBuf; -import com.ai.cloud.io.netty.buffer.Unpooled; -import com.ai.cloud.io.netty.util.Signal; -import com.ai.cloud.io.netty.util.internal.StringUtil; - -/** - * Special {@link ByteBuf} implementation which is used by the {@link ReplayingDecoder} - */ -final class ReplayingDecoderByteBuf extends ByteBuf { - - private static final Signal REPLAY = ReplayingDecoder.REPLAY; - - private ByteBuf buffer; - private boolean terminated; - private SwappedByteBuf swapped; - - static final ReplayingDecoderByteBuf EMPTY_BUFFER = new ReplayingDecoderByteBuf(Unpooled.EMPTY_BUFFER); - - static { - EMPTY_BUFFER.terminate(); - } - - ReplayingDecoderByteBuf() { } - - ReplayingDecoderByteBuf(ByteBuf buffer) { - setCumulation(buffer); - } - - void setCumulation(ByteBuf buffer) { - this.buffer = buffer; - } - - void terminate() { - terminated = true; - } - - @Override - public int capacity() { - if (terminated) { - return buffer.capacity(); - } else { - return Integer.MAX_VALUE; - } - } - - @Override - public ByteBuf capacity(int newCapacity) { - reject(); - return this; - } - - @Override - public int maxCapacity() { - return capacity(); - } - - @Override - public ByteBufAllocator alloc() { - return buffer.alloc(); - } - - @Override - public boolean isDirect() { - return buffer.isDirect(); - } - - @Override - public boolean hasArray() { - return false; - } - - @Override - public byte[] array() { - throw new UnsupportedOperationException(); - } - - @Override - public int arrayOffset() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean hasMemoryAddress() { - return false; - } - - @Override - public long memoryAddress() { - throw new UnsupportedOperationException(); - } - - @Override - public ByteBuf clear() { - reject(); - return this; - } - - @Override - public boolean equals(Object obj) { - return this == obj; - } - - @Override - public int compareTo(ByteBuf buffer) { - reject(); - return 0; - } - - @Override - public ByteBuf copy() { - reject(); - return this; - } - - @Override - public ByteBuf copy(int index, int length) { - checkIndex(index, length); - return buffer.copy(index, length); - } - - @Override - public ByteBuf discardReadBytes() { - reject(); - return this; - } - - @Override - public ByteBuf ensureWritable(int writableBytes) { - reject(); - return this; - } - - @Override - public int ensureWritable(int minWritableBytes, boolean force) { - reject(); - return 0; - } - - @Override - public ByteBuf duplicate() { - reject(); - return this; - } - - @Override - public boolean getBoolean(int index) { - checkIndex(index, 1); - return buffer.getBoolean(index); - } - - @Override - public byte getByte(int index) { - checkIndex(index, 1); - return buffer.getByte(index); - } - - @Override - public short getUnsignedByte(int index) { - checkIndex(index, 1); - return buffer.getUnsignedByte(index); - } - - @Override - public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - checkIndex(index, length); - buffer.getBytes(index, dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, byte[] dst) { - checkIndex(index, dst.length); - buffer.getBytes(index, dst); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuffer dst) { - reject(); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - checkIndex(index, length); - buffer.getBytes(index, dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst, int length) { - reject(); - return this; - } - - @Override - public ByteBuf getBytes(int index, ByteBuf dst) { - reject(); - return this; - } - - @Override - public int getBytes(int index, GatheringByteChannel out, int length) { - reject(); - return 0; - } - - @Override - public ByteBuf getBytes(int index, OutputStream out, int length) { - reject(); - return this; - } - - @Override - public int getInt(int index) { - checkIndex(index, 4); - return buffer.getInt(index); - } - - @Override - public long getUnsignedInt(int index) { - checkIndex(index, 4); - return buffer.getUnsignedInt(index); - } - - @Override - public long getLong(int index) { - checkIndex(index, 8); - return buffer.getLong(index); - } - - @Override - public int getMedium(int index) { - checkIndex(index, 3); - return buffer.getMedium(index); - } - - @Override - public int getUnsignedMedium(int index) { - checkIndex(index, 3); - return buffer.getUnsignedMedium(index); - } - - @Override - public short getShort(int index) { - checkIndex(index, 2); - return buffer.getShort(index); - } - - @Override - public int getUnsignedShort(int index) { - checkIndex(index, 2); - return buffer.getUnsignedShort(index); - } - - @Override - public char getChar(int index) { - checkIndex(index, 2); - return buffer.getChar(index); - } - - @Override - public float getFloat(int index) { - checkIndex(index, 4); - return buffer.getFloat(index); - } - - @Override - public double getDouble(int index) { - checkIndex(index, 8); - return buffer.getDouble(index); - } - - @Override - public int hashCode() { - reject(); - return 0; - } - - @Override - public int indexOf(int fromIndex, int toIndex, byte value) { - if (fromIndex == toIndex) { - return -1; - } - - if (Math.max(fromIndex, toIndex) > buffer.writerIndex()) { - throw REPLAY; - } - - return buffer.indexOf(fromIndex, toIndex, value); - } - - @Override - public int bytesBefore(byte value) { - int bytes = buffer.bytesBefore(value); - if (bytes < 0) { - throw REPLAY; - } - return bytes; - } - - @Override - public int bytesBefore(int length, byte value) { - final int readerIndex = buffer.readerIndex(); - return bytesBefore(readerIndex, buffer.writerIndex() - readerIndex, value); - } - - @Override - public int bytesBefore(int index, int length, byte value) { - final int writerIndex = buffer.writerIndex(); - if (index >= writerIndex) { - throw REPLAY; - } - - if (index <= writerIndex - length) { - return buffer.bytesBefore(index, length, value); - } - - int res = buffer.bytesBefore(index, writerIndex - index, value); - if (res < 0) { - throw REPLAY; - } else { - return res; - } - } - - @Override - public int forEachByte(ByteBufProcessor processor) { - int ret = buffer.forEachByte(processor); - if (ret < 0) { - throw REPLAY; - } else { - return ret; - } - } - - @Override - public int forEachByte(int index, int length, ByteBufProcessor processor) { - final int writerIndex = buffer.writerIndex(); - if (index >= writerIndex) { - throw REPLAY; - } - - if (index <= writerIndex - length) { - return buffer.forEachByte(index, length, processor); - } - - int ret = buffer.forEachByte(index, writerIndex - index, processor); - if (ret < 0) { - throw REPLAY; - } else { - return ret; - } - } - - @Override - public int forEachByteDesc(ByteBufProcessor processor) { - if (terminated) { - return buffer.forEachByteDesc(processor); - } else { - reject(); - return 0; - } - } - - @Override - public int forEachByteDesc(int index, int length, ByteBufProcessor processor) { - if (index + length > buffer.writerIndex()) { - throw REPLAY; - } - - return buffer.forEachByteDesc(index, length, processor); - } - - @Override - public ByteBuf markReaderIndex() { - buffer.markReaderIndex(); - return this; - } - - @Override - public ByteBuf markWriterIndex() { - reject(); - return this; - } - - @Override - public ByteOrder order() { - return buffer.order(); - } - - @Override - public ByteBuf order(ByteOrder endianness) { - if (endianness == null) { - throw new NullPointerException("endianness"); - } - if (endianness == order()) { - return this; - } - - SwappedByteBuf swapped = this.swapped; - if (swapped == null) { - this.swapped = swapped = new SwappedByteBuf(this); - } - return swapped; - } - - @Override - public boolean isReadable() { - return terminated? buffer.isReadable() : true; - } - - @Override - public boolean isReadable(int size) { - return terminated? buffer.isReadable(size) : true; - } - - @Override - public int readableBytes() { - if (terminated) { - return buffer.readableBytes(); - } else { - return Integer.MAX_VALUE - buffer.readerIndex(); - } - } - - @Override - public boolean readBoolean() { - checkReadableBytes(1); - return buffer.readBoolean(); - } - - @Override - public byte readByte() { - checkReadableBytes(1); - return buffer.readByte(); - } - - @Override - public short readUnsignedByte() { - checkReadableBytes(1); - return buffer.readUnsignedByte(); - } - - @Override - public ByteBuf readBytes(byte[] dst, int dstIndex, int length) { - checkReadableBytes(length); - buffer.readBytes(dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf readBytes(byte[] dst) { - checkReadableBytes(dst.length); - buffer.readBytes(dst); - return this; - } - - @Override - public ByteBuf readBytes(ByteBuffer dst) { - reject(); - return this; - } - - @Override - public ByteBuf readBytes(ByteBuf dst, int dstIndex, int length) { - checkReadableBytes(length); - buffer.readBytes(dst, dstIndex, length); - return this; - } - - @Override - public ByteBuf readBytes(ByteBuf dst, int length) { - reject(); - return this; - } - - @Override - public ByteBuf readBytes(ByteBuf dst) { - checkReadableBytes(dst.writableBytes()); - buffer.readBytes(dst); - return this; - } - - @Override - public int readBytes(GatheringByteChannel out, int length) { - reject(); - return 0; - } - - @Override - public ByteBuf readBytes(int length) { - checkReadableBytes(length); - return buffer.readBytes(length); - } - - @Override - public ByteBuf readSlice(int length) { - checkReadableBytes(length); - return buffer.readSlice(length); - } - - @Override - public ByteBuf readBytes(OutputStream out, int length) { - reject(); - return this; - } - - @Override - public int readerIndex() { - return buffer.readerIndex(); - } - - @Override - public ByteBuf readerIndex(int readerIndex) { - buffer.readerIndex(readerIndex); - return this; - } - - @Override - public int readInt() { - checkReadableBytes(4); - return buffer.readInt(); - } - - @Override - public long readUnsignedInt() { - checkReadableBytes(4); - return buffer.readUnsignedInt(); - } - - @Override - public long readLong() { - checkReadableBytes(8); - return buffer.readLong(); - } - - @Override - public int readMedium() { - checkReadableBytes(3); - return buffer.readMedium(); - } - - @Override - public int readUnsignedMedium() { - checkReadableBytes(3); - return buffer.readUnsignedMedium(); - } - - @Override - public short readShort() { - checkReadableBytes(2); - return buffer.readShort(); - } - - @Override - public int readUnsignedShort() { - checkReadableBytes(2); - return buffer.readUnsignedShort(); - } - - @Override - public char readChar() { - checkReadableBytes(2); - return buffer.readChar(); - } - - @Override - public float readFloat() { - checkReadableBytes(4); - return buffer.readFloat(); - } - - @Override - public double readDouble() { - checkReadableBytes(8); - return buffer.readDouble(); - } - - @Override - public ByteBuf resetReaderIndex() { - buffer.resetReaderIndex(); - return this; - } - - @Override - public ByteBuf resetWriterIndex() { - reject(); - return this; - } - - @Override - public ByteBuf setBoolean(int index, boolean value) { - reject(); - return this; - } - - @Override - public ByteBuf setByte(int index, int value) { - reject(); - return this; - } - - @Override - public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { - reject(); - return this; - } - - @Override - public ByteBuf setBytes(int index, byte[] src) { - reject(); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuffer src) { - reject(); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { - reject(); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src, int length) { - reject(); - return this; - } - - @Override - public ByteBuf setBytes(int index, ByteBuf src) { - reject(); - return this; - } - - @Override - public int setBytes(int index, InputStream in, int length) { - reject(); - return 0; - } - - @Override - public ByteBuf setZero(int index, int length) { - reject(); - return this; - } - - @Override - public int setBytes(int index, ScatteringByteChannel in, int length) { - reject(); - return 0; - } - - @Override - public ByteBuf setIndex(int readerIndex, int writerIndex) { - reject(); - return this; - } - - @Override - public ByteBuf setInt(int index, int value) { - reject(); - return this; - } - - @Override - public ByteBuf setLong(int index, long value) { - reject(); - return this; - } - - @Override - public ByteBuf setMedium(int index, int value) { - reject(); - return this; - } - - @Override - public ByteBuf setShort(int index, int value) { - reject(); - return this; - } - - @Override - public ByteBuf setChar(int index, int value) { - reject(); - return this; - } - - @Override - public ByteBuf setFloat(int index, float value) { - reject(); - return this; - } - - @Override - public ByteBuf setDouble(int index, double value) { - reject(); - return this; - } - - @Override - public ByteBuf skipBytes(int length) { - checkReadableBytes(length); - buffer.skipBytes(length); - return this; - } - - @Override - public ByteBuf slice() { - reject(); - return this; - } - - @Override - public ByteBuf slice(int index, int length) { - checkIndex(index, length); - return buffer.slice(index, length); - } - - @Override - public int nioBufferCount() { - return buffer.nioBufferCount(); - } - - @Override - public ByteBuffer nioBuffer() { - reject(); - return null; - } - - @Override - public ByteBuffer nioBuffer(int index, int length) { - checkIndex(index, length); - return buffer.nioBuffer(index, length); - } - - @Override - public ByteBuffer[] nioBuffers() { - reject(); - return null; - } - - @Override - public ByteBuffer[] nioBuffers(int index, int length) { - checkIndex(index, length); - return buffer.nioBuffers(index, length); - } - - @Override - public ByteBuffer internalNioBuffer(int index, int length) { - checkIndex(index, length); - return buffer.internalNioBuffer(index, length); - } - - @Override - public String toString(int index, int length, Charset charset) { - checkIndex(index, length); - return buffer.toString(index, length, charset); - } - - @Override - public String toString(Charset charsetName) { - reject(); - return null; - } - - @Override - public String toString() { - return StringUtil.simpleClassName(this) + '(' + - "ridx=" + - readerIndex() + - ", " + - "widx=" + - writerIndex() + - ')'; - } - - @Override - public boolean isWritable() { - return false; - } - - @Override - public boolean isWritable(int size) { - return false; - } - - @Override - public int writableBytes() { - return 0; - } - - @Override - public int maxWritableBytes() { - return 0; - } - - @Override - public ByteBuf writeBoolean(boolean value) { - reject(); - return this; - } - - @Override - public ByteBuf writeByte(int value) { - reject(); - return this; - } - - @Override - public ByteBuf writeBytes(byte[] src, int srcIndex, int length) { - reject(); - return this; - } - - @Override - public ByteBuf writeBytes(byte[] src) { - reject(); - return this; - } - - @Override - public ByteBuf writeBytes(ByteBuffer src) { - reject(); - return this; - } - - @Override - public ByteBuf writeBytes(ByteBuf src, int srcIndex, int length) { - reject(); - return this; - } - - @Override - public ByteBuf writeBytes(ByteBuf src, int length) { - reject(); - return this; - } - - @Override - public ByteBuf writeBytes(ByteBuf src) { - reject(); - return this; - } - - @Override - public int writeBytes(InputStream in, int length) { - reject(); - return 0; - } - - @Override - public int writeBytes(ScatteringByteChannel in, int length) { - reject(); - return 0; - } - - @Override - public ByteBuf writeInt(int value) { - reject(); - return this; - } - - @Override - public ByteBuf writeLong(long value) { - reject(); - return this; - } - - @Override - public ByteBuf writeMedium(int value) { - reject(); - return this; - } - - @Override - public ByteBuf writeZero(int length) { - reject(); - return this; - } - - @Override - public int writerIndex() { - return buffer.writerIndex(); - } - - @Override - public ByteBuf writerIndex(int writerIndex) { - reject(); - return this; - } - - @Override - public ByteBuf writeShort(int value) { - reject(); - return this; - } - - @Override - public ByteBuf writeChar(int value) { - reject(); - return this; - } - - @Override - public ByteBuf writeFloat(float value) { - reject(); - return this; - } - - @Override - public ByteBuf writeDouble(double value) { - reject(); - return this; - } - - private void checkIndex(int index, int length) { - if (index + length > buffer.writerIndex()) { - throw REPLAY; - } - } - - private void checkReadableBytes(int readableBytes) { - if (buffer.readableBytes() < readableBytes) { - throw REPLAY; - } - } - - @Override - public ByteBuf discardSomeReadBytes() { - reject(); - return this; - } - - @Override - public int refCnt() { - return buffer.refCnt(); - } - - @Override - public ByteBuf retain() { - reject(); - return this; - } - - @Override - public ByteBuf retain(int increment) { - reject(); - return this; - } - - @Override - public boolean release() { - reject(); - return false; - } - - @Override - public boolean release(int decrement) { - reject(); - return false; - } - - @Override - public ByteBuf unwrap() { - reject(); - return this; - } - - private static void reject() { - throw new UnsupportedOperationException("not a replayable operation"); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/TooLongFrameException.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/TooLongFrameException.java deleted file mode 100755 index 071a9a7e53..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/TooLongFrameException.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec; - -/** - * An {@link DecoderException} which is thrown when the length of the frame - * decoded is greater than the allowed maximum. - */ -public class TooLongFrameException extends DecoderException { - - private static final long serialVersionUID = -1995801950698951640L; - - /** - * Creates a new instance. - */ - public TooLongFrameException() { - } - - /** - * Creates a new instance. - */ - public TooLongFrameException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Creates a new instance. - */ - public TooLongFrameException(String message) { - super(message); - } - - /** - * Creates a new instance. - */ - public TooLongFrameException(Throwable cause) { - super(cause); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/UnsupportedMessageTypeException.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/UnsupportedMessageTypeException.java deleted file mode 100755 index 7a29160c4c..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/UnsupportedMessageTypeException.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec; - -/** - * Thrown if an unsupported message is received by an codec. - */ -public class UnsupportedMessageTypeException extends CodecException { - - private static final long serialVersionUID = 2799598826487038726L; - - public UnsupportedMessageTypeException( - Object message, Class... expectedTypes) { - super(message( - message == null? "null" : message.getClass().getName(), expectedTypes)); - } - - public UnsupportedMessageTypeException() { } - - public UnsupportedMessageTypeException(String message, Throwable cause) { - super(message, cause); - } - - public UnsupportedMessageTypeException(String s) { - super(s); - } - - public UnsupportedMessageTypeException(Throwable cause) { - super(cause); - } - - private static String message( - String actualType, Class... expectedTypes) { - StringBuilder buf = new StringBuilder(actualType); - - if (expectedTypes != null && expectedTypes.length > 0) { - buf.append(" (expected: ").append(expectedTypes[0].getName()); - for (int i = 1; i < expectedTypes.length; i ++) { - Class t = expectedTypes[i]; - if (t == null) { - break; - } - buf.append(", ").append(t.getName()); - } - buf.append(')'); - } - - return buf.toString(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/base64/Base64.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/base64/Base64.java deleted file mode 100755 index 33a568d6d1..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/base64/Base64.java +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -/* - * Written by Robert Harder and released to the public domain, as explained at - * http://creativecommons.org/licenses/publicdomain - */ -package com.ai.cloud.io.netty.handler.codec.base64; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.Unpooled; - -/** - * Utility class for {@link ByteBuf} that encodes and decodes to and from - * Base64 notation. - *

- * The encoding and decoding algorithm in this class has been derived from - * Robert Harder's Public Domain - * Base64 Encoder/Decoder. - */ -public final class Base64 { - - /** Maximum line length (76) of Base64 output. */ - private static final int MAX_LINE_LENGTH = 76; - - /** The equals sign (=) as a byte. */ - private static final byte EQUALS_SIGN = (byte) '='; - - /** The new line character (\n) as a byte. */ - private static final byte NEW_LINE = (byte) '\n'; - - private static final byte WHITE_SPACE_ENC = -5; // Indicates white space in encoding - - private static final byte EQUALS_SIGN_ENC = -1; // Indicates equals sign in encoding - - private static byte[] alphabet(Base64Dialect dialect) { - if (dialect == null) { - throw new NullPointerException("dialect"); - } - return dialect.alphabet; - } - - private static byte[] decodabet(Base64Dialect dialect) { - if (dialect == null) { - throw new NullPointerException("dialect"); - } - return dialect.decodabet; - } - - private static boolean breakLines(Base64Dialect dialect) { - if (dialect == null) { - throw new NullPointerException("dialect"); - } - return dialect.breakLinesByDefault; - } - - public static ByteBuf encode(ByteBuf src) { - return encode(src, Base64Dialect.STANDARD); - } - - public static ByteBuf encode(ByteBuf src, Base64Dialect dialect) { - return encode(src, breakLines(dialect), dialect); - } - - public static ByteBuf encode(ByteBuf src, boolean breakLines) { - return encode(src, breakLines, Base64Dialect.STANDARD); - } - - public static ByteBuf encode(ByteBuf src, boolean breakLines, Base64Dialect dialect) { - - if (src == null) { - throw new NullPointerException("src"); - } - - ByteBuf dest = encode(src, src.readerIndex(), src.readableBytes(), breakLines, dialect); - src.readerIndex(src.writerIndex()); - return dest; - } - - public static ByteBuf encode(ByteBuf src, int off, int len) { - return encode(src, off, len, Base64Dialect.STANDARD); - } - - public static ByteBuf encode(ByteBuf src, int off, int len, Base64Dialect dialect) { - return encode(src, off, len, breakLines(dialect), dialect); - } - - public static ByteBuf encode( - ByteBuf src, int off, int len, boolean breakLines) { - return encode(src, off, len, breakLines, Base64Dialect.STANDARD); - } - - public static ByteBuf encode( - ByteBuf src, int off, int len, boolean breakLines, Base64Dialect dialect) { - - if (src == null) { - throw new NullPointerException("src"); - } - if (dialect == null) { - throw new NullPointerException("dialect"); - } - - int len43 = len * 4 / 3; - ByteBuf dest = Unpooled.buffer( - len43 + - (len % 3 > 0 ? 4 : 0) + // Account for padding - (breakLines ? len43 / MAX_LINE_LENGTH : 0)).order(src.order()); // New lines - int d = 0; - int e = 0; - int len2 = len - 2; - int lineLength = 0; - for (; d < len2; d += 3, e += 4) { - encode3to4(src, d + off, 3, dest, e, dialect); - - lineLength += 4; - if (breakLines && lineLength == MAX_LINE_LENGTH) { - dest.setByte(e + 4, NEW_LINE); - e ++; - lineLength = 0; - } // end if: end of line - } // end for: each piece of array - - if (d < len) { - encode3to4(src, d + off, len - d, dest, e, dialect); - e += 4; - } // end if: some padding needed - - return dest.slice(0, e); - } - - private static void encode3to4( - ByteBuf src, int srcOffset, int numSigBytes, - ByteBuf dest, int destOffset, Base64Dialect dialect) { - - byte[] ALPHABET = alphabet(dialect); - - // 1 2 3 - // 01234567890123456789012345678901 Bit position - // --------000000001111111122222222 Array position from threeBytes - // --------| || || || | Six bit groups to index ALPHABET - // >>18 >>12 >> 6 >> 0 Right shift necessary - // 0x3f 0x3f 0x3f Additional AND - - // Create buffer with zero-padding if there are only one or two - // significant bytes passed in the array. - // We have to shift left 24 in order to flush out the 1's that appear - // when Java treats a value as negative that is cast from a byte to an int. - int inBuff = - (numSigBytes > 0? src.getByte(srcOffset) << 24 >>> 8 : 0) | - (numSigBytes > 1? src.getByte(srcOffset + 1) << 24 >>> 16 : 0) | - (numSigBytes > 2? src.getByte(srcOffset + 2) << 24 >>> 24 : 0); - - switch (numSigBytes) { - case 3: - dest.setByte(destOffset , ALPHABET[inBuff >>> 18 ]); - dest.setByte(destOffset + 1, ALPHABET[inBuff >>> 12 & 0x3f]); - dest.setByte(destOffset + 2, ALPHABET[inBuff >>> 6 & 0x3f]); - dest.setByte(destOffset + 3, ALPHABET[inBuff & 0x3f]); - break; - case 2: - dest.setByte(destOffset , ALPHABET[inBuff >>> 18 ]); - dest.setByte(destOffset + 1, ALPHABET[inBuff >>> 12 & 0x3f]); - dest.setByte(destOffset + 2, ALPHABET[inBuff >>> 6 & 0x3f]); - dest.setByte(destOffset + 3, EQUALS_SIGN); - break; - case 1: - dest.setByte(destOffset , ALPHABET[inBuff >>> 18 ]); - dest.setByte(destOffset + 1, ALPHABET[inBuff >>> 12 & 0x3f]); - dest.setByte(destOffset + 2, EQUALS_SIGN); - dest.setByte(destOffset + 3, EQUALS_SIGN); - break; - } - } - - public static ByteBuf decode(ByteBuf src) { - return decode(src, Base64Dialect.STANDARD); - } - - public static ByteBuf decode(ByteBuf src, Base64Dialect dialect) { - - if (src == null) { - throw new NullPointerException("src"); - } - - ByteBuf dest = decode(src, src.readerIndex(), src.readableBytes(), dialect); - src.readerIndex(src.writerIndex()); - return dest; - } - - public static ByteBuf decode( - ByteBuf src, int off, int len) { - return decode(src, off, len, Base64Dialect.STANDARD); - } - - public static ByteBuf decode( - ByteBuf src, int off, int len, Base64Dialect dialect) { - - if (src == null) { - throw new NullPointerException("src"); - } - if (dialect == null) { - throw new NullPointerException("dialect"); - } - - byte[] DECODABET = decodabet(dialect); - - int len34 = len * 3 / 4; - ByteBuf dest = src.alloc().buffer(len34).order(src.order()); // Upper limit on size of output - int outBuffPosn = 0; - - byte[] b4 = new byte[4]; - int b4Posn = 0; - int i; - byte sbiCrop; - byte sbiDecode; - for (i = off; i < off + len; i ++) { - sbiCrop = (byte) (src.getByte(i) & 0x7f); // Only the low seven bits - sbiDecode = DECODABET[sbiCrop]; - - if (sbiDecode >= WHITE_SPACE_ENC) { // White space, Equals sign or better - if (sbiDecode >= EQUALS_SIGN_ENC) { // Equals sign or better - b4[b4Posn ++] = sbiCrop; - if (b4Posn > 3) { // Quartet built - outBuffPosn += decode4to3( - b4, 0, dest, outBuffPosn, dialect); - b4Posn = 0; - - // If that was the equals sign, break out of 'for' loop - if (sbiCrop == EQUALS_SIGN) { - break; - } - } - } - } else { - throw new IllegalArgumentException( - "bad Base64 input character at " + i + ": " + - src.getUnsignedByte(i) + " (decimal)"); - } - } - - return dest.slice(0, outBuffPosn); - } - - private static int decode4to3( - byte[] src, int srcOffset, - ByteBuf dest, int destOffset, Base64Dialect dialect) { - - byte[] DECODABET = decodabet(dialect); - - if (src[srcOffset + 2] == EQUALS_SIGN) { - // Example: Dk== - int outBuff = - (DECODABET[src[srcOffset ]] & 0xFF) << 18 | - (DECODABET[src[srcOffset + 1]] & 0xFF) << 12; - - dest.setByte(destOffset, (byte) (outBuff >>> 16)); - return 1; - } else if (src[srcOffset + 3] == EQUALS_SIGN) { - // Example: DkL= - int outBuff = - (DECODABET[src[srcOffset ]] & 0xFF) << 18 | - (DECODABET[src[srcOffset + 1]] & 0xFF) << 12 | - (DECODABET[src[srcOffset + 2]] & 0xFF) << 6; - - dest.setByte(destOffset , (byte) (outBuff >>> 16)); - dest.setByte(destOffset + 1, (byte) (outBuff >>> 8)); - return 2; - } else { - // Example: DkLE - int outBuff; - try { - outBuff = - (DECODABET[src[srcOffset ]] & 0xFF) << 18 | - (DECODABET[src[srcOffset + 1]] & 0xFF) << 12 | - (DECODABET[src[srcOffset + 2]] & 0xFF) << 6 | - DECODABET[src[srcOffset + 3]] & 0xFF; - } catch (IndexOutOfBoundsException ignored) { - throw new IllegalArgumentException("not encoded in Base64"); - } - - dest.setByte(destOffset , (byte) (outBuff >> 16)); - dest.setByte(destOffset + 1, (byte) (outBuff >> 8)); - dest.setByte(destOffset + 2, (byte) outBuff); - return 3; - } - } - - private Base64() { - // Unused - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/base64/Base64Decoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/base64/Base64Decoder.java deleted file mode 100755 index ab6be09739..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/base64/Base64Decoder.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.base64; - -import java.util.List; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelPipeline; -import com.ai.cloud.io.netty.channel.ChannelHandler.Sharable; -import com.ai.cloud.io.netty.handler.codec.ByteToMessageDecoder; -import com.ai.cloud.io.netty.handler.codec.DelimiterBasedFrameDecoder; -import com.ai.cloud.io.netty.handler.codec.Delimiters; -import com.ai.cloud.io.netty.handler.codec.MessageToMessageDecoder; - -/** - * Decodes a Base64-encoded {@link ByteBuf} or US-ASCII {@link String} - * into a {@link ByteBuf}. Please note that this decoder must be used - * with a proper {@link ByteToMessageDecoder} such as {@link DelimiterBasedFrameDecoder} - * if you are using a stream-based transport such as TCP/IP. A typical decoder - * setup for TCP/IP would be: - *

- * {@link ChannelPipeline} pipeline = ...;
- *
- * // Decoders
- * pipeline.addLast("frameDecoder", new {@link DelimiterBasedFrameDecoder}(80, {@link Delimiters#nulDelimiter()}));
- * pipeline.addLast("base64Decoder", new {@link Base64Decoder}());
- *
- * // Encoder
- * pipeline.addLast("base64Encoder", new {@link Base64Encoder}());
- * 
- */ -@Sharable -public class Base64Decoder extends MessageToMessageDecoder { - - private final Base64Dialect dialect; - - public Base64Decoder() { - this(Base64Dialect.STANDARD); - } - - public Base64Decoder(Base64Dialect dialect) { - if (dialect == null) { - throw new NullPointerException("dialect"); - } - this.dialect = dialect; - } - - @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) throws Exception { - out.add(Base64.decode(msg, msg.readerIndex(), msg.readableBytes(), dialect)); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/base64/Base64Dialect.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/base64/Base64Dialect.java deleted file mode 100755 index d8442c418f..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/base64/Base64Dialect.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -/* - * Written by Robert Harder and released to the public domain, as explained at - * http://creativecommons.org/licenses/publicdomain - */ -package com.ai.cloud.io.netty.handler.codec.base64; - -/** - * Enumeration of supported Base64 dialects. - *

- * The internal lookup tables in this class has been derived from - * Robert Harder's Public Domain - * Base64 Encoder/Decoder. - */ -public enum Base64Dialect { - /** - * Standard Base64 encoding as described in the Section 3 of - * RFC3548. - */ - STANDARD(new byte[] { - (byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', - (byte) 'F', (byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', - (byte) 'K', (byte) 'L', (byte) 'M', (byte) 'N', (byte) 'O', - (byte) 'P', (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', - (byte) 'U', (byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', - (byte) 'Z', (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', - (byte) 'e', (byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', - (byte) 'j', (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', - (byte) 'o', (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', - (byte) 't', (byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', - (byte) 'y', (byte) 'z', (byte) '0', (byte) '1', (byte) '2', - (byte) '3', (byte) '4', (byte) '5', (byte) '6', (byte) '7', - (byte) '8', (byte) '9', (byte) '+', (byte) '/' }, - new byte[] { - -9, -9, -9, -9, -9, -9, - -9, -9, -9, // Decimal 0 - 8 - -5, -5, // Whitespace: Tab and Linefeed - -9, -9, // Decimal 11 - 12 - -5, // Whitespace: Carriage Return - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26 - -9, -9, -9, -9, -9, // Decimal 27 - 31 - -5, // Whitespace: Space - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 42 - 62, // Plus sign at decimal 43 - -9, -9, -9, // Decimal 44 - 46 - 63, // Slash at decimal 47 - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine - -9, -9, -9, // Decimal 58 - 60 - -1, // Equals sign at decimal 61 - -9, -9, -9, // Decimal 62 - 64 - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through 'N' - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O' through 'Z' - -9, -9, -9, -9, -9, -9, // Decimal 91 - 96 - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a' through 'm' - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n' through 'z' - -9, -9, -9, -9, // Decimal 123 - 126 - /* -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */ - }, true), - /** - * Base64-like encoding that is URL-safe as described in the Section 4 of - * RFC3548. It is - * important to note that data encoded this way is not officially - * valid Base64, or at the very least should not be called Base64 without - * also specifying that is was encoded using the URL-safe dialect. - */ - URL_SAFE(new byte[] { - (byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', - (byte) 'F', (byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', - (byte) 'K', (byte) 'L', (byte) 'M', (byte) 'N', (byte) 'O', - (byte) 'P', (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', - (byte) 'U', (byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', - (byte) 'Z', (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', - (byte) 'e', (byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', - (byte) 'j', (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', - (byte) 'o', (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', - (byte) 't', (byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', - (byte) 'y', (byte) 'z', (byte) '0', (byte) '1', (byte) '2', - (byte) '3', (byte) '4', (byte) '5', (byte) '6', (byte) '7', - (byte) '8', (byte) '9', (byte) '-', (byte) '_' }, - new byte[] { - -9, -9, -9, -9, -9, -9, - -9, -9, -9, // Decimal 0 - 8 - -5, -5, // Whitespace: Tab and Linefeed - -9, -9, // Decimal 11 - 12 - -5, // Whitespace: Carriage Return - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26 - -9, -9, -9, -9, -9, // Decimal 27 - 31 - -5, // Whitespace: Space - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 42 - -9, // Plus sign at decimal 43 - -9, // Decimal 44 - 62, // Minus sign at decimal 45 - -9, // Decimal 46 - -9, // Slash at decimal 47 - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine - -9, -9, -9, // Decimal 58 - 60 - -1, // Equals sign at decimal 61 - -9, -9, -9, // Decimal 62 - 64 - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through 'N' - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O' through 'Z' - -9, -9, -9, -9, // Decimal 91 - 94 - 63, // Underscore at decimal 95 - -9, // Decimal 96 - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a' through 'm' - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n' through 'z' - -9, -9, -9, -9, // Decimal 123 - 126 - /*-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */ - }, false), - /** - * Special "ordered" dialect of Base64 described in - * RFC1940. - */ - ORDERED(new byte[] { - (byte) '-', (byte) '0', (byte) '1', (byte) '2', (byte) '3', - (byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8', - (byte) '9', (byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', - (byte) 'E', (byte) 'F', (byte) 'G', (byte) 'H', (byte) 'I', - (byte) 'J', (byte) 'K', (byte) 'L', (byte) 'M', (byte) 'N', - (byte) 'O', (byte) 'P', (byte) 'Q', (byte) 'R', (byte) 'S', - (byte) 'T', (byte) 'U', (byte) 'V', (byte) 'W', (byte) 'X', - (byte) 'Y', (byte) 'Z', (byte) '_', (byte) 'a', (byte) 'b', - (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f', (byte) 'g', - (byte) 'h', (byte) 'i', (byte) 'j', (byte) 'k', (byte) 'l', - (byte) 'm', (byte) 'n', (byte) 'o', (byte) 'p', (byte) 'q', - (byte) 'r', (byte) 's', (byte) 't', (byte) 'u', (byte) 'v', - (byte) 'w', (byte) 'x', (byte) 'y', (byte) 'z' }, - new byte[] { - -9, -9, -9, -9, -9, -9, - -9, -9, -9, // Decimal 0 - 8 - -5, -5, // Whitespace: Tab and Linefeed - -9, -9, // Decimal 11 - 12 - -5, // Whitespace: Carriage Return - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26 - -9, -9, -9, -9, -9, // Decimal 27 - 31 - -5, // Whitespace: Space - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 42 - -9, // Plus sign at decimal 43 - -9, // Decimal 44 - 0, // Minus sign at decimal 45 - -9, // Decimal 46 - -9, // Slash at decimal 47 - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, // Numbers zero through nine - -9, -9, -9, // Decimal 58 - 60 - -1, // Equals sign at decimal 61 - -9, -9, -9, // Decimal 62 - 64 - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, // Letters 'A' through 'M' - 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, // Letters 'N' through 'Z' - -9, -9, -9, -9, // Decimal 91 - 94 - 37, // Underscore at decimal 95 - -9, // Decimal 96 - 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, // Letters 'a' through 'm' - 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, // Letters 'n' through 'z' - -9, -9, -9, -9, // Decimal 123 - 126 - /* -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */ - }, true); - - final byte[] alphabet; - final byte[] decodabet; - final boolean breakLinesByDefault; - - Base64Dialect(byte[] alphabet, byte[] decodabet, boolean breakLinesByDefault) { - this.alphabet = alphabet; - this.decodabet = decodabet; - this.breakLinesByDefault = breakLinesByDefault; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/base64/Base64Encoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/base64/Base64Encoder.java deleted file mode 100755 index a102d37729..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/base64/Base64Encoder.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.base64; - -import java.util.List; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelPipeline; -import com.ai.cloud.io.netty.channel.ChannelHandler.Sharable; -import com.ai.cloud.io.netty.handler.codec.DelimiterBasedFrameDecoder; -import com.ai.cloud.io.netty.handler.codec.Delimiters; -import com.ai.cloud.io.netty.handler.codec.MessageToMessageEncoder; - -/** - * Encodes a {@link ByteBuf} into a Base64-encoded {@link ByteBuf}. - * A typical setup for TCP/IP would be: - *

- * {@link ChannelPipeline} pipeline = ...;
- *
- * // Decoders
- * pipeline.addLast("frameDecoder", new {@link DelimiterBasedFrameDecoder}(80, {@link Delimiters#nulDelimiter()}));
- * pipeline.addLast("base64Decoder", new {@link Base64Decoder}());
- *
- * // Encoder
- * pipeline.addLast("base64Encoder", new {@link Base64Encoder}());
- * 
- */ -@Sharable -public class Base64Encoder extends MessageToMessageEncoder { - - private final boolean breakLines; - private final Base64Dialect dialect; - - public Base64Encoder() { - this(true); - } - - public Base64Encoder(boolean breakLines) { - this(breakLines, Base64Dialect.STANDARD); - } - - public Base64Encoder(boolean breakLines, Base64Dialect dialect) { - if (dialect == null) { - throw new NullPointerException("dialect"); - } - - this.breakLines = breakLines; - this.dialect = dialect; - } - - @Override - protected void encode(ChannelHandlerContext ctx, ByteBuf msg, List out) throws Exception { - out.add(Base64.encode(msg, msg.readerIndex(), msg.readableBytes(), breakLines, dialect)); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/base64/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/base64/package-info.java deleted file mode 100755 index b263ce9507..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/base64/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * Encoder and decoder which transform a - * Base64-encoded - * {@link java.lang.String} or {@link com.ai.cloud.io.netty.buffer.ByteBuf} - * into a decoded {@link com.ai.cloud.io.netty.buffer.ByteBuf} and vice versa. - */ -package com.ai.cloud.io.netty.handler.codec.base64; diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/bytes/ByteArrayDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/bytes/ByteArrayDecoder.java deleted file mode 100755 index 73cd592468..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/bytes/ByteArrayDecoder.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.bytes; - -import java.util.List; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelPipeline; -import com.ai.cloud.io.netty.handler.codec.LengthFieldBasedFrameDecoder; -import com.ai.cloud.io.netty.handler.codec.LengthFieldPrepender; -import com.ai.cloud.io.netty.handler.codec.MessageToMessageDecoder; - -/** - * Decodes a received {@link ByteBuf} into an array of bytes. - * A typical setup for TCP/IP would be: - *
- * {@link ChannelPipeline} pipeline = ...;
- *
- * // Decoders
- * pipeline.addLast("frameDecoder",
- *                  new {@link LengthFieldBasedFrameDecoder}(1048576, 0, 4, 0, 4));
- * pipeline.addLast("bytesDecoder",
- *                  new {@link ByteArrayDecoder}());
- *
- * // Encoder
- * pipeline.addLast("frameEncoder", new {@link LengthFieldPrepender}(4));
- * pipeline.addLast("bytesEncoder", new {@link ByteArrayEncoder}());
- * 
- * and then you can use an array of bytes instead of a {@link ByteBuf} - * as a message: - *
- * void channelRead({@link ChannelHandlerContext} ctx, byte[] bytes) {
- *     ...
- * }
- * 
- */ -public class ByteArrayDecoder extends MessageToMessageDecoder { - @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) throws Exception { - // copy the ByteBuf content to a byte array - byte[] array = new byte[msg.readableBytes()]; - msg.getBytes(0, array); - - out.add(array); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/bytes/ByteArrayEncoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/bytes/ByteArrayEncoder.java deleted file mode 100755 index f9ce630c34..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/bytes/ByteArrayEncoder.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.bytes; - -import java.util.List; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.Unpooled; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelPipeline; -import com.ai.cloud.io.netty.channel.ChannelHandler.Sharable; -import com.ai.cloud.io.netty.handler.codec.LengthFieldBasedFrameDecoder; -import com.ai.cloud.io.netty.handler.codec.LengthFieldPrepender; -import com.ai.cloud.io.netty.handler.codec.MessageToMessageEncoder; - -/** - * Encodes the requested array of bytes into a {@link ByteBuf}. - * A typical setup for TCP/IP would be: - *
- * {@link ChannelPipeline} pipeline = ...;
- *
- * // Decoders
- * pipeline.addLast("frameDecoder",
- *                  new {@link LengthFieldBasedFrameDecoder}(1048576, 0, 4, 0, 4));
- * pipeline.addLast("bytesDecoder",
- *                  new {@link ByteArrayDecoder}());
- *
- * // Encoder
- * pipeline.addLast("frameEncoder", new {@link LengthFieldPrepender}(4));
- * pipeline.addLast("bytesEncoder", new {@link ByteArrayEncoder}());
- * 
- * and then you can use an array of bytes instead of a {@link ByteBuf} - * as a message: - *
- * void channelRead({@link ChannelHandlerContext} ctx, byte[] bytes) {
- *     ...
- * }
- * 
- */ -@Sharable -public class ByteArrayEncoder extends MessageToMessageEncoder { - @Override - protected void encode(ChannelHandlerContext ctx, byte[] msg, List out) throws Exception { - out.add(Unpooled.wrappedBuffer(msg)); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/bytes/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/bytes/package-info.java deleted file mode 100755 index 4385a24f95..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/bytes/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * Encoder and decoder which transform an array of bytes into a - * {@link com.ai.cloud.io.netty.buffer.ByteBuf} and vice versa. - */ -package com.ai.cloud.io.netty.handler.codec.bytes; diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/CompressionException.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/CompressionException.java deleted file mode 100755 index 7677717736..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/CompressionException.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.compression; - -import com.ai.cloud.io.netty.handler.codec.EncoderException; - -/** - * An {@link EncoderException} that is raised when compression failed. - */ -public class CompressionException extends EncoderException { - - private static final long serialVersionUID = 5603413481274811897L; - - /** - * Creates a new instance. - */ - public CompressionException() { - } - - /** - * Creates a new instance. - */ - public CompressionException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Creates a new instance. - */ - public CompressionException(String message) { - super(message); - } - - /** - * Creates a new instance. - */ - public CompressionException(Throwable cause) { - super(cause); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/Crc32c.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/Crc32c.java deleted file mode 100755 index 20f68e0de1..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/Crc32c.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.compression; - -import java.util.zip.Checksum; - -/** - * Implements CRC32-C as defined in: - * "Optimization of Cyclic Redundancy-CHeck Codes with 24 and 32 Parity Bits", - * IEEE Transactions on Communications 41(6): 883-892 (1993). - * - * The implementation of this class has been sourced from the Appendix of RFC 3309, - * but with masking due to Java not being able to support unsigned types. - */ -class Crc32c implements Checksum { - private static final int[] CRC_TABLE = { - 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, - 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB, - 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, - 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24, - 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, - 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384, - 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, - 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B, - 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, - 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35, - 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, - 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA, - 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, - 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A, - 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, - 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, - 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, - 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957, - 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, - 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198, - 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, - 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, - 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, - 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7, - 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, - 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789, - 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, - 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46, - 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, - 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6, - 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, - 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829, - 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, - 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93, - 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, - 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C, - 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, - 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC, - 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, - 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033, - 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, - 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D, - 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, - 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982, - 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, - 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, - 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, - 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED, - 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, - 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F, - 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, - 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, - 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, - 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540, - 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, - 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F, - 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, - 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1, - 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, - 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E, - 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, - 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E, - 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, - 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351, - }; - - private static final long LONG_MASK = 0xFFFFFFFFL; - private static final int BYTE_MASK = 0xFF; - - private int crc = ~0; - - @Override - public void update(int b) { - crc = crc32c(crc, b); - } - - @Override - public void update(byte[] buffer, int offset, int length) { - for (int i = offset; i < offset + length; i++) { - crc = crc32c(crc, buffer[i]); - } - } - - @Override - public long getValue() { - return (crc ^ LONG_MASK) & LONG_MASK; - } - - @Override - public void reset() { - crc = ~0; - } - - private static int crc32c(int crc, int b) { - return crc >>> 8 ^ CRC_TABLE[(crc ^ b & BYTE_MASK) & BYTE_MASK]; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/DecompressionException.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/DecompressionException.java deleted file mode 100755 index e928b3d7a4..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/DecompressionException.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.compression; - -import com.ai.cloud.io.netty.handler.codec.DecoderException; - -/** - * A {@link DecoderException} that is raised when decompression failed. - */ -public class DecompressionException extends DecoderException { - - private static final long serialVersionUID = 3546272712208105199L; - - /** - * Creates a new instance. - */ - public DecompressionException() { - } - - /** - * Creates a new instance. - */ - public DecompressionException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Creates a new instance. - */ - public DecompressionException(String message) { - super(message); - } - - /** - * Creates a new instance. - */ - public DecompressionException(Throwable cause) { - super(cause); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/JZlibDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/JZlibDecoder.java deleted file mode 100755 index af4c2ada5a..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/JZlibDecoder.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.compression; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.jcraft.jzlib.Inflater; -import com.jcraft.jzlib.JZlib; - -import java.util.List; - -public class JZlibDecoder extends ZlibDecoder { - - private final Inflater z = new Inflater(); - private byte[] dictionary; - private volatile boolean finished; - - /** - * Creates a new instance with the default wrapper ({@link ZlibWrapper#ZLIB}). - * - * @throws DecompressionException if failed to initialize zlib - */ - public JZlibDecoder() { - this(ZlibWrapper.ZLIB); - } - - /** - * Creates a new instance with the specified wrapper. - * - * @throws DecompressionException if failed to initialize zlib - */ - public JZlibDecoder(ZlibWrapper wrapper) { - if (wrapper == null) { - throw new NullPointerException("wrapper"); - } - - int resultCode = z.init(ZlibUtil.convertWrapperType(wrapper)); - if (resultCode != JZlib.Z_OK) { - ZlibUtil.fail(z, "initialization failure", resultCode); - } - } - - /** - * Creates a new instance with the specified preset dictionary. The wrapper - * is always {@link ZlibWrapper#ZLIB} because it is the only format that - * supports the preset dictionary. - * - * @throws DecompressionException if failed to initialize zlib - */ - public JZlibDecoder(byte[] dictionary) { - if (dictionary == null) { - throw new NullPointerException("dictionary"); - } - this.dictionary = dictionary; - - int resultCode; - resultCode = z.inflateInit(JZlib.W_ZLIB); - if (resultCode != JZlib.Z_OK) { - ZlibUtil.fail(z, "initialization failure", resultCode); - } - } - - /** - * Returns {@code true} if and only if the end of the compressed stream - * has been reached. - */ - @Override - public boolean isClosed() { - return finished; - } - - @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { - if (finished) { - // Skip data received after finished. - in.skipBytes(in.readableBytes()); - return; - } - - final int inputLength = in.readableBytes(); - if (inputLength == 0) { - return; - } - - try { - // Configure input. - z.avail_in = inputLength; - if (in.hasArray()) { - z.next_in = in.array(); - z.next_in_index = in.arrayOffset() + in.readerIndex(); - } else { - byte[] array = new byte[inputLength]; - in.getBytes(in.readerIndex(), array); - z.next_in = array; - z.next_in_index = 0; - } - int oldNextInIndex = z.next_in_index; - - // Configure output. - int maxOutputLength = inputLength << 1; - ByteBuf decompressed = ctx.alloc().heapBuffer(maxOutputLength); - - try { - loop: for (;;) { - z.avail_out = maxOutputLength; - decompressed.ensureWritable(maxOutputLength); - z.next_out = decompressed.array(); - z.next_out_index = decompressed.arrayOffset() + decompressed.writerIndex(); - int oldNextOutIndex = z.next_out_index; - - // Decompress 'in' into 'out' - int resultCode = z.inflate(JZlib.Z_SYNC_FLUSH); - int outputLength = z.next_out_index - oldNextOutIndex; - if (outputLength > 0) { - decompressed.writerIndex(decompressed.writerIndex() + outputLength); - } - - switch (resultCode) { - case JZlib.Z_NEED_DICT: - if (dictionary == null) { - ZlibUtil.fail(z, "decompression failure", resultCode); - } else { - resultCode = z.inflateSetDictionary(dictionary, dictionary.length); - if (resultCode != JZlib.Z_OK) { - ZlibUtil.fail(z, "failed to set the dictionary", resultCode); - } - } - break; - case JZlib.Z_STREAM_END: - finished = true; // Do not decode anymore. - z.inflateEnd(); - break loop; - case JZlib.Z_OK: - break; - case JZlib.Z_BUF_ERROR: - if (z.avail_in <= 0) { - break loop; - } - break; - default: - ZlibUtil.fail(z, "decompression failure", resultCode); - } - } - } finally { - in.skipBytes(z.next_in_index - oldNextInIndex); - if (decompressed.isReadable()) { - out.add(decompressed); - } else { - decompressed.release(); - } - } - } finally { - // Deference the external references explicitly to tell the VM that - // the allocated byte arrays are temporary so that the call stack - // can be utilized. - // I'm not sure if the modern VMs do this optimization though. - z.next_in = null; - z.next_out = null; - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/JZlibEncoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/JZlibEncoder.java deleted file mode 100755 index 282ed0cf18..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/JZlibEncoder.java +++ /dev/null @@ -1,410 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.compression; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.Unpooled; -import com.ai.cloud.io.netty.channel.ChannelFuture; -import com.ai.cloud.io.netty.channel.ChannelFutureListener; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelPromise; -import com.ai.cloud.io.netty.channel.ChannelPromiseNotifier; -import com.ai.cloud.io.netty.util.concurrent.EventExecutor; -import com.ai.cloud.io.netty.util.internal.EmptyArrays; -import com.jcraft.jzlib.Deflater; -import com.jcraft.jzlib.JZlib; - -import java.util.concurrent.TimeUnit; - -/** - * Compresses a {@link ByteBuf} using the deflate algorithm. - */ -public class JZlibEncoder extends ZlibEncoder { - - private final int wrapperOverhead; - private final Deflater z = new Deflater(); - private volatile boolean finished; - private volatile ChannelHandlerContext ctx; - - /** - * Creates a new zlib encoder with the default compression level ({@code 6}), - * default window bits ({@code 15}), default memory level ({@code 8}), - * and the default wrapper ({@link ZlibWrapper#ZLIB}). - * - * @throws CompressionException if failed to initialize zlib - */ - public JZlibEncoder() { - this(6); - } - - /** - * Creates a new zlib encoder with the specified {@code compressionLevel}, - * default window bits ({@code 15}), default memory level ({@code 8}), - * and the default wrapper ({@link ZlibWrapper#ZLIB}). - * - * @param compressionLevel - * {@code 1} yields the fastest compression and {@code 9} yields the - * best compression. {@code 0} means no compression. The default - * compression level is {@code 6}. - * - * @throws CompressionException if failed to initialize zlib - */ - public JZlibEncoder(int compressionLevel) { - this(ZlibWrapper.ZLIB, compressionLevel); - } - - /** - * Creates a new zlib encoder with the default compression level ({@code 6}), - * default window bits ({@code 15}), default memory level ({@code 8}), - * and the specified wrapper. - * - * @throws CompressionException if failed to initialize zlib - */ - public JZlibEncoder(ZlibWrapper wrapper) { - this(wrapper, 6); - } - - /** - * Creates a new zlib encoder with the specified {@code compressionLevel}, - * default window bits ({@code 15}), default memory level ({@code 8}), - * and the specified wrapper. - * - * @param compressionLevel - * {@code 1} yields the fastest compression and {@code 9} yields the - * best compression. {@code 0} means no compression. The default - * compression level is {@code 6}. - * - * @throws CompressionException if failed to initialize zlib - */ - public JZlibEncoder(ZlibWrapper wrapper, int compressionLevel) { - this(wrapper, compressionLevel, 15, 8); - } - - /** - * Creates a new zlib encoder with the specified {@code compressionLevel}, - * the specified {@code windowBits}, the specified {@code memLevel}, and - * the specified wrapper. - * - * @param compressionLevel - * {@code 1} yields the fastest compression and {@code 9} yields the - * best compression. {@code 0} means no compression. The default - * compression level is {@code 6}. - * @param windowBits - * The base two logarithm of the size of the history buffer. The - * value should be in the range {@code 9} to {@code 15} inclusive. - * Larger values result in better compression at the expense of - * memory usage. The default value is {@code 15}. - * @param memLevel - * How much memory should be allocated for the internal compression - * state. {@code 1} uses minimum memory and {@code 9} uses maximum - * memory. Larger values result in better and faster compression - * at the expense of memory usage. The default value is {@code 8} - * - * @throws CompressionException if failed to initialize zlib - */ - public JZlibEncoder(ZlibWrapper wrapper, int compressionLevel, int windowBits, int memLevel) { - - if (compressionLevel < 0 || compressionLevel > 9) { - throw new IllegalArgumentException( - "compressionLevel: " + compressionLevel + - " (expected: 0-9)"); - } - if (windowBits < 9 || windowBits > 15) { - throw new IllegalArgumentException( - "windowBits: " + windowBits + " (expected: 9-15)"); - } - if (memLevel < 1 || memLevel > 9) { - throw new IllegalArgumentException( - "memLevel: " + memLevel + " (expected: 1-9)"); - } - if (wrapper == null) { - throw new NullPointerException("wrapper"); - } - if (wrapper == ZlibWrapper.ZLIB_OR_NONE) { - throw new IllegalArgumentException( - "wrapper '" + ZlibWrapper.ZLIB_OR_NONE + "' is not " + - "allowed for compression."); - } - - int resultCode = z.init( - compressionLevel, windowBits, memLevel, - ZlibUtil.convertWrapperType(wrapper)); - if (resultCode != JZlib.Z_OK) { - ZlibUtil.fail(z, "initialization failure", resultCode); - } - - wrapperOverhead = ZlibUtil.wrapperOverhead(wrapper); - } - - /** - * Creates a new zlib encoder with the default compression level ({@code 6}), - * default window bits ({@code 15}), default memory level ({@code 8}), - * and the specified preset dictionary. The wrapper is always - * {@link ZlibWrapper#ZLIB} because it is the only format that supports - * the preset dictionary. - * - * @param dictionary the preset dictionary - * - * @throws CompressionException if failed to initialize zlib - */ - public JZlibEncoder(byte[] dictionary) { - this(6, dictionary); - } - - /** - * Creates a new zlib encoder with the specified {@code compressionLevel}, - * default window bits ({@code 15}), default memory level ({@code 8}), - * and the specified preset dictionary. The wrapper is always - * {@link ZlibWrapper#ZLIB} because it is the only format that supports - * the preset dictionary. - * - * @param compressionLevel - * {@code 1} yields the fastest compression and {@code 9} yields the - * best compression. {@code 0} means no compression. The default - * compression level is {@code 6}. - * @param dictionary the preset dictionary - * - * @throws CompressionException if failed to initialize zlib - */ - public JZlibEncoder(int compressionLevel, byte[] dictionary) { - this(compressionLevel, 15, 8, dictionary); - } - - /** - * Creates a new zlib encoder with the specified {@code compressionLevel}, - * the specified {@code windowBits}, the specified {@code memLevel}, - * and the specified preset dictionary. The wrapper is always - * {@link ZlibWrapper#ZLIB} because it is the only format that supports - * the preset dictionary. - * - * @param compressionLevel - * {@code 1} yields the fastest compression and {@code 9} yields the - * best compression. {@code 0} means no compression. The default - * compression level is {@code 6}. - * @param windowBits - * The base two logarithm of the size of the history buffer. The - * value should be in the range {@code 9} to {@code 15} inclusive. - * Larger values result in better compression at the expense of - * memory usage. The default value is {@code 15}. - * @param memLevel - * How much memory should be allocated for the internal compression - * state. {@code 1} uses minimum memory and {@code 9} uses maximum - * memory. Larger values result in better and faster compression - * at the expense of memory usage. The default value is {@code 8} - * @param dictionary the preset dictionary - * - * @throws CompressionException if failed to initialize zlib - */ - public JZlibEncoder(int compressionLevel, int windowBits, int memLevel, byte[] dictionary) { - if (compressionLevel < 0 || compressionLevel > 9) { - throw new IllegalArgumentException("compressionLevel: " + compressionLevel + " (expected: 0-9)"); - } - if (windowBits < 9 || windowBits > 15) { - throw new IllegalArgumentException( - "windowBits: " + windowBits + " (expected: 9-15)"); - } - if (memLevel < 1 || memLevel > 9) { - throw new IllegalArgumentException( - "memLevel: " + memLevel + " (expected: 1-9)"); - } - if (dictionary == null) { - throw new NullPointerException("dictionary"); - } - int resultCode; - resultCode = z.deflateInit( - compressionLevel, windowBits, memLevel, - JZlib.W_ZLIB); // Default: ZLIB format - if (resultCode != JZlib.Z_OK) { - ZlibUtil.fail(z, "initialization failure", resultCode); - } else { - resultCode = z.deflateSetDictionary(dictionary, dictionary.length); - if (resultCode != JZlib.Z_OK) { - ZlibUtil.fail(z, "failed to set the dictionary", resultCode); - } - } - - wrapperOverhead = ZlibUtil.wrapperOverhead(ZlibWrapper.ZLIB); - } - - @Override - public ChannelFuture close() { - return close(ctx().channel().newPromise()); - } - - @Override - public ChannelFuture close(final ChannelPromise promise) { - ChannelHandlerContext ctx = ctx(); - EventExecutor executor = ctx.executor(); - if (executor.inEventLoop()) { - return finishEncode(ctx, promise); - } else { - final ChannelPromise p = ctx.newPromise(); - executor.execute(new Runnable() { - @Override - public void run() { - ChannelFuture f = finishEncode(ctx(), p); - f.addListener(new ChannelPromiseNotifier(promise)); - } - }); - return p; - } - } - - private ChannelHandlerContext ctx() { - ChannelHandlerContext ctx = this.ctx; - if (ctx == null) { - throw new IllegalStateException("not added to a pipeline"); - } - return ctx; - } - - @Override - public boolean isClosed() { - return finished; - } - - @Override - protected void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception { - if (finished) { - out.writeBytes(in); - return; - } - - int inputLength = in.readableBytes(); - if (inputLength == 0) { - return; - } - - try { - // Configure input. - boolean inHasArray = in.hasArray(); - z.avail_in = inputLength; - if (inHasArray) { - z.next_in = in.array(); - z.next_in_index = in.arrayOffset() + in.readerIndex(); - } else { - byte[] array = new byte[inputLength]; - in.getBytes(in.readerIndex(), array); - z.next_in = array; - z.next_in_index = 0; - } - int oldNextInIndex = z.next_in_index; - - // Configure output. - int maxOutputLength = (int) Math.ceil(inputLength * 1.001) + 12 + wrapperOverhead; - out.ensureWritable(maxOutputLength); - z.avail_out = maxOutputLength; - z.next_out = out.array(); - z.next_out_index = out.arrayOffset() + out.writerIndex(); - int oldNextOutIndex = z.next_out_index; - - // Note that Z_PARTIAL_FLUSH has been deprecated. - int resultCode; - try { - resultCode = z.deflate(JZlib.Z_SYNC_FLUSH); - } finally { - in.skipBytes(z.next_in_index - oldNextInIndex); - } - - if (resultCode != JZlib.Z_OK) { - ZlibUtil.fail(z, "compression failure", resultCode); - } - - int outputLength = z.next_out_index - oldNextOutIndex; - if (outputLength > 0) { - out.writerIndex(out.writerIndex() + outputLength); - } - } finally { - // Deference the external references explicitly to tell the VM that - // the allocated byte arrays are temporary so that the call stack - // can be utilized. - // I'm not sure if the modern VMs do this optimization though. - z.next_in = null; - z.next_out = null; - } - } - - @Override - public void close( - final ChannelHandlerContext ctx, - final ChannelPromise promise) { - ChannelFuture f = finishEncode(ctx, ctx.newPromise()); - f.addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture f) throws Exception { - ctx.close(promise); - } - }); - - if (!f.isDone()) { - // Ensure the channel is closed even if the write operation completes in time. - ctx.executor().schedule(new Runnable() { - @Override - public void run() { - ctx.close(promise); - } - }, 10, TimeUnit.SECONDS); // FIXME: Magic number - } - } - - private ChannelFuture finishEncode(ChannelHandlerContext ctx, ChannelPromise promise) { - if (finished) { - promise.setSuccess(); - return promise; - } - finished = true; - - ByteBuf footer; - try { - // Configure input. - z.next_in = EmptyArrays.EMPTY_BYTES; - z.next_in_index = 0; - z.avail_in = 0; - - // Configure output. - byte[] out = new byte[32]; // room for ADLER32 + ZLIB / CRC32 + GZIP header - z.next_out = out; - z.next_out_index = 0; - z.avail_out = out.length; - - // Write the ADLER32 checksum (stream footer). - int resultCode = z.deflate(JZlib.Z_FINISH); - if (resultCode != JZlib.Z_OK && resultCode != JZlib.Z_STREAM_END) { - promise.setFailure(ZlibUtil.deflaterException(z, "compression failure", resultCode)); - return promise; - } else if (z.next_out_index != 0) { - footer = Unpooled.wrappedBuffer(out, 0, z.next_out_index); - } else { - footer = Unpooled.EMPTY_BUFFER; - } - } finally { - z.deflateEnd(); - - // Deference the external references explicitly to tell the VM that - // the allocated byte arrays are temporary so that the call stack - // can be utilized. - // I'm not sure if the modern VMs do this optimization though. - z.next_in = null; - z.next_out = null; - } - return ctx.writeAndFlush(footer, promise); - } - - @Override - public void handlerAdded(ChannelHandlerContext ctx) throws Exception { - this.ctx = ctx; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/JdkZlibDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/JdkZlibDecoder.java deleted file mode 100755 index b73e925572..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/JdkZlibDecoder.java +++ /dev/null @@ -1,393 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.compression; - -import java.util.List; -import java.util.zip.CRC32; -import java.util.zip.DataFormatException; -import java.util.zip.Deflater; -import java.util.zip.Inflater; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; - -/** - * Decompress a {@link ByteBuf} using the inflate algorithm. - */ -public class JdkZlibDecoder extends ZlibDecoder { - private static final int FHCRC = 0x02; - private static final int FEXTRA = 0x04; - private static final int FNAME = 0x08; - private static final int FCOMMENT = 0x10; - private static final int FRESERVED = 0xE0; - - private Inflater inflater; - private final byte[] dictionary; - - // GZIP related - private final CRC32 crc; - - private enum GzipState { - HEADER_START, - HEADER_END, - FLG_READ, - XLEN_READ, - SKIP_FNAME, - SKIP_COMMENT, - PROCESS_FHCRC, - FOOTER_START, - } - - private GzipState gzipState = GzipState.HEADER_START; - private int flags = -1; - private int xlen = -1; - - private volatile boolean finished; - - private boolean decideZlibOrNone; - - /** - * Creates a new instance with the default wrapper ({@link ZlibWrapper#ZLIB}). - */ - public JdkZlibDecoder() { - this(ZlibWrapper.ZLIB, null); - } - - /** - * Creates a new instance with the specified preset dictionary. The wrapper - * is always {@link ZlibWrapper#ZLIB} because it is the only format that - * supports the preset dictionary. - */ - public JdkZlibDecoder(byte[] dictionary) { - this(ZlibWrapper.ZLIB, dictionary); - } - - /** - * Creates a new instance with the specified wrapper. - * Be aware that only {@link ZlibWrapper#GZIP}, {@link ZlibWrapper#ZLIB} and {@link ZlibWrapper#NONE} are - * supported atm. - */ - public JdkZlibDecoder(ZlibWrapper wrapper) { - this(wrapper, null); - } - - private JdkZlibDecoder(ZlibWrapper wrapper, byte[] dictionary) { - if (wrapper == null) { - throw new NullPointerException("wrapper"); - } - switch (wrapper) { - case GZIP: - inflater = new Inflater(true); - crc = new CRC32(); - break; - case NONE: - inflater = new Inflater(true); - crc = null; - break; - case ZLIB: - inflater = new Inflater(); - crc = null; - break; - case ZLIB_OR_NONE: - // Postpone the decision until decode(...) is called. - decideZlibOrNone = true; - crc = null; - break; - default: - throw new IllegalArgumentException("Only GZIP or ZLIB is supported, but you used " + wrapper); - } - this.dictionary = dictionary; - } - - @Override - public boolean isClosed() { - return finished; - } - - @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { - if (finished) { - // Skip data received after finished. - in.skipBytes(in.readableBytes()); - return; - } - - int readableBytes = in.readableBytes(); - if (readableBytes == 0) { - return; - } - - if (decideZlibOrNone) { - // First two bytes are needed to decide if it's a ZLIB stream. - if (readableBytes < 2) { - return; - } - - boolean nowrap = !looksLikeZlib(in.getShort(in.readerIndex())); - inflater = new Inflater(nowrap); - decideZlibOrNone = false; - } - - if (crc != null) { - switch (gzipState) { - case FOOTER_START: - if (readGZIPFooter(in)) { - finished = true; - } - return; - default: - if (gzipState != GzipState.HEADER_END) { - if (!readGZIPHeader(in)) { - return; - } - } - } - // Some bytes may have been consumed, and so we must re-set the number of readable bytes. - readableBytes = in.readableBytes(); - } - - if (in.hasArray()) { - inflater.setInput(in.array(), in.arrayOffset() + in.readerIndex(), readableBytes); - } else { - byte[] array = new byte[readableBytes]; - in.getBytes(in.readerIndex(), array); - inflater.setInput(array); - } - - int maxOutputLength = inflater.getRemaining() << 1; - ByteBuf decompressed = ctx.alloc().heapBuffer(maxOutputLength); - try { - boolean readFooter = false; - byte[] outArray = decompressed.array(); - while (!inflater.needsInput()) { - int writerIndex = decompressed.writerIndex(); - int outIndex = decompressed.arrayOffset() + writerIndex; - int length = decompressed.writableBytes(); - - if (length == 0) { - // completely filled the buffer allocate a new one and start to fill it - out.add(decompressed); - decompressed = ctx.alloc().heapBuffer(maxOutputLength); - outArray = decompressed.array(); - continue; - } - - int outputLength = inflater.inflate(outArray, outIndex, length); - if (outputLength > 0) { - decompressed.writerIndex(writerIndex + outputLength); - if (crc != null) { - crc.update(outArray, outIndex, outputLength); - } - } else { - if (inflater.needsDictionary()) { - if (dictionary == null) { - throw new DecompressionException( - "decompression failure, unable to set dictionary as non was specified"); - } - inflater.setDictionary(dictionary); - } - } - - if (inflater.finished()) { - if (crc == null) { - finished = true; // Do not decode anymore. - } else { - readFooter = true; - } - break; - } - } - - in.skipBytes(readableBytes - inflater.getRemaining()); - - if (readFooter) { - gzipState = GzipState.FOOTER_START; - if (readGZIPFooter(in)) { - finished = true; - } - } - } catch (DataFormatException e) { - throw new DecompressionException("decompression failure", e); - } finally { - - if (decompressed.isReadable()) { - out.add(decompressed); - } else { - decompressed.release(); - } - } - } - - @Override - protected void handlerRemoved0(ChannelHandlerContext ctx) throws Exception { - super.handlerRemoved0(ctx); - if (inflater != null) { - inflater.end(); - } - } - - private boolean readGZIPHeader(ByteBuf in) { - switch (gzipState) { - case HEADER_START: - if (in.readableBytes() < 10) { - return false; - } - // read magic numbers - int magic0 = in.readByte(); - int magic1 = in.readByte(); - - if (magic0 != 31) { - throw new DecompressionException("Input is not in the GZIP format"); - } - crc.update(magic0); - crc.update(magic1); - - int method = in.readUnsignedByte(); - if (method != Deflater.DEFLATED) { - throw new DecompressionException("Unsupported compression method " - + method + " in the GZIP header"); - } - crc.update(method); - - flags = in.readUnsignedByte(); - crc.update(flags); - - if ((flags & FRESERVED) != 0) { - throw new DecompressionException( - "Reserved flags are set in the GZIP header"); - } - - // mtime (int) - crc.update(in.readByte()); - crc.update(in.readByte()); - crc.update(in.readByte()); - crc.update(in.readByte()); - - crc.update(in.readUnsignedByte()); // extra flags - crc.update(in.readUnsignedByte()); // operating system - - gzipState = GzipState.FLG_READ; - case FLG_READ: - if ((flags & FEXTRA) != 0) { - if (in.readableBytes() < 2) { - return false; - } - int xlen1 = in.readUnsignedByte(); - int xlen2 = in.readUnsignedByte(); - crc.update(xlen1); - crc.update(xlen2); - - xlen |= xlen1 << 8 | xlen2; - } - gzipState = GzipState.XLEN_READ; - case XLEN_READ: - if (xlen != -1) { - if (in.readableBytes() < xlen) { - return false; - } - byte[] xtra = new byte[xlen]; - in.readBytes(xtra); - crc.update(xtra); - } - gzipState = GzipState.SKIP_FNAME; - case SKIP_FNAME: - if ((flags & FNAME) != 0) { - if (!in.isReadable()) { - return false; - } - do { - int b = in.readUnsignedByte(); - crc.update(b); - if (b == 0x00) { - break; - } - } while (in.isReadable()); - } - gzipState = GzipState.SKIP_COMMENT; - case SKIP_COMMENT: - if ((flags & FCOMMENT) != 0) { - if (!in.isReadable()) { - return false; - } - do { - int b = in.readUnsignedByte(); - crc.update(b); - if (b == 0x00) { - break; - } - } while (in.isReadable()); - } - gzipState = GzipState.PROCESS_FHCRC; - case PROCESS_FHCRC: - if ((flags & FHCRC) != 0) { - if (in.readableBytes() < 4) { - return false; - } - verifyCrc(in); - } - crc.reset(); - gzipState = GzipState.HEADER_END; - case HEADER_END: - return true; - default: - throw new IllegalStateException(); - } - } - - private boolean readGZIPFooter(ByteBuf buf) { - if (buf.readableBytes() < 8) { - return false; - } - - verifyCrc(buf); - - // read ISIZE and verify - int dataLength = 0; - for (int i = 0; i < 4; ++i) { - dataLength |= buf.readUnsignedByte() << i * 8; - } - int readLength = inflater.getTotalOut(); - if (dataLength != readLength) { - throw new DecompressionException( - "Number of bytes mismatch. Expected: " + dataLength + ", Got: " + readLength); - } - return true; - } - - private void verifyCrc(ByteBuf in) { - long crcValue = 0; - for (int i = 0; i < 4; ++i) { - crcValue |= (long) in.readUnsignedByte() << i * 8; - } - long readCrc = crc.getValue(); - if (crcValue != readCrc) { - throw new DecompressionException( - "CRC value missmatch. Expected: " + crcValue + ", Got: " + readCrc); - } - } - - /* - * Returns true if the cmf_flg parameter (think: first two bytes of a zlib stream) - * indicates that this is a zlib stream. - *

- * You can lookup the details in the ZLIB RFC: - * RFC 1950. - */ - private static boolean looksLikeZlib(short cmf_flg) { - return (cmf_flg & 0x7800) == 0x7800 && - cmf_flg % 31 == 0; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/JdkZlibEncoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/JdkZlibEncoder.java deleted file mode 100755 index 615e81d4c7..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/JdkZlibEncoder.java +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.compression; - -import java.util.concurrent.TimeUnit; -import java.util.zip.CRC32; -import java.util.zip.Deflater; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelFuture; -import com.ai.cloud.io.netty.channel.ChannelFutureListener; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelPromise; -import com.ai.cloud.io.netty.channel.ChannelPromiseNotifier; -import com.ai.cloud.io.netty.util.concurrent.EventExecutor; - -/** - * Compresses a {@link ByteBuf} using the deflate algorithm. - */ -public class JdkZlibEncoder extends ZlibEncoder { - - private final ZlibWrapper wrapper; - private final Deflater deflater; - private volatile boolean finished; - private volatile ChannelHandlerContext ctx; - - /* - * GZIP support - */ - private final CRC32 crc = new CRC32(); - private static final byte[] gzipHeader = {0x1f, (byte) 0x8b, Deflater.DEFLATED, 0, 0, 0, 0, 0, 0, 0}; - private boolean writeHeader = true; - - /** - * Creates a new zlib encoder with the default compression level ({@code 6}) - * and the default wrapper ({@link ZlibWrapper#ZLIB}). - * - * @throws CompressionException if failed to initialize zlib - */ - public JdkZlibEncoder() { - this(6); - } - - /** - * Creates a new zlib encoder with the specified {@code compressionLevel} - * and the default wrapper ({@link ZlibWrapper#ZLIB}). - * - * @param compressionLevel - * {@code 1} yields the fastest compression and {@code 9} yields the - * best compression. {@code 0} means no compression. The default - * compression level is {@code 6}. - * - * @throws CompressionException if failed to initialize zlib - */ - public JdkZlibEncoder(int compressionLevel) { - this(ZlibWrapper.ZLIB, compressionLevel); - } - - /** - * Creates a new zlib encoder with the default compression level ({@code 6}) - * and the specified wrapper. - * - * @throws CompressionException if failed to initialize zlib - */ - public JdkZlibEncoder(ZlibWrapper wrapper) { - this(wrapper, 6); - } - - /** - * Creates a new zlib encoder with the specified {@code compressionLevel} - * and the specified wrapper. - * - * @param compressionLevel - * {@code 1} yields the fastest compression and {@code 9} yields the - * best compression. {@code 0} means no compression. The default - * compression level is {@code 6}. - * - * @throws CompressionException if failed to initialize zlib - */ - public JdkZlibEncoder(ZlibWrapper wrapper, int compressionLevel) { - if (compressionLevel < 0 || compressionLevel > 9) { - throw new IllegalArgumentException( - "compressionLevel: " + compressionLevel + " (expected: 0-9)"); - } - if (wrapper == null) { - throw new NullPointerException("wrapper"); - } - if (wrapper == ZlibWrapper.ZLIB_OR_NONE) { - throw new IllegalArgumentException( - "wrapper '" + ZlibWrapper.ZLIB_OR_NONE + "' is not " + - "allowed for compression."); - } - - this.wrapper = wrapper; - deflater = new Deflater(compressionLevel, wrapper != ZlibWrapper.ZLIB); - } - - /** - * Creates a new zlib encoder with the default compression level ({@code 6}) - * and the specified preset dictionary. The wrapper is always - * {@link ZlibWrapper#ZLIB} because it is the only format that supports - * the preset dictionary. - * - * @param dictionary the preset dictionary - * - * @throws CompressionException if failed to initialize zlib - */ - public JdkZlibEncoder(byte[] dictionary) { - this(6, dictionary); - } - - /** - * Creates a new zlib encoder with the specified {@code compressionLevel} - * and the specified preset dictionary. The wrapper is always - * {@link ZlibWrapper#ZLIB} because it is the only format that supports - * the preset dictionary. - * - * @param compressionLevel - * {@code 1} yields the fastest compression and {@code 9} yields the - * best compression. {@code 0} means no compression. The default - * compression level is {@code 6}. - * @param dictionary the preset dictionary - * - * @throws CompressionException if failed to initialize zlib - */ - public JdkZlibEncoder(int compressionLevel, byte[] dictionary) { - if (compressionLevel < 0 || compressionLevel > 9) { - throw new IllegalArgumentException( - "compressionLevel: " + compressionLevel + " (expected: 0-9)"); - } - if (dictionary == null) { - throw new NullPointerException("dictionary"); - } - - wrapper = ZlibWrapper.ZLIB; - deflater = new Deflater(compressionLevel); - deflater.setDictionary(dictionary); - } - - @Override - public ChannelFuture close() { - return close(ctx().newPromise()); - } - - @Override - public ChannelFuture close(final ChannelPromise promise) { - ChannelHandlerContext ctx = ctx(); - EventExecutor executor = ctx.executor(); - if (executor.inEventLoop()) { - return finishEncode(ctx, promise); - } else { - final ChannelPromise p = ctx.newPromise(); - executor.execute(new Runnable() { - @Override - public void run() { - ChannelFuture f = finishEncode(ctx(), p); - f.addListener(new ChannelPromiseNotifier(promise)); - } - }); - return p; - } - } - - private ChannelHandlerContext ctx() { - ChannelHandlerContext ctx = this.ctx; - if (ctx == null) { - throw new IllegalStateException("not added to a pipeline"); - } - return ctx; - } - - @Override - public boolean isClosed() { - return finished; - } - - @Override - protected void encode(ChannelHandlerContext ctx, ByteBuf uncompressed, ByteBuf out) throws Exception { - if (finished) { - out.writeBytes(uncompressed); - return; - } - - int len = uncompressed.readableBytes(); - if (len == 0) { - return; - } - - int offset; - byte[] inAry; - if (uncompressed.hasArray()) { - // if it is backed by an array we not need to to do a copy at all - inAry = uncompressed.array(); - offset = uncompressed.arrayOffset() + uncompressed.readerIndex(); - // skip all bytes as we will consume all of them - uncompressed.skipBytes(len); - } else { - inAry = new byte[len]; - uncompressed.readBytes(inAry); - offset = 0; - } - - if (writeHeader) { - writeHeader = false; - if (wrapper == ZlibWrapper.GZIP) { - out.writeBytes(gzipHeader); - } - } - - if (wrapper == ZlibWrapper.GZIP) { - crc.update(inAry, offset, len); - } - - deflater.setInput(inAry, offset, len); - while (!deflater.needsInput()) { - deflate(out); - } - } - - @Override - protected final ByteBuf allocateBuffer(ChannelHandlerContext ctx, ByteBuf msg, - boolean preferDirect) throws Exception { - int sizeEstimate = (int) Math.ceil(msg.readableBytes() * 1.001) + 12; - if (writeHeader) { - switch (wrapper) { - case GZIP: - sizeEstimate += gzipHeader.length; - break; - case ZLIB: - sizeEstimate += 2; // first two magic bytes - break; - } - } - return ctx.alloc().heapBuffer(sizeEstimate); - } - - @Override - public void close(final ChannelHandlerContext ctx, final ChannelPromise promise) throws Exception { - ChannelFuture f = finishEncode(ctx, ctx.newPromise()); - f.addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture f) throws Exception { - ctx.close(promise); - } - }); - - if (!f.isDone()) { - // Ensure the channel is closed even if the write operation completes in time. - ctx.executor().schedule(new Runnable() { - @Override - public void run() { - ctx.close(promise); - } - }, 10, TimeUnit.SECONDS); // FIXME: Magic number - } - } - - private ChannelFuture finishEncode(final ChannelHandlerContext ctx, ChannelPromise promise) { - if (finished) { - promise.setSuccess(); - return promise; - } - - finished = true; - ByteBuf footer = ctx.alloc().heapBuffer(); - if (writeHeader && wrapper == ZlibWrapper.GZIP) { - // Write the GZIP header first if not written yet. (i.e. user wrote nothing.) - writeHeader = false; - footer.writeBytes(gzipHeader); - } - - deflater.finish(); - - while (!deflater.finished()) { - deflate(footer); - if (!footer.isWritable()) { - // no more space so write it to the channel and continue - ctx.write(footer); - footer = ctx.alloc().heapBuffer(); - } - } - if (wrapper == ZlibWrapper.GZIP) { - int crcValue = (int) crc.getValue(); - int uncBytes = deflater.getTotalIn(); - footer.writeByte(crcValue); - footer.writeByte(crcValue >>> 8); - footer.writeByte(crcValue >>> 16); - footer.writeByte(crcValue >>> 24); - footer.writeByte(uncBytes); - footer.writeByte(uncBytes >>> 8); - footer.writeByte(uncBytes >>> 16); - footer.writeByte(uncBytes >>> 24); - } - deflater.end(); - return ctx.writeAndFlush(footer, promise); - } - - private void deflate(ByteBuf out) { - int numBytes; - do { - int writerIndex = out.writerIndex(); - numBytes = deflater.deflate( - out.array(), out.arrayOffset() + writerIndex, out.writableBytes(), Deflater.SYNC_FLUSH); - out.writerIndex(writerIndex + numBytes); - } while (numBytes > 0); - } - - @Override - public void handlerAdded(ChannelHandlerContext ctx) throws Exception { - this.ctx = ctx; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/Snappy.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/Snappy.java deleted file mode 100755 index a4fff914b9..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/Snappy.java +++ /dev/null @@ -1,674 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.compression; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.ByteBufUtil; - -/** - * Uncompresses an input {@link ByteBuf} encoded with Snappy compression into an - * output {@link ByteBuf}. - * - * See http://code.google.com/p/snappy/source/browse/trunk/format_description.txt - */ -class Snappy { - - private static final int MAX_HT_SIZE = 1 << 14; - private static final int MIN_COMPRESSIBLE_BYTES = 15; - - // used as a return value to indicate that we haven't yet read our full preamble - private static final int PREAMBLE_NOT_FULL = -1; - private static final int NOT_ENOUGH_INPUT = -1; - - // constants for the tag types - private static final int LITERAL = 0; - private static final int COPY_1_BYTE_OFFSET = 1; - private static final int COPY_2_BYTE_OFFSET = 2; - private static final int COPY_4_BYTE_OFFSET = 3; - - private State state = State.READY; - private byte tag; - private int written; - - private enum State { - READY, - READING_PREAMBLE, - READING_TAG, - READING_LITERAL, - READING_COPY - } - - public void reset() { - state = State.READY; - tag = 0; - written = 0; - } - - public void encode(final ByteBuf in, final ByteBuf out, final int length) { - // Write the preamble length to the output buffer - for (int i = 0;; i ++) { - int b = length >>> i * 7; - if ((b & 0xFFFFFF80) != 0) { - out.writeByte(b & 0x7f | 0x80); - } else { - out.writeByte(b); - break; - } - } - - int inIndex = in.readerIndex(); - final int baseIndex = inIndex; - - final short[] table = getHashTable(length); - final int shift = 32 - (int) Math.floor(Math.log(table.length) / Math.log(2)); - - int nextEmit = inIndex; - - if (length - inIndex >= MIN_COMPRESSIBLE_BYTES) { - int nextHash = hash(in, ++inIndex, shift); - outer: while (true) { - int skip = 32; - - int candidate; - int nextIndex = inIndex; - do { - inIndex = nextIndex; - int hash = nextHash; - int bytesBetweenHashLookups = skip++ >> 5; - nextIndex = inIndex + bytesBetweenHashLookups; - - // We need at least 4 remaining bytes to read the hash - if (nextIndex > length - 4) { - break outer; - } - - nextHash = hash(in, nextIndex, shift); - - candidate = baseIndex + table[hash]; - - table[hash] = (short) (inIndex - baseIndex); - } - while (in.getInt(inIndex) != in.getInt(candidate)); - - encodeLiteral(in, out, inIndex - nextEmit); - - int insertTail; - do { - int base = inIndex; - int matched = 4 + findMatchingLength(in, candidate + 4, inIndex + 4, length); - inIndex += matched; - int offset = base - candidate; - encodeCopy(out, offset, matched); - in.readerIndex(in.readerIndex() + matched); - insertTail = inIndex - 1; - nextEmit = inIndex; - if (inIndex >= length - 4) { - break outer; - } - - int prevHash = hash(in, insertTail, shift); - table[prevHash] = (short) (inIndex - baseIndex - 1); - int currentHash = hash(in, insertTail + 1, shift); - candidate = baseIndex + table[currentHash]; - table[currentHash] = (short) (inIndex - baseIndex); - } - while (in.getInt(insertTail + 1) == in.getInt(candidate)); - - nextHash = hash(in, insertTail + 2, shift); - ++inIndex; - } - } - - // If there are any remaining characters, write them out as a literal - if (nextEmit < length) { - encodeLiteral(in, out, length - nextEmit); - } - } - - /** - * Hashes the 4 bytes located at index, shifting the resulting hash into - * the appropriate range for our hash table. - * - * @param in The input buffer to read 4 bytes from - * @param index The index to read at - * @param shift The shift value, for ensuring that the resulting value is - * withing the range of our hash table size - * @return A 32-bit hash of 4 bytes located at index - */ - private static int hash(ByteBuf in, int index, int shift) { - return in.getInt(index) + 0x1e35a7bd >>> shift; - } - - /** - * Creates an appropriately sized hashtable for the given input size - * - * @param inputSize The size of our input, ie. the number of bytes we need to encode - * @return An appropriately sized empty hashtable - */ - private static short[] getHashTable(int inputSize) { - int htSize = 256; - while (htSize < MAX_HT_SIZE && htSize < inputSize) { - htSize <<= 1; - } - - short[] table; - if (htSize <= 256) { - table = new short[256]; - } else { - table = new short[MAX_HT_SIZE]; - } - - return table; - } - - /** - * Iterates over the supplied input buffer between the supplied minIndex and - * maxIndex to find how long our matched copy overlaps with an already-written - * literal value. - * - * @param in The input buffer to scan over - * @param minIndex The index in the input buffer to start scanning from - * @param inIndex The index of the start of our copy - * @param maxIndex The length of our input buffer - * @return The number of bytes for which our candidate copy is a repeat of - */ - private static int findMatchingLength(ByteBuf in, int minIndex, int inIndex, int maxIndex) { - int matched = 0; - - while (inIndex <= maxIndex - 4 && - in.getInt(inIndex) == in.getInt(minIndex + matched)) { - inIndex += 4; - matched += 4; - } - - while (inIndex < maxIndex && in.getByte(minIndex + matched) == in.getByte(inIndex)) { - ++inIndex; - ++matched; - } - - return matched; - } - - /** - * Calculates the minimum number of bits required to encode a value. This can - * then in turn be used to calculate the number of septets or octets (as - * appropriate) to use to encode a length parameter. - * - * @param value The value to calculate the minimum number of bits required to encode - * @return The minimum number of bits required to encode the supplied value - */ - private static int bitsToEncode(int value) { - int highestOneBit = Integer.highestOneBit(value); - int bitLength = 0; - while ((highestOneBit >>= 1) != 0) { - bitLength++; - } - - return bitLength; - } - - /** - * Writes a literal to the supplied output buffer by directly copying from - * the input buffer. The literal is taken from the current readerIndex - * up to the supplied length. - * - * @param in The input buffer to copy from - * @param out The output buffer to copy to - * @param length The length of the literal to copy - */ - private static void encodeLiteral(ByteBuf in, ByteBuf out, int length) { - if (length < 61) { - out.writeByte(length - 1 << 2); - } else { - int bitLength = bitsToEncode(length - 1); - int bytesToEncode = 1 + bitLength / 8; - out.writeByte(59 + bytesToEncode << 2); - for (int i = 0; i < bytesToEncode; i++) { - out.writeByte(length - 1 >> i * 8 & 0x0ff); - } - } - - out.writeBytes(in, length); - } - - private static void encodeCopyWithOffset(ByteBuf out, int offset, int length) { - if (length < 12 && offset < 2048) { - out.writeByte(COPY_1_BYTE_OFFSET | length - 4 << 2 | offset >> 8 << 5); - out.writeByte(offset & 0x0ff); - } else { - out.writeByte(COPY_2_BYTE_OFFSET | length - 1 << 2); - out.writeByte(offset & 0x0ff); - out.writeByte(offset >> 8 & 0x0ff); - } - } - - /** - * Encodes a series of copies, each at most 64 bytes in length. - * - * @param out The output buffer to write the copy pointer to - * @param offset The offset at which the original instance lies - * @param length The length of the original instance - */ - private static void encodeCopy(ByteBuf out, int offset, int length) { - while (length >= 68) { - encodeCopyWithOffset(out, offset, 64); - length -= 64; - } - - if (length > 64) { - encodeCopyWithOffset(out, offset, 60); - length -= 60; - } - - encodeCopyWithOffset(out, offset, length); - } - - public void decode(ByteBuf in, ByteBuf out) { - while (in.isReadable()) { - switch (state) { - case READY: - state = State.READING_PREAMBLE; - case READING_PREAMBLE: - int uncompressedLength = readPreamble(in); - if (uncompressedLength == PREAMBLE_NOT_FULL) { - // We've not yet read all of the preamble, so wait until we can - return; - } - if (uncompressedLength == 0) { - // Should never happen, but it does mean we have nothing further to do - state = State.READY; - return; - } - out.ensureWritable(uncompressedLength); - state = State.READING_TAG; - case READING_TAG: - if (!in.isReadable()) { - return; - } - tag = in.readByte(); - switch (tag & 0x03) { - case LITERAL: - state = State.READING_LITERAL; - break; - case COPY_1_BYTE_OFFSET: - case COPY_2_BYTE_OFFSET: - case COPY_4_BYTE_OFFSET: - state = State.READING_COPY; - break; - } - break; - case READING_LITERAL: - int literalWritten = decodeLiteral(tag, in, out); - if (literalWritten != NOT_ENOUGH_INPUT) { - state = State.READING_TAG; - written += literalWritten; - } else { - // Need to wait for more data - return; - } - break; - case READING_COPY: - int decodeWritten; - switch (tag & 0x03) { - case COPY_1_BYTE_OFFSET: - decodeWritten = decodeCopyWith1ByteOffset(tag, in, out, written); - if (decodeWritten != NOT_ENOUGH_INPUT) { - state = State.READING_TAG; - written += decodeWritten; - } else { - // Need to wait for more data - return; - } - break; - case COPY_2_BYTE_OFFSET: - decodeWritten = decodeCopyWith2ByteOffset(tag, in, out, written); - if (decodeWritten != NOT_ENOUGH_INPUT) { - state = State.READING_TAG; - written += decodeWritten; - } else { - // Need to wait for more data - return; - } - break; - case COPY_4_BYTE_OFFSET: - decodeWritten = decodeCopyWith4ByteOffset(tag, in, out, written); - if (decodeWritten != NOT_ENOUGH_INPUT) { - state = State.READING_TAG; - written += decodeWritten; - } else { - // Need to wait for more data - return; - } - break; - } - } - } - } - - /** - * Reads the length varint (a series of bytes, where the lower 7 bits - * are data and the upper bit is a flag to indicate more bytes to be - * read). - * - * @param in The input buffer to read the preamble from - * @return The calculated length based on the input buffer, or 0 if - * no preamble is able to be calculated - */ - private static int readPreamble(ByteBuf in) { - int length = 0; - int byteIndex = 0; - while (in.isReadable()) { - int current = in.readUnsignedByte(); - length |= (current & 0x7f) << byteIndex++ * 7; - if ((current & 0x80) == 0) { - return length; - } - - if (byteIndex >= 4) { - throw new DecompressionException("Preamble is greater than 4 bytes"); - } - } - - return 0; - } - - /** - * Reads a literal from the input buffer directly to the output buffer. - * A "literal" is an uncompressed segment of data stored directly in the - * byte stream. - * - * @param tag The tag that identified this segment as a literal is also - * used to encode part of the length of the data - * @param in The input buffer to read the literal from - * @param out The output buffer to write the literal to - * @return The number of bytes appended to the output buffer, or -1 to indicate "try again later" - */ - private static int decodeLiteral(byte tag, ByteBuf in, ByteBuf out) { - in.markReaderIndex(); - int length; - switch(tag >> 2 & 0x3F) { - case 60: - if (!in.isReadable()) { - return NOT_ENOUGH_INPUT; - } - length = in.readUnsignedByte(); - break; - case 61: - if (in.readableBytes() < 2) { - return NOT_ENOUGH_INPUT; - } - length = ByteBufUtil.swapShort(in.readShort()); - break; - case 62: - if (in.readableBytes() < 3) { - return NOT_ENOUGH_INPUT; - } - length = ByteBufUtil.swapMedium(in.readUnsignedMedium()); - break; - case 64: - if (in.readableBytes() < 4) { - return NOT_ENOUGH_INPUT; - } - length = ByteBufUtil.swapInt(in.readInt()); - break; - default: - length = tag >> 2 & 0x3F; - } - length += 1; - - if (in.readableBytes() < length) { - in.resetReaderIndex(); - return NOT_ENOUGH_INPUT; - } - - out.writeBytes(in, length); - return length; - } - - /** - * Reads a compressed reference offset and length from the supplied input - * buffer, seeks back to the appropriate place in the input buffer and - * writes the found data to the supplied output stream. - * - * @param tag The tag used to identify this as a copy is also used to encode - * the length and part of the offset - * @param in The input buffer to read from - * @param out The output buffer to write to - * @return The number of bytes appended to the output buffer, or -1 to indicate - * "try again later" - * @throws DecompressionException If the read offset is invalid - */ - private static int decodeCopyWith1ByteOffset(byte tag, ByteBuf in, ByteBuf out, int writtenSoFar) { - if (!in.isReadable()) { - return NOT_ENOUGH_INPUT; - } - - int initialIndex = out.writerIndex(); - int length = 4 + ((tag & 0x01c) >> 2); - int offset = (tag & 0x0e0) << 8 >> 5 | in.readUnsignedByte(); - - validateOffset(offset, writtenSoFar); - - out.markReaderIndex(); - if (offset < length) { - int copies = length / offset; - for (; copies > 0; copies--) { - out.readerIndex(initialIndex - offset); - out.readBytes(out, offset); - } - if (length % offset != 0) { - out.readerIndex(initialIndex - offset); - out.readBytes(out, length % offset); - } - } else { - out.readerIndex(initialIndex - offset); - out.readBytes(out, length); - } - out.resetReaderIndex(); - - return length; - } - - /** - * Reads a compressed reference offset and length from the supplied input - * buffer, seeks back to the appropriate place in the input buffer and - * writes the found data to the supplied output stream. - * - * @param tag The tag used to identify this as a copy is also used to encode - * the length and part of the offset - * @param in The input buffer to read from - * @param out The output buffer to write to - * @throws DecompressionException If the read offset is invalid - * @return The number of bytes appended to the output buffer, or -1 to indicate - * "try again later" - */ - private static int decodeCopyWith2ByteOffset(byte tag, ByteBuf in, ByteBuf out, int writtenSoFar) { - if (in.readableBytes() < 2) { - return NOT_ENOUGH_INPUT; - } - - int initialIndex = out.writerIndex(); - int length = 1 + (tag >> 2 & 0x03f); - int offset = ByteBufUtil.swapShort(in.readShort()); - - validateOffset(offset, writtenSoFar); - - out.markReaderIndex(); - if (offset < length) { - int copies = length / offset; - for (; copies > 0; copies--) { - out.readerIndex(initialIndex - offset); - out.readBytes(out, offset); - } - if (length % offset != 0) { - out.readerIndex(initialIndex - offset); - out.readBytes(out, length % offset); - } - } else { - out.readerIndex(initialIndex - offset); - out.readBytes(out, length); - } - out.resetReaderIndex(); - - return length; - } - - /** - * Reads a compressed reference offset and length from the supplied input - * buffer, seeks back to the appropriate place in the input buffer and - * writes the found data to the supplied output stream. - * - * @param tag The tag used to identify this as a copy is also used to encode - * the length and part of the offset - * @param in The input buffer to read from - * @param out The output buffer to write to - * @return The number of bytes appended to the output buffer, or -1 to indicate - * "try again later" - * @throws DecompressionException If the read offset is invalid - */ - private static int decodeCopyWith4ByteOffset(byte tag, ByteBuf in, ByteBuf out, int writtenSoFar) { - if (in.readableBytes() < 4) { - return NOT_ENOUGH_INPUT; - } - - int initialIndex = out.writerIndex(); - int length = 1 + (tag >> 2 & 0x03F); - int offset = ByteBufUtil.swapInt(in.readInt()); - - validateOffset(offset, writtenSoFar); - - out.markReaderIndex(); - if (offset < length) { - int copies = length / offset; - for (; copies > 0; copies--) { - out.readerIndex(initialIndex - offset); - out.readBytes(out, offset); - } - if (length % offset != 0) { - out.readerIndex(initialIndex - offset); - out.readBytes(out, length % offset); - } - } else { - out.readerIndex(initialIndex - offset); - out.readBytes(out, length); - } - out.resetReaderIndex(); - - return length; - } - - /** - * Validates that the offset extracted from a compressed reference is within - * the permissible bounds of an offset (4 <= offset <= 32768), and does not - * exceed the length of the chunk currently read so far. - * - * @param offset The offset extracted from the compressed reference - * @param chunkSizeSoFar The number of bytes read so far from this chunk - * @throws DecompressionException if the offset is invalid - */ - private static void validateOffset(int offset, int chunkSizeSoFar) { - if (offset > Short.MAX_VALUE) { - throw new DecompressionException("Offset exceeds maximum permissible value"); - } - - if (offset <= 0) { - throw new DecompressionException("Offset is less than minimum permissible value"); - } - - if (offset > chunkSizeSoFar) { - throw new DecompressionException("Offset exceeds size of chunk"); - } - } - - /** - * Computes the CRC32C checksum of the supplied data and performs the "mask" operation - * on the computed checksum - * - * @param data The input data to calculate the CRC32C checksum of - */ - public static int calculateChecksum(ByteBuf data) { - return calculateChecksum(data, data.readerIndex(), data.readableBytes()); - } - - /** - * Computes the CRC32C checksum of the supplied data and performs the "mask" operation - * on the computed checksum - * - * @param data The input data to calculate the CRC32C checksum of - */ - public static int calculateChecksum(ByteBuf data, int offset, int length) { - Crc32c crc32 = new Crc32c(); - try { - if (data.hasArray()) { - crc32.update(data.array(), data.arrayOffset() + offset, length); - } else { - byte[] array = new byte[length]; - data.getBytes(offset, array); - crc32.update(array, 0, length); - } - - return maskChecksum((int) crc32.getValue()); - } finally { - crc32.reset(); - } - } - - /** - * Computes the CRC32C checksum of the supplied data, performs the "mask" operation - * on the computed checksum, and then compares the resulting masked checksum to the - * supplied checksum. - * - * @param expectedChecksum The checksum decoded from the stream to compare against - * @param data The input data to calculate the CRC32C checksum of - * @throws DecompressionException If the calculated and supplied checksums do not match - */ - static void validateChecksum(int expectedChecksum, ByteBuf data) { - validateChecksum(expectedChecksum, data, data.readerIndex(), data.readableBytes()); - } - - /** - * Computes the CRC32C checksum of the supplied data, performs the "mask" operation - * on the computed checksum, and then compares the resulting masked checksum to the - * supplied checksum. - * - * @param expectedChecksum The checksum decoded from the stream to compare against - * @param data The input data to calculate the CRC32C checksum of - * @throws DecompressionException If the calculated and supplied checksums do not match - */ - static void validateChecksum(int expectedChecksum, ByteBuf data, int offset, int length) { - final int actualChecksum = calculateChecksum(data, offset, length); - if (actualChecksum != expectedChecksum) { - throw new DecompressionException( - "mismatching checksum: " + Integer.toHexString(actualChecksum) + - " (expected: " + Integer.toHexString(expectedChecksum) + ')'); - } - } - - /** - * From the spec: - * - * "Checksums are not stored directly, but masked, as checksumming data and - * then its own checksum can be problematic. The masking is the same as used - * in Apache Hadoop: Rotate the checksum by 15 bits, then add the constant - * 0xa282ead8 (using wraparound as normal for unsigned integers)." - * - * @param checksum The actual checksum of the data - * @return The masked checksum - */ - static int maskChecksum(int checksum) { - return (checksum >> 15 | checksum << 17) + 0xa282ead8; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/SnappyFramedDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/SnappyFramedDecoder.java deleted file mode 100755 index 7b70535ce1..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/SnappyFramedDecoder.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.compression; - -import static com.ai.cloud.io.netty.handler.codec.compression.Snappy.validateChecksum; - -import java.util.Arrays; -import java.util.List; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.ByteBufUtil; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.handler.codec.ByteToMessageDecoder; - -/** - * Uncompresses a {@link ByteBuf} encoded with the Snappy framing format. - * - * See http://code.google.com/p/snappy/source/browse/trunk/framing_format.txt - * - * Note that by default, validation of the checksum header in each chunk is - * DISABLED for performance improvements. If performance is less of an issue, - * or if you would prefer the safety that checksum validation brings, please - * use the {@link #SnappyFramedDecoder(boolean)} constructor with the argument - * set to {@code true}. - */ -public class SnappyFramedDecoder extends ByteToMessageDecoder { - - private enum ChunkType { - STREAM_IDENTIFIER, - COMPRESSED_DATA, - UNCOMPRESSED_DATA, - RESERVED_UNSKIPPABLE, - RESERVED_SKIPPABLE - } - - private static final byte[] SNAPPY = { 's', 'N', 'a', 'P', 'p', 'Y' }; - private static final int MAX_UNCOMPRESSED_DATA_SIZE = 65536 + 4; - - private final Snappy snappy = new Snappy(); - private final boolean validateChecksums; - - private boolean started; - private boolean corrupted; - - /** - * Creates a new snappy-framed decoder with validation of checksums - * turned OFF. To turn checksum validation on, please use the alternate - * {@link #SnappyFramedDecoder(boolean)} constructor. - */ - public SnappyFramedDecoder() { - this(false); - } - - /** - * Creates a new snappy-framed decoder with validation of checksums - * as specified. - * - * @param validateChecksums - * If true, the checksum field will be validated against the actual - * uncompressed data, and if the checksums do not match, a suitable - * {@link DecompressionException} will be thrown - */ - public SnappyFramedDecoder(boolean validateChecksums) { - this.validateChecksums = validateChecksums; - } - - @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { - if (corrupted) { - in.skipBytes(in.readableBytes()); - return; - } - - try { - int idx = in.readerIndex(); - final int inSize = in.readableBytes(); - if (inSize < 4) { - // We need to be at least able to read the chunk type identifier (one byte), - // and the length of the chunk (3 bytes) in order to proceed - return; - } - - final int chunkTypeVal = in.getUnsignedByte(idx); - final ChunkType chunkType = mapChunkType((byte) chunkTypeVal); - final int chunkLength = ByteBufUtil.swapMedium(in.getUnsignedMedium(idx + 1)); - - switch (chunkType) { - case STREAM_IDENTIFIER: - if (chunkLength != SNAPPY.length) { - throw new DecompressionException("Unexpected length of stream identifier: " + chunkLength); - } - - if (inSize < 4 + SNAPPY.length) { - break; - } - - byte[] identifier = new byte[chunkLength]; - in.skipBytes(4).readBytes(identifier); - - if (!Arrays.equals(identifier, SNAPPY)) { - throw new DecompressionException("Unexpected stream identifier contents. Mismatched snappy " + - "protocol version?"); - } - - started = true; - break; - case RESERVED_SKIPPABLE: - if (!started) { - throw new DecompressionException("Received RESERVED_SKIPPABLE tag before STREAM_IDENTIFIER"); - } - - if (inSize < 4 + chunkLength) { - // TODO: Don't keep skippable bytes - return; - } - - in.skipBytes(4 + chunkLength); - break; - case RESERVED_UNSKIPPABLE: - // The spec mandates that reserved unskippable chunks must immediately - // return an error, as we must assume that we cannot decode the stream - // correctly - throw new DecompressionException( - "Found reserved unskippable chunk type: 0x" + Integer.toHexString(chunkTypeVal)); - case UNCOMPRESSED_DATA: - if (!started) { - throw new DecompressionException("Received UNCOMPRESSED_DATA tag before STREAM_IDENTIFIER"); - } - if (chunkLength > MAX_UNCOMPRESSED_DATA_SIZE) { - throw new DecompressionException("Received UNCOMPRESSED_DATA larger than 65540 bytes"); - } - - if (inSize < 4 + chunkLength) { - return; - } - - in.skipBytes(4); - if (validateChecksums) { - int checksum = ByteBufUtil.swapInt(in.readInt()); - validateChecksum(checksum, in, in.readerIndex(), chunkLength - 4); - } else { - in.skipBytes(4); - } - out.add(in.readSlice(chunkLength - 4).retain()); - break; - case COMPRESSED_DATA: - if (!started) { - throw new DecompressionException("Received COMPRESSED_DATA tag before STREAM_IDENTIFIER"); - } - - if (inSize < 4 + chunkLength) { - return; - } - - in.skipBytes(4); - int checksum = ByteBufUtil.swapInt(in.readInt()); - ByteBuf uncompressed = ctx.alloc().buffer(0); - if (validateChecksums) { - int oldWriterIndex = in.writerIndex(); - try { - in.writerIndex(in.readerIndex() + chunkLength - 4); - snappy.decode(in, uncompressed); - } finally { - in.writerIndex(oldWriterIndex); - } - validateChecksum(checksum, uncompressed, 0, uncompressed.writerIndex()); - } else { - snappy.decode(in.readSlice(chunkLength - 4), uncompressed); - } - out.add(uncompressed); - snappy.reset(); - break; - } - } catch (Exception e) { - corrupted = true; - throw e; - } - } - - /** - * Decodes the chunk type from the type tag byte. - * - * @param type The tag byte extracted from the stream - * @return The appropriate {@link ChunkType}, defaulting to {@link ChunkType#RESERVED_UNSKIPPABLE} - */ - private static ChunkType mapChunkType(byte type) { - if (type == 0) { - return ChunkType.COMPRESSED_DATA; - } else if (type == 1) { - return ChunkType.UNCOMPRESSED_DATA; - } else if (type == (byte) 0xff) { - return ChunkType.STREAM_IDENTIFIER; - } else if ((type & 0x80) == 0x80) { - return ChunkType.RESERVED_SKIPPABLE; - } else { - return ChunkType.RESERVED_UNSKIPPABLE; - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/SnappyFramedEncoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/SnappyFramedEncoder.java deleted file mode 100755 index f9697e59ff..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/SnappyFramedEncoder.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.compression; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.ByteBufUtil; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.handler.codec.MessageToByteEncoder; - -import static com.ai.cloud.io.netty.handler.codec.compression.Snappy.*; - -/** - * Compresses a {@link ByteBuf} using the Snappy framing format. - * - * See http://code.google.com/p/snappy/source/browse/trunk/framing_format.txt - */ -public class SnappyFramedEncoder extends MessageToByteEncoder { - /** - * The minimum amount that we'll consider actually attempting to compress. - * This value is preamble + the minimum length our Snappy service will - * compress (instead of just emitting a literal). - */ - private static final int MIN_COMPRESSIBLE_LENGTH = 18; - - /** - * All streams should start with the "Stream identifier", containing chunk - * type 0xff, a length field of 0x6, and 'sNaPpY' in ASCII. - */ - private static final byte[] STREAM_START = { - (byte) 0xff, 0x06, 0x00, 0x00, 0x73, 0x4e, 0x61, 0x50, 0x70, 0x59 - }; - - private final Snappy snappy = new Snappy(); - private boolean started; - - @Override - protected void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception { - if (!in.isReadable()) { - return; - } - - if (!started) { - started = true; - out.writeBytes(STREAM_START); - } - - int dataLength = in.readableBytes(); - if (dataLength > MIN_COMPRESSIBLE_LENGTH) { - for (;;) { - final int lengthIdx = out.writerIndex() + 1; - if (dataLength < MIN_COMPRESSIBLE_LENGTH) { - ByteBuf slice = in.readSlice(dataLength); - writeUnencodedChunk(slice, out, dataLength); - break; - } - - out.writeInt(0); - if (dataLength > Short.MAX_VALUE) { - ByteBuf slice = in.readSlice(Short.MAX_VALUE); - calculateAndWriteChecksum(slice, out); - snappy.encode(slice, out, Short.MAX_VALUE); - setChunkLength(out, lengthIdx); - dataLength -= Short.MAX_VALUE; - } else { - ByteBuf slice = in.readSlice(dataLength); - calculateAndWriteChecksum(slice, out); - snappy.encode(slice, out, dataLength); - setChunkLength(out, lengthIdx); - break; - } - } - } else { - writeUnencodedChunk(in, out, dataLength); - } - } - - private static void writeUnencodedChunk(ByteBuf in, ByteBuf out, int dataLength) { - out.writeByte(1); - writeChunkLength(out, dataLength + 4); - calculateAndWriteChecksum(in, out); - out.writeBytes(in, dataLength); - } - - private static void setChunkLength(ByteBuf out, int lengthIdx) { - int chunkLength = out.writerIndex() - lengthIdx - 3; - if (chunkLength >>> 24 != 0) { - throw new CompressionException("compressed data too large: " + chunkLength); - } - out.setMedium(lengthIdx, ByteBufUtil.swapMedium(chunkLength)); - } - - /** - * Writes the 2-byte chunk length to the output buffer. - * - * @param out The buffer to write to - * @param chunkLength The length to write - */ - private static void writeChunkLength(ByteBuf out, int chunkLength) { - out.writeMedium(ByteBufUtil.swapMedium(chunkLength)); - } - - /** - * Calculates and writes the 4-byte checksum to the output buffer - * - * @param slice The data to calculate the checksum for - * @param out The output buffer to write the checksum to - */ - private static void calculateAndWriteChecksum(ByteBuf slice, ByteBuf out) { - out.writeInt(ByteBufUtil.swapInt(calculateChecksum(slice))); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/ZlibCodecFactory.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/ZlibCodecFactory.java deleted file mode 100755 index 267d651270..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/ZlibCodecFactory.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.compression; - -import com.ai.cloud.io.netty.util.internal.PlatformDependent; -import com.ai.cloud.io.netty.util.internal.SystemPropertyUtil; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * Creates a new {@link ZlibEncoder} and a new {@link ZlibDecoder}. - */ -public final class ZlibCodecFactory { - private static final InternalLogger logger = InternalLoggerFactory.getInstance(ZlibCodecFactory.class); - - private static final int DEFAULT_JDK_WINDOW_SIZE = 15; - private static final int DEFAULT_JDK_MEM_LEVEL = 8; - - private static final boolean noJdkZlibDecoder; - private static final boolean noJdkZlibEncoder; - - static { - noJdkZlibDecoder = SystemPropertyUtil.getBoolean("io.netty.noJdkZlibDecoder", true); - logger.debug("-Dio.netty.noJdkZlibDecoder: {}", noJdkZlibDecoder); - - noJdkZlibEncoder = SystemPropertyUtil.getBoolean("io.netty.noJdkZlibEncoder", false); - logger.debug("-Dio.netty.noJdkZlibEncoder: {}", noJdkZlibEncoder); - } - - public static ZlibEncoder newZlibEncoder(int compressionLevel) { - if (PlatformDependent.javaVersion() < 7 || noJdkZlibEncoder) { - return new JZlibEncoder(compressionLevel); - } else { - return new JdkZlibEncoder(compressionLevel); - } - } - - public static ZlibEncoder newZlibEncoder(ZlibWrapper wrapper) { - if (PlatformDependent.javaVersion() < 7 || noJdkZlibEncoder) { - return new JZlibEncoder(wrapper); - } else { - return new JdkZlibEncoder(wrapper); - } - } - - public static ZlibEncoder newZlibEncoder(ZlibWrapper wrapper, int compressionLevel) { - if (PlatformDependent.javaVersion() < 7 || noJdkZlibEncoder) { - return new JZlibEncoder(wrapper, compressionLevel); - } else { - return new JdkZlibEncoder(wrapper, compressionLevel); - } - } - - public static ZlibEncoder newZlibEncoder(ZlibWrapper wrapper, int compressionLevel, int windowBits, int memLevel) { - if (PlatformDependent.javaVersion() < 7 || noJdkZlibEncoder || - windowBits != DEFAULT_JDK_WINDOW_SIZE || memLevel != DEFAULT_JDK_MEM_LEVEL) { - return new JZlibEncoder(wrapper, compressionLevel, windowBits, memLevel); - } else { - return new JdkZlibEncoder(wrapper, compressionLevel); - } - } - - public static ZlibEncoder newZlibEncoder(byte[] dictionary) { - if (PlatformDependent.javaVersion() < 7 || noJdkZlibEncoder) { - return new JZlibEncoder(dictionary); - } else { - return new JdkZlibEncoder(dictionary); - } - } - - public static ZlibEncoder newZlibEncoder(int compressionLevel, byte[] dictionary) { - if (PlatformDependent.javaVersion() < 7 || noJdkZlibEncoder) { - return new JZlibEncoder(compressionLevel, dictionary); - } else { - return new JdkZlibEncoder(compressionLevel, dictionary); - } - } - - public static ZlibEncoder newZlibEncoder(int compressionLevel, int windowBits, int memLevel, byte[] dictionary) { - if (PlatformDependent.javaVersion() < 7 || noJdkZlibEncoder || - windowBits != DEFAULT_JDK_WINDOW_SIZE || memLevel != DEFAULT_JDK_MEM_LEVEL) { - return new JZlibEncoder(compressionLevel, windowBits, memLevel, dictionary); - } else { - return new JdkZlibEncoder(compressionLevel, dictionary); - } - } - - public static ZlibDecoder newZlibDecoder() { - if (PlatformDependent.javaVersion() < 7 || noJdkZlibDecoder) { - return new JZlibDecoder(); - } else { - return new JdkZlibDecoder(); - } - } - - public static ZlibDecoder newZlibDecoder(ZlibWrapper wrapper) { - if (PlatformDependent.javaVersion() < 7 || noJdkZlibDecoder) { - return new JZlibDecoder(wrapper); - } else { - return new JdkZlibDecoder(wrapper); - } - } - - public static ZlibDecoder newZlibDecoder(byte[] dictionary) { - if (PlatformDependent.javaVersion() < 7 || noJdkZlibDecoder) { - return new JZlibDecoder(dictionary); - } else { - return new JdkZlibDecoder(dictionary); - } - } - - private ZlibCodecFactory() { - // Unused - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/ZlibDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/ZlibDecoder.java deleted file mode 100755 index 0470a60fc7..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/ZlibDecoder.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.compression; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.handler.codec.ByteToMessageDecoder; - -/** - * Decompresses a {@link ByteBuf} using the deflate algorithm. - */ -public abstract class ZlibDecoder extends ByteToMessageDecoder { - - /** - * Returns {@code true} if and only if the end of the compressed stream - * has been reached. - */ - public abstract boolean isClosed(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/ZlibEncoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/ZlibEncoder.java deleted file mode 100755 index 7f22d2c884..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/ZlibEncoder.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.compression; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelFuture; -import com.ai.cloud.io.netty.channel.ChannelPromise; -import com.ai.cloud.io.netty.handler.codec.MessageToByteEncoder; - -/** - * Compresses a {@link ByteBuf} using the deflate algorithm. - */ -public abstract class ZlibEncoder extends MessageToByteEncoder { - - protected ZlibEncoder() { - super(false); - } - - /** - * Returns {@code true} if and only if the end of the compressed stream - * has been reached. - */ - public abstract boolean isClosed(); - - /** - * Close this {@link ZlibEncoder} and so finish the encoding. - * - * The returned {@link ChannelFuture} will be notified once the - * operation completes. - */ - public abstract ChannelFuture close(); - - /** - * Close this {@link ZlibEncoder} and so finish the encoding. - * The given {@link ChannelFuture} will be notified once the operation - * completes and will also be returned. - */ - public abstract ChannelFuture close(ChannelPromise promise); - -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/ZlibUtil.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/ZlibUtil.java deleted file mode 100755 index dc2f10a699..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/ZlibUtil.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.compression; - -import com.jcraft.jzlib.Deflater; -import com.jcraft.jzlib.Inflater; -import com.jcraft.jzlib.JZlib; - -/** - * Utility methods used by {@link JZlibEncoder} and {@link JZlibDecoder}. - */ -final class ZlibUtil { - - static void fail(Inflater z, String message, int resultCode) { - throw inflaterException(z, message, resultCode); - } - - static void fail(Deflater z, String message, int resultCode) { - throw deflaterException(z, message, resultCode); - } - - static DecompressionException inflaterException(Inflater z, String message, int resultCode) { - return new DecompressionException(message + " (" + resultCode + ')' + (z.msg != null? ": " + z.msg : "")); - } - - static CompressionException deflaterException(Deflater z, String message, int resultCode) { - return new CompressionException(message + " (" + resultCode + ')' + (z.msg != null? ": " + z.msg : "")); - } - - static JZlib.WrapperType convertWrapperType(ZlibWrapper wrapper) { - JZlib.WrapperType convertedWrapperType; - switch (wrapper) { - case NONE: - convertedWrapperType = JZlib.W_NONE; - break; - case ZLIB: - convertedWrapperType = JZlib.W_ZLIB; - break; - case GZIP: - convertedWrapperType = JZlib.W_GZIP; - break; - case ZLIB_OR_NONE: - convertedWrapperType = JZlib.W_ANY; - break; - default: - throw new Error(); - } - return convertedWrapperType; - } - - static int wrapperOverhead(ZlibWrapper wrapper) { - int overhead; - switch (wrapper) { - case NONE: - overhead = 0; - break; - case ZLIB: - case ZLIB_OR_NONE: - overhead = 2; - break; - case GZIP: - overhead = 10; - break; - default: - throw new Error(); - } - return overhead; - } - - private ZlibUtil() { - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/ZlibWrapper.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/ZlibWrapper.java deleted file mode 100755 index 185f8053cb..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/ZlibWrapper.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.compression; - -/** - * The container file formats that wrap the stream compressed by the DEFLATE - * algorithm. - */ -public enum ZlibWrapper { - /** - * The ZLIB wrapper as specified in RFC 1950. - */ - ZLIB, - /** - * The GZIP wrapper as specified in RFC 1952. - */ - GZIP, - /** - * Raw DEFLATE stream only (no header and no footer). - */ - NONE, - /** - * Try {@link #ZLIB} first and then {@link #NONE} if the first attempt fails. - * Please note that you can specify this wrapper type only when decompressing. - */ - ZLIB_OR_NONE -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/package-info.java deleted file mode 100755 index 95d1604561..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/compression/package-info.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * Encoder and decoder which compresses and decompresses {@link com.ai.cloud.io.netty.buffer.ByteBuf}s - * in a compression format such as zlib, - * gzip, and - * Snappy. - */ -package com.ai.cloud.io.netty.handler.codec.compression; -// TODO Implement bzip2 and lzma handlers diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/haproxy/HAProxyCommand.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/haproxy/HAProxyCommand.java deleted file mode 100755 index 7de064e1df..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/haproxy/HAProxyCommand.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.haproxy; - -/** - * The command of an HAProxy proxy protocol header - */ -public enum HAProxyCommand { - /** - * The LOCAL command represents a connection that was established on purpose by the proxy - * without being relayed. - */ - LOCAL(HAProxyConstants.COMMAND_LOCAL_BYTE), - /** - * The PROXY command represents a connection that was established on behalf of another node, - * and reflects the original connection endpoints. - */ - PROXY(HAProxyConstants.COMMAND_PROXY_BYTE); - - /** - * The command is specified in the lowest 4 bits of the protocol version and command byte - */ - private static final byte COMMAND_MASK = 0x0f; - - private final byte byteValue; - - /** - * Creates a new instance - */ - HAProxyCommand(byte byteValue) { - this.byteValue = byteValue; - } - - /** - * Returns the {@link HAProxyCommand} represented by the lowest 4 bits of the specified byte. - * - * @param verCmdByte protocol version and command byte - */ - public static HAProxyCommand valueOf(byte verCmdByte) { - int cmd = verCmdByte & COMMAND_MASK; - switch ((byte) cmd) { - case HAProxyConstants.COMMAND_PROXY_BYTE: - return PROXY; - case HAProxyConstants.COMMAND_LOCAL_BYTE: - return LOCAL; - default: - throw new IllegalArgumentException("unknown command: " + cmd); - } - } - - /** - * Returns the byte value of this command. - */ - public byte byteValue() { - return byteValue; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/haproxy/HAProxyConstants.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/haproxy/HAProxyConstants.java deleted file mode 100755 index d2b3984ecd..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/haproxy/HAProxyConstants.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.handler.codec.haproxy; - -final class HAProxyConstants { - - /** - * Command byte constants - */ - static final byte COMMAND_LOCAL_BYTE = 0x00; - static final byte COMMAND_PROXY_BYTE = 0x01; - - /** - * Version byte constants - */ - static final byte VERSION_ONE_BYTE = 0x10; - static final byte VERSION_TWO_BYTE = 0x20; - - /** - * Transport protocol byte constants - */ - static final byte TRANSPORT_UNSPEC_BYTE = 0x00; - static final byte TRANSPORT_STREAM_BYTE = 0x01; - static final byte TRANSPORT_DGRAM_BYTE = 0x02; - - /** - * Address family byte constants - */ - static final byte AF_UNSPEC_BYTE = 0x00; - static final byte AF_IPV4_BYTE = 0x10; - static final byte AF_IPV6_BYTE = 0x20; - static final byte AF_UNIX_BYTE = 0x30; - - /** - * Transport protocol and address family byte constants - */ - static final byte TPAF_UNKNOWN_BYTE = 0x00; - static final byte TPAF_TCP4_BYTE = 0x11; - static final byte TPAF_TCP6_BYTE = 0x21; - static final byte TPAF_UDP4_BYTE = 0x12; - static final byte TPAF_UDP6_BYTE = 0x22; - static final byte TPAF_UNIX_STREAM_BYTE = 0x31; - static final byte TPAF_UNIX_DGRAM_BYTE = 0x32; - - private HAProxyConstants() { } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/haproxy/HAProxyMessage.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/haproxy/HAProxyMessage.java deleted file mode 100755 index 9fbaab6ade..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/haproxy/HAProxyMessage.java +++ /dev/null @@ -1,429 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.haproxy; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.ByteBufProcessor; -import com.ai.cloud.io.netty.handler.codec.haproxy.HAProxyProxiedProtocol.AddressFamily; -import com.ai.cloud.io.netty.util.CharsetUtil; -import com.ai.cloud.io.netty.util.NetUtil; -import com.ai.cloud.io.netty.util.internal.StringUtil; - -/** - * Message container for decoded HAProxy proxy protocol parameters - */ -public final class HAProxyMessage { - - /** - * Version 1 proxy protocol message for 'UNKNOWN' proxied protocols. Per spec, when the proxied protocol is - * 'UNKNOWN' we must discard all other header values. - */ - private static final HAProxyMessage V1_UNKNOWN_MSG = new HAProxyMessage( - HAProxyProtocolVersion.V1, HAProxyCommand.PROXY, HAProxyProxiedProtocol.UNKNOWN, null, null, 0, 0); - - /** - * Version 2 proxy protocol message for 'UNKNOWN' proxied protocols. Per spec, when the proxied protocol is - * 'UNKNOWN' we must discard all other header values. - */ - private static final HAProxyMessage V2_UNKNOWN_MSG = new HAProxyMessage( - HAProxyProtocolVersion.V2, HAProxyCommand.PROXY, HAProxyProxiedProtocol.UNKNOWN, null, null, 0, 0); - - /** - * Version 2 proxy protocol message for local requests. Per spec, we should use an unspecified protocol and family - * for 'LOCAL' commands. Per spec, when the proxied protocol is 'UNKNOWN' we must discard all other header values. - */ - private static final HAProxyMessage V2_LOCAL_MSG = new HAProxyMessage( - HAProxyProtocolVersion.V2, HAProxyCommand.LOCAL, HAProxyProxiedProtocol.UNKNOWN, null, null, 0, 0); - - private final HAProxyProtocolVersion protocolVersion; - private final HAProxyCommand command; - private final HAProxyProxiedProtocol proxiedProtocol; - private final String sourceAddress; - private final String destinationAddress; - private final int sourcePort; - private final int destinationPort; - - /** - * Creates a new instance - */ - private HAProxyMessage( - HAProxyProtocolVersion protocolVersion, HAProxyCommand command, HAProxyProxiedProtocol proxiedProtocol, - String sourceAddress, String destinationAddress, String sourcePort, String destinationPort) { - this( - protocolVersion, command, proxiedProtocol, - sourceAddress, destinationAddress, portStringToInt(sourcePort), portStringToInt(destinationPort)); - } - - /** - * Creates a new instance - */ - private HAProxyMessage( - HAProxyProtocolVersion protocolVersion, HAProxyCommand command, HAProxyProxiedProtocol proxiedProtocol, - String sourceAddress, String destinationAddress, int sourcePort, int destinationPort) { - - if (proxiedProtocol == null) { - throw new NullPointerException("proxiedProtocol"); - } - AddressFamily addrFamily = proxiedProtocol.addressFamily(); - - checkAddress(sourceAddress, addrFamily); - checkAddress(destinationAddress, addrFamily); - checkPort(sourcePort); - checkPort(destinationPort); - - this.protocolVersion = protocolVersion; - this.command = command; - this.proxiedProtocol = proxiedProtocol; - this.sourceAddress = sourceAddress; - this.destinationAddress = destinationAddress; - this.sourcePort = sourcePort; - this.destinationPort = destinationPort; - } - - /** - * Decodes a version 2, binary proxy protocol header. - * - * @param header a version 2 proxy protocol header - * @return {@link HAProxyMessage} instance - * @throws HAProxyProtocolException if any portion of the header is invalid - */ - static HAProxyMessage decodeHeader(ByteBuf header) { - if (header == null) { - throw new NullPointerException("header"); - } - - if (header.readableBytes() < 16) { - throw new HAProxyProtocolException( - "incomplete header: " + header.readableBytes() + " bytes (expected: 16+ bytes)"); - } - - // Per spec, the 13th byte is the protocol version and command byte - header.skipBytes(12); - final byte verCmdByte = header.readByte(); - - HAProxyProtocolVersion ver; - try { - ver = HAProxyProtocolVersion.valueOf(verCmdByte); - } catch (IllegalArgumentException e) { - throw new HAProxyProtocolException(e); - } - - if (ver != HAProxyProtocolVersion.V2) { - throw new HAProxyProtocolException("version 1 unsupported: 0x" + Integer.toHexString(verCmdByte)); - } - - HAProxyCommand cmd; - try { - cmd = HAProxyCommand.valueOf(verCmdByte); - } catch (IllegalArgumentException e) { - throw new HAProxyProtocolException(e); - } - - if (cmd == HAProxyCommand.LOCAL) { - return V2_LOCAL_MSG; - } - - // Per spec, the 14th byte is the protocol and address family byte - HAProxyProxiedProtocol protAndFam; - try { - protAndFam = HAProxyProxiedProtocol.valueOf(header.readByte()); - } catch (IllegalArgumentException e) { - throw new HAProxyProtocolException(e); - } - - if (protAndFam == HAProxyProxiedProtocol.UNKNOWN) { - return V2_UNKNOWN_MSG; - } - - int addressInfoLen = header.readUnsignedShort(); - - String srcAddress; - String dstAddress; - int addressLen; - int srcPort = 0; - int dstPort = 0; - - AddressFamily addressFamily = protAndFam.addressFamily(); - - if (addressFamily == AddressFamily.AF_UNIX) { - // unix sockets require 216 bytes for address information - if (addressInfoLen < 216 || header.readableBytes() < 216) { - throw new HAProxyProtocolException( - "incomplete UNIX socket address information: " + - Math.min(addressInfoLen, header.readableBytes()) + " bytes (expected: 216+ bytes)"); - } - int startIdx = header.readerIndex(); - int addressEnd = header.forEachByte(startIdx, 108, ByteBufProcessor.FIND_NUL); - if (addressEnd == -1) { - addressLen = 108; - } else { - addressLen = addressEnd - startIdx; - } - srcAddress = header.toString(startIdx, addressLen, CharsetUtil.US_ASCII); - - startIdx += 108; - - addressEnd = header.forEachByte(startIdx, 108, ByteBufProcessor.FIND_NUL); - if (addressEnd == -1) { - addressLen = 108; - } else { - addressLen = addressEnd - startIdx; - } - dstAddress = header.toString(startIdx, addressLen, CharsetUtil.US_ASCII); - } else { - if (addressFamily == AddressFamily.AF_IPv4) { - // IPv4 requires 12 bytes for address information - if (addressInfoLen < 12 || header.readableBytes() < 12) { - throw new HAProxyProtocolException( - "incomplete IPv4 address information: " + - Math.min(addressInfoLen, header.readableBytes()) + " bytes (expected: 12+ bytes)"); - } - addressLen = 4; - } else if (addressFamily == AddressFamily.AF_IPv6) { - // IPv6 requires 36 bytes for address information - if (addressInfoLen < 36 || header.readableBytes() < 36) { - throw new HAProxyProtocolException( - "incomplete IPv6 address information: " + - Math.min(addressInfoLen, header.readableBytes()) + " bytes (expected: 36+ bytes)"); - } - addressLen = 16; - } else { - throw new HAProxyProtocolException( - "unable to parse address information (unkown address family: " + addressFamily + ')'); - } - - // Per spec, the src address begins at the 17th byte - srcAddress = ipBytestoString(header, addressLen); - dstAddress = ipBytestoString(header, addressLen); - srcPort = header.readUnsignedShort(); - dstPort = header.readUnsignedShort(); - } - - return new HAProxyMessage(ver, cmd, protAndFam, srcAddress, dstAddress, srcPort, dstPort); - } - - /** - * Decodes a version 1, human-readable proxy protocol header. - * - * @param header a version 1 proxy protocol header - * @return {@link HAProxyMessage} instance - * @throws HAProxyProtocolException if any portion of the header is invalid - */ - static HAProxyMessage decodeHeader(String header) { - if (header == null) { - throw new HAProxyProtocolException("header"); - } - - String[] parts = StringUtil.split(header, ' '); - int numParts = parts.length; - - if (numParts < 2) { - throw new HAProxyProtocolException( - "invalid header: " + header + " (expected: 'PROXY' and proxied protocol values)"); - } - - if (!"PROXY".equals(parts[0])) { - throw new HAProxyProtocolException("unknown identifier: " + parts[0]); - } - - HAProxyProxiedProtocol protAndFam; - try { - protAndFam = HAProxyProxiedProtocol.valueOf(parts[1]); - } catch (IllegalArgumentException e) { - throw new HAProxyProtocolException(e); - } - - if (protAndFam != HAProxyProxiedProtocol.TCP4 && - protAndFam != HAProxyProxiedProtocol.TCP6 && - protAndFam != HAProxyProxiedProtocol.UNKNOWN) { - throw new HAProxyProtocolException("unsupported v1 proxied protocol: " + parts[1]); - } - - if (protAndFam == HAProxyProxiedProtocol.UNKNOWN) { - return V1_UNKNOWN_MSG; - } - - if (numParts != 6) { - throw new HAProxyProtocolException("invalid TCP4/6 header: " + header + " (expected: 6 parts)"); - } - - return new HAProxyMessage( - HAProxyProtocolVersion.V1, HAProxyCommand.PROXY, - protAndFam, parts[2], parts[3], parts[4], parts[5]); - } - - /** - * Convert ip address bytes to string representation - * - * @param header buffer containing ip address bytes - * @param addressLen number of bytes to read (4 bytes for IPv4, 16 bytes for IPv6) - * @return string representation of the ip address - */ - private static String ipBytestoString(ByteBuf header, int addressLen) { - StringBuilder sb = new StringBuilder(); - if (addressLen == 4) { - sb.append(header.readByte() & 0xff); - sb.append('.'); - sb.append(header.readByte() & 0xff); - sb.append('.'); - sb.append(header.readByte() & 0xff); - sb.append('.'); - sb.append(header.readByte() & 0xff); - } else { - sb.append(Integer.toHexString(header.readUnsignedShort())); - sb.append(':'); - sb.append(Integer.toHexString(header.readUnsignedShort())); - sb.append(':'); - sb.append(Integer.toHexString(header.readUnsignedShort())); - sb.append(':'); - sb.append(Integer.toHexString(header.readUnsignedShort())); - sb.append(':'); - sb.append(Integer.toHexString(header.readUnsignedShort())); - sb.append(':'); - sb.append(Integer.toHexString(header.readUnsignedShort())); - sb.append(':'); - sb.append(Integer.toHexString(header.readUnsignedShort())); - sb.append(':'); - sb.append(Integer.toHexString(header.readUnsignedShort())); - } - return sb.toString(); - } - - /** - * Convert port to integer - * - * @param value the port - * @return port as an integer - * @throws HAProxyProtocolException if port is not a valid integer - */ - private static int portStringToInt(String value) { - int port; - try { - port = Integer.parseInt(value); - } catch (NumberFormatException e) { - throw new HAProxyProtocolException("invalid port: " + value, e); - } - - if (port <= 0 || port > 65535) { - throw new HAProxyProtocolException("invalid port: " + value + " (expected: 1 ~ 65535)"); - } - - return port; - } - - /** - * Validate an address (IPv4, IPv6, Unix Socket) - * - * @param address human-readable address - * @param addrFamily the {@link AddressFamily} to check the address against - * @throws HAProxyProtocolException if the address is invalid - */ - private static void checkAddress(String address, AddressFamily addrFamily) { - if (addrFamily == null) { - throw new NullPointerException("addrFamily"); - } - - switch (addrFamily) { - case AF_UNSPEC: - if (address != null) { - throw new HAProxyProtocolException("unable to validate an AF_UNSPEC address: " + address); - } - return; - case AF_UNIX: - return; - } - - if (address == null) { - throw new NullPointerException("address"); - } - - switch (addrFamily) { - case AF_IPv4: - if (!NetUtil.isValidIpV4Address(address)) { - throw new HAProxyProtocolException("invalid IPv4 address: " + address); - } - break; - case AF_IPv6: - if (!NetUtil.isValidIpV6Address(address)) { - throw new HAProxyProtocolException("invalid IPv6 address: " + address); - } - break; - default: - throw new Error(); - } - } - - /** - * Validate a UDP/TCP port - * - * @param port the UDP/TCP port - * @throws HAProxyProtocolException if the port is out of range (0-65535 inclusive) - */ - private static void checkPort(int port) { - if (port < 0 || port > 65535) { - throw new HAProxyProtocolException("invalid port: " + port + " (expected: 1 ~ 65535)"); - } - } - - /** - * Returns the {@link HAProxyProtocolVersion} of this {@link HAProxyMessage}. - */ - public HAProxyProtocolVersion protocolVersion() { - return protocolVersion; - } - - /** - * Returns the {@link HAProxyCommand} of this {@link HAProxyMessage}. - */ - public HAProxyCommand command() { - return command; - } - - /** - * Returns the {@link HAProxyProxiedProtocol} of this {@link HAProxyMessage}. - */ - public HAProxyProxiedProtocol proxiedProtocol() { - return proxiedProtocol; - } - - /** - * Returns the human-readable source address of this {@link HAProxyMessage}. - */ - public String sourceAddress() { - return sourceAddress; - } - - /** - * Returns the human-readable destination address of this {@link HAProxyMessage}. - */ - public String destinationAddress() { - return destinationAddress; - } - - /** - * Returns the UDP/TCP source port of this {@link HAProxyMessage}. - */ - public int sourcePort() { - return sourcePort; - } - - /** - * Returns the UDP/TCP destination port of this {@link HAProxyMessage}. - */ - public int destinationPort() { - return destinationPort; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/haproxy/HAProxyMessageDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/haproxy/HAProxyMessageDecoder.java deleted file mode 100755 index 76ba035416..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/haproxy/HAProxyMessageDecoder.java +++ /dev/null @@ -1,402 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.haproxy; - -import java.util.List; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.handler.codec.ByteToMessageDecoder; -import com.ai.cloud.io.netty.handler.codec.LineBasedFrameDecoder; -import com.ai.cloud.io.netty.handler.codec.ProtocolDetectionResult; -import com.ai.cloud.io.netty.util.CharsetUtil; - -/** - * Decodes an HAProxy proxy protocol header - * - * @see Proxy Protocol Specification - */ -public class HAProxyMessageDecoder extends ByteToMessageDecoder { - /** - * Maximum possible length of a v1 proxy protocol header per spec - */ - private static final int V1_MAX_LENGTH = 108; - - /** - * Maximum possible length of a v2 proxy protocol header (fixed 16 bytes + max unsigned short) - */ - private static final int V2_MAX_LENGTH = 16 + 65535; - - /** - * Minimum possible length of a fully functioning v2 proxy protocol header (fixed 16 bytes + v2 address info space) - */ - private static final int V2_MIN_LENGTH = 16 + 216; - - /** - * Maximum possible length for v2 additional TLV data (max unsigned short - max v2 address info space) - */ - private static final int V2_MAX_TLV = 65535 - 216; - - /** - * Version 1 header delimiter is always '\r\n' per spec - */ - private static final int DELIMITER_LENGTH = 2; - - /** - * Binary header prefix - */ - private static final byte[] BINARY_PREFIX = { - (byte) 0x0D, - (byte) 0x0A, - (byte) 0x0D, - (byte) 0x0A, - (byte) 0x00, - (byte) 0x0D, - (byte) 0x0A, - (byte) 0x51, - (byte) 0x55, - (byte) 0x49, - (byte) 0x54, - (byte) 0x0A - }; - - private static final byte[] TEXT_PREFIX = { - (byte) 'P', - (byte) 'R', - (byte) 'O', - (byte) 'X', - (byte) 'Y', - }; - - /** - * Binary header prefix length - */ - private static final int BINARY_PREFIX_LENGTH = BINARY_PREFIX.length; - - /** - * {@link ProtocolDetectionResult} for {@link HAProxyProtocolVersion#V1}. - */ - private static final ProtocolDetectionResult DETECTION_RESULT_V1 = - ProtocolDetectionResult.detected(HAProxyProtocolVersion.V1); - - /** - * {@link ProtocolDetectionResult} for {@link HAProxyProtocolVersion#V2}. - */ - private static final ProtocolDetectionResult DETECTION_RESULT_V2 = - ProtocolDetectionResult.detected(HAProxyProtocolVersion.V2); - - /** - * {@code true} if we're discarding input because we're already over maxLength - */ - private boolean discarding; - - /** - * Number of discarded bytes - */ - private int discardedBytes; - - /** - * {@code true} if we're finished decoding the proxy protocol header - */ - private boolean finished; - - /** - * Protocol specification version - */ - private int version = -1; - - /** - * The latest v2 spec (2014/05/18) allows for additional data to be sent in the proxy protocol header beyond the - * address information block so now we need a configurable max header size - */ - private final int v2MaxHeaderSize; - - /** - * Creates a new decoder with no additional data (TLV) restrictions - */ - public HAProxyMessageDecoder() { - v2MaxHeaderSize = V2_MAX_LENGTH; - } - - /** - * Creates a new decoder with restricted additional data (TLV) size - *

- * Note: limiting TLV size only affects processing of v2, binary headers. Also, as allowed by the 1.5 spec - * TLV data is currently ignored. For maximum performance it would be best to configure your upstream proxy host to - * NOT send TLV data and instantiate with a max TLV size of {@code 0}. - *

- * - * @param maxTlvSize maximum number of bytes allowed for additional data (Type-Length-Value vectors) in a v2 header - */ - public HAProxyMessageDecoder(int maxTlvSize) { - if (maxTlvSize < 1) { - v2MaxHeaderSize = V2_MIN_LENGTH; - } else if (maxTlvSize > V2_MAX_TLV) { - v2MaxHeaderSize = V2_MAX_LENGTH; - } else { - int calcMax = maxTlvSize + V2_MIN_LENGTH; - if (calcMax > V2_MAX_LENGTH) { - v2MaxHeaderSize = V2_MAX_LENGTH; - } else { - v2MaxHeaderSize = calcMax; - } - } - } - - /** - * Returns the proxy protocol specification version in the buffer if the version is found. - * Returns -1 if no version was found in the buffer. - */ - private static int findVersion(final ByteBuf buffer) { - final int n = buffer.readableBytes(); - // per spec, the version number is found in the 13th byte - if (n < 13) { - return -1; - } - - int idx = buffer.readerIndex(); - return match(BINARY_PREFIX, buffer, idx) ? buffer.getByte(idx + BINARY_PREFIX_LENGTH) : 1; - } - - /** - * Returns the index in the buffer of the end of header if found. - * Returns -1 if no end of header was found in the buffer. - */ - private static int findEndOfHeader(final ByteBuf buffer) { - final int n = buffer.readableBytes(); - - // per spec, the 15th and 16th bytes contain the address length in bytes - if (n < 16) { - return -1; - } - - int offset = buffer.readerIndex() + 14; - - // the total header length will be a fixed 16 byte sequence + the dynamic address information block - int totalHeaderBytes = 16 + buffer.getUnsignedShort(offset); - - // ensure we actually have the full header available - if (n >= totalHeaderBytes) { - return totalHeaderBytes; - } else { - return -1; - } - } - - /** - * Returns the index in the buffer of the end of line found. - * Returns -1 if no end of line was found in the buffer. - */ - private static int findEndOfLine(final ByteBuf buffer) { - final int n = buffer.writerIndex(); - for (int i = buffer.readerIndex(); i < n; i++) { - final byte b = buffer.getByte(i); - if (b == '\r' && i < n - 1 && buffer.getByte(i + 1) == '\n') { - return i; // \r\n - } - } - return -1; // Not found. - } - - @Override - public boolean isSingleDecode() { - // ByteToMessageDecoder uses this method to optionally break out of the decoding loop after each unit of work. - // Since we only ever want to decode a single header we always return true to save a bit of work here. - return true; - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - super.channelRead(ctx, msg); - if (finished) { - ctx.pipeline().remove(this); - } - } - - @Override - protected final void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { - // determine the specification version - if (version == -1) { - if ((version = findVersion(in)) == -1) { - return; - } - } - - ByteBuf decoded; - - if (version == 1) { - decoded = decodeLine(ctx, in); - } else { - decoded = decodeStruct(ctx, in); - } - - if (decoded != null) { - finished = true; - try { - if (version == 1) { - out.add(HAProxyMessage.decodeHeader(decoded.toString(CharsetUtil.US_ASCII))); - } else { - out.add(HAProxyMessage.decodeHeader(decoded)); - } - } catch (HAProxyProtocolException e) { - fail(ctx, null, e); - } - } - } - - /** - * Create a frame out of the {@link ByteBuf} and return it. - * Based on code from {@link LineBasedFrameDecoder#decode(ChannelHandlerContext, ByteBuf)}. - * - * @param ctx the {@link ChannelHandlerContext} which this {@link HAProxyMessageDecoder} belongs to - * @param buffer the {@link ByteBuf} from which to read data - * @return frame the {@link ByteBuf} which represent the frame or {@code null} if no frame could - * be created - */ - private ByteBuf decodeStruct(ChannelHandlerContext ctx, ByteBuf buffer) throws Exception { - final int eoh = findEndOfHeader(buffer); - if (!discarding) { - if (eoh >= 0) { - final int length = eoh - buffer.readerIndex(); - if (length > v2MaxHeaderSize) { - buffer.readerIndex(eoh); - failOverLimit(ctx, length); - return null; - } - return buffer.readSlice(length); - } else { - final int length = buffer.readableBytes(); - if (length > v2MaxHeaderSize) { - discardedBytes = length; - buffer.skipBytes(length); - discarding = true; - failOverLimit(ctx, "over " + discardedBytes); - } - return null; - } - } else { - if (eoh >= 0) { - buffer.readerIndex(eoh); - discardedBytes = 0; - discarding = false; - } else { - discardedBytes = buffer.readableBytes(); - buffer.skipBytes(discardedBytes); - } - return null; - } - } - - /** - * Create a frame out of the {@link ByteBuf} and return it. - * Based on code from {@link LineBasedFrameDecoder#decode(ChannelHandlerContext, ByteBuf)}. - * - * @param ctx the {@link ChannelHandlerContext} which this {@link HAProxyMessageDecoder} belongs to - * @param buffer the {@link ByteBuf} from which to read data - * @return frame the {@link ByteBuf} which represent the frame or {@code null} if no frame could - * be created - */ - private ByteBuf decodeLine(ChannelHandlerContext ctx, ByteBuf buffer) throws Exception { - final int eol = findEndOfLine(buffer); - if (!discarding) { - if (eol >= 0) { - final int length = eol - buffer.readerIndex(); - if (length > V1_MAX_LENGTH) { - buffer.readerIndex(eol + DELIMITER_LENGTH); - failOverLimit(ctx, length); - return null; - } - ByteBuf frame = buffer.readSlice(length); - buffer.skipBytes(DELIMITER_LENGTH); - return frame; - } else { - final int length = buffer.readableBytes(); - if (length > V1_MAX_LENGTH) { - discardedBytes = length; - buffer.skipBytes(length); - discarding = true; - failOverLimit(ctx, "over " + discardedBytes); - } - return null; - } - } else { - if (eol >= 0) { - final int delimLength = buffer.getByte(eol) == '\r' ? 2 : 1; - buffer.readerIndex(eol + delimLength); - discardedBytes = 0; - discarding = false; - } else { - discardedBytes = buffer.readableBytes(); - buffer.skipBytes(discardedBytes); - } - return null; - } - } - - private void failOverLimit(final ChannelHandlerContext ctx, int length) { - failOverLimit(ctx, String.valueOf(length)); - } - - private void failOverLimit(final ChannelHandlerContext ctx, String length) { - int maxLength = version == 1 ? V1_MAX_LENGTH : v2MaxHeaderSize; - fail(ctx, "header length (" + length + ") exceeds the allowed maximum (" + maxLength + ')', null); - } - - private void fail(final ChannelHandlerContext ctx, String errMsg, Throwable t) { - finished = true; - ctx.close(); // drop connection immediately per spec - HAProxyProtocolException ppex; - if (errMsg != null && t != null) { - ppex = new HAProxyProtocolException(errMsg, t); - } else if (errMsg != null) { - ppex = new HAProxyProtocolException(errMsg); - } else if (t != null) { - ppex = new HAProxyProtocolException(t); - } else { - ppex = new HAProxyProtocolException(); - } - throw ppex; - } - - /** - * Returns the {@link ProtocolDetectionResult} for the given {@link ByteBuf}. - */ - public static ProtocolDetectionResult detectProtocol(ByteBuf buffer) { - if (buffer.readableBytes() < 12) { - return ProtocolDetectionResult.needsMoreData(); - } - - int idx = buffer.readerIndex(); - - if (match(BINARY_PREFIX, buffer, idx)) { - return DETECTION_RESULT_V2; - } - if (match(TEXT_PREFIX, buffer, idx)) { - return DETECTION_RESULT_V1; - } - return ProtocolDetectionResult.invalid(); - } - - private static boolean match(byte[] prefix, ByteBuf buffer, int idx) { - for (int i = 0; i < prefix.length; i++) { - final byte b = buffer.getByte(idx + i); - if (b != prefix[i]) { - return false; - } - } - return true; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/haproxy/HAProxyProtocolException.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/haproxy/HAProxyProtocolException.java deleted file mode 100755 index db74efe713..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/haproxy/HAProxyProtocolException.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.haproxy; - -import com.ai.cloud.io.netty.handler.codec.DecoderException; - -/** - * A {@link DecoderException} which is thrown when an invalid HAProxy proxy protocol header is encountered - */ -public class HAProxyProtocolException extends DecoderException { - - private static final long serialVersionUID = 713710864325167351L; - - /** - * Creates a new instance - */ - public HAProxyProtocolException() { } - - /** - * Creates a new instance - */ - public HAProxyProtocolException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Creates a new instance - */ - public HAProxyProtocolException(String message) { - super(message); - } - - /** - * Creates a new instance - */ - public HAProxyProtocolException(Throwable cause) { - super(cause); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/haproxy/HAProxyProtocolVersion.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/haproxy/HAProxyProtocolVersion.java deleted file mode 100755 index dd4e23f86d..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/haproxy/HAProxyProtocolVersion.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.haproxy; - -import static com.ai.cloud.io.netty.handler.codec.haproxy.HAProxyConstants.*; - -/** - * The HAProxy proxy protocol specification version. - */ -public enum HAProxyProtocolVersion { - /** - * The ONE proxy protocol version represents a version 1 (human-readable) header. - */ - V1(VERSION_ONE_BYTE), - /** - * The TWO proxy protocol version represents a version 2 (binary) header. - */ - V2(VERSION_TWO_BYTE); - - /** - * The highest 4 bits of the protocol version and command byte contain the version - */ - private static final byte VERSION_MASK = (byte) 0xf0; - - private final byte byteValue; - - /** - * Creates a new instance - */ - HAProxyProtocolVersion(byte byteValue) { - this.byteValue = byteValue; - } - - /** - * Returns the {@link HAProxyProtocolVersion} represented by the higest 4 bits of the specified byte. - * - * @param verCmdByte protocol version and command byte - */ - public static HAProxyProtocolVersion valueOf(byte verCmdByte) { - int version = verCmdByte & VERSION_MASK; - switch ((byte) version) { - case VERSION_TWO_BYTE: - return V2; - case VERSION_ONE_BYTE: - return V1; - default: - throw new IllegalArgumentException("unknown version: " + version); - } - } - - /** - * Returns the byte value of this version. - */ - public byte byteValue() { - return byteValue; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/haproxy/HAProxyProxiedProtocol.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/haproxy/HAProxyProxiedProtocol.java deleted file mode 100755 index baaee7c9db..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/haproxy/HAProxyProxiedProtocol.java +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.haproxy; - -import static com.ai.cloud.io.netty.handler.codec.haproxy.HAProxyConstants.*; - -/** - * A protocol proxied by HAProxy which is represented by its transport protocol and address family. - */ -public enum HAProxyProxiedProtocol { - /** - * The UNKNOWN represents a connection which was forwarded for an unknown protocol and an unknown address family. - */ - UNKNOWN(TPAF_UNKNOWN_BYTE, AddressFamily.AF_UNSPEC, TransportProtocol.UNSPEC), - /** - * The TCP4 represents a connection which was forwarded for an IPv4 client over TCP. - */ - TCP4(TPAF_TCP4_BYTE, AddressFamily.AF_IPv4, TransportProtocol.STREAM), - /** - * The TCP6 represents a connection which was forwarded for an IPv6 client over TCP. - */ - TCP6(TPAF_TCP6_BYTE, AddressFamily.AF_IPv6, TransportProtocol.STREAM), - /** - * The UDP4 represents a connection which was forwarded for an IPv4 client over UDP. - */ - UDP4(TPAF_UDP4_BYTE, AddressFamily.AF_IPv4, TransportProtocol.DGRAM), - /** - * The UDP6 represents a connection which was forwarded for an IPv6 client over UDP. - */ - UDP6(TPAF_UDP6_BYTE, AddressFamily.AF_IPv6, TransportProtocol.DGRAM), - /** - * The UNIX_STREAM represents a connection which was forwarded for a UNIX stream socket. - */ - UNIX_STREAM(TPAF_UNIX_STREAM_BYTE, AddressFamily.AF_UNIX, TransportProtocol.STREAM), - /** - * The UNIX_DGRAM represents a connection which was forwarded for a UNIX datagram socket. - */ - UNIX_DGRAM(TPAF_UNIX_DGRAM_BYTE, AddressFamily.AF_UNIX, TransportProtocol.DGRAM); - - private final byte byteValue; - private final AddressFamily addressFamily; - private final TransportProtocol transportProtocol; - - /** - * Creates a new instance. - */ - HAProxyProxiedProtocol( - byte byteValue, - AddressFamily addressFamily, - TransportProtocol transportProtocol) { - - this.byteValue = byteValue; - this.addressFamily = addressFamily; - this.transportProtocol = transportProtocol; - } - - /** - * Returns the {@link HAProxyProxiedProtocol} represented by the specified byte. - * - * @param tpafByte transport protocol and address family byte - */ - public static HAProxyProxiedProtocol valueOf(byte tpafByte) { - switch (tpafByte) { - case TPAF_TCP4_BYTE: - return TCP4; - case TPAF_TCP6_BYTE: - return TCP6; - case TPAF_UNKNOWN_BYTE: - return UNKNOWN; - case TPAF_UDP4_BYTE: - return UDP4; - case TPAF_UDP6_BYTE: - return UDP6; - case TPAF_UNIX_STREAM_BYTE: - return UNIX_STREAM; - case TPAF_UNIX_DGRAM_BYTE: - return UNIX_DGRAM; - default: - throw new IllegalArgumentException( - "unknown transport protocol + address family: " + (tpafByte & 0xFF)); - } - } - - /** - * Returns the byte value of this protocol and address family. - */ - public byte byteValue() { - return byteValue; - } - - /** - * Returns the {@link AddressFamily} of this protocol and address family. - */ - public AddressFamily addressFamily() { - return addressFamily; - } - - /** - * Returns the {@link TransportProtocol} of this protocol and address family. - */ - public TransportProtocol transportProtocol() { - return transportProtocol; - } - - /** - * The address family of an HAProxy proxy protocol header. - */ - public enum AddressFamily { - /** - * The UNSPECIFIED address family represents a connection which was forwarded for an unkown protocol. - */ - AF_UNSPEC(AF_UNSPEC_BYTE), - /** - * The IPV4 address family represents a connection which was forwarded for an IPV4 client. - */ - AF_IPv4(AF_IPV4_BYTE), - /** - * The IPV6 address family represents a connection which was forwarded for an IPV6 client. - */ - AF_IPv6(AF_IPV6_BYTE), - /** - * The UNIX address family represents a connection which was forwarded for a unix socket. - */ - AF_UNIX(AF_UNIX_BYTE); - - /** - * The highest 4 bits of the transport protocol and address family byte contain the address family - */ - private static final byte FAMILY_MASK = (byte) 0xf0; - - private final byte byteValue; - - /** - * Creates a new instance - */ - AddressFamily(byte byteValue) { - this.byteValue = byteValue; - } - - /** - * Returns the {@link AddressFamily} represented by the highest 4 bits of the specified byte. - * - * @param tpafByte transport protocol and address family byte - */ - public static AddressFamily valueOf(byte tpafByte) { - int addressFamily = tpafByte & FAMILY_MASK; - switch((byte) addressFamily) { - case AF_IPV4_BYTE: - return AF_IPv4; - case AF_IPV6_BYTE: - return AF_IPv6; - case AF_UNSPEC_BYTE: - return AF_UNSPEC; - case AF_UNIX_BYTE: - return AF_UNIX; - default: - throw new IllegalArgumentException("unknown address family: " + addressFamily); - } - } - - /** - * Returns the byte value of this address family. - */ - public byte byteValue() { - return byteValue; - } - } - - /** - * The transport protocol of an HAProxy proxy protocol header - */ - public enum TransportProtocol { - /** - * The UNSPEC transport protocol represents a connection which was forwarded for an unkown protocol. - */ - UNSPEC(TRANSPORT_UNSPEC_BYTE), - /** - * The STREAM transport protocol represents a connection which was forwarded for a TCP connection. - */ - STREAM(TRANSPORT_STREAM_BYTE), - /** - * The DGRAM transport protocol represents a connection which was forwarded for a UDP connection. - */ - DGRAM(TRANSPORT_DGRAM_BYTE); - - /** - * The transport protocol is specified in the lowest 4 bits of the transport protocol and address family byte - */ - private static final byte TRANSPORT_MASK = 0x0f; - - private final byte transportByte; - - /** - * Creates a new instance. - */ - TransportProtocol(byte transportByte) { - this.transportByte = transportByte; - } - - /** - * Returns the {@link TransportProtocol} represented by the lowest 4 bits of the specified byte. - * - * @param tpafByte transport protocol and address family byte - */ - public static TransportProtocol valueOf(byte tpafByte) { - int transportProtocol = tpafByte & TRANSPORT_MASK; - switch ((byte) transportProtocol) { - case TRANSPORT_STREAM_BYTE: - return STREAM; - case TRANSPORT_UNSPEC_BYTE: - return UNSPEC; - case TRANSPORT_DGRAM_BYTE: - return DGRAM; - default: - throw new IllegalArgumentException("unknown transport protocol: " + transportProtocol); - } - } - - /** - * Returns the byte value of this transport protocol. - */ - public byte byteValue() { - return transportByte; - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/haproxy/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/haproxy/package-info.java deleted file mode 100755 index 9f3a9d61a1..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/haproxy/package-info.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * Decodes an HAProxy proxy protocol header - * - * @see Proxy Protocol Specification - */ -package com.ai.cloud.io.netty.handler.codec.haproxy; diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/ClientCookieEncoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/ClientCookieEncoder.java deleted file mode 100755 index 2114ee0d4f..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/ClientCookieEncoder.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -/** - * Encodes client-side {@link Cookie}s into an HTTP header value. This encoder can encode - * the HTTP cookie version 0, 1, and 2. - *
- * // Example
- * {@link HttpRequest} req = ...;
- * res.setHeader("Cookie", {@link ClientCookieEncoder}.encode("JSESSIONID", "1234"));
- * 
- * - * @see CookieDecoder - * @deprecated Use {@link com.ai.cloud.io.netty.handler.codec.http.cookie.ClientCookieEncoder} instead. - */ -@Deprecated -public final class ClientCookieEncoder { - - /** - * Encodes the specified cookie into an HTTP header value. - */ - @Deprecated - public static String encode(String name, String value) { - return com.ai.cloud.io.netty.handler.codec.http.cookie.ClientCookieEncoder.LAX.encode(name, value); - } - - @Deprecated - public static String encode(Cookie cookie) { - return com.ai.cloud.io.netty.handler.codec.http.cookie.ClientCookieEncoder.LAX.encode(cookie); - } - - @Deprecated - public static String encode(Cookie... cookies) { - return com.ai.cloud.io.netty.handler.codec.http.cookie.ClientCookieEncoder.LAX.encode(cookies); - } - - @Deprecated - public static String encode(Iterable cookies) { - return com.ai.cloud.io.netty.handler.codec.http.cookie.ClientCookieEncoder.LAX.encode(cookies); - } - - private ClientCookieEncoder() { - // Unused - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/ComposedLastHttpContent.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/ComposedLastHttpContent.java deleted file mode 100755 index 5be9cc41a8..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/ComposedLastHttpContent.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.Unpooled; -import com.ai.cloud.io.netty.handler.codec.DecoderResult; - - -final class ComposedLastHttpContent implements LastHttpContent { - private final HttpHeaders trailingHeaders; - private DecoderResult result; - - ComposedLastHttpContent(HttpHeaders trailingHeaders) { - this.trailingHeaders = trailingHeaders; - } - @Override - public HttpHeaders trailingHeaders() { - return trailingHeaders; - } - - @Override - public LastHttpContent copy() { - LastHttpContent content = new DefaultLastHttpContent(Unpooled.EMPTY_BUFFER); - content.trailingHeaders().set(trailingHeaders()); - return content; - } - - @Override - public LastHttpContent retain(int increment) { - return this; - } - - @Override - public LastHttpContent retain() { - return this; - } - - @Override - public HttpContent duplicate() { - return copy(); - } - - @Override - public ByteBuf content() { - return Unpooled.EMPTY_BUFFER; - } - - @Override - public DecoderResult getDecoderResult() { - return result; - } - - @Override - public void setDecoderResult(DecoderResult result) { - this.result = result; - } - - @Override - public int refCnt() { - return 1; - } - - @Override - public boolean release() { - return false; - } - - @Override - public boolean release(int decrement) { - return false; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/Cookie.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/Cookie.java deleted file mode 100755 index 85bbb61bc5..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/Cookie.java +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import java.util.Set; - -/** - * An interface defining an - * HTTP cookie. - * @deprecated Use {@link com.ai.cloud.io.netty.handler.codec.http.cookie.Cookie} instead. - */ -@Deprecated -public interface Cookie extends com.ai.cloud.io.netty.handler.codec.http.cookie.Cookie { - - /** - * @deprecated Use {@link #name()} instead. - */ - @Deprecated - String getName(); - - /** - * @deprecated Use {@link #value()} instead. - */ - @Deprecated - String getValue(); - - /** - * @deprecated Use {@link #domain()} instead. - */ - @Deprecated - String getDomain(); - - /** - * @deprecated Use {@link #path()} instead. - */ - @Deprecated - String getPath(); - - /** - * @deprecated Use {@link #comment()} instead. - */ - @Deprecated - String getComment(); - - /** - * Returns the comment of this {@link Cookie}. - * - * @return The comment of this {@link Cookie} - * - * @deprecated Not part of RFC6265 - */ - @Deprecated - String comment(); - - /** - * Sets the comment of this {@link Cookie}. - * - * @param comment The comment to use - * - * @deprecated Not part of RFC6265 - */ - @Deprecated - void setComment(String comment); - - /** - * @deprecated Use {@link #maxAge()} instead. - */ - @Deprecated - long getMaxAge(); - - /** - * Returns the maximum age of this {@link Cookie} in seconds or {@link Long#MIN_VALUE} if unspecified - * - * @return The maximum age of this {@link Cookie} - * - * @deprecated Not part of RFC6265 - */ - @Deprecated - long maxAge(); - - /** - * Sets the maximum age of this {@link Cookie} in seconds. - * If an age of {@code 0} is specified, this {@link Cookie} will be - * automatically removed by browser because it will expire immediately. - * If {@link Long#MIN_VALUE} is specified, this {@link Cookie} will be removed when the - * browser is closed. - * - * @param maxAge The maximum age of this {@link Cookie} in seconds - * - * @deprecated Not part of RFC6265 - */ - @Deprecated - void setMaxAge(long maxAge); - - /** - * @deprecated Use {@link #version()} instead. - */ - @Deprecated - int getVersion(); - - /** - * Returns the version of this {@link Cookie}. - * - * @return The version of this {@link Cookie} - * - * @deprecated Not part of RFC6265 - */ - @Deprecated - int version(); - - /** - * Sets the version of this {@link Cookie}. - * - * @param version The new version to use - * - * @deprecated Not part of RFC6265 - */ - @Deprecated - void setVersion(int version); - - /** - * @deprecated Use {@link #commentUrl()} instead. - */ - @Deprecated - String getCommentUrl(); - - /** - * Returns the comment URL of this {@link Cookie}. - * - * @return The comment URL of this {@link Cookie} - * - * @deprecated Not part of RFC6265 - */ - @Deprecated - String commentUrl(); - - /** - * Sets the comment URL of this {@link Cookie}. - * - * @param commentUrl The comment URL to use - * - * @deprecated Not part of RFC6265 - */ - @Deprecated - void setCommentUrl(String commentUrl); - - /** - * Checks to see if this {@link Cookie} is to be discarded by the browser - * at the end of the current session. - * - * @return True if this {@link Cookie} is to be discarded, otherwise false - * - * @deprecated Not part of RFC6265 - */ - @Deprecated - boolean isDiscard(); - - /** - * Sets the discard flag of this {@link Cookie}. - * If set to true, this {@link Cookie} will be discarded by the browser - * at the end of the current session - * - * @param discard True if the {@link Cookie} is to be discarded - * - * @deprecated Not part of RFC6265 - */ - @Deprecated - void setDiscard(boolean discard); - - /** - * @deprecated Use {@link #ports()} instead. - */ - @Deprecated - Set getPorts(); - - /** - * Returns the ports that this {@link Cookie} can be accessed on. - * - * @return The {@link Set} of ports that this {@link Cookie} can use - * - * @deprecated Not part of RFC6265 - */ - @Deprecated - Set ports(); - - /** - * Sets the ports that this {@link Cookie} can be accessed on. - * - * @param ports The ports that this {@link Cookie} can be accessed on - * - * @deprecated Not part of RFC6265 - */ - @Deprecated - void setPorts(int... ports); - - /** - * Sets the ports that this {@link Cookie} can be accessed on. - * - * @param ports The {@link Iterable} collection of ports that this - * {@link Cookie} can be accessed on. - * - * @deprecated Not part of RFC6265 - */ - @Deprecated - void setPorts(Iterable ports); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/CookieDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/CookieDecoder.java deleted file mode 100755 index 09eb2ffc64..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/CookieDecoder.java +++ /dev/null @@ -1,375 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import static com.ai.cloud.io.netty.handler.codec.http.CookieUtil.firstInvalidCookieNameOctet; -import static com.ai.cloud.io.netty.handler.codec.http.CookieUtil.firstInvalidCookieValueOctet; -import static com.ai.cloud.io.netty.handler.codec.http.CookieUtil.unwrapValue; - -import java.text.ParseException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.TreeSet; - -import com.ai.cloud.io.netty.handler.codec.http.cookie.CookieHeaderNames; -import com.ai.cloud.io.netty.util.internal.StringUtil; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * @deprecated Use {@link com.ai.cloud.io.netty.handler.codec.http.cookie.ClientCookieDecoder} - * or {@link com.ai.cloud.io.netty.handler.codec.http.cookie.ServerCookieDecoder} instead. - * - * Decodes an HTTP header value into {@link Cookie}s. This decoder can decode - * the HTTP cookie version 0, 1, and 2. - * - *
- * {@link HttpRequest} req = ...;
- * String value = req.getHeader("Cookie");
- * Set<{@link Cookie}> cookies = {@link CookieDecoder}.decode(value);
- * 
- * - * @see com.ai.cloud.io.netty.handler.codec.http.cookie.ClientCookieDecoder - * @see com.ai.cloud.io.netty.handler.codec.http.cookie.ServerCookieDecoder - */ -@Deprecated -public final class CookieDecoder { - - private final InternalLogger logger = InternalLoggerFactory.getInstance(getClass()); - - private static final CookieDecoder STRICT = new CookieDecoder(true); - - private static final CookieDecoder LAX = new CookieDecoder(false); - - private static final String COMMENT = "Comment"; - - private static final String COMMENTURL = "CommentURL"; - - private static final String DISCARD = "Discard"; - - private static final String PORT = "Port"; - - private static final String VERSION = "Version"; - - private static final char COMMA = ','; - - private final boolean strict; - - public static Set decode(String header) { - return decode(header, true); - } - - public static Set decode(String header, boolean strict) { - return (strict ? STRICT : LAX).doDecode(header); - } - - /** - * Decodes the specified HTTP header value into {@link Cookie}s. - * - * @return the decoded {@link Cookie}s - */ - private Set doDecode(String header) { - List names = new ArrayList(8); - List values = new ArrayList(8); - extractKeyValuePairs(header, names, values); - - if (names.isEmpty()) { - return Collections.emptySet(); - } - - int i; - int version = 0; - - // $Version is the only attribute that can appear before the actual - // cookie name-value pair. - if (names.get(0).equalsIgnoreCase(VERSION)) { - try { - version = Integer.parseInt(values.get(0)); - } catch (NumberFormatException e) { - // Ignore. - } - i = 1; - } else { - i = 0; - } - - if (names.size() <= i) { - // There's a version attribute, but nothing more. - return Collections.emptySet(); - } - - Set cookies = new TreeSet(); - for (; i < names.size(); i ++) { - String name = names.get(i); - String value = values.get(i); - if (value == null) { - value = ""; - } - - Cookie c = initCookie(name, value); - - if (c == null) { - break; - } - - boolean discard = false; - boolean secure = false; - boolean httpOnly = false; - String comment = null; - String commentURL = null; - String domain = null; - String path = null; - long maxAge = Long.MIN_VALUE; - List ports = new ArrayList(2); - - for (int j = i + 1; j < names.size(); j++, i++) { - name = names.get(j); - value = values.get(j); - - if (DISCARD.equalsIgnoreCase(name)) { - discard = true; - } else if (CookieHeaderNames.SECURE.equalsIgnoreCase(name)) { - secure = true; - } else if (CookieHeaderNames.HTTPONLY.equalsIgnoreCase(name)) { - httpOnly = true; - } else if (COMMENT.equalsIgnoreCase(name)) { - comment = value; - } else if (COMMENTURL.equalsIgnoreCase(name)) { - commentURL = value; - } else if (CookieHeaderNames.DOMAIN.equalsIgnoreCase(name)) { - domain = value; - } else if (CookieHeaderNames.PATH.equalsIgnoreCase(name)) { - path = value; - } else if (CookieHeaderNames.EXPIRES.equalsIgnoreCase(name)) { - try { - long maxAgeMillis = - HttpHeaderDateFormat.get().parse(value).getTime() - - System.currentTimeMillis(); - - maxAge = maxAgeMillis / 1000 + (maxAgeMillis % 1000 != 0? 1 : 0); - } catch (ParseException e) { - // Ignore. - } - } else if (CookieHeaderNames.MAX_AGE.equalsIgnoreCase(name)) { - maxAge = Integer.parseInt(value); - } else if (VERSION.equalsIgnoreCase(name)) { - version = Integer.parseInt(value); - } else if (PORT.equalsIgnoreCase(name)) { - String[] portList = StringUtil.split(value, COMMA); - for (String s1: portList) { - try { - ports.add(Integer.valueOf(s1)); - } catch (NumberFormatException e) { - // Ignore. - } - } - } else { - break; - } - } - - c.setVersion(version); - c.setMaxAge(maxAge); - c.setPath(path); - c.setDomain(domain); - c.setSecure(secure); - c.setHttpOnly(httpOnly); - if (version > 0) { - c.setComment(comment); - } - if (version > 1) { - c.setCommentUrl(commentURL); - c.setPorts(ports); - c.setDiscard(discard); - } - - cookies.add(c); - } - - return cookies; - } - - private static void extractKeyValuePairs( - final String header, final List names, final List values) { - final int headerLen = header.length(); - loop: for (int i = 0;;) { - - // Skip spaces and separators. - for (;;) { - if (i == headerLen) { - break loop; - } - switch (header.charAt(i)) { - case '\t': case '\n': case 0x0b: case '\f': case '\r': - case ' ': case ',': case ';': - i ++; - continue; - } - break; - } - - // Skip '$'. - for (;;) { - if (i == headerLen) { - break loop; - } - if (header.charAt(i) == '$') { - i ++; - continue; - } - break; - } - - String name; - String value; - - if (i == headerLen) { - name = null; - value = null; - } else { - int newNameStart = i; - keyValLoop: for (;;) { - switch (header.charAt(i)) { - case ';': - // NAME; (no value till ';') - name = header.substring(newNameStart, i); - value = null; - break keyValLoop; - case '=': - // NAME=VALUE - name = header.substring(newNameStart, i); - i ++; - if (i == headerLen) { - // NAME= (empty value, i.e. nothing after '=') - value = ""; - break keyValLoop; - } - - int newValueStart = i; - char c = header.charAt(i); - if (c == '"' || c == '\'') { - // NAME="VALUE" or NAME='VALUE' - StringBuilder newValueBuf = new StringBuilder(header.length() - i); - final char q = c; - boolean hadBackslash = false; - i ++; - for (;;) { - if (i == headerLen) { - value = newValueBuf.toString(); - break keyValLoop; - } - if (hadBackslash) { - hadBackslash = false; - c = header.charAt(i ++); - switch (c) { - case '\\': case '"': case '\'': - // Escape last backslash. - newValueBuf.setCharAt(newValueBuf.length() - 1, c); - break; - default: - // Do not escape last backslash. - newValueBuf.append(c); - } - } else { - c = header.charAt(i ++); - if (c == q) { - value = newValueBuf.toString(); - break keyValLoop; - } - newValueBuf.append(c); - if (c == '\\') { - hadBackslash = true; - } - } - } - } else { - // NAME=VALUE; - int semiPos = header.indexOf(';', i); - if (semiPos > 0) { - value = header.substring(newValueStart, semiPos); - i = semiPos; - } else { - value = header.substring(newValueStart); - i = headerLen; - } - } - break keyValLoop; - default: - i ++; - } - - if (i == headerLen) { - // NAME (no value till the end of string) - name = header.substring(newNameStart); - value = null; - break; - } - } - } - - names.add(name); - values.add(value); - } - } - - private CookieDecoder(boolean strict) { - this.strict = strict; - } - - private DefaultCookie initCookie(String name, String value) { - if (name == null || name.length() == 0) { - logger.debug("Skipping cookie with null name"); - return null; - } - - if (value == null) { - logger.debug("Skipping cookie with null value"); - return null; - } - - CharSequence unwrappedValue = unwrapValue(value); - if (unwrappedValue == null) { - logger.debug("Skipping cookie because starting quotes are not properly balanced in '{}'", - unwrappedValue); - return null; - } - - int invalidOctetPos; - if (strict && (invalidOctetPos = firstInvalidCookieNameOctet(name)) >= 0) { - if (logger.isDebugEnabled()) { - logger.debug("Skipping cookie because name '{}' contains invalid char '{}'", - name, name.charAt(invalidOctetPos)); - } - return null; - } - - final boolean wrap = unwrappedValue.length() != value.length(); - - if (strict && (invalidOctetPos = firstInvalidCookieValueOctet(unwrappedValue)) >= 0) { - if (logger.isDebugEnabled()) { - logger.debug("Skipping cookie because value '{}' contains invalid char '{}'", - unwrappedValue, unwrappedValue.charAt(invalidOctetPos)); - } - return null; - } - - DefaultCookie cookie = new DefaultCookie(name, unwrappedValue.toString()); - cookie.setWrap(wrap); - return cookie; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/CookieUtil.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/CookieUtil.java deleted file mode 100755 index 15083220c7..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/CookieUtil.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import java.util.BitSet; - -/** - * @deprecated Duplicate of package private ${@link com.ai.cloud.io.netty.handler.codec.http.cookie.CookieUtil} - */ -@Deprecated -final class CookieUtil { - - private static final BitSet VALID_COOKIE_VALUE_OCTETS = validCookieValueOctets(); - - private static final BitSet VALID_COOKIE_NAME_OCTETS = validCookieNameOctets(VALID_COOKIE_VALUE_OCTETS); - - // US-ASCII characters excluding CTLs, whitespace, DQUOTE, comma, semicolon, and backslash - private static BitSet validCookieValueOctets() { - BitSet bits = new BitSet(8); - for (int i = 35; i < 127; i++) { - // US-ASCII characters excluding CTLs (%x00-1F / %x7F) - bits.set(i); - } - bits.set('"', false); // exclude DQUOTE = %x22 - bits.set(',', false); // exclude comma = %x2C - bits.set(';', false); // exclude semicolon = %x3B - bits.set('\\', false); // exclude backslash = %x5C - return bits; - } - - // token = 1* - // separators = "(" | ")" | "<" | ">" | "@" - // | "," | ";" | ":" | "\" | <"> - // | "/" | "[" | "]" | "?" | "=" - // | "{" | "}" | SP | HT - private static BitSet validCookieNameOctets(BitSet validCookieValueOctets) { - BitSet bits = new BitSet(8); - bits.or(validCookieValueOctets); - bits.set('(', false); - bits.set(')', false); - bits.set('<', false); - bits.set('>', false); - bits.set('@', false); - bits.set(':', false); - bits.set('/', false); - bits.set('[', false); - bits.set(']', false); - bits.set('?', false); - bits.set('=', false); - bits.set('{', false); - bits.set('}', false); - bits.set(' ', false); - bits.set('\t', false); - return bits; - } - - static int firstInvalidCookieNameOctet(CharSequence cs) { - return firstInvalidOctet(cs, VALID_COOKIE_NAME_OCTETS); - } - - static int firstInvalidCookieValueOctet(CharSequence cs) { - return firstInvalidOctet(cs, VALID_COOKIE_VALUE_OCTETS); - } - - static int firstInvalidOctet(CharSequence cs, BitSet bits) { - for (int i = 0; i < cs.length(); i++) { - char c = cs.charAt(i); - if (!bits.get(c)) { - return i; - } - } - return -1; - } - - static CharSequence unwrapValue(CharSequence cs) { - final int len = cs.length(); - if (len > 0 && cs.charAt(0) == '"') { - if (len >= 2 && cs.charAt(len - 1) == '"') { - // properly balanced - return len == 2 ? "" : cs.subSequence(1, len - 1); - } else { - return null; - } - } - return cs; - } - - private CookieUtil() { - // Unused - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultCookie.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultCookie.java deleted file mode 100755 index de72359690..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultCookie.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import java.util.Collections; -import java.util.Set; -import java.util.TreeSet; - -/** - * The default {@link Cookie} implementation. - * - * @deprecated Use {@link com.ai.cloud.io.netty.handler.codec.http.cookie.DefaultCookie} instead. - */ -@Deprecated -public class DefaultCookie extends com.ai.cloud.io.netty.handler.codec.http.cookie.DefaultCookie implements Cookie { - - private String comment; - private String commentUrl; - private boolean discard; - private Set ports = Collections.emptySet(); - private Set unmodifiablePorts = ports; - private int version; - - /** - * Creates a new cookie with the specified name and value. - */ - public DefaultCookie(String name, String value) { - super(name, value); - } - - @Override - @Deprecated - public String getName() { - return name(); - } - - @Override - @Deprecated - public String getValue() { - return value(); - } - - @Override - @Deprecated - public String getDomain() { - return domain(); - } - - @Override - @Deprecated - public String getPath() { - return path(); - } - - @Override - @Deprecated - public String getComment() { - return comment(); - } - - @Override - @Deprecated - public String comment() { - return comment; - } - - @Override - @Deprecated - public void setComment(String comment) { - this.comment = validateValue("comment", comment); - } - - @Override - @Deprecated - public String getCommentUrl() { - return commentUrl(); - } - - @Override - @Deprecated - public String commentUrl() { - return commentUrl; - } - - @Override - @Deprecated - public void setCommentUrl(String commentUrl) { - this.commentUrl = validateValue("commentUrl", commentUrl); - } - - @Override - @Deprecated - public boolean isDiscard() { - return discard; - } - - @Override - @Deprecated - public void setDiscard(boolean discard) { - this.discard = discard; - } - - @Override - @Deprecated - public Set getPorts() { - return ports(); - } - - @Override - @Deprecated - public Set ports() { - if (unmodifiablePorts == null) { - unmodifiablePorts = Collections.unmodifiableSet(ports); - } - return unmodifiablePorts; - } - - @Override - @Deprecated - public void setPorts(int... ports) { - if (ports == null) { - throw new NullPointerException("ports"); - } - - int[] portsCopy = ports.clone(); - if (portsCopy.length == 0) { - unmodifiablePorts = this.ports = Collections.emptySet(); - } else { - Set newPorts = new TreeSet(); - for (int p: portsCopy) { - if (p <= 0 || p > 65535) { - throw new IllegalArgumentException("port out of range: " + p); - } - newPorts.add(Integer.valueOf(p)); - } - this.ports = newPorts; - unmodifiablePorts = null; - } - } - - @Override - @Deprecated - public void setPorts(Iterable ports) { - Set newPorts = new TreeSet(); - for (int p: ports) { - if (p <= 0 || p > 65535) { - throw new IllegalArgumentException("port out of range: " + p); - } - newPorts.add(Integer.valueOf(p)); - } - if (newPorts.isEmpty()) { - unmodifiablePorts = this.ports = Collections.emptySet(); - } else { - this.ports = newPorts; - unmodifiablePorts = null; - } - } - - @Override - @Deprecated - public long getMaxAge() { - return maxAge(); - } - - @Override - @Deprecated - public int getVersion() { - return version(); - } - - @Override - @Deprecated - public int version() { - return version; - } - - @Override - @Deprecated - public void setVersion(int version) { - this.version = version; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultFullHttpRequest.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultFullHttpRequest.java deleted file mode 100755 index e703e0614f..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultFullHttpRequest.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.Unpooled; - -/** - * Default implementation of {@link FullHttpRequest}. - */ -public class DefaultFullHttpRequest extends DefaultHttpRequest implements FullHttpRequest { - private final ByteBuf content; - private final HttpHeaders trailingHeader; - private final boolean validateHeaders; - - public DefaultFullHttpRequest(HttpVersion httpVersion, HttpMethod method, String uri) { - this(httpVersion, method, uri, Unpooled.buffer(0)); - } - - public DefaultFullHttpRequest(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) { - this(httpVersion, method, uri, content, true); - } - - public DefaultFullHttpRequest(HttpVersion httpVersion, HttpMethod method, String uri, - ByteBuf content, boolean validateHeaders) { - super(httpVersion, method, uri, validateHeaders); - if (content == null) { - throw new NullPointerException("content"); - } - this.content = content; - trailingHeader = new DefaultHttpHeaders(validateHeaders); - this.validateHeaders = validateHeaders; - } - - @Override - public HttpHeaders trailingHeaders() { - return trailingHeader; - } - - @Override - public ByteBuf content() { - return content; - } - - @Override - public int refCnt() { - return content.refCnt(); - } - - @Override - public FullHttpRequest retain() { - content.retain(); - return this; - } - - @Override - public FullHttpRequest retain(int increment) { - content.retain(increment); - return this; - } - - @Override - public boolean release() { - return content.release(); - } - - @Override - public boolean release(int decrement) { - return content.release(decrement); - } - - @Override - public FullHttpRequest setProtocolVersion(HttpVersion version) { - super.setProtocolVersion(version); - return this; - } - - @Override - public FullHttpRequest setMethod(HttpMethod method) { - super.setMethod(method); - return this; - } - - @Override - public FullHttpRequest setUri(String uri) { - super.setUri(uri); - return this; - } - - @Override - public FullHttpRequest copy() { - DefaultFullHttpRequest copy = new DefaultFullHttpRequest( - getProtocolVersion(), getMethod(), getUri(), content().copy(), validateHeaders); - copy.headers().set(headers()); - copy.trailingHeaders().set(trailingHeaders()); - return copy; - } - - @Override - public FullHttpRequest duplicate() { - DefaultFullHttpRequest duplicate = new DefaultFullHttpRequest( - getProtocolVersion(), getMethod(), getUri(), content().duplicate(), validateHeaders); - duplicate.headers().set(headers()); - duplicate.trailingHeaders().set(trailingHeaders()); - return duplicate; - } - - @Override - public String toString() { - return HttpMessageUtil.appendFullRequest(new StringBuilder(256), this).toString(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultFullHttpResponse.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultFullHttpResponse.java deleted file mode 100755 index 07d3d21230..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultFullHttpResponse.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.Unpooled; - - -/** - * Default implementation of a {@link FullHttpResponse}. - */ -public class DefaultFullHttpResponse extends DefaultHttpResponse implements FullHttpResponse { - - private final ByteBuf content; - private final HttpHeaders trailingHeaders; - private final boolean validateHeaders; - - public DefaultFullHttpResponse(HttpVersion version, HttpResponseStatus status) { - this(version, status, Unpooled.buffer(0)); - } - - public DefaultFullHttpResponse(HttpVersion version, HttpResponseStatus status, ByteBuf content) { - this(version, status, content, true); - } - - public DefaultFullHttpResponse(HttpVersion version, HttpResponseStatus status, - ByteBuf content, boolean validateHeaders) { - super(version, status, validateHeaders); - if (content == null) { - throw new NullPointerException("content"); - } - this.content = content; - trailingHeaders = new DefaultHttpHeaders(validateHeaders); - this.validateHeaders = validateHeaders; - } - - @Override - public HttpHeaders trailingHeaders() { - return trailingHeaders; - } - - @Override - public ByteBuf content() { - return content; - } - - @Override - public int refCnt() { - return content.refCnt(); - } - - @Override - public FullHttpResponse retain() { - content.retain(); - return this; - } - - @Override - public FullHttpResponse retain(int increment) { - content.retain(increment); - return this; - } - - @Override - public boolean release() { - return content.release(); - } - - @Override - public boolean release(int decrement) { - return content.release(decrement); - } - - @Override - public FullHttpResponse setProtocolVersion(HttpVersion version) { - super.setProtocolVersion(version); - return this; - } - - @Override - public FullHttpResponse setStatus(HttpResponseStatus status) { - super.setStatus(status); - return this; - } - - @Override - public FullHttpResponse copy() { - DefaultFullHttpResponse copy = new DefaultFullHttpResponse( - getProtocolVersion(), getStatus(), content().copy(), validateHeaders); - copy.headers().set(headers()); - copy.trailingHeaders().set(trailingHeaders()); - return copy; - } - - @Override - public FullHttpResponse duplicate() { - DefaultFullHttpResponse duplicate = new DefaultFullHttpResponse(getProtocolVersion(), getStatus(), - content().duplicate(), validateHeaders); - duplicate.headers().set(headers()); - duplicate.trailingHeaders().set(trailingHeaders()); - return duplicate; - } - - @Override - public String toString() { - return HttpMessageUtil.appendFullResponse(new StringBuilder(256), this).toString(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultHttpContent.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultHttpContent.java deleted file mode 100755 index 19c207d732..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultHttpContent.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.util.internal.StringUtil; - -/** - * The default {@link HttpContent} implementation. - */ -public class DefaultHttpContent extends DefaultHttpObject implements HttpContent { - - private final ByteBuf content; - - /** - * Creates a new instance with the specified chunk content. - */ - public DefaultHttpContent(ByteBuf content) { - if (content == null) { - throw new NullPointerException("content"); - } - this.content = content; - } - - @Override - public ByteBuf content() { - return content; - } - - @Override - public HttpContent copy() { - return new DefaultHttpContent(content.copy()); - } - - @Override - public HttpContent duplicate() { - return new DefaultHttpContent(content.duplicate()); - } - - @Override - public int refCnt() { - return content.refCnt(); - } - - @Override - public HttpContent retain() { - content.retain(); - return this; - } - - @Override - public HttpContent retain(int increment) { - content.retain(increment); - return this; - } - - @Override - public boolean release() { - return content.release(); - } - - @Override - public boolean release(int decrement) { - return content.release(decrement); - } - - @Override - public String toString() { - return StringUtil.simpleClassName(this) + - "(data: " + content() + ", decoderResult: " + getDecoderResult() + ')'; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultHttpHeaders.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultHttpHeaders.java deleted file mode 100755 index 9a0f437399..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultHttpHeaders.java +++ /dev/null @@ -1,504 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import java.util.Arrays; -import java.util.Calendar; -import java.util.Date; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.NoSuchElementException; -import java.util.Set; - -import com.ai.cloud.io.netty.buffer.ByteBuf; - -import static com.ai.cloud.io.netty.util.internal.ObjectUtil.checkNotNull; - -public class DefaultHttpHeaders extends HttpHeaders { - - private static final int BUCKET_SIZE = 17; - - private static int index(int hash) { - return hash % BUCKET_SIZE; - } - - private final HeaderEntry[] entries = new HeaderEntry[BUCKET_SIZE]; - private final HeaderEntry head = new HeaderEntry(); - protected final boolean validate; - - public DefaultHttpHeaders() { - this(true); - } - - public DefaultHttpHeaders(boolean validate) { - this.validate = validate; - head.before = head.after = head; - } - - void validateHeaderName0(CharSequence headerName) { - validateHeaderName(headerName); - } - - @Override - public HttpHeaders add(HttpHeaders headers) { - if (headers instanceof DefaultHttpHeaders) { - if (headers == this) { - throw new IllegalArgumentException("can't add to itself."); - } - DefaultHttpHeaders defaultHttpHeaders = (DefaultHttpHeaders) headers; - HeaderEntry e = defaultHttpHeaders.head.after; - while (e != defaultHttpHeaders.head) { - add(e.key, e.value); - e = e.after; - } - return this; - } else { - return super.add(headers); - } - } - - @Override - public HttpHeaders set(HttpHeaders headers) { - if (headers instanceof DefaultHttpHeaders) { - if (headers == this) { - throw new IllegalArgumentException("can't add to itself."); - } - clear(); - DefaultHttpHeaders defaultHttpHeaders = (DefaultHttpHeaders) headers; - HeaderEntry e = defaultHttpHeaders.head.after; - while (e != defaultHttpHeaders.head) { - add(e.key, e.value); - e = e.after; - } - return this; - } else { - return super.set(headers); - } - } - - @Override - public HttpHeaders add(final String name, final Object value) { - return add((CharSequence) name, value); - } - - @Override - public HttpHeaders add(final CharSequence name, final Object value) { - CharSequence strVal; - if (validate) { - validateHeaderName0(name); - strVal = toCharSequence(value); - validateHeaderValue(strVal); - } else { - strVal = toCharSequence(value); - } - int h = hash(name); - int i = index(h); - add0(h, i, name, strVal); - return this; - } - - @Override - public HttpHeaders add(String name, Iterable values) { - return add((CharSequence) name, values); - } - - @Override - public HttpHeaders add(CharSequence name, Iterable values) { - if (validate) { - validateHeaderName0(name); - } - int h = hash(name); - int i = index(h); - for (Object v: values) { - CharSequence vstr = toCharSequence(v); - if (validate) { - validateHeaderValue(vstr); - } - add0(h, i, name, vstr); - } - return this; - } - - private void add0(int h, int i, final CharSequence name, final CharSequence value) { - // Update the hash table. - HeaderEntry e = entries[i]; - HeaderEntry newEntry; - entries[i] = newEntry = new HeaderEntry(h, name, value); - newEntry.next = e; - - // Update the linked list. - newEntry.addBefore(head); - } - - @Override - public HttpHeaders remove(final String name) { - return remove((CharSequence) name); - } - - @Override - public HttpHeaders remove(final CharSequence name) { - if (name == null) { - throw new NullPointerException("name"); - } - int h = hash(name); - int i = index(h); - remove0(h, i, name); - return this; - } - - private void remove0(int h, int i, CharSequence name) { - HeaderEntry e = entries[i]; - if (e == null) { - return; - } - - for (;;) { - if (e.hash == h && equalsIgnoreCase(name, e.key)) { - e.remove(); - HeaderEntry next = e.next; - if (next != null) { - entries[i] = next; - e = next; - } else { - entries[i] = null; - return; - } - } else { - break; - } - } - - for (;;) { - HeaderEntry next = e.next; - if (next == null) { - break; - } - if (next.hash == h && equalsIgnoreCase(name, next.key)) { - e.next = next.next; - next.remove(); - } else { - e = next; - } - } - } - - @Override - public HttpHeaders set(final String name, final Object value) { - return set((CharSequence) name, value); - } - - @Override - public HttpHeaders set(final CharSequence name, final Object value) { - CharSequence strVal; - if (validate) { - validateHeaderName0(name); - strVal = toCharSequence(value); - validateHeaderValue(strVal); - } else { - strVal = toCharSequence(value); - } - int h = hash(name); - int i = index(h); - remove0(h, i, name); - add0(h, i, name, strVal); - return this; - } - - @Override - public HttpHeaders set(final String name, final Iterable values) { - return set((CharSequence) name, values); - } - - @Override - public HttpHeaders set(final CharSequence name, final Iterable values) { - if (values == null) { - throw new NullPointerException("values"); - } - if (validate) { - validateHeaderName0(name); - } - - int h = hash(name); - int i = index(h); - - remove0(h, i, name); - for (Object v: values) { - if (v == null) { - break; - } - CharSequence strVal = toCharSequence(v); - if (validate) { - validateHeaderValue(strVal); - } - add0(h, i, name, strVal); - } - - return this; - } - - @Override - public HttpHeaders clear() { - Arrays.fill(entries, null); - head.before = head.after = head; - return this; - } - - @Override - public String get(final String name) { - return get((CharSequence) name); - } - - @Override - public String get(final CharSequence name) { - if (name == null) { - throw new NullPointerException("name"); - } - - int h = hash(name); - int i = index(h); - HeaderEntry e = entries[i]; - CharSequence value = null; - // loop until the first header was found - while (e != null) { - if (e.hash == h && equalsIgnoreCase(name, e.key)) { - value = e.value; - } - - e = e.next; - } - if (value == null) { - return null; - } - return value.toString(); - } - - @Override - public List getAll(final String name) { - return getAll((CharSequence) name); - } - - @Override - public List getAll(final CharSequence name) { - if (name == null) { - throw new NullPointerException("name"); - } - - LinkedList values = new LinkedList(); - - int h = hash(name); - int i = index(h); - HeaderEntry e = entries[i]; - while (e != null) { - if (e.hash == h && equalsIgnoreCase(name, e.key)) { - values.addFirst(e.getValue()); - } - e = e.next; - } - return values; - } - - @Override - public List> entries() { - List> all = - new LinkedList>(); - - HeaderEntry e = head.after; - while (e != head) { - all.add(e); - e = e.after; - } - return all; - } - - @Override - public Iterator> iterator() { - return new HeaderIterator(); - } - - @Override - public boolean contains(String name) { - return get(name) != null; - } - - @Override - public boolean contains(CharSequence name) { - return get(name) != null; - } - - @Override - public boolean isEmpty() { - return head == head.after; - } - - @Override - public boolean contains(String name, String value, boolean ignoreCaseValue) { - return contains((CharSequence) name, (CharSequence) value, ignoreCaseValue); - } - - @Override - public boolean contains(CharSequence name, CharSequence value, boolean ignoreCaseValue) { - if (name == null) { - throw new NullPointerException("name"); - } - - int h = hash(name); - int i = index(h); - HeaderEntry e = entries[i]; - while (e != null) { - if (e.hash == h && equalsIgnoreCase(name, e.key)) { - if (ignoreCaseValue) { - if (equalsIgnoreCase(e.value, value)) { - return true; - } - } else { - if (e.value.equals(value)) { - return true; - } - } - } - e = e.next; - } - return false; - } - - @Override - public Set names() { - Set names = new LinkedHashSet(); - HeaderEntry e = head.after; - while (e != head) { - names.add(e.getKey()); - e = e.after; - } - return names; - } - - private static CharSequence toCharSequence(Object value) { - checkNotNull(value, "value"); - if (value instanceof CharSequence) { - return (CharSequence) value; - } - if (value instanceof Number) { - return value.toString(); - } - if (value instanceof Date) { - return HttpHeaderDateFormat.get().format((Date) value); - } - if (value instanceof Calendar) { - return HttpHeaderDateFormat.get().format(((Calendar) value).getTime()); - } - return value.toString(); - } - - void encode(ByteBuf buf) { - HeaderEntry e = head.after; - while (e != head) { - e.encode(buf); - e = e.after; - } - } - - private final class HeaderIterator implements Iterator> { - - private HeaderEntry current = head; - - @Override - public boolean hasNext() { - return current.after != head; - } - - @Override - public Entry next() { - current = current.after; - - if (current == head) { - throw new NoSuchElementException(); - } - - return current; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - } - - private final class HeaderEntry implements Map.Entry { - final int hash; - final CharSequence key; - CharSequence value; - HeaderEntry next; - HeaderEntry before, after; - - HeaderEntry(int hash, CharSequence key, CharSequence value) { - this.hash = hash; - this.key = key; - this.value = value; - } - - HeaderEntry() { - hash = -1; - key = null; - value = null; - } - - void remove() { - before.after = after; - after.before = before; - } - - void addBefore(HeaderEntry e) { - after = e; - before = e.before; - before.after = this; - after.before = this; - } - - @Override - public String getKey() { - return key.toString(); - } - - @Override - public String getValue() { - return value.toString(); - } - - @Override - public String setValue(String value) { - if (value == null) { - throw new NullPointerException("value"); - } - validateHeaderValue(value); - CharSequence oldValue = this.value; - this.value = value; - return oldValue.toString(); - } - - @Override - public String toString() { - return key.toString() + '=' + value.toString(); - } - - void encode(ByteBuf buf) { - HttpHeaders.encode(key, value, buf); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultHttpMessage.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultHttpMessage.java deleted file mode 100755 index 7f5075ffee..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultHttpMessage.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -/** - * The default {@link HttpMessage} implementation. - */ -public abstract class DefaultHttpMessage extends DefaultHttpObject implements HttpMessage { - - private HttpVersion version; - private final HttpHeaders headers; - - /** - * Creates a new instance. - */ - protected DefaultHttpMessage(final HttpVersion version) { - this(version, true); - } - - protected DefaultHttpMessage(final HttpVersion version, boolean validate) { - if (version == null) { - throw new NullPointerException("version"); - } - this.version = version; - headers = new DefaultHttpHeaders(validate); - } - - @Override - public HttpHeaders headers() { - return headers; - } - - @Override - public HttpVersion getProtocolVersion() { - return version; - } - - @Override - public HttpMessage setProtocolVersion(HttpVersion version) { - if (version == null) { - throw new NullPointerException("version"); - } - this.version = version; - return this; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultHttpObject.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultHttpObject.java deleted file mode 100755 index daff000447..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultHttpObject.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import com.ai.cloud.io.netty.handler.codec.DecoderResult; - -public class DefaultHttpObject implements HttpObject { - - private DecoderResult decoderResult = DecoderResult.SUCCESS; - - protected DefaultHttpObject() { - // Disallow direct instantiation - } - - @Override - public DecoderResult getDecoderResult() { - return decoderResult; - } - - @Override - public void setDecoderResult(DecoderResult decoderResult) { - if (decoderResult == null) { - throw new NullPointerException("decoderResult"); - } - this.decoderResult = decoderResult; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultHttpRequest.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultHttpRequest.java deleted file mode 100755 index c5215a80cd..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultHttpRequest.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -/** - * The default {@link HttpRequest} implementation. - */ -public class DefaultHttpRequest extends DefaultHttpMessage implements HttpRequest { - - private HttpMethod method; - private String uri; - - /** - * Creates a new instance. - * - * @param httpVersion the HTTP version of the request - * @param method the HTTP getMethod of the request - * @param uri the URI or path of the request - */ - public DefaultHttpRequest(HttpVersion httpVersion, HttpMethod method, String uri) { - this(httpVersion, method, uri, true); - } - - /** - * Creates a new instance. - * - * @param httpVersion the HTTP version of the request - * @param method the HTTP getMethod of the request - * @param uri the URI or path of the request - * @param validateHeaders validate the headers when adding them - */ - public DefaultHttpRequest(HttpVersion httpVersion, HttpMethod method, String uri, boolean validateHeaders) { - super(httpVersion, validateHeaders); - if (method == null) { - throw new NullPointerException("method"); - } - if (uri == null) { - throw new NullPointerException("uri"); - } - this.method = method; - this.uri = uri; - } - - @Override - public HttpMethod getMethod() { - return method; - } - - @Override - public String getUri() { - return uri; - } - - @Override - public HttpRequest setMethod(HttpMethod method) { - if (method == null) { - throw new NullPointerException("method"); - } - this.method = method; - return this; - } - - @Override - public HttpRequest setUri(String uri) { - if (uri == null) { - throw new NullPointerException("uri"); - } - this.uri = uri; - return this; - } - - @Override - public HttpRequest setProtocolVersion(HttpVersion version) { - super.setProtocolVersion(version); - return this; - } - - @Override - public String toString() { - return HttpMessageUtil.appendRequest(new StringBuilder(256), this).toString(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultHttpResponse.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultHttpResponse.java deleted file mode 100755 index 75e6e0ef3d..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultHttpResponse.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -/** - * The default {@link HttpResponse} implementation. - */ -public class DefaultHttpResponse extends DefaultHttpMessage implements HttpResponse { - - private HttpResponseStatus status; - - /** - * Creates a new instance. - * - * @param version the HTTP version of this response - * @param status the getStatus of this response - */ - public DefaultHttpResponse(HttpVersion version, HttpResponseStatus status) { - this(version, status, true); - } - - /** - * Creates a new instance. - * - * @param version the HTTP version of this response - * @param status the getStatus of this response - * @param validateHeaders validate the headers when adding them - */ - public DefaultHttpResponse(HttpVersion version, HttpResponseStatus status, boolean validateHeaders) { - super(version, validateHeaders); - if (status == null) { - throw new NullPointerException("status"); - } - this.status = status; - } - - @Override - public HttpResponseStatus getStatus() { - return status; - } - - @Override - public HttpResponse setStatus(HttpResponseStatus status) { - if (status == null) { - throw new NullPointerException("status"); - } - this.status = status; - return this; - } - - @Override - public HttpResponse setProtocolVersion(HttpVersion version) { - super.setProtocolVersion(version); - return this; - } - - @Override - public String toString() { - return HttpMessageUtil.appendResponse(new StringBuilder(256), this).toString(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultLastHttpContent.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultLastHttpContent.java deleted file mode 100755 index afb1fdf3fb..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/DefaultLastHttpContent.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import java.util.Map; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.Unpooled; -import com.ai.cloud.io.netty.util.internal.StringUtil; - -/** - * The default {@link LastHttpContent} implementation. - */ -public class DefaultLastHttpContent extends DefaultHttpContent implements LastHttpContent { - - private final HttpHeaders trailingHeaders; - private final boolean validateHeaders; - - public DefaultLastHttpContent() { - this(Unpooled.buffer(0)); - } - - public DefaultLastHttpContent(ByteBuf content) { - this(content, true); - } - - public DefaultLastHttpContent(ByteBuf content, boolean validateHeaders) { - super(content); - trailingHeaders = new TrailingHeaders(validateHeaders); - this.validateHeaders = validateHeaders; - } - - @Override - public LastHttpContent copy() { - DefaultLastHttpContent copy = new DefaultLastHttpContent(content().copy(), validateHeaders); - copy.trailingHeaders().set(trailingHeaders()); - return copy; - } - - @Override - public LastHttpContent duplicate() { - DefaultLastHttpContent copy = new DefaultLastHttpContent(content().duplicate(), validateHeaders); - copy.trailingHeaders().set(trailingHeaders()); - return copy; - } - - @Override - public LastHttpContent retain(int increment) { - super.retain(increment); - return this; - } - - @Override - public LastHttpContent retain() { - super.retain(); - return this; - } - - @Override - public HttpHeaders trailingHeaders() { - return trailingHeaders; - } - - @Override - public String toString() { - StringBuilder buf = new StringBuilder(super.toString()); - buf.append(StringUtil.NEWLINE); - appendHeaders(buf); - - // Remove the last newline. - buf.setLength(buf.length() - StringUtil.NEWLINE.length()); - return buf.toString(); - } - - private void appendHeaders(StringBuilder buf) { - for (Map.Entry e: trailingHeaders()) { - buf.append(e.getKey()); - buf.append(": "); - buf.append(e.getValue()); - buf.append(StringUtil.NEWLINE); - } - } - - private static final class TrailingHeaders extends DefaultHttpHeaders { - TrailingHeaders(boolean validate) { - super(validate); - } - - @Override - void validateHeaderName0(CharSequence name) { - super.validateHeaderName0(name); - if (HttpHeaders.equalsIgnoreCase(HttpHeaders.Names.CONTENT_LENGTH, name) || - HttpHeaders.equalsIgnoreCase(HttpHeaders.Names.TRANSFER_ENCODING, name) || - HttpHeaders.equalsIgnoreCase(HttpHeaders.Names.TRAILER, name)) { - throw new IllegalArgumentException( - "prohibited trailing header: " + name); - } - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/FullHttpMessage.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/FullHttpMessage.java deleted file mode 100755 index cdc884257b..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/FullHttpMessage.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -/** - * Combines {@link HttpMessage} and {@link LastHttpContent} into one - * message. So it represent a complete http message. - */ -public interface FullHttpMessage extends HttpMessage, LastHttpContent { - @Override - FullHttpMessage copy(); - - @Override - FullHttpMessage retain(int increment); - - @Override - FullHttpMessage retain(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/FullHttpRequest.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/FullHttpRequest.java deleted file mode 100755 index 56b4de98cf..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/FullHttpRequest.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -/** - * Combinate the {@link HttpRequest} and {@link FullHttpMessage}, so the request is a complete HTTP - * request. - */ -public interface FullHttpRequest extends HttpRequest, FullHttpMessage { - @Override - FullHttpRequest copy(); - - @Override - FullHttpRequest retain(int increment); - - @Override - FullHttpRequest retain(); - - @Override - FullHttpRequest setProtocolVersion(HttpVersion version); - - @Override - FullHttpRequest setMethod(HttpMethod method); - - @Override - FullHttpRequest setUri(String uri); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/FullHttpResponse.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/FullHttpResponse.java deleted file mode 100755 index 7f24383175..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/FullHttpResponse.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -/** - * Combination of a {@link HttpResponse} and {@link FullHttpMessage}. - * So it represent a complete http response. - */ -public interface FullHttpResponse extends HttpResponse, FullHttpMessage { - @Override - FullHttpResponse copy(); - - @Override - FullHttpResponse retain(int increment); - - @Override - FullHttpResponse retain(); - - @Override - FullHttpResponse setProtocolVersion(HttpVersion version); - - @Override - FullHttpResponse setStatus(HttpResponseStatus status); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpChunkedInput.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpChunkedInput.java deleted file mode 100755 index fb2320b712..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpChunkedInput.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.handler.stream.ChunkedInput; - -/** - * A {@link ChunkedInput} that fetches data chunk by chunk for use with HTTP chunked transfers. - *

- * Each chunk from the input data will be wrapped within a {@link HttpContent}. At the end of the input data, - * {@link LastHttpContent} will be written. - *

- * Ensure that your HTTP response header contains {@code Transfer-Encoding: chunked}. - *

- *

- * public void messageReceived(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception {
- *     HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
- *     response.headers().set(TRANSFER_ENCODING, CHUNKED);
- *     ctx.write(response);
- *
- *     HttpContentChunkedInput httpChunkWriter = new HttpChunkedInput(
- *         new ChunkedFile("/tmp/myfile.txt"));
- *     ChannelFuture sendFileFuture = ctx.write(httpChunkWriter);
- * }
- * 
- */ -public class HttpChunkedInput implements ChunkedInput { - - private final ChunkedInput input; - private final LastHttpContent lastHttpContent; - private boolean sentLastChunk; - - /** - * Creates a new instance using the specified input. - * @param input {@link ChunkedInput} containing data to write - */ - public HttpChunkedInput(ChunkedInput input) { - this.input = input; - lastHttpContent = LastHttpContent.EMPTY_LAST_CONTENT; - } - - /** - * Creates a new instance using the specified input. {@code lastHttpContent} will be written as the terminating - * chunk. - * @param input {@link ChunkedInput} containing data to write - * @param lastHttpContent {@link LastHttpContent} that will be written as the terminating chunk. Use this for - * training headers. - */ - public HttpChunkedInput(ChunkedInput input, LastHttpContent lastHttpContent) { - this.input = input; - this.lastHttpContent = lastHttpContent; - } - - @Override - public boolean isEndOfInput() throws Exception { - if (input.isEndOfInput()) { - // Only end of input after last HTTP chunk has been sent - return sentLastChunk; - } else { - return false; - } - } - - @Override - public void close() throws Exception { - input.close(); - } - - @Override - public HttpContent readChunk(ChannelHandlerContext ctx) throws Exception { - if (input.isEndOfInput()) { - if (sentLastChunk) { - return null; - } else { - // Send last chunk for this input - sentLastChunk = true; - return lastHttpContent; - } - } else { - ByteBuf buf = input.readChunk(ctx); - return new DefaultHttpContent(buf); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpClientCodec.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpClientCodec.java deleted file mode 100755 index 05bae4c121..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpClientCodec.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import java.util.ArrayDeque; -import java.util.List; -import java.util.Queue; -import java.util.concurrent.atomic.AtomicLong; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.CombinedChannelDuplexHandler; -import com.ai.cloud.io.netty.handler.codec.PrematureChannelClosureException; - -/** - * A combination of {@link HttpRequestEncoder} and {@link HttpResponseDecoder} - * which enables easier client side HTTP implementation. {@link HttpClientCodec} - * provides additional state management for HEAD and CONNECT - * requests, which {@link HttpResponseDecoder} lacks. Please refer to - * {@link HttpResponseDecoder} to learn what additional state management needs - * to be done for HEAD and CONNECT and why - * {@link HttpResponseDecoder} can not handle it by itself. - * - * If the {@link Channel} is closed and there are missing responses, - * a {@link PrematureChannelClosureException} is thrown. - * - * @see HttpServerCodec - */ -public final class HttpClientCodec - extends CombinedChannelDuplexHandler { - - /** A queue that is used for correlating a request and a response. */ - private final Queue queue = new ArrayDeque(); - - /** If true, decoding stops (i.e. pass-through) */ - private boolean done; - - private final AtomicLong requestResponseCounter = new AtomicLong(); - private final boolean failOnMissingResponse; - - /** - * Creates a new instance with the default decoder options - * ({@code maxInitialLineLength (4096}}, {@code maxHeaderSize (8192)}, and - * {@code maxChunkSize (8192)}). - */ - public HttpClientCodec() { - this(4096, 8192, 8192, false); - } - - public void setSingleDecode(boolean singleDecode) { - inboundHandler().setSingleDecode(singleDecode); - } - - public boolean isSingleDecode() { - return inboundHandler().isSingleDecode(); - } - - /** - * Creates a new instance with the specified decoder options. - */ - public HttpClientCodec(int maxInitialLineLength, int maxHeaderSize, int maxChunkSize) { - this(maxInitialLineLength, maxHeaderSize, maxChunkSize, false); - } - - /** - * Creates a new instance with the specified decoder options. - */ - public HttpClientCodec( - int maxInitialLineLength, int maxHeaderSize, int maxChunkSize, boolean failOnMissingResponse) { - this(maxInitialLineLength, maxHeaderSize, maxChunkSize, failOnMissingResponse, true); - } - - /** - * Creates a new instance with the specified decoder options. - */ - public HttpClientCodec( - int maxInitialLineLength, int maxHeaderSize, int maxChunkSize, boolean failOnMissingResponse, - boolean validateHeaders) { - init(new Decoder(maxInitialLineLength, maxHeaderSize, maxChunkSize, validateHeaders), new Encoder()); - this.failOnMissingResponse = failOnMissingResponse; - } - - private final class Encoder extends HttpRequestEncoder { - - @Override - protected void encode( - ChannelHandlerContext ctx, Object msg, List out) throws Exception { - if (msg instanceof HttpRequest && !done) { - queue.offer(((HttpRequest) msg).getMethod()); - } - - super.encode(ctx, msg, out); - - if (failOnMissingResponse) { - // check if the request is chunked if so do not increment - if (msg instanceof LastHttpContent) { - // increment as its the last chunk - requestResponseCounter.incrementAndGet(); - } - } - } - } - - private final class Decoder extends HttpResponseDecoder { - Decoder(int maxInitialLineLength, int maxHeaderSize, int maxChunkSize, boolean validateHeaders) { - super(maxInitialLineLength, maxHeaderSize, maxChunkSize, validateHeaders); - } - - @Override - protected void decode( - ChannelHandlerContext ctx, ByteBuf buffer, List out) throws Exception { - if (done) { - int readable = actualReadableBytes(); - if (readable == 0) { - // if non is readable just return null - // https://github.com/netty/netty/issues/1159 - return; - } - out.add(buffer.readBytes(readable)); - } else { - int oldSize = out.size(); - super.decode(ctx, buffer, out); - if (failOnMissingResponse) { - int size = out.size(); - for (int i = oldSize; i < size; i++) { - decrement(out.get(i)); - } - } - } - } - - private void decrement(Object msg) { - if (msg == null) { - return; - } - - // check if it's an Header and its transfer encoding is not chunked. - if (msg instanceof LastHttpContent) { - requestResponseCounter.decrementAndGet(); - } - } - - @Override - protected boolean isContentAlwaysEmpty(HttpMessage msg) { - final int statusCode = ((HttpResponse) msg).getStatus().code(); - if (statusCode == 100) { - // 100-continue response should be excluded from paired comparison. - return true; - } - - // Get the getMethod of the HTTP request that corresponds to the - // current response. - HttpMethod method = queue.poll(); - - char firstChar = method.name().charAt(0); - switch (firstChar) { - case 'H': - // According to 4.3, RFC2616: - // All responses to the HEAD request getMethod MUST NOT include a - // message-body, even though the presence of entity-header fields - // might lead one to believe they do. - if (HttpMethod.HEAD.equals(method)) { - return true; - - // The following code was inserted to work around the servers - // that behave incorrectly. It has been commented out - // because it does not work with well behaving servers. - // Please note, even if the 'Transfer-Encoding: chunked' - // header exists in the HEAD response, the response should - // have absolutely no content. - // - //// Interesting edge case: - //// Some poorly implemented servers will send a zero-byte - //// chunk if Transfer-Encoding of the response is 'chunked'. - //// - //// return !msg.isChunked(); - } - break; - case 'C': - // Successful CONNECT request results in a response with empty body. - if (statusCode == 200) { - if (HttpMethod.CONNECT.equals(method)) { - // Proxy connection established - Not HTTP anymore. - done = true; - queue.clear(); - return true; - } - } - break; - } - - return super.isContentAlwaysEmpty(msg); - } - - @Override - public void channelInactive(ChannelHandlerContext ctx) - throws Exception { - super.channelInactive(ctx); - - if (failOnMissingResponse) { - long missingResponses = requestResponseCounter.get(); - if (missingResponses > 0) { - ctx.fireExceptionCaught(new PrematureChannelClosureException( - "channel gone inactive with " + missingResponses + - " missing response(s)")); - } - } - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpConstants.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpConstants.java deleted file mode 100755 index cbb4aa0541..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpConstants.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import java.nio.charset.Charset; - -import com.ai.cloud.io.netty.util.CharsetUtil; - -public final class HttpConstants { - - /** - * Horizontal space - */ - public static final byte SP = 32; - - /** - * Horizontal tab - */ - public static final byte HT = 9; - - /** - * Carriage return - */ - public static final byte CR = 13; - - /** - * Equals '=' - */ - public static final byte EQUALS = 61; - - /** - * Line feed character - */ - public static final byte LF = 10; - - /** - * Colon ':' - */ - public static final byte COLON = 58; - - /** - * Semicolon ';' - */ - public static final byte SEMICOLON = 59; - - /** - * Comma ',' - */ - public static final byte COMMA = 44; - - /** - * Double quote '"' - */ - public static final byte DOUBLE_QUOTE = '"'; - - /** - * Default character set (UTF-8) - */ - public static final Charset DEFAULT_CHARSET = CharsetUtil.UTF_8; - - /** - * Horizontal space - */ - public static final char SP_CHAR = (char) SP; - - private HttpConstants() { - // Unused - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpContent.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpContent.java deleted file mode 100755 index ce87f47651..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpContent.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import com.ai.cloud.io.netty.buffer.ByteBufHolder; -import com.ai.cloud.io.netty.channel.ChannelPipeline; - -/** - * An HTTP chunk which is used for HTTP chunked transfer-encoding. - * {@link HttpObjectDecoder} generates {@link HttpContent} after - * {@link HttpMessage} when the content is large or the encoding of the content - * is 'chunked. If you prefer not to receive {@link HttpContent} in your handler, - * place {@link HttpObjectAggregator} after {@link HttpObjectDecoder} in the - * {@link ChannelPipeline}. - */ -public interface HttpContent extends HttpObject, ByteBufHolder { - @Override - HttpContent copy(); - - @Override - HttpContent duplicate(); - - @Override - HttpContent retain(); - - @Override - HttpContent retain(int increment); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpContentCompressor.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpContentCompressor.java deleted file mode 100755 index d7c844b6ed..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpContentCompressor.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import com.ai.cloud.io.netty.channel.embedded.EmbeddedChannel; -import com.ai.cloud.io.netty.handler.codec.compression.ZlibCodecFactory; -import com.ai.cloud.io.netty.handler.codec.compression.ZlibWrapper; -import com.ai.cloud.io.netty.util.internal.StringUtil; - -/** - * Compresses an {@link HttpMessage} and an {@link HttpContent} in {@code gzip} or - * {@code deflate} encoding while respecting the {@code "Accept-Encoding"} header. - * If there is no matching encoding, no compression is done. For more - * information on how this handler modifies the message, please refer to - * {@link HttpContentEncoder}. - */ -public class HttpContentCompressor extends HttpContentEncoder { - - private final int compressionLevel; - private final int windowBits; - private final int memLevel; - - /** - * Creates a new handler with the default compression level (6), - * default window size (15) and default memory level (8). - */ - public HttpContentCompressor() { - this(6); - } - - /** - * Creates a new handler with the specified compression level, default - * window size (15) and default memory level (8). - * - * @param compressionLevel - * {@code 1} yields the fastest compression and {@code 9} yields the - * best compression. {@code 0} means no compression. The default - * compression level is {@code 6}. - */ - public HttpContentCompressor(int compressionLevel) { - this(compressionLevel, 15, 8); - } - - /** - * Creates a new handler with the specified compression level, window size, - * and memory level.. - * - * @param compressionLevel - * {@code 1} yields the fastest compression and {@code 9} yields the - * best compression. {@code 0} means no compression. The default - * compression level is {@code 6}. - * @param windowBits - * The base two logarithm of the size of the history buffer. The - * value should be in the range {@code 9} to {@code 15} inclusive. - * Larger values result in better compression at the expense of - * memory usage. The default value is {@code 15}. - * @param memLevel - * How much memory should be allocated for the internal compression - * state. {@code 1} uses minimum memory and {@code 9} uses maximum - * memory. Larger values result in better and faster compression - * at the expense of memory usage. The default value is {@code 8} - */ - public HttpContentCompressor(int compressionLevel, int windowBits, int memLevel) { - if (compressionLevel < 0 || compressionLevel > 9) { - throw new IllegalArgumentException( - "compressionLevel: " + compressionLevel + - " (expected: 0-9)"); - } - if (windowBits < 9 || windowBits > 15) { - throw new IllegalArgumentException( - "windowBits: " + windowBits + " (expected: 9-15)"); - } - if (memLevel < 1 || memLevel > 9) { - throw new IllegalArgumentException( - "memLevel: " + memLevel + " (expected: 1-9)"); - } - this.compressionLevel = compressionLevel; - this.windowBits = windowBits; - this.memLevel = memLevel; - } - - @Override - protected Result beginEncode(HttpResponse headers, String acceptEncoding) throws Exception { - String contentEncoding = headers.headers().get(HttpHeaders.Names.CONTENT_ENCODING); - if (contentEncoding != null && - !HttpHeaders.Values.IDENTITY.equalsIgnoreCase(contentEncoding)) { - return null; - } - - ZlibWrapper wrapper = determineWrapper(acceptEncoding); - if (wrapper == null) { - return null; - } - - String targetContentEncoding; - switch (wrapper) { - case GZIP: - targetContentEncoding = "gzip"; - break; - case ZLIB: - targetContentEncoding = "deflate"; - break; - default: - throw new Error(); - } - - return new Result( - targetContentEncoding, - new EmbeddedChannel(ZlibCodecFactory.newZlibEncoder( - wrapper, compressionLevel, windowBits, memLevel))); - } - - @SuppressWarnings("FloatingPointEquality") - protected ZlibWrapper determineWrapper(String acceptEncoding) { - float starQ = -1.0f; - float gzipQ = -1.0f; - float deflateQ = -1.0f; - for (String encoding: StringUtil.split(acceptEncoding, ',')) { - float q = 1.0f; - int equalsPos = encoding.indexOf('='); - if (equalsPos != -1) { - try { - q = Float.valueOf(encoding.substring(equalsPos + 1)); - } catch (NumberFormatException e) { - // Ignore encoding - q = 0.0f; - } - } - if (encoding.contains("*")) { - starQ = q; - } else if (encoding.contains("gzip") && q > gzipQ) { - gzipQ = q; - } else if (encoding.contains("deflate") && q > deflateQ) { - deflateQ = q; - } - } - if (gzipQ > 0.0f || deflateQ > 0.0f) { - if (gzipQ >= deflateQ) { - return ZlibWrapper.GZIP; - } else { - return ZlibWrapper.ZLIB; - } - } - if (starQ > 0.0f) { - if (gzipQ == -1.0f) { - return ZlibWrapper.GZIP; - } - if (deflateQ == -1.0f) { - return ZlibWrapper.ZLIB; - } - } - return null; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpContentDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpContentDecoder.java deleted file mode 100755 index 354fdf7660..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpContentDecoder.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import java.util.List; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.embedded.EmbeddedChannel; -import com.ai.cloud.io.netty.handler.codec.CodecException; -import com.ai.cloud.io.netty.handler.codec.MessageToMessageDecoder; -import com.ai.cloud.io.netty.util.ReferenceCountUtil; - -/** - * Decodes the content of the received {@link HttpRequest} and {@link HttpContent}. - * The original content is replaced with the new content decoded by the - * {@link EmbeddedChannel}, which is created by {@link #newContentDecoder(String)}. - * Once decoding is finished, the value of the 'Content-Encoding' - * header is set to the target content encoding, as returned by {@link #getTargetContentEncoding(String)}. - * Also, the 'Content-Length' header is updated to the length of the - * decoded content. If the content encoding of the original is not supported - * by the decoder, {@link #newContentDecoder(String)} should return {@code null} - * so that no decoding occurs (i.e. pass-through). - *

- * Please note that this is an abstract class. You have to extend this class - * and implement {@link #newContentDecoder(String)} properly to make this class - * functional. For example, refer to the source code of {@link HttpContentDecompressor}. - *

- * This handler must be placed after {@link HttpObjectDecoder} in the pipeline - * so that this handler can intercept HTTP requests after {@link HttpObjectDecoder} - * converts {@link ByteBuf}s into HTTP requests. - */ -public abstract class HttpContentDecoder extends MessageToMessageDecoder { - - private EmbeddedChannel decoder; - private boolean continueResponse; - - @Override - protected void decode(ChannelHandlerContext ctx, HttpObject msg, List out) throws Exception { - if (msg instanceof HttpResponse && ((HttpResponse) msg).getStatus().code() == 100) { - - if (!(msg instanceof LastHttpContent)) { - continueResponse = true; - } - // 100-continue response must be passed through. - out.add(ReferenceCountUtil.retain(msg)); - return; - } - - if (continueResponse) { - if (msg instanceof LastHttpContent) { - continueResponse = false; - } - // 100-continue response must be passed through. - out.add(ReferenceCountUtil.retain(msg)); - return; - } - - if (msg instanceof HttpMessage) { - cleanup(); - final HttpMessage message = (HttpMessage) msg; - final HttpHeaders headers = message.headers(); - - // Determine the content encoding. - String contentEncoding = headers.get(HttpHeaders.Names.CONTENT_ENCODING); - if (contentEncoding != null) { - contentEncoding = contentEncoding.trim(); - } else { - contentEncoding = HttpHeaders.Values.IDENTITY; - } - decoder = newContentDecoder(contentEncoding); - - if (decoder == null) { - if (message instanceof HttpContent) { - ((HttpContent) message).retain(); - } - out.add(message); - return; - } - - // Remove content-length header: - // the correct value can be set only after all chunks are processed/decoded. - // If buffering is not an issue, add HttpObjectAggregator down the chain, it will set the header. - // Otherwise, rely on LastHttpContent message. - headers.remove(HttpHeaders.Names.CONTENT_LENGTH); - - // set new content encoding, - CharSequence targetContentEncoding = getTargetContentEncoding(contentEncoding); - if (HttpHeaders.Values.IDENTITY.equals(targetContentEncoding)) { - // Do NOT set the 'Content-Encoding' header if the target encoding is 'identity' - // as per: http://tools.ietf.org/html/rfc2616#section-14.11 - headers.remove(HttpHeaders.Names.CONTENT_ENCODING); - } else { - headers.set(HttpHeaders.Names.CONTENT_ENCODING, targetContentEncoding); - } - - if (message instanceof HttpContent) { - // If message is a full request or response object (headers + data), don't copy data part into out. - // Output headers only; data part will be decoded below. - // Note: "copy" object must not be an instance of LastHttpContent class, - // as this would (erroneously) indicate the end of the HttpMessage to other handlers. - HttpMessage copy; - if (message instanceof HttpRequest) { - HttpRequest r = (HttpRequest) message; // HttpRequest or FullHttpRequest - copy = new DefaultHttpRequest(r.getProtocolVersion(), r.getMethod(), r.getUri()); - } else if (message instanceof HttpResponse) { - HttpResponse r = (HttpResponse) message; // HttpResponse or FullHttpResponse - copy = new DefaultHttpResponse(r.getProtocolVersion(), r.getStatus()); - } else { - throw new CodecException("Object of class " + message.getClass().getName() + - " is not a HttpRequest or HttpResponse"); - } - copy.headers().set(message.headers()); - copy.setDecoderResult(message.getDecoderResult()); - out.add(copy); - } else { - out.add(message); - } - } - - if (msg instanceof HttpContent) { - final HttpContent c = (HttpContent) msg; - if (decoder == null) { - out.add(c.retain()); - } else { - decodeContent(c, out); - } - } - } - - private void decodeContent(HttpContent c, List out) { - ByteBuf content = c.content(); - - decode(content, out); - - if (c instanceof LastHttpContent) { - finishDecode(out); - - LastHttpContent last = (LastHttpContent) c; - // Generate an additional chunk if the decoder produced - // the last product on closure, - HttpHeaders headers = last.trailingHeaders(); - if (headers.isEmpty()) { - out.add(LastHttpContent.EMPTY_LAST_CONTENT); - } else { - out.add(new ComposedLastHttpContent(headers)); - } - } - } - - /** - * Returns a new {@link EmbeddedChannel} that decodes the HTTP message - * content encoded in the specified contentEncoding. - * - * @param contentEncoding the value of the {@code "Content-Encoding"} header - * @return a new {@link EmbeddedChannel} if the specified encoding is supported. - * {@code null} otherwise (alternatively, you can throw an exception - * to block unknown encoding). - */ - protected abstract EmbeddedChannel newContentDecoder(String contentEncoding) throws Exception; - - /** - * Returns the expected content encoding of the decoded content. - * This getMethod returns {@code "identity"} by default, which is the case for - * most decoders. - * - * @param contentEncoding the value of the {@code "Content-Encoding"} header - * @return the expected content encoding of the new content - */ - protected String getTargetContentEncoding( - @SuppressWarnings("UnusedParameters") String contentEncoding) throws Exception { - return HttpHeaders.Values.IDENTITY; - } - - @Override - public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { - cleanup(); - super.handlerRemoved(ctx); - } - - @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { - cleanup(); - super.channelInactive(ctx); - } - - private void cleanup() { - if (decoder != null) { - // Clean-up the previous decoder if not cleaned up correctly. - if (decoder.finish()) { - for (;;) { - ByteBuf buf = (ByteBuf) decoder.readInbound(); - if (buf == null) { - break; - } - // Release the buffer - buf.release(); - } - } - decoder = null; - } - } - - private void decode(ByteBuf in, List out) { - // call retain here as it will call release after its written to the channel - decoder.writeInbound(in.retain()); - fetchDecoderOutput(out); - } - - private void finishDecode(List out) { - if (decoder.finish()) { - fetchDecoderOutput(out); - } - decoder = null; - } - - private void fetchDecoderOutput(List out) { - for (;;) { - ByteBuf buf = (ByteBuf) decoder.readInbound(); - if (buf == null) { - break; - } - if (!buf.isReadable()) { - buf.release(); - continue; - } - out.add(new DefaultHttpContent(buf)); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpContentDecompressor.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpContentDecompressor.java deleted file mode 100755 index e4c8a9e9f9..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpContentDecompressor.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import com.ai.cloud.io.netty.channel.embedded.EmbeddedChannel; -import com.ai.cloud.io.netty.handler.codec.compression.ZlibCodecFactory; -import com.ai.cloud.io.netty.handler.codec.compression.ZlibWrapper; - -/** - * Decompresses an {@link HttpMessage} and an {@link HttpContent} compressed in - * {@code gzip} or {@code deflate} encoding. For more information on how this - * handler modifies the message, please refer to {@link HttpContentDecoder}. - */ -public class HttpContentDecompressor extends HttpContentDecoder { - - private final boolean strict; - - /** - * Create a new {@link HttpContentDecompressor} in non-strict mode. - */ - public HttpContentDecompressor() { - this(false); - } - - /** - * Create a new {@link HttpContentDecompressor}. - * - * @param strict if {@code true} use strict handling of deflate if used, otherwise handle it in a - * more lenient fashion. - */ - public HttpContentDecompressor(boolean strict) { - this.strict = strict; - } - - @Override - protected EmbeddedChannel newContentDecoder(String contentEncoding) throws Exception { - if ("gzip".equalsIgnoreCase(contentEncoding) || "x-gzip".equalsIgnoreCase(contentEncoding)) { - return new EmbeddedChannel(ZlibCodecFactory.newZlibDecoder(ZlibWrapper.GZIP)); - } - if ("deflate".equalsIgnoreCase(contentEncoding) || "x-deflate".equalsIgnoreCase(contentEncoding)) { - ZlibWrapper wrapper; - if (strict) { - wrapper = ZlibWrapper.ZLIB; - } else { - wrapper = ZlibWrapper.ZLIB_OR_NONE; - } - // To be strict, 'deflate' means ZLIB, but some servers were not implemented correctly. - return new EmbeddedChannel(ZlibCodecFactory.newZlibDecoder(wrapper)); - } - - // 'identity' or unsupported - return null; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpContentEncoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpContentEncoder.java deleted file mode 100755 index 8d86580c21..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpContentEncoder.java +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import java.util.ArrayDeque; -import java.util.List; -import java.util.Queue; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.ByteBufHolder; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.embedded.EmbeddedChannel; -import com.ai.cloud.io.netty.handler.codec.MessageToMessageCodec; -import com.ai.cloud.io.netty.handler.codec.http.HttpHeaders.Names; -import com.ai.cloud.io.netty.handler.codec.http.HttpHeaders.Values; -import com.ai.cloud.io.netty.util.ReferenceCountUtil; - -/** - * Encodes the content of the outbound {@link HttpResponse} and {@link HttpContent}. - * The original content is replaced with the new content encoded by the - * {@link EmbeddedChannel}, which is created by {@link #beginEncode(HttpResponse, String)}. - * Once encoding is finished, the value of the 'Content-Encoding' header - * is set to the target content encoding, as returned by - * {@link #beginEncode(HttpResponse, String)}. - * Also, the 'Content-Length' header is updated to the length of the - * encoded content. If there is no supported or allowed encoding in the - * corresponding {@link HttpRequest}'s {@code "Accept-Encoding"} header, - * {@link #beginEncode(HttpResponse, String)} should return {@code null} so that - * no encoding occurs (i.e. pass-through). - *

- * Please note that this is an abstract class. You have to extend this class - * and implement {@link #beginEncode(HttpResponse, String)} properly to make - * this class functional. For example, refer to the source code of - * {@link HttpContentCompressor}. - *

- * This handler must be placed after {@link HttpObjectEncoder} in the pipeline - * so that this handler can intercept HTTP responses before {@link HttpObjectEncoder} - * converts them into {@link ByteBuf}s. - */ -public abstract class HttpContentEncoder extends MessageToMessageCodec { - - private enum State { - PASS_THROUGH, - AWAIT_HEADERS, - AWAIT_CONTENT - } - - private static final CharSequence ZERO_LENGTH_HEAD = "HEAD"; - private static final CharSequence ZERO_LENGTH_CONNECT = "CONNECT"; - private static final int CONTINUE_CODE = HttpResponseStatus.CONTINUE.code(); - - private final Queue acceptEncodingQueue = new ArrayDeque(); - private CharSequence acceptEncoding; - private EmbeddedChannel encoder; - private State state = State.AWAIT_HEADERS; - - @Override - public boolean acceptOutboundMessage(Object msg) throws Exception { - return msg instanceof HttpContent || msg instanceof HttpResponse; - } - - @Override - protected void decode(ChannelHandlerContext ctx, HttpRequest msg, List out) - throws Exception { - CharSequence acceptedEncoding = msg.headers().get(HttpHeaders.Names.ACCEPT_ENCODING); - if (acceptedEncoding == null) { - acceptedEncoding = HttpHeaders.Values.IDENTITY; - } - - HttpMethod meth = msg.getMethod(); - if (meth == HttpMethod.HEAD) { - acceptedEncoding = ZERO_LENGTH_HEAD; - } else if (meth == HttpMethod.CONNECT) { - acceptedEncoding = ZERO_LENGTH_CONNECT; - } - - acceptEncodingQueue.add(acceptedEncoding); - out.add(ReferenceCountUtil.retain(msg)); - } - - @Override - protected void encode(ChannelHandlerContext ctx, HttpObject msg, List out) throws Exception { - final boolean isFull = msg instanceof HttpResponse && msg instanceof LastHttpContent; - switch (state) { - case AWAIT_HEADERS: { - ensureHeaders(msg); - assert encoder == null; - - final HttpResponse res = (HttpResponse) msg; - final int code = res.getStatus().code(); - if (code == CONTINUE_CODE) { - // We need to not poll the encoding when response with CONTINUE as another response will follow - // for the issued request. See https://github.com/netty/netty/issues/4079 - acceptEncoding = null; - } else { - // Get the list of encodings accepted by the peer. - acceptEncoding = acceptEncodingQueue.poll(); - if (acceptEncoding == null) { - throw new IllegalStateException("cannot send more responses than requests"); - } - } - - /* - * per rfc2616 4.3 Message Body - * All 1xx (informational), 204 (no content), and 304 (not modified) responses MUST NOT include a - * message-body. All other responses do include a message-body, although it MAY be of zero length. - * - * 9.4 HEAD - * The HEAD method is identical to GET except that the server MUST NOT return a message-body - * in the response. - * - * This code is now inline with HttpClientDecoder.Decoder - */ - if (isPassthru(code, acceptEncoding)) { - if (isFull) { - out.add(ReferenceCountUtil.retain(res)); - } else { - out.add(res); - // Pass through all following contents. - state = State.PASS_THROUGH; - } - break; - } - - if (isFull) { - // Pass through the full response with empty content and continue waiting for the the next resp. - if (!((ByteBufHolder) res).content().isReadable()) { - out.add(ReferenceCountUtil.retain(res)); - break; - } - } - - // Prepare to encode the content. - final Result result = beginEncode(res, acceptEncoding.toString()); - - // If unable to encode, pass through. - if (result == null) { - if (isFull) { - out.add(ReferenceCountUtil.retain(res)); - } else { - out.add(res); - // Pass through all following contents. - state = State.PASS_THROUGH; - } - break; - } - - encoder = result.contentEncoder(); - - // Encode the content and remove or replace the existing headers - // so that the message looks like a decoded message. - res.headers().set(Names.CONTENT_ENCODING, result.targetContentEncoding()); - - // Make the response chunked to simplify content transformation. - res.headers().remove(Names.CONTENT_LENGTH); - res.headers().set(Names.TRANSFER_ENCODING, Values.CHUNKED); - - // Output the rewritten response. - if (isFull) { - // Convert full message into unfull one. - HttpResponse newRes = new DefaultHttpResponse(res.getProtocolVersion(), res.getStatus()); - newRes.headers().set(res.headers()); - out.add(newRes); - // Fall through to encode the content of the full response. - } else { - out.add(res); - state = State.AWAIT_CONTENT; - if (!(msg instanceof HttpContent)) { - // only break out the switch statement if we have not content to process - // See https://github.com/netty/netty/issues/2006 - break; - } - // Fall through to encode the content - } - } - case AWAIT_CONTENT: { - ensureContent(msg); - if (encodeContent((HttpContent) msg, out)) { - state = State.AWAIT_HEADERS; - } - break; - } - case PASS_THROUGH: { - ensureContent(msg); - out.add(ReferenceCountUtil.retain(msg)); - // Passed through all following contents of the current response. - if (msg instanceof LastHttpContent) { - state = State.AWAIT_HEADERS; - } - break; - } - } - } - - private static boolean isPassthru(int code, CharSequence httpMethod) { - return code < 200 || code == 204 || code == 304 || - (httpMethod == ZERO_LENGTH_HEAD || (httpMethod == ZERO_LENGTH_CONNECT && code == 200)); - } - - private static void ensureHeaders(HttpObject msg) { - if (!(msg instanceof HttpResponse)) { - throw new IllegalStateException( - "unexpected message type: " + - msg.getClass().getName() + " (expected: " + HttpResponse.class.getSimpleName() + ')'); - } - } - - private static void ensureContent(HttpObject msg) { - if (!(msg instanceof HttpContent)) { - throw new IllegalStateException( - "unexpected message type: " + - msg.getClass().getName() + " (expected: " + HttpContent.class.getSimpleName() + ')'); - } - } - - private boolean encodeContent(HttpContent c, List out) { - ByteBuf content = c.content(); - - encode(content, out); - - if (c instanceof LastHttpContent) { - finishEncode(out); - LastHttpContent last = (LastHttpContent) c; - - // Generate an additional chunk if the decoder produced - // the last product on closure, - HttpHeaders headers = last.trailingHeaders(); - if (headers.isEmpty()) { - out.add(LastHttpContent.EMPTY_LAST_CONTENT); - } else { - out.add(new ComposedLastHttpContent(headers)); - } - return true; - } - return false; - } - - /** - * Prepare to encode the HTTP message content. - * - * @param headers - * the headers - * @param acceptEncoding - * the value of the {@code "Accept-Encoding"} header - * - * @return the result of preparation, which is composed of the determined - * target content encoding and a new {@link EmbeddedChannel} that - * encodes the content into the target content encoding. - * {@code null} if {@code acceptEncoding} is unsupported or rejected - * and thus the content should be handled as-is (i.e. no encoding). - */ - protected abstract Result beginEncode(HttpResponse headers, String acceptEncoding) throws Exception; - - @Override - public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { - cleanup(); - super.handlerRemoved(ctx); - } - - @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { - cleanup(); - super.channelInactive(ctx); - } - - private void cleanup() { - if (encoder != null) { - // Clean-up the previous encoder if not cleaned up correctly. - if (encoder.finish()) { - for (;;) { - ByteBuf buf = (ByteBuf) encoder.readOutbound(); - if (buf == null) { - break; - } - // Release the buffer - // https://github.com/netty/netty/issues/1524 - buf.release(); - } - } - encoder = null; - } - } - - private void encode(ByteBuf in, List out) { - // call retain here as it will call release after its written to the channel - encoder.writeOutbound(in.retain()); - fetchEncoderOutput(out); - } - - private void finishEncode(List out) { - if (encoder.finish()) { - fetchEncoderOutput(out); - } - encoder = null; - } - - private void fetchEncoderOutput(List out) { - for (;;) { - ByteBuf buf = (ByteBuf) encoder.readOutbound(); - if (buf == null) { - break; - } - if (!buf.isReadable()) { - buf.release(); - continue; - } - out.add(new DefaultHttpContent(buf)); - } - } - - public static final class Result { - private final String targetContentEncoding; - private final EmbeddedChannel contentEncoder; - - public Result(String targetContentEncoding, EmbeddedChannel contentEncoder) { - if (targetContentEncoding == null) { - throw new NullPointerException("targetContentEncoding"); - } - if (contentEncoder == null) { - throw new NullPointerException("contentEncoder"); - } - - this.targetContentEncoding = targetContentEncoding; - this.contentEncoder = contentEncoder; - } - - public String targetContentEncoding() { - return targetContentEncoding; - } - - public EmbeddedChannel contentEncoder() { - return contentEncoder; - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpExpectationFailedEvent.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpExpectationFailedEvent.java deleted file mode 100755 index 2020cebb98..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpExpectationFailedEvent.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -/** - * A user event designed to communicate that a expectation has failed and there should be no expectation that a - * body will follow. - */ -public final class HttpExpectationFailedEvent { - public static final HttpExpectationFailedEvent INSTANCE = new HttpExpectationFailedEvent(); - private HttpExpectationFailedEvent() { } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpHeaderDateFormat.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpHeaderDateFormat.java deleted file mode 100755 index c1ccf2c79d..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpHeaderDateFormat.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import java.text.ParsePosition; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Locale; -import java.util.TimeZone; - -import com.ai.cloud.io.netty.util.concurrent.FastThreadLocal; - -/** - * This DateFormat decodes 3 formats of {@link Date}, but only encodes the one, - * the first: - *
    - *
  • Sun, 06 Nov 1994 08:49:37 GMT: standard specification, the only one with - * valid generation
  • - *
  • Sun, 06 Nov 1994 08:49:37 GMT: obsolete specification
  • - *
  • Sun Nov 6 08:49:37 1994: obsolete specification
  • - *
- */ -public final class HttpHeaderDateFormat extends SimpleDateFormat { - private static final long serialVersionUID = -925286159755905325L; - - private final SimpleDateFormat format1 = new HttpHeaderDateFormatObsolete1(); - private final SimpleDateFormat format2 = new HttpHeaderDateFormatObsolete2(); - - private static final FastThreadLocal dateFormatThreadLocal = - new FastThreadLocal() { - @Override - protected HttpHeaderDateFormat initialValue() { - return new HttpHeaderDateFormat(); - } - }; - - public static HttpHeaderDateFormat get() { - return dateFormatThreadLocal.get(); - } - - /** - * Standard date format

- * Sun, 06 Nov 1994 08:49:37 GMT -> E, d MMM yyyy HH:mm:ss z - */ - private HttpHeaderDateFormat() { - super("E, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH); - setTimeZone(TimeZone.getTimeZone("GMT")); - } - - @Override - public Date parse(String text, ParsePosition pos) { - Date date = super.parse(text, pos); - if (date == null) { - date = format1.parse(text, pos); - } - if (date == null) { - date = format2.parse(text, pos); - } - return date; - } - - /** - * First obsolete format

- * Sunday, 06-Nov-94 08:49:37 GMT -> E, d-MMM-y HH:mm:ss z - */ - private static final class HttpHeaderDateFormatObsolete1 extends SimpleDateFormat { - private static final long serialVersionUID = -3178072504225114298L; - - HttpHeaderDateFormatObsolete1() { - super("E, dd-MMM-yy HH:mm:ss z", Locale.ENGLISH); - setTimeZone(TimeZone.getTimeZone("GMT")); - } - } - - /** - * Second obsolete format - *

- * Sun Nov 6 08:49:37 1994 -> EEE, MMM d HH:mm:ss yyyy - */ - private static final class HttpHeaderDateFormatObsolete2 extends SimpleDateFormat { - private static final long serialVersionUID = 3010674519968303714L; - - HttpHeaderDateFormatObsolete2() { - super("E MMM d HH:mm:ss yyyy", Locale.ENGLISH); - setTimeZone(TimeZone.getTimeZone("GMT")); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpHeaderEntity.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpHeaderEntity.java deleted file mode 100755 index ef3a9d891b..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpHeaderEntity.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.util.CharsetUtil; - -final class HttpHeaderEntity implements CharSequence { - - private final String name; - private final int hash; - private final byte[] bytes; - private final int separatorLen; - - public HttpHeaderEntity(String name) { - this(name, null); - } - - public HttpHeaderEntity(String name, byte[] separator) { - this.name = name; - hash = HttpHeaders.hash(name); - byte[] nameBytes = name.getBytes(CharsetUtil.US_ASCII); - if (separator == null) { - bytes = nameBytes; - separatorLen = 0; - } else { - separatorLen = separator.length; - bytes = new byte[nameBytes.length + separator.length]; - System.arraycopy(nameBytes, 0, bytes, 0, nameBytes.length); - System.arraycopy(separator, 0, bytes, nameBytes.length, separator.length); - } - } - - int hash() { - return hash; - } - - @Override - public int length() { - return bytes.length - separatorLen; - } - - @Override - public char charAt(int index) { - if ((bytes.length - separatorLen) <= index) { - throw new IndexOutOfBoundsException(); - } - return (char) bytes[index]; - } - - @Override - public CharSequence subSequence(int start, int end) { - return new HttpHeaderEntity(name.substring(start, end)); - } - - @Override - public String toString() { - return name; - } - - boolean encode(ByteBuf buf) { - buf.writeBytes(bytes); - return separatorLen > 0; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpHeaders.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpHeaders.java deleted file mode 100755 index 47b6e8fde9..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpHeaders.java +++ /dev/null @@ -1,1683 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import java.text.ParseException; -import java.util.Calendar; -import java.util.Collections; -import java.util.Date; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -import com.ai.cloud.io.netty.buffer.ByteBuf; - -import static com.ai.cloud.io.netty.handler.codec.http.HttpConstants.*; - -/** - * Provides the constants for the standard HTTP header names and values and - * commonly used utility methods that accesses an {@link HttpMessage}. - */ -public abstract class HttpHeaders implements Iterable> { - - private static final byte[] HEADER_SEPERATOR = { COLON, SP }; - private static final byte[] CRLF = { CR, LF }; - private static final CharSequence CONTENT_LENGTH_ENTITY = newEntity(Names.CONTENT_LENGTH); - private static final CharSequence CONNECTION_ENTITY = newEntity(Names.CONNECTION); - private static final CharSequence CLOSE_ENTITY = newEntity(Values.CLOSE); - private static final CharSequence KEEP_ALIVE_ENTITY = newEntity(Values.KEEP_ALIVE); - private static final CharSequence HOST_ENTITY = newEntity(Names.HOST); - private static final CharSequence DATE_ENTITY = newEntity(Names.DATE); - private static final CharSequence EXPECT_ENTITY = newEntity(Names.EXPECT); - private static final CharSequence CONTINUE_ENTITY = newEntity(Values.CONTINUE); - private static final CharSequence TRANSFER_ENCODING_ENTITY = newEntity(Names.TRANSFER_ENCODING); - private static final CharSequence CHUNKED_ENTITY = newEntity(Values.CHUNKED); - private static final CharSequence SEC_WEBSOCKET_KEY1_ENTITY = newEntity(Names.SEC_WEBSOCKET_KEY1); - private static final CharSequence SEC_WEBSOCKET_KEY2_ENTITY = newEntity(Names.SEC_WEBSOCKET_KEY2); - private static final CharSequence SEC_WEBSOCKET_ORIGIN_ENTITY = newEntity(Names.SEC_WEBSOCKET_ORIGIN); - private static final CharSequence SEC_WEBSOCKET_LOCATION_ENTITY = newEntity(Names.SEC_WEBSOCKET_LOCATION); - - public static final HttpHeaders EMPTY_HEADERS = new HttpHeaders() { - @Override - public String get(String name) { - return null; - } - - @Override - public List getAll(String name) { - return Collections.emptyList(); - } - - @Override - public List> entries() { - return Collections.emptyList(); - } - - @Override - public boolean contains(String name) { - return false; - } - - @Override - public boolean isEmpty() { - return true; - } - - @Override - public Set names() { - return Collections.emptySet(); - } - - @Override - public HttpHeaders add(String name, Object value) { - throw new UnsupportedOperationException("read only"); - } - - @Override - public HttpHeaders add(String name, Iterable values) { - throw new UnsupportedOperationException("read only"); - } - - @Override - public HttpHeaders set(String name, Object value) { - throw new UnsupportedOperationException("read only"); - } - - @Override - public HttpHeaders set(String name, Iterable values) { - throw new UnsupportedOperationException("read only"); - } - - @Override - public HttpHeaders remove(String name) { - throw new UnsupportedOperationException("read only"); - } - - @Override - public HttpHeaders clear() { - throw new UnsupportedOperationException("read only"); - } - - @Override - public Iterator> iterator() { - return entries().iterator(); - } - }; - - /** - * Standard HTTP header names. - */ - public static final class Names { - /** - * {@code "Accept"} - */ - public static final String ACCEPT = "Accept"; - /** - * {@code "Accept-Charset"} - */ - public static final String ACCEPT_CHARSET = "Accept-Charset"; - /** - * {@code "Accept-Encoding"} - */ - public static final String ACCEPT_ENCODING = "Accept-Encoding"; - /** - * {@code "Accept-Language"} - */ - public static final String ACCEPT_LANGUAGE = "Accept-Language"; - /** - * {@code "Accept-Ranges"} - */ - public static final String ACCEPT_RANGES = "Accept-Ranges"; - /** - * {@code "Accept-Patch"} - */ - public static final String ACCEPT_PATCH = "Accept-Patch"; - /** - * {@code "Access-Control-Allow-Credentials"} - */ - public static final String ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials"; - /** - * {@code "Access-Control-Allow-Headers"} - */ - public static final String ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers"; - /** - * {@code "Access-Control-Allow-Methods"} - */ - public static final String ACCESS_CONTROL_ALLOW_METHODS = "Access-Control-Allow-Methods"; - /** - * {@code "Access-Control-Allow-Origin"} - */ - public static final String ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin"; - /** - * {@code "Access-Control-Expose-Headers"} - */ - public static final String ACCESS_CONTROL_EXPOSE_HEADERS = "Access-Control-Expose-Headers"; - /** - * {@code "Access-Control-Max-Age"} - */ - public static final String ACCESS_CONTROL_MAX_AGE = "Access-Control-Max-Age"; - /** - * {@code "Access-Control-Request-Headers"} - */ - public static final String ACCESS_CONTROL_REQUEST_HEADERS = "Access-Control-Request-Headers"; - /** - * {@code "Access-Control-Request-Method"} - */ - public static final String ACCESS_CONTROL_REQUEST_METHOD = "Access-Control-Request-Method"; - /** - * {@code "Age"} - */ - public static final String AGE = "Age"; - /** - * {@code "Allow"} - */ - public static final String ALLOW = "Allow"; - /** - * {@code "Authorization"} - */ - public static final String AUTHORIZATION = "Authorization"; - /** - * {@code "Cache-Control"} - */ - public static final String CACHE_CONTROL = "Cache-Control"; - /** - * {@code "Connection"} - */ - public static final String CONNECTION = "Connection"; - /** - * {@code "Content-Base"} - */ - public static final String CONTENT_BASE = "Content-Base"; - /** - * {@code "Content-Encoding"} - */ - public static final String CONTENT_ENCODING = "Content-Encoding"; - /** - * {@code "Content-Language"} - */ - public static final String CONTENT_LANGUAGE = "Content-Language"; - /** - * {@code "Content-Length"} - */ - public static final String CONTENT_LENGTH = "Content-Length"; - /** - * {@code "Content-Location"} - */ - public static final String CONTENT_LOCATION = "Content-Location"; - /** - * {@code "Content-Transfer-Encoding"} - */ - public static final String CONTENT_TRANSFER_ENCODING = "Content-Transfer-Encoding"; - /** - * {@code "Content-MD5"} - */ - public static final String CONTENT_MD5 = "Content-MD5"; - /** - * {@code "Content-Range"} - */ - public static final String CONTENT_RANGE = "Content-Range"; - /** - * {@code "Content-Type"} - */ - public static final String CONTENT_TYPE = "Content-Type"; - /** - * {@code "Cookie"} - */ - public static final String COOKIE = "Cookie"; - /** - * {@code "Date"} - */ - public static final String DATE = "Date"; - /** - * {@code "ETag"} - */ - public static final String ETAG = "ETag"; - /** - * {@code "Expect"} - */ - public static final String EXPECT = "Expect"; - /** - * {@code "Expires"} - */ - public static final String EXPIRES = "Expires"; - /** - * {@code "From"} - */ - public static final String FROM = "From"; - /** - * {@code "Host"} - */ - public static final String HOST = "Host"; - /** - * {@code "If-Match"} - */ - public static final String IF_MATCH = "If-Match"; - /** - * {@code "If-Modified-Since"} - */ - public static final String IF_MODIFIED_SINCE = "If-Modified-Since"; - /** - * {@code "If-None-Match"} - */ - public static final String IF_NONE_MATCH = "If-None-Match"; - /** - * {@code "If-Range"} - */ - public static final String IF_RANGE = "If-Range"; - /** - * {@code "If-Unmodified-Since"} - */ - public static final String IF_UNMODIFIED_SINCE = "If-Unmodified-Since"; - /** - * {@code "Last-Modified"} - */ - public static final String LAST_MODIFIED = "Last-Modified"; - /** - * {@code "Location"} - */ - public static final String LOCATION = "Location"; - /** - * {@code "Max-Forwards"} - */ - public static final String MAX_FORWARDS = "Max-Forwards"; - /** - * {@code "Origin"} - */ - public static final String ORIGIN = "Origin"; - /** - * {@code "Pragma"} - */ - public static final String PRAGMA = "Pragma"; - /** - * {@code "Proxy-Authenticate"} - */ - public static final String PROXY_AUTHENTICATE = "Proxy-Authenticate"; - /** - * {@code "Proxy-Authorization"} - */ - public static final String PROXY_AUTHORIZATION = "Proxy-Authorization"; - /** - * {@code "Range"} - */ - public static final String RANGE = "Range"; - /** - * {@code "Referer"} - */ - public static final String REFERER = "Referer"; - /** - * {@code "Retry-After"} - */ - public static final String RETRY_AFTER = "Retry-After"; - /** - * {@code "Sec-WebSocket-Key1"} - */ - public static final String SEC_WEBSOCKET_KEY1 = "Sec-WebSocket-Key1"; - /** - * {@code "Sec-WebSocket-Key2"} - */ - public static final String SEC_WEBSOCKET_KEY2 = "Sec-WebSocket-Key2"; - /** - * {@code "Sec-WebSocket-Location"} - */ - public static final String SEC_WEBSOCKET_LOCATION = "Sec-WebSocket-Location"; - /** - * {@code "Sec-WebSocket-Origin"} - */ - public static final String SEC_WEBSOCKET_ORIGIN = "Sec-WebSocket-Origin"; - /** - * {@code "Sec-WebSocket-Protocol"} - */ - public static final String SEC_WEBSOCKET_PROTOCOL = "Sec-WebSocket-Protocol"; - /** - * {@code "Sec-WebSocket-Version"} - */ - public static final String SEC_WEBSOCKET_VERSION = "Sec-WebSocket-Version"; - /** - * {@code "Sec-WebSocket-Key"} - */ - public static final String SEC_WEBSOCKET_KEY = "Sec-WebSocket-Key"; - /** - * {@code "Sec-WebSocket-Accept"} - */ - public static final String SEC_WEBSOCKET_ACCEPT = "Sec-WebSocket-Accept"; - /** - * {@code "Server"} - */ - public static final String SERVER = "Server"; - /** - * {@code "Set-Cookie"} - */ - public static final String SET_COOKIE = "Set-Cookie"; - /** - * {@code "Set-Cookie2"} - */ - public static final String SET_COOKIE2 = "Set-Cookie2"; - /** - * {@code "TE"} - */ - public static final String TE = "TE"; - /** - * {@code "Trailer"} - */ - public static final String TRAILER = "Trailer"; - /** - * {@code "Transfer-Encoding"} - */ - public static final String TRANSFER_ENCODING = "Transfer-Encoding"; - /** - * {@code "Upgrade"} - */ - public static final String UPGRADE = "Upgrade"; - /** - * {@code "User-Agent"} - */ - public static final String USER_AGENT = "User-Agent"; - /** - * {@code "Vary"} - */ - public static final String VARY = "Vary"; - /** - * {@code "Via"} - */ - public static final String VIA = "Via"; - /** - * {@code "Warning"} - */ - public static final String WARNING = "Warning"; - /** - * {@code "WebSocket-Location"} - */ - public static final String WEBSOCKET_LOCATION = "WebSocket-Location"; - /** - * {@code "WebSocket-Origin"} - */ - public static final String WEBSOCKET_ORIGIN = "WebSocket-Origin"; - /** - * {@code "WebSocket-Protocol"} - */ - public static final String WEBSOCKET_PROTOCOL = "WebSocket-Protocol"; - /** - * {@code "WWW-Authenticate"} - */ - public static final String WWW_AUTHENTICATE = "WWW-Authenticate"; - - private Names() { - } - } - - /** - * Standard HTTP header values. - */ - public static final class Values { - /** - * {@code "application/x-www-form-urlencoded"} - */ - public static final String APPLICATION_X_WWW_FORM_URLENCODED = - "application/x-www-form-urlencoded"; - /** - * {@code "base64"} - */ - public static final String BASE64 = "base64"; - /** - * {@code "binary"} - */ - public static final String BINARY = "binary"; - /** - * {@code "boundary"} - */ - public static final String BOUNDARY = "boundary"; - /** - * {@code "bytes"} - */ - public static final String BYTES = "bytes"; - /** - * {@code "charset"} - */ - public static final String CHARSET = "charset"; - /** - * {@code "chunked"} - */ - public static final String CHUNKED = "chunked"; - /** - * {@code "close"} - */ - public static final String CLOSE = "close"; - /** - * {@code "compress"} - */ - public static final String COMPRESS = "compress"; - /** - * {@code "100-continue"} - */ - public static final String CONTINUE = "100-continue"; - /** - * {@code "deflate"} - */ - public static final String DEFLATE = "deflate"; - /** - * {@code "gzip"} - */ - public static final String GZIP = "gzip"; - /** - * {@code "identity"} - */ - public static final String IDENTITY = "identity"; - /** - * {@code "keep-alive"} - */ - public static final String KEEP_ALIVE = "keep-alive"; - /** - * {@code "max-age"} - */ - public static final String MAX_AGE = "max-age"; - /** - * {@code "max-stale"} - */ - public static final String MAX_STALE = "max-stale"; - /** - * {@code "min-fresh"} - */ - public static final String MIN_FRESH = "min-fresh"; - /** - * {@code "multipart/form-data"} - */ - public static final String MULTIPART_FORM_DATA = "multipart/form-data"; - /** - * {@code "must-revalidate"} - */ - public static final String MUST_REVALIDATE = "must-revalidate"; - /** - * {@code "no-cache"} - */ - public static final String NO_CACHE = "no-cache"; - /** - * {@code "no-store"} - */ - public static final String NO_STORE = "no-store"; - /** - * {@code "no-transform"} - */ - public static final String NO_TRANSFORM = "no-transform"; - /** - * {@code "none"} - */ - public static final String NONE = "none"; - /** - * {@code "only-if-cached"} - */ - public static final String ONLY_IF_CACHED = "only-if-cached"; - /** - * {@code "private"} - */ - public static final String PRIVATE = "private"; - /** - * {@code "proxy-revalidate"} - */ - public static final String PROXY_REVALIDATE = "proxy-revalidate"; - /** - * {@code "public"} - */ - public static final String PUBLIC = "public"; - /** - * {@code "quoted-printable"} - */ - public static final String QUOTED_PRINTABLE = "quoted-printable"; - /** - * {@code "s-maxage"} - */ - public static final String S_MAXAGE = "s-maxage"; - /** - * {@code "trailers"} - */ - public static final String TRAILERS = "trailers"; - /** - * {@code "Upgrade"} - */ - public static final String UPGRADE = "Upgrade"; - /** - * {@code "WebSocket"} - */ - public static final String WEBSOCKET = "WebSocket"; - - private Values() { - } - } - - /** - * Returns {@code true} if and only if the connection can remain open and - * thus 'kept alive'. This methods respects the value of the - * {@code "Connection"} header first and then the return value of - * {@link HttpVersion#isKeepAliveDefault()}. - */ - public static boolean isKeepAlive(HttpMessage message) { - String connection = message.headers().get(CONNECTION_ENTITY); - if (connection != null && equalsIgnoreCase(CLOSE_ENTITY, connection)) { - return false; - } - - if (message.getProtocolVersion().isKeepAliveDefault()) { - return !equalsIgnoreCase(CLOSE_ENTITY, connection); - } else { - return equalsIgnoreCase(KEEP_ALIVE_ENTITY, connection); - } - } - - /** - * Sets the value of the {@code "Connection"} header depending on the - * protocol version of the specified message. This getMethod sets or removes - * the {@code "Connection"} header depending on what the default keep alive - * mode of the message's protocol version is, as specified by - * {@link HttpVersion#isKeepAliveDefault()}. - *

    - *
  • If the connection is kept alive by default: - *
      - *
    • set to {@code "close"} if {@code keepAlive} is {@code false}.
    • - *
    • remove otherwise.
    • - *
  • - *
  • If the connection is closed by default: - *
      - *
    • set to {@code "keep-alive"} if {@code keepAlive} is {@code true}.
    • - *
    • remove otherwise.
    • - *
  • - *
- */ - public static void setKeepAlive(HttpMessage message, boolean keepAlive) { - HttpHeaders h = message.headers(); - if (message.getProtocolVersion().isKeepAliveDefault()) { - if (keepAlive) { - h.remove(CONNECTION_ENTITY); - } else { - h.set(CONNECTION_ENTITY, CLOSE_ENTITY); - } - } else { - if (keepAlive) { - h.set(CONNECTION_ENTITY, KEEP_ALIVE_ENTITY); - } else { - h.remove(CONNECTION_ENTITY); - } - } - } - - /** - * @see {@link #getHeader(HttpMessage, CharSequence)} - */ - public static String getHeader(HttpMessage message, String name) { - return message.headers().get(name); - } - - /** - * Returns the header value with the specified header name. If there are - * more than one header value for the specified header name, the first - * value is returned. - * - * @return the header value or {@code null} if there is no such header - */ - public static String getHeader(HttpMessage message, CharSequence name) { - return message.headers().get(name); - } - - /** - * @see {@link #getHeader(HttpMessage, CharSequence, String)} - */ - public static String getHeader(HttpMessage message, String name, String defaultValue) { - return getHeader(message, (CharSequence) name, defaultValue); - } - - /** - * Returns the header value with the specified header name. If there are - * more than one header value for the specified header name, the first - * value is returned. - * - * @return the header value or the {@code defaultValue} if there is no such - * header - */ - public static String getHeader(HttpMessage message, CharSequence name, String defaultValue) { - String value = message.headers().get(name); - if (value == null) { - return defaultValue; - } - return value; - } - - /** - * @see {@link #setHeader(HttpMessage, CharSequence, Object)} - */ - public static void setHeader(HttpMessage message, String name, Object value) { - message.headers().set(name, value); - } - - /** - * Sets a new header with the specified name and value. If there is an - * existing header with the same name, the existing header is removed. - * If the specified value is not a {@link String}, it is converted into a - * {@link String} by {@link Object#toString()}, except for {@link Date} - * and {@link Calendar} which are formatted to the date format defined in - * RFC2616. - */ - public static void setHeader(HttpMessage message, CharSequence name, Object value) { - message.headers().set(name, value); - } - - /** - * - * @see {@link #setHeader(HttpMessage, CharSequence, Iterable)} - */ - public static void setHeader(HttpMessage message, String name, Iterable values) { - message.headers().set(name, values); - } - - /** - * Sets a new header with the specified name and values. If there is an - * existing header with the same name, the existing header is removed. - * This getMethod can be represented approximately as the following code: - *
-     * removeHeader(message, name);
-     * for (Object v: values) {
-     *     if (v == null) {
-     *         break;
-     *     }
-     *     addHeader(message, name, v);
-     * }
-     * 
- */ - public static void setHeader(HttpMessage message, CharSequence name, Iterable values) { - message.headers().set(name, values); - } - - /** - * @see {@link #addHeader(HttpMessage, CharSequence, Object)} - */ - public static void addHeader(HttpMessage message, String name, Object value) { - message.headers().add(name, value); - } - - /** - * Adds a new header with the specified name and value. - * If the specified value is not a {@link String}, it is converted into a - * {@link String} by {@link Object#toString()}, except for {@link Date} - * and {@link Calendar} which are formatted to the date format defined in - * RFC2616. - */ - public static void addHeader(HttpMessage message, CharSequence name, Object value) { - message.headers().add(name, value); - } - - /** - * @see {@link #removeHeader(HttpMessage, CharSequence)} - */ - public static void removeHeader(HttpMessage message, String name) { - message.headers().remove(name); - } - - /** - * Removes the header with the specified name. - */ - public static void removeHeader(HttpMessage message, CharSequence name) { - message.headers().remove(name); - } - - /** - * Removes all headers from the specified message. - */ - public static void clearHeaders(HttpMessage message) { - message.headers().clear(); - } - - /** - * @see {@link #getIntHeader(HttpMessage, CharSequence)} - */ - public static int getIntHeader(HttpMessage message, String name) { - return getIntHeader(message, (CharSequence) name); - } - - /** - * Returns the integer header value with the specified header name. If - * there are more than one header value for the specified header name, the - * first value is returned. - * - * @return the header value - * @throws NumberFormatException - * if there is no such header or the header value is not a number - */ - public static int getIntHeader(HttpMessage message, CharSequence name) { - String value = getHeader(message, name); - if (value == null) { - throw new NumberFormatException("header not found: " + name); - } - return Integer.parseInt(value); - } - - /** - * @see {@link #getIntHeader(HttpMessage, CharSequence, int)} - */ - public static int getIntHeader(HttpMessage message, String name, int defaultValue) { - return getIntHeader(message, (CharSequence) name, defaultValue); - } - - /** - * Returns the integer header value with the specified header name. If - * there are more than one header value for the specified header name, the - * first value is returned. - * - * @return the header value or the {@code defaultValue} if there is no such - * header or the header value is not a number - */ - public static int getIntHeader(HttpMessage message, CharSequence name, int defaultValue) { - String value = getHeader(message, name); - if (value == null) { - return defaultValue; - } - - try { - return Integer.parseInt(value); - } catch (NumberFormatException ignored) { - return defaultValue; - } - } - - /** - * @see {@link #setIntHeader(HttpMessage, CharSequence, int)} - */ - public static void setIntHeader(HttpMessage message, String name, int value) { - message.headers().set(name, value); - } - - /** - * Sets a new integer header with the specified name and value. If there - * is an existing header with the same name, the existing header is removed. - */ - public static void setIntHeader(HttpMessage message, CharSequence name, int value) { - message.headers().set(name, value); - } - - /** - * @see {@link #setIntHeader(HttpMessage, CharSequence, Iterable)} - */ - public static void setIntHeader(HttpMessage message, String name, Iterable values) { - message.headers().set(name, values); - } - - /** - * Sets a new integer header with the specified name and values. If there - * is an existing header with the same name, the existing header is removed. - */ - public static void setIntHeader(HttpMessage message, CharSequence name, Iterable values) { - message.headers().set(name, values); - } - - /** - * - * @see {@link #addIntHeader(HttpMessage, CharSequence, int)} - */ - public static void addIntHeader(HttpMessage message, String name, int value) { - message.headers().add(name, value); - } - - /** - * Adds a new integer header with the specified name and value. - */ - public static void addIntHeader(HttpMessage message, CharSequence name, int value) { - message.headers().add(name, value); - } - - /** - * @see {@link #getDateHeader(HttpMessage, CharSequence)} - */ - public static Date getDateHeader(HttpMessage message, String name) throws ParseException { - return getDateHeader(message, (CharSequence) name); - } - - /** - * Returns the date header value with the specified header name. If - * there are more than one header value for the specified header name, the - * first value is returned. - * - * @return the header value - * @throws ParseException - * if there is no such header or the header value is not a formatted date - */ - public static Date getDateHeader(HttpMessage message, CharSequence name) throws ParseException { - String value = getHeader(message, name); - if (value == null) { - throw new ParseException("header not found: " + name, 0); - } - return HttpHeaderDateFormat.get().parse(value); - } - - /** - * @see {@link #getDateHeader(HttpMessage, CharSequence, Date)} - */ - public static Date getDateHeader(HttpMessage message, String name, Date defaultValue) { - return getDateHeader(message, (CharSequence) name, defaultValue); - } - - /** - * Returns the date header value with the specified header name. If - * there are more than one header value for the specified header name, the - * first value is returned. - * - * @return the header value or the {@code defaultValue} if there is no such - * header or the header value is not a formatted date - */ - public static Date getDateHeader(HttpMessage message, CharSequence name, Date defaultValue) { - final String value = getHeader(message, name); - if (value == null) { - return defaultValue; - } - - try { - return HttpHeaderDateFormat.get().parse(value); - } catch (ParseException ignored) { - return defaultValue; - } - } - - /** - * @see {@link #setDateHeader(HttpMessage, CharSequence, Date)} - */ - public static void setDateHeader(HttpMessage message, String name, Date value) { - setDateHeader(message, (CharSequence) name, value); - } - - /** - * Sets a new date header with the specified name and value. If there - * is an existing header with the same name, the existing header is removed. - * The specified value is formatted as defined in - * RFC2616 - */ - public static void setDateHeader(HttpMessage message, CharSequence name, Date value) { - if (value != null) { - message.headers().set(name, HttpHeaderDateFormat.get().format(value)); - } else { - message.headers().set(name, null); - } - } - - /** - * @see {@link #setDateHeader(HttpMessage, CharSequence, Iterable)} - */ - public static void setDateHeader(HttpMessage message, String name, Iterable values) { - message.headers().set(name, values); - } - - /** - * Sets a new date header with the specified name and values. If there - * is an existing header with the same name, the existing header is removed. - * The specified values are formatted as defined in - * RFC2616 - */ - public static void setDateHeader(HttpMessage message, CharSequence name, Iterable values) { - message.headers().set(name, values); - } - - /** - * @see {@link #addDateHeader(HttpMessage, CharSequence, Date)} - */ - public static void addDateHeader(HttpMessage message, String name, Date value) { - message.headers().add(name, value); - } - - /** - * Adds a new date header with the specified name and value. The specified - * value is formatted as defined in - * RFC2616 - */ - public static void addDateHeader(HttpMessage message, CharSequence name, Date value) { - message.headers().add(name, value); - } - - /** - * Returns the length of the content. Please note that this value is - * not retrieved from {@link HttpContent#content()} but from the - * {@code "Content-Length"} header, and thus they are independent from each - * other. - * - * @return the content length - * - * @throws NumberFormatException - * if the message does not have the {@code "Content-Length"} header - * or its value is not a number - */ - public static long getContentLength(HttpMessage message) { - String value = getHeader(message, CONTENT_LENGTH_ENTITY); - if (value != null) { - return Long.parseLong(value); - } - - // We know the content length if it's a Web Socket message even if - // Content-Length header is missing. - long webSocketContentLength = getWebSocketContentLength(message); - if (webSocketContentLength >= 0) { - return webSocketContentLength; - } - - // Otherwise we don't. - throw new NumberFormatException("header not found: " + Names.CONTENT_LENGTH); - } - - /** - * Returns the length of the content. Please note that this value is - * not retrieved from {@link HttpContent#content()} but from the - * {@code "Content-Length"} header, and thus they are independent from each - * other. - * - * @return the content length or {@code defaultValue} if this message does - * not have the {@code "Content-Length"} header or its value is not - * a number - */ - public static long getContentLength(HttpMessage message, long defaultValue) { - String contentLength = message.headers().get(CONTENT_LENGTH_ENTITY); - if (contentLength != null) { - try { - return Long.parseLong(contentLength); - } catch (NumberFormatException ignored) { - return defaultValue; - } - } - - // We know the content length if it's a Web Socket message even if - // Content-Length header is missing. - long webSocketContentLength = getWebSocketContentLength(message); - if (webSocketContentLength >= 0) { - return webSocketContentLength; - } - - // Otherwise we don't. - return defaultValue; - } - - /** - * Returns the content length of the specified web socket message. If the - * specified message is not a web socket message, {@code -1} is returned. - */ - private static int getWebSocketContentLength(HttpMessage message) { - // WebSockset messages have constant content-lengths. - HttpHeaders h = message.headers(); - if (message instanceof HttpRequest) { - HttpRequest req = (HttpRequest) message; - if (HttpMethod.GET.equals(req.getMethod()) && - h.contains(SEC_WEBSOCKET_KEY1_ENTITY) && - h.contains(SEC_WEBSOCKET_KEY2_ENTITY)) { - return 8; - } - } else if (message instanceof HttpResponse) { - HttpResponse res = (HttpResponse) message; - if (res.getStatus().code() == 101 && - h.contains(SEC_WEBSOCKET_ORIGIN_ENTITY) && - h.contains(SEC_WEBSOCKET_LOCATION_ENTITY)) { - return 16; - } - } - - // Not a web socket message - return -1; - } - - /** - * Sets the {@code "Content-Length"} header. - */ - public static void setContentLength(HttpMessage message, long length) { - message.headers().set(CONTENT_LENGTH_ENTITY, length); - } - - /** - * Returns the value of the {@code "Host"} header. - */ - public static String getHost(HttpMessage message) { - return message.headers().get(HOST_ENTITY); - } - - /** - * Returns the value of the {@code "Host"} header. If there is no such - * header, the {@code defaultValue} is returned. - */ - public static String getHost(HttpMessage message, String defaultValue) { - return getHeader(message, HOST_ENTITY, defaultValue); - } - - /** - * @see {@link #setHost(HttpMessage, CharSequence)} - */ - public static void setHost(HttpMessage message, String value) { - message.headers().set(HOST_ENTITY, value); - } - - /** - * Sets the {@code "Host"} header. - */ - public static void setHost(HttpMessage message, CharSequence value) { - message.headers().set(HOST_ENTITY, value); - } - - /** - * Returns the value of the {@code "Date"} header. - * - * @throws ParseException - * if there is no such header or the header value is not a formatted date - */ - public static Date getDate(HttpMessage message) throws ParseException { - return getDateHeader(message, DATE_ENTITY); - } - - /** - * Returns the value of the {@code "Date"} header. If there is no such - * header or the header is not a formatted date, the {@code defaultValue} - * is returned. - */ - public static Date getDate(HttpMessage message, Date defaultValue) { - return getDateHeader(message, DATE_ENTITY, defaultValue); - } - - /** - * Sets the {@code "Date"} header. - */ - public static void setDate(HttpMessage message, Date value) { - if (value != null) { - message.headers().set(DATE_ENTITY, HttpHeaderDateFormat.get().format(value)); - } else { - message.headers().set(DATE_ENTITY, null); - } - } - - /** - * Returns {@code true} if and only if the specified message contains the - * {@code "Expect: 100-continue"} header. - */ - public static boolean is100ContinueExpected(HttpMessage message) { - // Expect: 100-continue is for requests only. - if (!(message instanceof HttpRequest)) { - return false; - } - - // It works only on HTTP/1.1 or later. - if (message.getProtocolVersion().compareTo(HttpVersion.HTTP_1_1) < 0) { - return false; - } - - // In most cases, there will be one or zero 'Expect' header. - String value = message.headers().get(EXPECT_ENTITY); - if (value == null) { - return false; - } - if (equalsIgnoreCase(CONTINUE_ENTITY, value)) { - return true; - } - - // Multiple 'Expect' headers. Search through them. - return message.headers().contains(EXPECT_ENTITY, CONTINUE_ENTITY, true); - } - - /** - * Sets the {@code "Expect: 100-continue"} header to the specified message. - * If there is any existing {@code "Expect"} header, they are replaced with - * the new one. - */ - public static void set100ContinueExpected(HttpMessage message) { - set100ContinueExpected(message, true); - } - - /** - * Sets or removes the {@code "Expect: 100-continue"} header to / from the - * specified message. If the specified {@code value} is {@code true}, - * the {@code "Expect: 100-continue"} header is set and all other previous - * {@code "Expect"} headers are removed. Otherwise, all {@code "Expect"} - * headers are removed completely. - */ - public static void set100ContinueExpected(HttpMessage message, boolean set) { - if (set) { - message.headers().set(EXPECT_ENTITY, CONTINUE_ENTITY); - } else { - message.headers().remove(EXPECT_ENTITY); - } - } - - /** - * Validates the name of a header - * - * @param headerName The header name being validated - */ - static void validateHeaderName(CharSequence headerName) { - //Check to see if the name is null - if (headerName == null) { - throw new NullPointerException("Header names cannot be null"); - } - //Go through each of the characters in the name - for (int index = 0; index < headerName.length(); index ++) { - //Actually get the character - char character = headerName.charAt(index); - - //Check to see if the character is not an ASCII character - if (character > 127) { - throw new IllegalArgumentException( - "Header name cannot contain non-ASCII characters: " + headerName); - } - - //Check for prohibited characters. - switch (character) { - case '\t': case '\n': case 0x0b: case '\f': case '\r': - case ' ': case ',': case ':': case ';': case '=': - throw new IllegalArgumentException( - "Header name cannot contain the following prohibited characters: " + - "=,;: \\t\\r\\n\\v\\f: " + headerName); - } - } - } - - /** - * Validates the specified header value - * - * @param headerValue The value being validated - */ - static void validateHeaderValue(CharSequence headerValue) { - //Check to see if the value is null - if (headerValue == null) { - throw new NullPointerException("Header values cannot be null"); - } - - /* - * Set up the state of the validation - * - * States are as follows: - * - * 0: Previous character was neither CR nor LF - * 1: The previous character was CR - * 2: The previous character was LF - */ - int state = 0; - - //Start looping through each of the character - - for (int index = 0; index < headerValue.length(); index ++) { - char character = headerValue.charAt(index); - - //Check the absolutely prohibited characters. - switch (character) { - case 0x0b: // Vertical tab - throw new IllegalArgumentException( - "Header value contains a prohibited character '\\v': " + headerValue); - case '\f': - throw new IllegalArgumentException( - "Header value contains a prohibited character '\\f': " + headerValue); - } - - // Check the CRLF (HT | SP) pattern - switch (state) { - case 0: - switch (character) { - case '\r': - state = 1; - break; - case '\n': - state = 2; - break; - } - break; - case 1: - switch (character) { - case '\n': - state = 2; - break; - default: - throw new IllegalArgumentException( - "Only '\\n' is allowed after '\\r': " + headerValue); - } - break; - case 2: - switch (character) { - case '\t': case ' ': - state = 0; - break; - default: - throw new IllegalArgumentException( - "Only ' ' and '\\t' are allowed after '\\n': " + headerValue); - } - } - } - - if (state != 0) { - throw new IllegalArgumentException( - "Header value must not end with '\\r' or '\\n':" + headerValue); - } - } - - /** - * Checks to see if the transfer encoding in a specified {@link HttpMessage} is chunked - * - * @param message The message to check - * @return True if transfer encoding is chunked, otherwise false - */ - public static boolean isTransferEncodingChunked(HttpMessage message) { - return message.headers().contains(TRANSFER_ENCODING_ENTITY, CHUNKED_ENTITY, true); - } - - public static void removeTransferEncodingChunked(HttpMessage m) { - List values = m.headers().getAll(TRANSFER_ENCODING_ENTITY); - if (values.isEmpty()) { - return; - } - Iterator valuesIt = values.iterator(); - while (valuesIt.hasNext()) { - String value = valuesIt.next(); - if (equalsIgnoreCase(value, CHUNKED_ENTITY)) { - valuesIt.remove(); - } - } - if (values.isEmpty()) { - m.headers().remove(TRANSFER_ENCODING_ENTITY); - } else { - m.headers().set(TRANSFER_ENCODING_ENTITY, values); - } - } - - public static void setTransferEncodingChunked(HttpMessage m) { - addHeader(m, TRANSFER_ENCODING_ENTITY, CHUNKED_ENTITY); - removeHeader(m, CONTENT_LENGTH_ENTITY); - } - - public static boolean isContentLengthSet(HttpMessage m) { - return m.headers().contains(CONTENT_LENGTH_ENTITY); - } - - /** - * Returns {@code true} if both {@link CharSequence}'s are equals when ignore the case. - * This only supports US_ASCII. - */ - public static boolean equalsIgnoreCase(CharSequence name1, CharSequence name2) { - if (name1 == name2) { - return true; - } - - if (name1 == null || name2 == null) { - return false; - } - - int nameLen = name1.length(); - if (nameLen != name2.length()) { - return false; - } - - for (int i = nameLen - 1; i >= 0; i --) { - char c1 = name1.charAt(i); - char c2 = name2.charAt(i); - if (c1 != c2) { - if (c1 >= 'A' && c1 <= 'Z') { - c1 += 32; - } - if (c2 >= 'A' && c2 <= 'Z') { - c2 += 32; - } - if (c1 != c2) { - return false; - } - } - } - return true; - } - - static int hash(CharSequence name) { - if (name instanceof HttpHeaderEntity) { - return ((HttpHeaderEntity) name).hash(); - } - int h = 0; - for (int i = name.length() - 1; i >= 0; i --) { - char c = name.charAt(i); - if (c >= 'A' && c <= 'Z') { - c += 32; - } - h = 31 * h + c; - } - - if (h > 0) { - return h; - } else if (h == Integer.MIN_VALUE) { - return Integer.MAX_VALUE; - } else { - return -h; - } - } - - static void encode(HttpHeaders headers, ByteBuf buf) { - if (headers instanceof DefaultHttpHeaders) { - ((DefaultHttpHeaders) headers).encode(buf); - } else { - for (Entry header: headers) { - encode(header.getKey(), header.getValue(), buf); - } - } - } - - @SuppressWarnings("deprecation") - static void encode(CharSequence key, CharSequence value, ByteBuf buf) { - if (!encodeAscii(key, buf)) { - buf.writeBytes(HEADER_SEPERATOR); - } - if (!encodeAscii(value, buf)) { - buf.writeBytes(CRLF); - } - } - - public static boolean encodeAscii(CharSequence seq, ByteBuf buf) { - if (seq instanceof HttpHeaderEntity) { - return ((HttpHeaderEntity) seq).encode(buf); - } else { - encodeAscii0(seq, buf); - return false; - } - } - - static void encodeAscii0(CharSequence seq, ByteBuf buf) { - int length = seq.length(); - for (int i = 0 ; i < length; i++) { - buf.writeByte(c2b(seq.charAt(i))); - } - } - - private static byte c2b(char c) { - if (c > 255) { - return '?'; - } - return (byte) c; - } - - /** - * Create a new {@link CharSequence} which is optimized for reuse as {@link HttpHeaders} name or value. - * So if you have a Header name or value that you want to reuse you should make use of this. - */ - public static CharSequence newEntity(String name) { - if (name == null) { - throw new NullPointerException("name"); - } - return new HttpHeaderEntity(name); - } - - /** - * Create a new {@link CharSequence} which is optimized for reuse as {@link HttpHeaders} name. - * So if you have a Header name that you want to reuse you should make use of this. - */ - public static CharSequence newNameEntity(String name) { - if (name == null) { - throw new NullPointerException("name"); - } - return new HttpHeaderEntity(name, HEADER_SEPERATOR); - } - - /** - * Create a new {@link CharSequence} which is optimized for reuse as {@link HttpHeaders} value. - * So if you have a Header value that you want to reuse you should make use of this. - */ - public static CharSequence newValueEntity(String name) { - if (name == null) { - throw new NullPointerException("name"); - } - return new HttpHeaderEntity(name, CRLF); - } - - protected HttpHeaders() { } - - /** - * @see {@link #get(CharSequence)} - */ - public abstract String get(String name); - - /** - * Returns the value of a header with the specified name. If there are - * more than one values for the specified name, the first value is returned. - * - * @param name The name of the header to search - * @return The first header value or {@code null} if there is no such header - */ - public String get(CharSequence name) { - return get(name.toString()); - } - - /** - * @see {@link #getAll(CharSequence)} - */ - public abstract List getAll(String name); - - /** - * Returns the values of headers with the specified name - * - * @param name The name of the headers to search - * @return A {@link List} of header values which will be empty if no values - * are found - */ - public List getAll(CharSequence name) { - return getAll(name.toString()); - } - - /** - * Returns a new {@link List} that contains all headers in this object. Note that modifying the - * returned {@link List} will not affect the state of this object. If you intend to enumerate over the header - * entries only, use {@link #iterator()} instead, which has much less overhead. - */ - public abstract List> entries(); - - /** - * @see {@link #contains(CharSequence)} - */ - public abstract boolean contains(String name); - - /** - * Checks to see if there is a header with the specified name - * - * @param name The name of the header to search for - * @return True if at least one header is found - */ - public boolean contains(CharSequence name) { - return contains(name.toString()); - } - - /** - * Checks if no header exists. - */ - public abstract boolean isEmpty(); - - /** - * Returns a new {@link Set} that contains the names of all headers in this object. Note that modifying the - * returned {@link Set} will not affect the state of this object. If you intend to enumerate over the header - * entries only, use {@link #iterator()} instead, which has much less overhead. - */ - public abstract Set names(); - - /** - * @see {@link #add(CharSequence, Object)} - */ - public abstract HttpHeaders add(String name, Object value); - - /** - * Adds a new header with the specified name and value. - * - * If the specified value is not a {@link String}, it is converted - * into a {@link String} by {@link Object#toString()}, except in the cases - * of {@link Date} and {@link Calendar}, which are formatted to the date - * format defined in RFC2616. - * - * @param name The name of the header being added - * @param value The value of the header being added - * - * @return {@code this} - */ - public HttpHeaders add(CharSequence name, Object value) { - return add(name.toString(), value); - } - - /** - * @see {@link #add(CharSequence, Iterable)} - */ - public abstract HttpHeaders add(String name, Iterable values); - - /** - * Adds a new header with the specified name and values. - * - * This getMethod can be represented approximately as the following code: - *
-     * for (Object v: values) {
-     *     if (v == null) {
-     *         break;
-     *     }
-     *     headers.add(name, v);
-     * }
-     * 
- * - * @param name The name of the headers being set - * @param values The values of the headers being set - * @return {@code this} - */ - public HttpHeaders add(CharSequence name, Iterable values) { - return add(name.toString(), values); - } - - /** - * Adds all header entries of the specified {@code headers}. - * - * @return {@code this} - */ - public HttpHeaders add(HttpHeaders headers) { - if (headers == null) { - throw new NullPointerException("headers"); - } - for (Map.Entry e: headers) { - add(e.getKey(), e.getValue()); - } - return this; - } - - /** - * @see {@link #set(CharSequence, Object)} - */ - public abstract HttpHeaders set(String name, Object value); - - /** - * Sets a header with the specified name and value. - * - * If there is an existing header with the same name, it is removed. - * If the specified value is not a {@link String}, it is converted into a - * {@link String} by {@link Object#toString()}, except for {@link Date} - * and {@link Calendar}, which are formatted to the date format defined in - * RFC2616. - * - * @param name The name of the header being set - * @param value The value of the header being set - * @return {@code this} - */ - public HttpHeaders set(CharSequence name, Object value) { - return set(name.toString(), value); - } - - /** - * @see {@link #set(CharSequence, Iterable)} - */ - public abstract HttpHeaders set(String name, Iterable values); - - /** - * Sets a header with the specified name and values. - * - * If there is an existing header with the same name, it is removed. - * This getMethod can be represented approximately as the following code: - *
-     * headers.remove(name);
-     * for (Object v: values) {
-     *     if (v == null) {
-     *         break;
-     *     }
-     *     headers.add(name, v);
-     * }
-     * 
- * - * @param name The name of the headers being set - * @param values The values of the headers being set - * @return {@code this} - */ - public HttpHeaders set(CharSequence name, Iterable values) { - return set(name.toString(), values); - } - - /** - * Cleans the current header entries and copies all header entries of the specified {@code headers}. - * - * @return {@code this} - */ - public HttpHeaders set(HttpHeaders headers) { - if (headers == null) { - throw new NullPointerException("headers"); - } - clear(); - for (Map.Entry e: headers) { - add(e.getKey(), e.getValue()); - } - return this; - } - - /** - * @see {@link #remove(CharSequence)} - */ - public abstract HttpHeaders remove(String name); - - /** - * Removes the header with the specified name. - * - * @param name The name of the header to remove - * @return {@code this} - */ - public HttpHeaders remove(CharSequence name) { - return remove(name.toString()); - } - - /** - * Removes all headers from this {@link HttpMessage}. - * - * @return {@code this} - */ - public abstract HttpHeaders clear(); - - /** - * @see {@link #contains(CharSequence, CharSequence, boolean)} - */ - public boolean contains(String name, String value, boolean ignoreCaseValue) { - List values = getAll(name); - if (values.isEmpty()) { - return false; - } - - for (String v: values) { - if (ignoreCaseValue) { - if (equalsIgnoreCase(v, value)) { - return true; - } - } else { - if (v.equals(value)) { - return true; - } - } - } - return false; - } - - /** - * Returns {@code true} if a header with the name and value exists. - * - * @param name the headername - * @param value the value - * @param ignoreCaseValue {@code true} if case should be ignored - * @return contains {@code true} if it contains it {@code false} otherwise - */ - public boolean contains(CharSequence name, CharSequence value, boolean ignoreCaseValue) { - return contains(name.toString(), value.toString(), ignoreCaseValue); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpMessage.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpMessage.java deleted file mode 100755 index 1cd6c616e7..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpMessage.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - - -/** - * An interface that defines a HTTP message, providing common properties for - * {@link HttpRequest} and {@link HttpResponse}. - * - * @see HttpResponse - * @see HttpRequest - * @see HttpHeaders - */ -public interface HttpMessage extends HttpObject { - - /** - * Returns the protocol version of this {@link HttpMessage} - * - * @return The protocol version - */ - HttpVersion getProtocolVersion(); - - /** - * Set the protocol version of this {@link HttpMessage} - */ - HttpMessage setProtocolVersion(HttpVersion version); - - /** - * Returns the headers of this message. - */ - HttpHeaders headers(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpMessageUtil.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpMessageUtil.java deleted file mode 100755 index 995f73e5c2..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpMessageUtil.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.handler.codec.http; - -import java.util.Map; - -import com.ai.cloud.io.netty.util.internal.StringUtil; - -/** - * Provides some utility methods for HTTP message implementations. - */ -final class HttpMessageUtil { - - static StringBuilder appendRequest(StringBuilder buf, HttpRequest req) { - appendCommon(buf, req); - appendInitialLine(buf, req); - appendHeaders(buf, req.headers()); - removeLastNewLine(buf); - return buf; - } - - static StringBuilder appendResponse(StringBuilder buf, HttpResponse res) { - appendCommon(buf, res); - appendInitialLine(buf, res); - appendHeaders(buf, res.headers()); - removeLastNewLine(buf); - return buf; - } - - private static void appendCommon(StringBuilder buf, HttpMessage msg) { - buf.append(StringUtil.simpleClassName(msg)); - buf.append("(decodeResult: "); - buf.append(msg.getDecoderResult()); - buf.append(", version: "); - buf.append(msg.getProtocolVersion()); - buf.append(')'); - buf.append(StringUtil.NEWLINE); - } - - static StringBuilder appendFullRequest(StringBuilder buf, FullHttpRequest req) { - appendFullCommon(buf, req); - appendInitialLine(buf, req); - appendHeaders(buf, req.headers()); - appendHeaders(buf, req.trailingHeaders()); - removeLastNewLine(buf); - return buf; - } - - static StringBuilder appendFullResponse(StringBuilder buf, FullHttpResponse res) { - appendFullCommon(buf, res); - appendInitialLine(buf, res); - appendHeaders(buf, res.headers()); - appendHeaders(buf, res.trailingHeaders()); - removeLastNewLine(buf); - return buf; - } - - private static void appendFullCommon(StringBuilder buf, FullHttpMessage msg) { - buf.append(StringUtil.simpleClassName(msg)); - buf.append("(decodeResult: "); - buf.append(msg.getDecoderResult()); - buf.append(", version: "); - buf.append(msg.getProtocolVersion()); - buf.append(", content: "); - buf.append(msg.content()); - buf.append(')'); - buf.append(StringUtil.NEWLINE); - } - - private static void appendInitialLine(StringBuilder buf, HttpRequest req) { - buf.append(req.getMethod()); - buf.append(' '); - buf.append(req.getUri()); - buf.append(' '); - buf.append(req.getProtocolVersion()); - buf.append(StringUtil.NEWLINE); - } - - private static void appendInitialLine(StringBuilder buf, HttpResponse res) { - buf.append(res.getProtocolVersion()); - buf.append(' '); - buf.append(res.getStatus()); - buf.append(StringUtil.NEWLINE); - } - - private static void appendHeaders(StringBuilder buf, HttpHeaders headers) { - for (Map.Entry e: headers) { - buf.append(e.getKey()); - buf.append(": "); - buf.append(e.getValue()); - buf.append(StringUtil.NEWLINE); - } - } - - private static void removeLastNewLine(StringBuilder buf) { - buf.setLength(buf.length() - StringUtil.NEWLINE.length()); - } - - private HttpMessageUtil() { } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpMethod.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpMethod.java deleted file mode 100755 index 75e7a9a533..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpMethod.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import java.util.HashMap; -import java.util.Map; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.util.CharsetUtil; - -/** - * The request getMethod of HTTP or its derived protocols, such as - * RTSP and - * ICAP. - */ -public class HttpMethod implements Comparable { - /** - * The OPTIONS getMethod represents a request for information about the communication options - * available on the request/response chain identified by the Request-URI. This getMethod allows - * the client to determine the options and/or requirements associated with a resource, or the - * capabilities of a server, without implying a resource action or initiating a resource - * retrieval. - */ - public static final HttpMethod OPTIONS = new HttpMethod("OPTIONS", true); - - /** - * The GET getMethod means retrieve whatever information (in the form of an entity) is identified - * by the Request-URI. If the Request-URI refers to a data-producing process, it is the - * produced data which shall be returned as the entity in the response and not the source text - * of the process, unless that text happens to be the output of the process. - */ - public static final HttpMethod GET = new HttpMethod("GET", true); - - /** - * The HEAD getMethod is identical to GET except that the server MUST NOT return a message-body - * in the response. - */ - public static final HttpMethod HEAD = new HttpMethod("HEAD", true); - - /** - * The POST getMethod is used to request that the origin server accept the entity enclosed in the - * request as a new subordinate of the resource identified by the Request-URI in the - * Request-Line. - */ - public static final HttpMethod POST = new HttpMethod("POST", true); - - /** - * The PUT getMethod requests that the enclosed entity be stored under the supplied Request-URI. - */ - public static final HttpMethod PUT = new HttpMethod("PUT", true); - - /** - * The PATCH getMethod requests that a set of changes described in the - * request entity be applied to the resource identified by the Request-URI. - */ - public static final HttpMethod PATCH = new HttpMethod("PATCH", true); - - /** - * The DELETE getMethod requests that the origin server delete the resource identified by the - * Request-URI. - */ - public static final HttpMethod DELETE = new HttpMethod("DELETE", true); - - /** - * The TRACE getMethod is used to invoke a remote, application-layer loop- back of the request - * message. - */ - public static final HttpMethod TRACE = new HttpMethod("TRACE", true); - - /** - * This specification reserves the getMethod name CONNECT for use with a proxy that can dynamically - * switch to being a tunnel - */ - public static final HttpMethod CONNECT = new HttpMethod("CONNECT", true); - - private static final Map methodMap = - new HashMap(); - - static { - methodMap.put(OPTIONS.toString(), OPTIONS); - methodMap.put(GET.toString(), GET); - methodMap.put(HEAD.toString(), HEAD); - methodMap.put(POST.toString(), POST); - methodMap.put(PUT.toString(), PUT); - methodMap.put(PATCH.toString(), PATCH); - methodMap.put(DELETE.toString(), DELETE); - methodMap.put(TRACE.toString(), TRACE); - methodMap.put(CONNECT.toString(), CONNECT); - } - - /** - * Returns the {@link HttpMethod} represented by the specified name. - * If the specified name is a standard HTTP getMethod name, a cached instance - * will be returned. Otherwise, a new instance will be returned. - */ - public static HttpMethod valueOf(String name) { - if (name == null) { - throw new NullPointerException("name"); - } - - name = name.trim(); - if (name.isEmpty()) { - throw new IllegalArgumentException("empty name"); - } - - HttpMethod result = methodMap.get(name); - if (result != null) { - return result; - } else { - return new HttpMethod(name); - } - } - - private final String name; - private final byte[] bytes; - - /** - * Creates a new HTTP getMethod with the specified name. You will not need to - * create a new getMethod unless you are implementing a protocol derived from - * HTTP, such as - * RTSP and - * ICAP - */ - public HttpMethod(String name) { - this(name, false); - } - - private HttpMethod(String name, boolean bytes) { - if (name == null) { - throw new NullPointerException("name"); - } - - name = name.trim(); - if (name.isEmpty()) { - throw new IllegalArgumentException("empty name"); - } - - for (int i = 0; i < name.length(); i ++) { - if (Character.isISOControl(name.charAt(i)) || - Character.isWhitespace(name.charAt(i))) { - throw new IllegalArgumentException("invalid character in name"); - } - } - - this.name = name; - if (bytes) { - this.bytes = name.getBytes(CharsetUtil.US_ASCII); - } else { - this.bytes = null; - } - } - - /** - * Returns the name of this getMethod. - */ - public String name() { - return name; - } - - @Override - public int hashCode() { - return name().hashCode(); - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof HttpMethod)) { - return false; - } - - HttpMethod that = (HttpMethod) o; - return name().equals(that.name()); - } - - @Override - public String toString() { - return name(); - } - - @Override - public int compareTo(HttpMethod o) { - return name().compareTo(o.name()); - } - - void encode(ByteBuf buf) { - if (bytes == null) { - HttpHeaders.encodeAscii0(name, buf); - } else { - buf.writeBytes(bytes); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpObject.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpObject.java deleted file mode 100755 index 0754bd43d7..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpObject.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import com.ai.cloud.io.netty.handler.codec.DecoderResult; - -public interface HttpObject { - /** - * Returns the result of decoding this message. - */ - DecoderResult getDecoderResult(); - - /** - * Updates the result of decoding this message. This method is supposed to be invoked by {@link HttpObjectDecoder}. - * Do not call this method unless you know what you are doing. - */ - void setDecoderResult(DecoderResult result); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpObjectAggregator.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpObjectAggregator.java deleted file mode 100755 index 46934d9eea..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpObjectAggregator.java +++ /dev/null @@ -1,534 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import java.util.List; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.ByteBufHolder; -import com.ai.cloud.io.netty.buffer.CompositeByteBuf; -import com.ai.cloud.io.netty.buffer.Unpooled; -import com.ai.cloud.io.netty.channel.ChannelFuture; -import com.ai.cloud.io.netty.channel.ChannelFutureListener; -import com.ai.cloud.io.netty.channel.ChannelHandler; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelPipeline; -import com.ai.cloud.io.netty.handler.codec.DecoderResult; -import com.ai.cloud.io.netty.handler.codec.MessageToMessageDecoder; -import com.ai.cloud.io.netty.handler.codec.TooLongFrameException; -import com.ai.cloud.io.netty.handler.codec.http.HttpHeaders.Names; - -import static com.ai.cloud.io.netty.handler.codec.http.HttpHeaders.is100ContinueExpected; -import static com.ai.cloud.io.netty.handler.codec.http.HttpHeaders.isContentLengthSet; -import static com.ai.cloud.io.netty.handler.codec.http.HttpHeaders.removeTransferEncodingChunked; - -/** - * A {@link ChannelHandler} that aggregates an {@link HttpMessage} - * and its following {@link HttpContent}s into a single {@link FullHttpRequest} - * or {@link FullHttpResponse} (depending on if it used to handle requests or responses) - * with no following {@link HttpContent}s. It is useful when you don't want to take - * care of HTTP messages whose transfer encoding is 'chunked'. Insert this - * handler after {@link HttpObjectDecoder} in the {@link ChannelPipeline}: - *
- * {@link ChannelPipeline} p = ...;
- * ...
- * p.addLast("encoder", new {@link HttpResponseEncoder}());
- * p.addLast("decoder", new {@link HttpRequestDecoder}());
- * p.addLast("aggregator", new {@link HttpObjectAggregator}(1048576));
- * ...
- * p.addLast("handler", new HttpRequestHandler());
- * 
- * Be aware that you need to have the {@link HttpResponseEncoder} or {@link HttpRequestEncoder} - * before the {@link HttpObjectAggregator} in the {@link ChannelPipeline}. - */ -public class HttpObjectAggregator extends MessageToMessageDecoder { - public static final int DEFAULT_MAX_COMPOSITEBUFFER_COMPONENTS = 1024; - private static final FullHttpResponse CONTINUE = - new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.CONTINUE, Unpooled.EMPTY_BUFFER); - private static final FullHttpResponse EXPECTATION_FAILED = new DefaultFullHttpResponse( - HttpVersion.HTTP_1_1, HttpResponseStatus.EXPECTATION_FAILED, Unpooled.EMPTY_BUFFER); - - static { - HttpHeaders.setContentLength(EXPECTATION_FAILED, 0); - } - - private final int maxContentLength; - private AggregatedFullHttpMessage currentMessage; - private boolean tooLongFrameFound; - private final boolean closeOnExpectationFailed; - - private int maxCumulationBufferComponents = DEFAULT_MAX_COMPOSITEBUFFER_COMPONENTS; - private ChannelHandlerContext ctx; - - /** - * Creates a new instance. - * - * @param maxContentLength - * the maximum length of the aggregated content in bytes. - * If the length of the aggregated content exceeds this value, - * a {@link TooLongFrameException} will be raised. - */ - public HttpObjectAggregator(int maxContentLength) { - this(maxContentLength, false); - } - - /** - * Creates a new instance. - * @param maxContentLength - * the maximum length of the aggregated content in bytes. - * If the length of the aggregated content exceeds this value, - * a {@link TooLongFrameException} will be raised. - * @param closeOnExpectationFailed If a 100-continue response is detected but the content length is too large - * then {@code true} means close the connection. otherwise the connection will remain open and data will be - * consumed and discarded until the next request is received. - */ - public HttpObjectAggregator(int maxContentLength, boolean closeOnExpectationFailed) { - if (maxContentLength <= 0) { - throw new IllegalArgumentException("maxContentLength must be a positive integer: " + maxContentLength); - } - this.maxContentLength = maxContentLength; - this.closeOnExpectationFailed = closeOnExpectationFailed; - } - /** - * Returns the maximum number of components in the cumulation buffer. If the number of - * the components in the cumulation buffer exceeds this value, the components of the - * cumulation buffer are consolidated into a single component, involving memory copies. - * The default value of this property is {@link #DEFAULT_MAX_COMPOSITEBUFFER_COMPONENTS}. - */ - public final int getMaxCumulationBufferComponents() { - return maxCumulationBufferComponents; - } - - /** - * Sets the maximum number of components in the cumulation buffer. If the number of - * the components in the cumulation buffer exceeds this value, the components of the - * cumulation buffer are consolidated into a single component, involving memory copies. - * The default value of this property is {@link #DEFAULT_MAX_COMPOSITEBUFFER_COMPONENTS} - * and its minimum allowed value is {@code 2}. - */ - public final void setMaxCumulationBufferComponents(int maxCumulationBufferComponents) { - if (maxCumulationBufferComponents < 2) { - throw new IllegalArgumentException( - "maxCumulationBufferComponents: " + maxCumulationBufferComponents + - " (expected: >= 2)"); - } - - if (ctx == null) { - this.maxCumulationBufferComponents = maxCumulationBufferComponents; - } else { - throw new IllegalStateException( - "decoder properties cannot be changed once the decoder is added to a pipeline."); - } - } - - @Override - protected void decode(final ChannelHandlerContext ctx, HttpObject msg, List out) throws Exception { - AggregatedFullHttpMessage currentMessage = this.currentMessage; - - if (msg instanceof HttpMessage) { - tooLongFrameFound = false; - assert currentMessage == null; - - HttpMessage m = (HttpMessage) msg; - - // Handle the 'Expect: 100-continue' header if necessary. - if (is100ContinueExpected(m)) { - if (HttpHeaders.getContentLength(m, 0) > maxContentLength) { - tooLongFrameFound = true; - final ChannelFuture future = ctx.writeAndFlush(EXPECTATION_FAILED.duplicate().retain()); - future.addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - if (!future.isSuccess()) { - ctx.fireExceptionCaught(future.cause()); - } - } - }); - if (closeOnExpectationFailed) { - future.addListener(ChannelFutureListener.CLOSE); - } - ctx.pipeline().fireUserEventTriggered(HttpExpectationFailedEvent.INSTANCE); - return; - } - ctx.writeAndFlush(CONTINUE.duplicate().retain()).addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - if (!future.isSuccess()) { - ctx.fireExceptionCaught(future.cause()); - } - } - }); - } - - if (!m.getDecoderResult().isSuccess()) { - removeTransferEncodingChunked(m); - out.add(toFullMessage(m)); - this.currentMessage = null; - return; - } - if (msg instanceof HttpRequest) { - HttpRequest header = (HttpRequest) msg; - this.currentMessage = currentMessage = new AggregatedFullHttpRequest( - header, ctx.alloc().compositeBuffer(maxCumulationBufferComponents), null); - } else if (msg instanceof HttpResponse) { - HttpResponse header = (HttpResponse) msg; - this.currentMessage = currentMessage = new AggregatedFullHttpResponse( - header, - Unpooled.compositeBuffer(maxCumulationBufferComponents), null); - } else { - throw new Error(); - } - - // A streamed message - initialize the cumulative buffer, and wait for incoming chunks. - removeTransferEncodingChunked(currentMessage); - } else if (msg instanceof HttpContent) { - if (tooLongFrameFound) { - if (msg instanceof LastHttpContent) { - this.currentMessage = null; - } - // already detect the too long frame so just discard the content - return; - } - assert currentMessage != null; - - // Merge the received chunk into the content of the current message. - HttpContent chunk = (HttpContent) msg; - CompositeByteBuf content = (CompositeByteBuf) currentMessage.content(); - - if (content.readableBytes() > maxContentLength - chunk.content().readableBytes()) { - tooLongFrameFound = true; - - // release current message to prevent leaks - currentMessage.release(); - this.currentMessage = null; - - throw new TooLongFrameException( - "HTTP content length exceeded " + maxContentLength + - " bytes."); - } - - // Append the content of the chunk - if (chunk.content().isReadable()) { - chunk.retain(); - content.addComponent(chunk.content()); - content.writerIndex(content.writerIndex() + chunk.content().readableBytes()); - } - - final boolean last; - if (!chunk.getDecoderResult().isSuccess()) { - currentMessage.setDecoderResult( - DecoderResult.failure(chunk.getDecoderResult().cause())); - last = true; - } else { - last = chunk instanceof LastHttpContent; - } - - if (last) { - this.currentMessage = null; - - // Merge trailing headers into the message. - if (chunk instanceof LastHttpContent) { - LastHttpContent trailer = (LastHttpContent) chunk; - currentMessage.setTrailingHeaders(trailer.trailingHeaders()); - } else { - currentMessage.setTrailingHeaders(new DefaultHttpHeaders()); - } - - // Set the 'Content-Length' header. If one isn't already set. - // This is important as HEAD responses will use a 'Content-Length' header which - // does not match the actual body, but the number of bytes that would be - // transmitted if a GET would have been used. - // - // See rfc2616 14.13 Content-Length - if (!isContentLengthSet(currentMessage)) { - currentMessage.headers().set( - Names.CONTENT_LENGTH, - String.valueOf(content.readableBytes())); - } - // All done - out.add(currentMessage); - } - } else { - throw new Error(); - } - } - - @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { - super.channelInactive(ctx); - - // release current message if it is not null as it may be a left-over - if (currentMessage != null) { - currentMessage.release(); - currentMessage = null; - } - } - - @Override - public void handlerAdded(ChannelHandlerContext ctx) throws Exception { - this.ctx = ctx; - } - - @Override - public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { - super.handlerRemoved(ctx); - // release current message if it is not null as it may be a left-over as there is not much more we can do in - // this case - if (currentMessage != null) { - currentMessage.release(); - currentMessage = null; - } - } - - private static FullHttpMessage toFullMessage(HttpMessage msg) { - if (msg instanceof FullHttpMessage) { - return ((FullHttpMessage) msg).retain(); - } - - FullHttpMessage fullMsg; - if (msg instanceof HttpRequest) { - fullMsg = new AggregatedFullHttpRequest( - (HttpRequest) msg, Unpooled.EMPTY_BUFFER, new DefaultHttpHeaders()); - } else if (msg instanceof HttpResponse) { - fullMsg = new AggregatedFullHttpResponse( - (HttpResponse) msg, Unpooled.EMPTY_BUFFER, new DefaultHttpHeaders()); - } else { - throw new IllegalStateException(); - } - - return fullMsg; - } - - private abstract static class AggregatedFullHttpMessage implements ByteBufHolder, FullHttpMessage { - protected final HttpMessage message; - private final ByteBuf content; - private HttpHeaders trailingHeaders; - - AggregatedFullHttpMessage(HttpMessage message, ByteBuf content, HttpHeaders trailingHeaders) { - this.message = message; - this.content = content; - this.trailingHeaders = trailingHeaders; - } - - @Override - public HttpHeaders trailingHeaders() { - HttpHeaders trailingHeaders = this.trailingHeaders; - if (trailingHeaders == null) { - return HttpHeaders.EMPTY_HEADERS; - } else { - return trailingHeaders; - } - } - - void setTrailingHeaders(HttpHeaders trailingHeaders) { - this.trailingHeaders = trailingHeaders; - } - - @Override - public HttpVersion getProtocolVersion() { - return message.getProtocolVersion(); - } - - @Override - public FullHttpMessage setProtocolVersion(HttpVersion version) { - message.setProtocolVersion(version); - return this; - } - - @Override - public HttpHeaders headers() { - return message.headers(); - } - - @Override - public DecoderResult getDecoderResult() { - return message.getDecoderResult(); - } - - @Override - public void setDecoderResult(DecoderResult result) { - message.setDecoderResult(result); - } - - @Override - public ByteBuf content() { - return content; - } - - @Override - public int refCnt() { - return content.refCnt(); - } - - @Override - public FullHttpMessage retain() { - content.retain(); - return this; - } - - @Override - public FullHttpMessage retain(int increment) { - content.retain(increment); - return this; - } - - @Override - public boolean release() { - return content.release(); - } - - @Override - public boolean release(int decrement) { - return content.release(decrement); - } - - @Override - public abstract FullHttpMessage copy(); - - @Override - public abstract FullHttpMessage duplicate(); - } - - private static final class AggregatedFullHttpRequest extends AggregatedFullHttpMessage implements FullHttpRequest { - - AggregatedFullHttpRequest(HttpRequest request, ByteBuf content, HttpHeaders trailingHeaders) { - super(request, content, trailingHeaders); - } - - @Override - public FullHttpRequest copy() { - DefaultFullHttpRequest copy = new DefaultFullHttpRequest( - getProtocolVersion(), getMethod(), getUri(), content().copy()); - copy.headers().set(headers()); - copy.trailingHeaders().set(trailingHeaders()); - return copy; - } - - @Override - public FullHttpRequest duplicate() { - DefaultFullHttpRequest duplicate = new DefaultFullHttpRequest( - getProtocolVersion(), getMethod(), getUri(), content().duplicate()); - duplicate.headers().set(headers()); - duplicate.trailingHeaders().set(trailingHeaders()); - return duplicate; - } - - @Override - public FullHttpRequest retain(int increment) { - super.retain(increment); - return this; - } - - @Override - public FullHttpRequest retain() { - super.retain(); - return this; - } - - @Override - public FullHttpRequest setMethod(HttpMethod method) { - ((HttpRequest) message).setMethod(method); - return this; - } - - @Override - public FullHttpRequest setUri(String uri) { - ((HttpRequest) message).setUri(uri); - return this; - } - - @Override - public HttpMethod getMethod() { - return ((HttpRequest) message).getMethod(); - } - - @Override - public String getUri() { - return ((HttpRequest) message).getUri(); - } - - @Override - public FullHttpRequest setProtocolVersion(HttpVersion version) { - super.setProtocolVersion(version); - return this; - } - - @Override - public String toString() { - return HttpMessageUtil.appendFullRequest(new StringBuilder(256), this).toString(); - } - } - - private static final class AggregatedFullHttpResponse extends AggregatedFullHttpMessage - implements FullHttpResponse { - - AggregatedFullHttpResponse(HttpResponse message, ByteBuf content, HttpHeaders trailingHeaders) { - super(message, content, trailingHeaders); - } - - @Override - public FullHttpResponse copy() { - DefaultFullHttpResponse copy = new DefaultFullHttpResponse( - getProtocolVersion(), getStatus(), content().copy()); - copy.headers().set(headers()); - copy.trailingHeaders().set(trailingHeaders()); - return copy; - } - - @Override - public FullHttpResponse duplicate() { - DefaultFullHttpResponse duplicate = new DefaultFullHttpResponse(getProtocolVersion(), getStatus(), - content().duplicate()); - duplicate.headers().set(headers()); - duplicate.trailingHeaders().set(trailingHeaders()); - return duplicate; - } - - @Override - public FullHttpResponse setStatus(HttpResponseStatus status) { - ((HttpResponse) message).setStatus(status); - return this; - } - - @Override - public HttpResponseStatus getStatus() { - return ((HttpResponse) message).getStatus(); - } - - @Override - public FullHttpResponse setProtocolVersion(HttpVersion version) { - super.setProtocolVersion(version); - return this; - } - - @Override - public FullHttpResponse retain(int increment) { - super.retain(increment); - return this; - } - - @Override - public FullHttpResponse retain() { - super.retain(); - return this; - } - - @Override - public String toString() { - return HttpMessageUtil.appendFullResponse(new StringBuilder(256), this).toString(); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpObjectDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpObjectDecoder.java deleted file mode 100755 index a1628d4a61..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpObjectDecoder.java +++ /dev/null @@ -1,835 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import java.util.List; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.ByteBufProcessor; -import com.ai.cloud.io.netty.buffer.Unpooled; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelPipeline; -import com.ai.cloud.io.netty.channel.socket.ChannelInputShutdownEvent; -import com.ai.cloud.io.netty.handler.codec.ByteToMessageDecoder; -import com.ai.cloud.io.netty.handler.codec.DecoderResult; -import com.ai.cloud.io.netty.handler.codec.TooLongFrameException; -import com.ai.cloud.io.netty.util.internal.AppendableCharSequence; - -/** - * Decodes {@link ByteBuf}s into {@link HttpMessage}s and - * {@link HttpContent}s. - * - *

Parameters that prevents excessive memory consumption

- * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
NameMeaning
{@code maxInitialLineLength}The maximum length of the initial line - * (e.g. {@code "GET / HTTP/1.0"} or {@code "HTTP/1.0 200 OK"}) - * If the length of the initial line exceeds this value, a - * {@link TooLongFrameException} will be raised.
{@code maxHeaderSize}The maximum length of all headers. If the sum of the length of each - * header exceeds this value, a {@link TooLongFrameException} will be raised.
{@code maxChunkSize}The maximum length of the content or each chunk. If the content length - * (or the length of each chunk) exceeds this value, the content or chunk - * will be split into multiple {@link HttpContent}s whose length is - * {@code maxChunkSize} at maximum.
- * - *

Chunked Content

- * - * If the content of an HTTP message is greater than {@code maxChunkSize} or - * the transfer encoding of the HTTP message is 'chunked', this decoder - * generates one {@link HttpMessage} instance and its following - * {@link HttpContent}s per single HTTP message to avoid excessive memory - * consumption. For example, the following HTTP message: - *
- * GET / HTTP/1.1
- * Transfer-Encoding: chunked
- *
- * 1a
- * abcdefghijklmnopqrstuvwxyz
- * 10
- * 1234567890abcdef
- * 0
- * Content-MD5: ...
- * [blank line]
- * 
- * triggers {@link HttpRequestDecoder} to generate 3 objects: - *
    - *
  1. An {@link HttpRequest},
  2. - *
  3. The first {@link HttpContent} whose content is {@code 'abcdefghijklmnopqrstuvwxyz'},
  4. - *
  5. The second {@link LastHttpContent} whose content is {@code '1234567890abcdef'}, which marks - * the end of the content.
  6. - *
- * - * If you prefer not to handle {@link HttpContent}s by yourself for your - * convenience, insert {@link HttpObjectAggregator} after this decoder in the - * {@link ChannelPipeline}. However, please note that your server might not - * be as memory efficient as without the aggregator. - * - *

Extensibility

- * - * Please note that this decoder is designed to be extended to implement - * a protocol derived from HTTP, such as - * RTSP and - * ICAP. - * To implement the decoder of such a derived protocol, extend this class and - * implement all abstract methods properly. - */ -public abstract class HttpObjectDecoder extends ByteToMessageDecoder { - private static final String EMPTY_VALUE = ""; - - private final int maxChunkSize; - private final boolean chunkedSupported; - protected final boolean validateHeaders; - private final HeaderParser headerParser; - private final LineParser lineParser; - - private HttpMessage message; - private long chunkSize; - private long contentLength = Long.MIN_VALUE; - private volatile boolean resetRequested; - - // These will be updated by splitHeader(...) - private CharSequence name; - private CharSequence value; - - private LastHttpContent trailer; - - /** - * The internal state of {@link HttpObjectDecoder}. - * Internal use only. - */ - private enum State { - SKIP_CONTROL_CHARS, - READ_INITIAL, - READ_HEADER, - READ_VARIABLE_LENGTH_CONTENT, - READ_FIXED_LENGTH_CONTENT, - READ_CHUNK_SIZE, - READ_CHUNKED_CONTENT, - READ_CHUNK_DELIMITER, - READ_CHUNK_FOOTER, - BAD_MESSAGE, - UPGRADED - } - - private State currentState = State.SKIP_CONTROL_CHARS; - - /** - * Creates a new instance with the default - * {@code maxInitialLineLength (4096}}, {@code maxHeaderSize (8192)}, and - * {@code maxChunkSize (8192)}. - */ - protected HttpObjectDecoder() { - this(4096, 8192, 8192, true); - } - - /** - * Creates a new instance with the specified parameters. - */ - protected HttpObjectDecoder( - int maxInitialLineLength, int maxHeaderSize, int maxChunkSize, boolean chunkedSupported) { - this(maxInitialLineLength, maxHeaderSize, maxChunkSize, chunkedSupported, true); - } - - /** - * Creates a new instance with the specified parameters. - */ - protected HttpObjectDecoder( - int maxInitialLineLength, int maxHeaderSize, int maxChunkSize, - boolean chunkedSupported, boolean validateHeaders) { - - if (maxInitialLineLength <= 0) { - throw new IllegalArgumentException( - "maxInitialLineLength must be a positive integer: " + - maxInitialLineLength); - } - if (maxHeaderSize <= 0) { - throw new IllegalArgumentException( - "maxHeaderSize must be a positive integer: " + - maxHeaderSize); - } - if (maxChunkSize <= 0) { - throw new IllegalArgumentException( - "maxChunkSize must be a positive integer: " + - maxChunkSize); - } - this.maxChunkSize = maxChunkSize; - this.chunkedSupported = chunkedSupported; - this.validateHeaders = validateHeaders; - AppendableCharSequence seq = new AppendableCharSequence(128); - lineParser = new LineParser(seq, maxInitialLineLength); - headerParser = new HeaderParser(seq, maxHeaderSize); - } - - @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List out) throws Exception { - if (resetRequested) { - resetNow(); - } - - switch (currentState) { - case SKIP_CONTROL_CHARS: { - if (!skipControlCharacters(buffer)) { - return; - } - currentState = State.READ_INITIAL; - } - case READ_INITIAL: try { - AppendableCharSequence line = lineParser.parse(buffer); - if (line == null) { - return; - } - String[] initialLine = splitInitialLine(line); - if (initialLine.length < 3) { - // Invalid initial line - ignore. - currentState = State.SKIP_CONTROL_CHARS; - return; - } - - message = createMessage(initialLine); - currentState = State.READ_HEADER; - // fall-through - } catch (Exception e) { - out.add(invalidMessage(buffer, e)); - return; - } - case READ_HEADER: try { - State nextState = readHeaders(buffer); - if (nextState == null) { - return; - } - currentState = nextState; - switch (nextState) { - case SKIP_CONTROL_CHARS: - // fast-path - // No content is expected. - out.add(message); - out.add(LastHttpContent.EMPTY_LAST_CONTENT); - resetNow(); - return; - case READ_CHUNK_SIZE: - if (!chunkedSupported) { - throw new IllegalArgumentException("Chunked messages not supported"); - } - // Chunked encoding - generate HttpMessage first. HttpChunks will follow. - out.add(message); - return; - default: - /** - * RFC 7230, 3.3.3 states that - * if a request does not have either a transfer-encoding or a content-length header then the - * message body length is 0. However for a response the body length is the number of octets - * received prior to the server closing the connection. So we treat this as variable length - * chunked encoding. - */ - long contentLength = contentLength(); - if (contentLength == 0 || contentLength == -1 && isDecodingRequest()) { - out.add(message); - out.add(LastHttpContent.EMPTY_LAST_CONTENT); - resetNow(); - return; - } - - assert nextState == State.READ_FIXED_LENGTH_CONTENT || - nextState == State.READ_VARIABLE_LENGTH_CONTENT; - - out.add(message); - - if (nextState == State.READ_FIXED_LENGTH_CONTENT) { - // chunkSize will be decreased as the READ_FIXED_LENGTH_CONTENT state reads data chunk by - // chunk. - chunkSize = contentLength; - } - - // We return here, this forces decode to be called again where we will decode the content - return; - } - } catch (Exception e) { - out.add(invalidMessage(buffer, e)); - return; - } - case READ_VARIABLE_LENGTH_CONTENT: { - // Keep reading data as a chunk until the end of connection is reached. - int toRead = Math.min(buffer.readableBytes(), maxChunkSize); - if (toRead > 0) { - ByteBuf content = buffer.readSlice(toRead).retain(); - out.add(new DefaultHttpContent(content)); - } - return; - } - case READ_FIXED_LENGTH_CONTENT: { - int readLimit = buffer.readableBytes(); - - // Check if the buffer is readable first as we use the readable byte count - // to create the HttpChunk. This is needed as otherwise we may end up with - // create a HttpChunk instance that contains an empty buffer and so is - // handled like it is the last HttpChunk. - // - // See https://github.com/netty/netty/issues/433 - if (readLimit == 0) { - return; - } - - int toRead = Math.min(readLimit, maxChunkSize); - if (toRead > chunkSize) { - toRead = (int) chunkSize; - } - ByteBuf content = buffer.readSlice(toRead).retain(); - chunkSize -= toRead; - - if (chunkSize == 0) { - // Read all content. - out.add(new DefaultLastHttpContent(content, validateHeaders)); - resetNow(); - } else { - out.add(new DefaultHttpContent(content)); - } - return; - } - /** - * everything else after this point takes care of reading chunked content. basically, read chunk size, - * read chunk, read and ignore the CRLF and repeat until 0 - */ - case READ_CHUNK_SIZE: try { - AppendableCharSequence line = lineParser.parse(buffer); - if (line == null) { - return; - } - int chunkSize = getChunkSize(line.toString()); - this.chunkSize = chunkSize; - if (chunkSize == 0) { - currentState = State.READ_CHUNK_FOOTER; - return; - } - currentState = State.READ_CHUNKED_CONTENT; - // fall-through - } catch (Exception e) { - out.add(invalidChunk(buffer, e)); - return; - } - case READ_CHUNKED_CONTENT: { - assert chunkSize <= Integer.MAX_VALUE; - int toRead = Math.min((int) chunkSize, maxChunkSize); - toRead = Math.min(toRead, buffer.readableBytes()); - if (toRead == 0) { - return; - } - HttpContent chunk = new DefaultHttpContent(buffer.readSlice(toRead).retain()); - chunkSize -= toRead; - - out.add(chunk); - - if (chunkSize != 0) { - return; - } - currentState = State.READ_CHUNK_DELIMITER; - // fall-through - } - case READ_CHUNK_DELIMITER: { - final int wIdx = buffer.writerIndex(); - int rIdx = buffer.readerIndex(); - while (wIdx > rIdx) { - byte next = buffer.getByte(rIdx++); - if (next == HttpConstants.LF) { - currentState = State.READ_CHUNK_SIZE; - break; - } - } - buffer.readerIndex(rIdx); - return; - } - case READ_CHUNK_FOOTER: try { - LastHttpContent trailer = readTrailingHeaders(buffer); - if (trailer == null) { - return; - } - out.add(trailer); - resetNow(); - return; - } catch (Exception e) { - out.add(invalidChunk(buffer, e)); - return; - } - case BAD_MESSAGE: { - // Keep discarding until disconnection. - buffer.skipBytes(buffer.readableBytes()); - break; - } - case UPGRADED: { - int readableBytes = buffer.readableBytes(); - if (readableBytes > 0) { - // Keep on consuming as otherwise we may trigger an DecoderException, - // other handler will replace this codec with the upgraded protocol codec to - // take the traffic over at some point then. - // See https://github.com/netty/netty/issues/2173 - out.add(buffer.readBytes(readableBytes)); - } - break; - } - } - } - - @Override - protected void decodeLast(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { - decode(ctx, in, out); - - // Handle the last unfinished message. - if (message != null) { - boolean chunked = HttpHeaders.isTransferEncodingChunked(message); - if (currentState == State.READ_VARIABLE_LENGTH_CONTENT && !in.isReadable() && !chunked) { - // End of connection. - out.add(LastHttpContent.EMPTY_LAST_CONTENT); - reset(); - return; - } - // Check if the closure of the connection signifies the end of the content. - boolean prematureClosure; - if (isDecodingRequest() || chunked) { - // The last request did not wait for a response. - prematureClosure = true; - } else { - // Compare the length of the received content and the 'Content-Length' header. - // If the 'Content-Length' header is absent, the length of the content is determined by the end of the - // connection, so it is perfectly fine. - prematureClosure = contentLength() > 0; - } - resetNow(); - - if (!prematureClosure) { - out.add(LastHttpContent.EMPTY_LAST_CONTENT); - } - } - } - - @Override - public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { - if (evt instanceof ChannelInputShutdownEvent) { - // The decodeLast method is invoked when a channelInactive event is encountered. - // This method is responsible for ending requests in some situations and must be called - // when the input has been shutdown. - super.channelInactive(ctx); - } else if (evt instanceof HttpExpectationFailedEvent) { - switch (currentState) { - case READ_FIXED_LENGTH_CONTENT: - case READ_VARIABLE_LENGTH_CONTENT: - case READ_CHUNK_SIZE: - reset(); - break; - default: - break; - } - } - super.userEventTriggered(ctx, evt); - } - - protected boolean isContentAlwaysEmpty(HttpMessage msg) { - if (msg instanceof HttpResponse) { - HttpResponse res = (HttpResponse) msg; - int code = res.getStatus().code(); - - // Correctly handle return codes of 1xx. - // - // See: - // - http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html Section 4.4 - // - https://github.com/netty/netty/issues/222 - if (code >= 100 && code < 200) { - // One exception: Hixie 76 websocket handshake response - return !(code == 101 && !res.headers().contains(HttpHeaders.Names.SEC_WEBSOCKET_ACCEPT) - && res.headers().contains(HttpHeaders.Names.UPGRADE, HttpHeaders.Values.WEBSOCKET, true)); - } - - switch (code) { - case 204: case 205: case 304: - return true; - } - } - return false; - } - - /** - * Resets the state of the decoder so that it is ready to decode a new message. - * This method is useful for handling a rejected request with {@code Expect: 100-continue} header. - */ - public void reset() { - resetRequested = true; - } - - private void resetNow() { - HttpMessage message = this.message; - this.message = null; - name = null; - value = null; - contentLength = Long.MIN_VALUE; - lineParser.reset(); - headerParser.reset(); - trailer = null; - if (!isDecodingRequest()) { - HttpResponse res = (HttpResponse) message; - if (res != null && res.getStatus().code() == 101) { - currentState = State.UPGRADED; - return; - } - } - - currentState = State.SKIP_CONTROL_CHARS; - } - - private HttpMessage invalidMessage(ByteBuf in, Exception cause) { - currentState = State.BAD_MESSAGE; - - // Advance the readerIndex so that ByteToMessageDecoder does not complain - // when we produced an invalid message without consuming anything. - in.skipBytes(in.readableBytes()); - - if (message != null) { - message.setDecoderResult(DecoderResult.failure(cause)); - } else { - message = createInvalidMessage(); - message.setDecoderResult(DecoderResult.failure(cause)); - } - - HttpMessage ret = message; - message = null; - return ret; - } - - private HttpContent invalidChunk(ByteBuf in, Exception cause) { - currentState = State.BAD_MESSAGE; - - // Advance the readerIndex so that ByteToMessageDecoder does not complain - // when we produced an invalid message without consuming anything. - in.skipBytes(in.readableBytes()); - - HttpContent chunk = new DefaultLastHttpContent(Unpooled.EMPTY_BUFFER); - chunk.setDecoderResult(DecoderResult.failure(cause)); - message = null; - trailer = null; - return chunk; - } - - private static boolean skipControlCharacters(ByteBuf buffer) { - boolean skiped = false; - final int wIdx = buffer.writerIndex(); - int rIdx = buffer.readerIndex(); - while (wIdx > rIdx) { - int c = buffer.getUnsignedByte(rIdx++); - if (!Character.isISOControl(c) && !Character.isWhitespace(c)) { - rIdx--; - skiped = true; - break; - } - } - buffer.readerIndex(rIdx); - return skiped; - } - - private State readHeaders(ByteBuf buffer) { - final HttpMessage message = this.message; - final HttpHeaders headers = message.headers(); - - AppendableCharSequence line = headerParser.parse(buffer); - if (line == null) { - return null; - } - if (line.length() > 0) { - do { - char firstChar = line.charAt(0); - if (name != null && (firstChar == ' ' || firstChar == '\t')) { - StringBuilder buf = new StringBuilder(value.length() + line.length() + 1); - buf.append(value) - .append(' ') - .append(line.toString().trim()); - value = buf.toString(); - } else { - if (name != null) { - headers.add(name, value); - } - splitHeader(line); - } - - line = headerParser.parse(buffer); - if (line == null) { - return null; - } - } while (line.length() > 0); - } - - // Add the last header. - if (name != null) { - headers.add(name, value); - } - // reset name and value fields - name = null; - value = null; - - State nextState; - - if (isContentAlwaysEmpty(message)) { - HttpHeaders.removeTransferEncodingChunked(message); - nextState = State.SKIP_CONTROL_CHARS; - } else if (HttpHeaders.isTransferEncodingChunked(message)) { - nextState = State.READ_CHUNK_SIZE; - } else if (contentLength() >= 0) { - nextState = State.READ_FIXED_LENGTH_CONTENT; - } else { - nextState = State.READ_VARIABLE_LENGTH_CONTENT; - } - return nextState; - } - - private long contentLength() { - if (contentLength == Long.MIN_VALUE) { - contentLength = HttpHeaders.getContentLength(message, -1); - } - return contentLength; - } - - private LastHttpContent readTrailingHeaders(ByteBuf buffer) { - AppendableCharSequence line = headerParser.parse(buffer); - if (line == null) { - return null; - } - CharSequence lastHeader = null; - if (line.length() > 0) { - LastHttpContent trailer = this.trailer; - if (trailer == null) { - trailer = this.trailer = new DefaultLastHttpContent(Unpooled.EMPTY_BUFFER, validateHeaders); - } - do { - char firstChar = line.charAt(0); - if (lastHeader != null && (firstChar == ' ' || firstChar == '\t')) { - List current = trailer.trailingHeaders().getAll(lastHeader); - if (!current.isEmpty()) { - int lastPos = current.size() - 1; - String lineTrimmed = line.toString().trim(); - CharSequence currentLastPos = current.get(lastPos); - StringBuilder b = new StringBuilder(currentLastPos.length() + lineTrimmed.length()); - b.append(currentLastPos) - .append(lineTrimmed); - current.set(lastPos, b.toString()); - } else { - // Content-Length, Transfer-Encoding, or Trailer - } - } else { - splitHeader(line); - CharSequence headerName = name; - if (!HttpHeaders.equalsIgnoreCase(HttpHeaders.Names.CONTENT_LENGTH, headerName) && - !HttpHeaders.equalsIgnoreCase(HttpHeaders.Names.TRANSFER_ENCODING, headerName) && - !HttpHeaders.equalsIgnoreCase(HttpHeaders.Names.TRAILER, headerName)) { - trailer.trailingHeaders().add(headerName, value); - } - lastHeader = name; - // reset name and value fields - name = null; - value = null; - } - - line = headerParser.parse(buffer); - if (line == null) { - return null; - } - } while (line.length() > 0); - - this.trailer = null; - return trailer; - } - - return LastHttpContent.EMPTY_LAST_CONTENT; - } - - protected abstract boolean isDecodingRequest(); - protected abstract HttpMessage createMessage(String[] initialLine) throws Exception; - protected abstract HttpMessage createInvalidMessage(); - - private static int getChunkSize(String hex) { - hex = hex.trim(); - for (int i = 0; i < hex.length(); i ++) { - char c = hex.charAt(i); - if (c == ';' || Character.isWhitespace(c) || Character.isISOControl(c)) { - hex = hex.substring(0, i); - break; - } - } - - return Integer.parseInt(hex, 16); - } - - private static String[] splitInitialLine(AppendableCharSequence sb) { - int aStart; - int aEnd; - int bStart; - int bEnd; - int cStart; - int cEnd; - - aStart = findNonWhitespace(sb, 0); - aEnd = findWhitespace(sb, aStart); - - bStart = findNonWhitespace(sb, aEnd); - bEnd = findWhitespace(sb, bStart); - - cStart = findNonWhitespace(sb, bEnd); - cEnd = findEndOfString(sb); - - return new String[] { - sb.subStringUnsafe(aStart, aEnd), - sb.subStringUnsafe(bStart, bEnd), - cStart < cEnd? sb.subStringUnsafe(cStart, cEnd) : "" }; - } - - private void splitHeader(AppendableCharSequence sb) { - final int length = sb.length(); - int nameStart; - int nameEnd; - int colonEnd; - int valueStart; - int valueEnd; - - nameStart = findNonWhitespace(sb, 0); - for (nameEnd = nameStart; nameEnd < length; nameEnd ++) { - char ch = sb.charAt(nameEnd); - if (ch == ':' || Character.isWhitespace(ch)) { - break; - } - } - - for (colonEnd = nameEnd; colonEnd < length; colonEnd ++) { - if (sb.charAt(colonEnd) == ':') { - colonEnd ++; - break; - } - } - - name = sb.subStringUnsafe(nameStart, nameEnd); - valueStart = findNonWhitespace(sb, colonEnd); - if (valueStart == length) { - value = EMPTY_VALUE; - } else { - valueEnd = findEndOfString(sb); - value = sb.subStringUnsafe(valueStart, valueEnd); - } - } - - private static int findNonWhitespace(AppendableCharSequence sb, int offset) { - for (int result = offset; result < sb.length(); ++result) { - if (!Character.isWhitespace(sb.charAtUnsafe(result))) { - return result; - } - } - return sb.length(); - } - - private static int findWhitespace(AppendableCharSequence sb, int offset) { - for (int result = offset; result < sb.length(); ++result) { - if (Character.isWhitespace(sb.charAtUnsafe(result))) { - return result; - } - } - return sb.length(); - } - - private static int findEndOfString(AppendableCharSequence sb) { - for (int result = sb.length() - 1; result > 0; --result) { - if (!Character.isWhitespace(sb.charAtUnsafe(result))) { - return result + 1; - } - } - return 0; - } - - private static class HeaderParser implements ByteBufProcessor { - private final AppendableCharSequence seq; - private final int maxLength; - private int size; - - HeaderParser(AppendableCharSequence seq, int maxLength) { - this.seq = seq; - this.maxLength = maxLength; - } - - public AppendableCharSequence parse(ByteBuf buffer) { - final int oldSize = size; - seq.reset(); - int i = buffer.forEachByte(this); - if (i == -1) { - size = oldSize; - return null; - } - buffer.readerIndex(i + 1); - return seq; - } - - public void reset() { - size = 0; - } - - @Override - public boolean process(byte value) throws Exception { - char nextByte = (char) value; - if (nextByte == HttpConstants.CR) { - return true; - } - if (nextByte == HttpConstants.LF) { - return false; - } - - if (++ size > maxLength) { - // TODO: Respond with Bad Request and discard the traffic - // or close the connection. - // No need to notify the upstream handlers - just log. - // If decoding a response, just throw an exception. - throw newException(maxLength); - } - - seq.append(nextByte); - return true; - } - - protected TooLongFrameException newException(int maxLength) { - return new TooLongFrameException("HTTP header is larger than " + maxLength + " bytes."); - } - } - - private static final class LineParser extends HeaderParser { - - LineParser(AppendableCharSequence seq, int maxLength) { - super(seq, maxLength); - } - - @Override - public AppendableCharSequence parse(ByteBuf buffer) { - reset(); - return super.parse(buffer); - } - - @Override - protected TooLongFrameException newException(int maxLength) { - return new TooLongFrameException("An HTTP line is larger than " + maxLength + " bytes."); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpObjectEncoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpObjectEncoder.java deleted file mode 100755 index be12826fb3..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpObjectEncoder.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import java.util.List; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.FileRegion; -import com.ai.cloud.io.netty.handler.codec.MessageToMessageEncoder; -import com.ai.cloud.io.netty.util.CharsetUtil; -import com.ai.cloud.io.netty.util.internal.StringUtil; - -import static com.ai.cloud.io.netty.buffer.Unpooled.*; -import static com.ai.cloud.io.netty.handler.codec.http.HttpConstants.*; - -/** - * Encodes an {@link HttpMessage} or an {@link HttpContent} into - * a {@link ByteBuf}. - * - *

Extensibility

- * - * Please note that this encoder is designed to be extended to implement - * a protocol derived from HTTP, such as - * RTSP and - * ICAP. - * To implement the encoder of such a derived protocol, extend this class and - * implement all abstract methods properly. - */ -public abstract class HttpObjectEncoder extends MessageToMessageEncoder { - private static final byte[] CRLF = { CR, LF }; - private static final byte[] ZERO_CRLF = { '0', CR, LF }; - private static final byte[] ZERO_CRLF_CRLF = { '0', CR, LF, CR, LF }; - private static final ByteBuf CRLF_BUF = unreleasableBuffer(directBuffer(CRLF.length).writeBytes(CRLF)); - private static final ByteBuf ZERO_CRLF_CRLF_BUF = unreleasableBuffer(directBuffer(ZERO_CRLF_CRLF.length) - .writeBytes(ZERO_CRLF_CRLF)); - - private static final int ST_INIT = 0; - private static final int ST_CONTENT_NON_CHUNK = 1; - private static final int ST_CONTENT_CHUNK = 2; - - @SuppressWarnings("RedundantFieldInitialization") - private int state = ST_INIT; - - @Override - protected void encode(ChannelHandlerContext ctx, Object msg, List out) throws Exception { - ByteBuf buf = null; - if (msg instanceof HttpMessage) { - if (state != ST_INIT) { - throw new IllegalStateException("unexpected message type: " + StringUtil.simpleClassName(msg)); - } - - @SuppressWarnings({ "unchecked", "CastConflictsWithInstanceof" }) - H m = (H) msg; - - buf = ctx.alloc().buffer(); - // Encode the message. - encodeInitialLine(buf, m); - encodeHeaders(m.headers(), buf); - buf.writeBytes(CRLF); - state = HttpHeaders.isTransferEncodingChunked(m) ? ST_CONTENT_CHUNK : ST_CONTENT_NON_CHUNK; - } - - // Bypass the encoder in case of an empty buffer, so that the following idiom works: - // - // ch.write(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE); - // - // See https://github.com/netty/netty/issues/2983 for more information. - - if (msg instanceof ByteBuf && !((ByteBuf) msg).isReadable()) { - out.add(EMPTY_BUFFER); - return; - } - - if (msg instanceof HttpContent || msg instanceof ByteBuf || msg instanceof FileRegion) { - - if (state == ST_INIT) { - throw new IllegalStateException("unexpected message type: " + StringUtil.simpleClassName(msg)); - } - - final long contentLength = contentLength(msg); - if (state == ST_CONTENT_NON_CHUNK) { - if (contentLength > 0) { - if (buf != null && buf.writableBytes() >= contentLength && msg instanceof HttpContent) { - // merge into other buffer for performance reasons - buf.writeBytes(((HttpContent) msg).content()); - out.add(buf); - } else { - if (buf != null) { - out.add(buf); - } - out.add(encodeAndRetain(msg)); - } - } else { - if (buf != null) { - out.add(buf); - } else { - // Need to produce some output otherwise an - // IllegalStateException will be thrown - out.add(EMPTY_BUFFER); - } - } - - if (msg instanceof LastHttpContent) { - state = ST_INIT; - } - } else if (state == ST_CONTENT_CHUNK) { - if (buf != null) { - out.add(buf); - } - encodeChunkedContent(ctx, msg, contentLength, out); - } else { - throw new Error(); - } - } else { - if (buf != null) { - out.add(buf); - } - } - } - - /** - * Encode the {@link HttpHeaders} into a {@link ByteBuf}. - */ - protected void encodeHeaders(HttpHeaders headers, ByteBuf buf) { - HttpHeaders.encode(headers, buf); - } - - private void encodeChunkedContent(ChannelHandlerContext ctx, Object msg, long contentLength, List out) { - if (contentLength > 0) { - byte[] length = Long.toHexString(contentLength).getBytes(CharsetUtil.US_ASCII); - ByteBuf buf = ctx.alloc().buffer(length.length + 2); - buf.writeBytes(length); - buf.writeBytes(CRLF); - out.add(buf); - out.add(encodeAndRetain(msg)); - out.add(CRLF_BUF.duplicate()); - } - - if (msg instanceof LastHttpContent) { - HttpHeaders headers = ((LastHttpContent) msg).trailingHeaders(); - if (headers.isEmpty()) { - out.add(ZERO_CRLF_CRLF_BUF.duplicate()); - } else { - ByteBuf buf = ctx.alloc().buffer(); - buf.writeBytes(ZERO_CRLF); - encodeHeaders(headers, buf); - buf.writeBytes(CRLF); - out.add(buf); - } - - state = ST_INIT; - } else { - if (contentLength == 0) { - // Need to produce some output otherwise an - // IllegalstateException will be thrown - out.add(EMPTY_BUFFER); - } - } - } - - @Override - public boolean acceptOutboundMessage(Object msg) throws Exception { - return msg instanceof HttpObject || msg instanceof ByteBuf || msg instanceof FileRegion; - } - - private static Object encodeAndRetain(Object msg) { - if (msg instanceof ByteBuf) { - return ((ByteBuf) msg).retain(); - } - if (msg instanceof HttpContent) { - return ((HttpContent) msg).content().retain(); - } - if (msg instanceof FileRegion) { - return ((FileRegion) msg).retain(); - } - throw new IllegalStateException("unexpected message type: " + StringUtil.simpleClassName(msg)); - } - - private static long contentLength(Object msg) { - if (msg instanceof HttpContent) { - return ((HttpContent) msg).content().readableBytes(); - } - if (msg instanceof ByteBuf) { - return ((ByteBuf) msg).readableBytes(); - } - if (msg instanceof FileRegion) { - return ((FileRegion) msg).count(); - } - throw new IllegalStateException("unexpected message type: " + StringUtil.simpleClassName(msg)); - } - - @Deprecated - protected static void encodeAscii(String s, ByteBuf buf) { - HttpHeaders.encodeAscii0(s, buf); - } - - protected abstract void encodeInitialLine(ByteBuf buf, H message) throws Exception; -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpRequest.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpRequest.java deleted file mode 100755 index 5c5c3e34c3..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpRequest.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -/** - * An HTTP request. - * - *

Accessing Query Parameters and Cookie

- *

- * Unlike the Servlet API, a query string is constructed and decomposed by - * {@link QueryStringEncoder} and {@link QueryStringDecoder}. - * - * {@link com.ai.cloud.io.netty.handler.codec.http.cookie.Cookie} support is also provided - * separately via {@link com.ai.cloud.io.netty.handler.codec.http.cookie.ServerCookieDecoder}, - * {@link com.ai.cloud.io.netty.handler.codec.http.cookie.ClientCookieDecoder}, - * {@link com.ai.cloud.io.netty.handler.codec.http.cookie.ServerCookieEncoder}, - * and {@link @io.netty.handler.codec.http.cookie.ClientCookieEncoder}. - * - * @see HttpResponse - * @see com.ai.cloud.io.netty.handler.codec.http.cookie.ServerCookieDecoder - * @see com.ai.cloud.io.netty.handler.codec.http.cookie.ClientCookieDecoder - * @see com.ai.cloud.io.netty.handler.codec.http.cookie.ServerCookieEncoder - * @see com.ai.cloud.io.netty.handler.codec.http.cookie.ClientCookieEncoder - */ -public interface HttpRequest extends HttpMessage { - - /** - * Returns the {@link HttpMethod} of this {@link HttpRequest}. - * - * @return The {@link HttpMethod} of this {@link HttpRequest} - */ - HttpMethod getMethod(); - - /** - * Set the {@link HttpMethod} of this {@link HttpRequest}. - */ - HttpRequest setMethod(HttpMethod method); - - /** - * Returns the requested URI (or alternatively, path) - * - * @return The URI being requested - */ - String getUri(); - - /** - * Set the requested URI (or alternatively, path) - */ - HttpRequest setUri(String uri); - - @Override - HttpRequest setProtocolVersion(HttpVersion version); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpRequestDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpRequestDecoder.java deleted file mode 100755 index cfae601eb3..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpRequestDecoder.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.Unpooled; -import com.ai.cloud.io.netty.channel.ChannelPipeline; -import com.ai.cloud.io.netty.handler.codec.TooLongFrameException; - - -/** - * Decodes {@link ByteBuf}s into {@link HttpRequest}s and {@link HttpContent}s. - * - *

Parameters that prevents excessive memory consumption

- * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
NameMeaning
{@code maxInitialLineLength}The maximum length of the initial line (e.g. {@code "GET / HTTP/1.0"}) - * If the length of the initial line exceeds this value, a - * {@link TooLongFrameException} will be raised.
{@code maxHeaderSize}The maximum length of all headers. If the sum of the length of each - * header exceeds this value, a {@link TooLongFrameException} will be raised.
{@code maxChunkSize}The maximum length of the content or each chunk. If the content length - * exceeds this value, the transfer encoding of the decoded request will be - * converted to 'chunked' and the content will be split into multiple - * {@link HttpContent}s. If the transfer encoding of the HTTP request is - * 'chunked' already, each chunk will be split into smaller chunks if the - * length of the chunk exceeds this value. If you prefer not to handle - * {@link HttpContent}s in your handler, insert {@link HttpObjectAggregator} - * after this decoder in the {@link ChannelPipeline}.
- */ -public class HttpRequestDecoder extends HttpObjectDecoder { - - /** - * Creates a new instance with the default - * {@code maxInitialLineLength (4096)}, {@code maxHeaderSize (8192)}, and - * {@code maxChunkSize (8192)}. - */ - public HttpRequestDecoder() { - } - - /** - * Creates a new instance with the specified parameters. - */ - public HttpRequestDecoder( - int maxInitialLineLength, int maxHeaderSize, int maxChunkSize) { - super(maxInitialLineLength, maxHeaderSize, maxChunkSize, true); - } - - public HttpRequestDecoder( - int maxInitialLineLength, int maxHeaderSize, int maxChunkSize, boolean validateHeaders) { - super(maxInitialLineLength, maxHeaderSize, maxChunkSize, true, validateHeaders); - } - - @Override - protected HttpMessage createMessage(String[] initialLine) throws Exception { - return new DefaultHttpRequest( - HttpVersion.valueOf(initialLine[2]), - HttpMethod.valueOf(initialLine[0]), initialLine[1], validateHeaders); - } - - @Override - protected HttpMessage createInvalidMessage() { - return new DefaultFullHttpRequest( - HttpVersion.HTTP_1_0, HttpMethod.GET, "/bad-request", Unpooled.EMPTY_BUFFER, validateHeaders); - } - - @Override - protected boolean isDecodingRequest() { - return true; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpRequestEncoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpRequestEncoder.java deleted file mode 100755 index 54d06f7ec1..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpRequestEncoder.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.util.CharsetUtil; - -import static com.ai.cloud.io.netty.handler.codec.http.HttpConstants.*; - -/** - * Encodes an {@link HttpRequest} or an {@link HttpContent} into - * a {@link ByteBuf}. - */ -public class HttpRequestEncoder extends HttpObjectEncoder { - private static final char SLASH = '/'; - private static final char QUESTION_MARK = '?'; - private static final byte[] CRLF = { CR, LF }; - - @Override - public boolean acceptOutboundMessage(Object msg) throws Exception { - return super.acceptOutboundMessage(msg) && !(msg instanceof HttpResponse); - } - - @Override - protected void encodeInitialLine(ByteBuf buf, HttpRequest request) throws Exception { - request.getMethod().encode(buf); - buf.writeByte(SP); - - // Add / as absolute path if no is present. - // See http://tools.ietf.org/html/rfc2616#section-5.1.2 - String uri = request.getUri(); - - if (uri.length() == 0) { - uri += SLASH; - } else { - int start = uri.indexOf("://"); - if (start != -1 && uri.charAt(0) != SLASH) { - int startIndex = start + 3; - // Correctly handle query params. - // See https://github.com/netty/netty/issues/2732 - int index = uri.indexOf(QUESTION_MARK, startIndex); - if (index == -1) { - if (uri.lastIndexOf(SLASH) <= startIndex) { - uri += SLASH; - } - } else { - if (uri.lastIndexOf(SLASH, index) <= startIndex) { - int len = uri.length(); - StringBuilder sb = new StringBuilder(len + 1); - sb.append(uri, 0, index) - .append(SLASH) - .append(uri, index, len); - uri = sb.toString(); - } - } - } - } - - buf.writeBytes(uri.getBytes(CharsetUtil.UTF_8)); - - buf.writeByte(SP); - request.getProtocolVersion().encode(buf); - buf.writeBytes(CRLF); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpResponse.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpResponse.java deleted file mode 100755 index 938c8fe01c..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpResponse.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - - -/** - * An HTTP response. - * - *

Accessing Cookies

- *

- * Unlike the Servlet API, {@link com.ai.cloud.io.netty.handler.codec.http.cookie.Cookie} support is provided - * separately via {@link com.ai.cloud.io.netty.handler.codec.http.cookie.ServerCookieDecoder}, - * {@link com.ai.cloud.io.netty.handler.codec.http.cookie.ClientCookieDecoder}, - * {@link com.ai.cloud.io.netty.handler.codec.http.cookie.ServerCookieEncoder}, - * and {@link @io.netty.handler.codec.http.cookie.ClientCookieEncoder}. - * - * @see HttpRequest - * @see com.ai.cloud.io.netty.handler.codec.http.cookie.ServerCookieDecoder - * @see com.ai.cloud.io.netty.handler.codec.http.cookie.ClientCookieDecoder - * @see com.ai.cloud.io.netty.handler.codec.http.cookie.ServerCookieEncoder - * @see com.ai.cloud.io.netty.handler.codec.http.cookie.ClientCookieEncoder - */ -public interface HttpResponse extends HttpMessage { - - /** - * Returns the status of this {@link HttpResponse}. - * - * @return The {@link HttpResponseStatus} of this {@link HttpResponse} - */ - HttpResponseStatus getStatus(); - - /** - * Set the status of this {@link HttpResponse}. - */ - HttpResponse setStatus(HttpResponseStatus status); - - @Override - HttpResponse setProtocolVersion(HttpVersion version); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpResponseDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpResponseDecoder.java deleted file mode 100755 index 8f3c58f6bf..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpResponseDecoder.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.Unpooled; -import com.ai.cloud.io.netty.channel.ChannelPipeline; -import com.ai.cloud.io.netty.handler.codec.TooLongFrameException; - - -/** - * Decodes {@link ByteBuf}s into {@link HttpResponse}s and - * {@link HttpContent}s. - * - *

Parameters that prevents excessive memory consumption

- * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
NameMeaning
{@code maxInitialLineLength}The maximum length of the initial line (e.g. {@code "HTTP/1.0 200 OK"}) - * If the length of the initial line exceeds this value, a - * {@link TooLongFrameException} will be raised.
{@code maxHeaderSize}The maximum length of all headers. If the sum of the length of each - * header exceeds this value, a {@link TooLongFrameException} will be raised.
{@code maxChunkSize}The maximum length of the content or each chunk. If the content length - * exceeds this value, the transfer encoding of the decoded response will be - * converted to 'chunked' and the content will be split into multiple - * {@link HttpContent}s. If the transfer encoding of the HTTP response is - * 'chunked' already, each chunk will be split into smaller chunks if the - * length of the chunk exceeds this value. If you prefer not to handle - * {@link HttpContent}s in your handler, insert {@link HttpObjectAggregator} - * after this decoder in the {@link ChannelPipeline}.
- * - *

Decoding a response for a HEAD request

- *

- * Unlike other HTTP requests, the successful response of a HEAD - * request does not have any content even if there is Content-Length - * header. Because {@link HttpResponseDecoder} is not able to determine if the - * response currently being decoded is associated with a HEAD request, - * you must override {@link #isContentAlwaysEmpty(HttpMessage)} to return - * true for the response of the HEAD request. - *

- * If you are writing an HTTP client that issues a HEAD request, - * please use {@link HttpClientCodec} instead of this decoder. It will perform - * additional state management to handle the responses for HEAD - * requests correctly. - *

- * - *

Decoding a response for a CONNECT request

- *

- * You also need to do additional state management to handle the response of a - * CONNECT request properly, like you did for HEAD. One - * difference is that the decoder should stop decoding completely after decoding - * the successful 200 response since the connection is not an HTTP connection - * anymore. - *

- * {@link HttpClientCodec} also handles this edge case correctly, so you have to - * use {@link HttpClientCodec} if you are writing an HTTP client that issues a - * CONNECT request. - *

- */ -public class HttpResponseDecoder extends HttpObjectDecoder { - - private static final HttpResponseStatus UNKNOWN_STATUS = new HttpResponseStatus(999, "Unknown"); - - /** - * Creates a new instance with the default - * {@code maxInitialLineLength (4096)}, {@code maxHeaderSize (8192)}, and - * {@code maxChunkSize (8192)}. - */ - public HttpResponseDecoder() { - } - - /** - * Creates a new instance with the specified parameters. - */ - public HttpResponseDecoder( - int maxInitialLineLength, int maxHeaderSize, int maxChunkSize) { - super(maxInitialLineLength, maxHeaderSize, maxChunkSize, true); - } - - public HttpResponseDecoder( - int maxInitialLineLength, int maxHeaderSize, int maxChunkSize, boolean validateHeaders) { - super(maxInitialLineLength, maxHeaderSize, maxChunkSize, true, validateHeaders); - } - - @Override - protected HttpMessage createMessage(String[] initialLine) { - return new DefaultHttpResponse( - HttpVersion.valueOf(initialLine[0]), - new HttpResponseStatus(Integer.parseInt(initialLine[1]), initialLine[2]), validateHeaders); - } - - @Override - protected HttpMessage createInvalidMessage() { - return new DefaultFullHttpResponse( - HttpVersion.HTTP_1_0, UNKNOWN_STATUS, Unpooled.EMPTY_BUFFER, validateHeaders); - } - - @Override - protected boolean isDecodingRequest() { - return false; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpResponseEncoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpResponseEncoder.java deleted file mode 100755 index 8a6936c21b..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpResponseEncoder.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import com.ai.cloud.io.netty.buffer.ByteBuf; - -import static com.ai.cloud.io.netty.handler.codec.http.HttpConstants.*; - -/** - * Encodes an {@link HttpResponse} or an {@link HttpContent} into - * a {@link ByteBuf}. - */ -public class HttpResponseEncoder extends HttpObjectEncoder { - private static final byte[] CRLF = { CR, LF }; - - @Override - public boolean acceptOutboundMessage(Object msg) throws Exception { - return super.acceptOutboundMessage(msg) && !(msg instanceof HttpRequest); - } - - @Override - protected void encodeInitialLine(ByteBuf buf, HttpResponse response) throws Exception { - response.getProtocolVersion().encode(buf); - buf.writeByte(SP); - response.getStatus().encode(buf); - buf.writeBytes(CRLF); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpResponseStatus.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpResponseStatus.java deleted file mode 100755 index 8167fd7aa9..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpResponseStatus.java +++ /dev/null @@ -1,560 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.util.CharsetUtil; - -import static com.ai.cloud.io.netty.handler.codec.http.HttpConstants.SP; - -/** - * The response code and its description of HTTP or its derived protocols, such as - * RTSP and - * ICAP. - */ -public class HttpResponseStatus implements Comparable { - - /** - * 100 Continue - */ - public static final HttpResponseStatus CONTINUE = new HttpResponseStatus(100, "Continue", true); - - /** - * 101 Switching Protocols - */ - public static final HttpResponseStatus SWITCHING_PROTOCOLS = - new HttpResponseStatus(101, "Switching Protocols", true); - - /** - * 102 Processing (WebDAV, RFC2518) - */ - public static final HttpResponseStatus PROCESSING = new HttpResponseStatus(102, "Processing", true); - - /** - * 200 OK - */ - public static final HttpResponseStatus OK = new HttpResponseStatus(200, "OK", true); - - /** - * 201 Created - */ - public static final HttpResponseStatus CREATED = new HttpResponseStatus(201, "Created", true); - - /** - * 202 Accepted - */ - public static final HttpResponseStatus ACCEPTED = new HttpResponseStatus(202, "Accepted", true); - - /** - * 203 Non-Authoritative Information (since HTTP/1.1) - */ - public static final HttpResponseStatus NON_AUTHORITATIVE_INFORMATION = - new HttpResponseStatus(203, "Non-Authoritative Information", true); - - /** - * 204 No Content - */ - public static final HttpResponseStatus NO_CONTENT = new HttpResponseStatus(204, "No Content", true); - - /** - * 205 Reset Content - */ - public static final HttpResponseStatus RESET_CONTENT = new HttpResponseStatus(205, "Reset Content", true); - - /** - * 206 Partial Content - */ - public static final HttpResponseStatus PARTIAL_CONTENT = new HttpResponseStatus(206, "Partial Content", true); - - /** - * 207 Multi-Status (WebDAV, RFC2518) - */ - public static final HttpResponseStatus MULTI_STATUS = new HttpResponseStatus(207, "Multi-Status", true); - - /** - * 300 Multiple Choices - */ - public static final HttpResponseStatus MULTIPLE_CHOICES = new HttpResponseStatus(300, "Multiple Choices", true); - - /** - * 301 Moved Permanently - */ - public static final HttpResponseStatus MOVED_PERMANENTLY = new HttpResponseStatus(301, "Moved Permanently", true); - - /** - * 302 Found - */ - public static final HttpResponseStatus FOUND = new HttpResponseStatus(302, "Found", true); - - /** - * 303 See Other (since HTTP/1.1) - */ - public static final HttpResponseStatus SEE_OTHER = new HttpResponseStatus(303, "See Other", true); - - /** - * 304 Not Modified - */ - public static final HttpResponseStatus NOT_MODIFIED = new HttpResponseStatus(304, "Not Modified", true); - - /** - * 305 Use Proxy (since HTTP/1.1) - */ - public static final HttpResponseStatus USE_PROXY = new HttpResponseStatus(305, "Use Proxy", true); - - /** - * 307 Temporary Redirect (since HTTP/1.1) - */ - public static final HttpResponseStatus TEMPORARY_REDIRECT = new HttpResponseStatus(307, "Temporary Redirect", true); - - /** - * 400 Bad Request - */ - public static final HttpResponseStatus BAD_REQUEST = new HttpResponseStatus(400, "Bad Request", true); - - /** - * 401 Unauthorized - */ - public static final HttpResponseStatus UNAUTHORIZED = new HttpResponseStatus(401, "Unauthorized", true); - - /** - * 402 Payment Required - */ - public static final HttpResponseStatus PAYMENT_REQUIRED = new HttpResponseStatus(402, "Payment Required", true); - - /** - * 403 Forbidden - */ - public static final HttpResponseStatus FORBIDDEN = new HttpResponseStatus(403, "Forbidden", true); - - /** - * 404 Not Found - */ - public static final HttpResponseStatus NOT_FOUND = new HttpResponseStatus(404, "Not Found", true); - - /** - * 405 Method Not Allowed - */ - public static final HttpResponseStatus METHOD_NOT_ALLOWED = new HttpResponseStatus(405, "Method Not Allowed", true); - - /** - * 406 Not Acceptable - */ - public static final HttpResponseStatus NOT_ACCEPTABLE = new HttpResponseStatus(406, "Not Acceptable", true); - - /** - * 407 Proxy Authentication Required - */ - public static final HttpResponseStatus PROXY_AUTHENTICATION_REQUIRED = - new HttpResponseStatus(407, "Proxy Authentication Required", true); - - /** - * 408 Request Timeout - */ - public static final HttpResponseStatus REQUEST_TIMEOUT = new HttpResponseStatus(408, "Request Timeout", true); - - /** - * 409 Conflict - */ - public static final HttpResponseStatus CONFLICT = new HttpResponseStatus(409, "Conflict", true); - - /** - * 410 Gone - */ - public static final HttpResponseStatus GONE = new HttpResponseStatus(410, "Gone", true); - - /** - * 411 Length Required - */ - public static final HttpResponseStatus LENGTH_REQUIRED = new HttpResponseStatus(411, "Length Required", true); - - /** - * 412 Precondition Failed - */ - public static final HttpResponseStatus PRECONDITION_FAILED = - new HttpResponseStatus(412, "Precondition Failed", true); - - /** - * 413 Request Entity Too Large - */ - public static final HttpResponseStatus REQUEST_ENTITY_TOO_LARGE = - new HttpResponseStatus(413, "Request Entity Too Large", true); - - /** - * 414 Request-URI Too Long - */ - public static final HttpResponseStatus REQUEST_URI_TOO_LONG = - new HttpResponseStatus(414, "Request-URI Too Long", true); - - /** - * 415 Unsupported Media Type - */ - public static final HttpResponseStatus UNSUPPORTED_MEDIA_TYPE = - new HttpResponseStatus(415, "Unsupported Media Type", true); - - /** - * 416 Requested Range Not Satisfiable - */ - public static final HttpResponseStatus REQUESTED_RANGE_NOT_SATISFIABLE = - new HttpResponseStatus(416, "Requested Range Not Satisfiable", true); - - /** - * 417 Expectation Failed - */ - public static final HttpResponseStatus EXPECTATION_FAILED = - new HttpResponseStatus(417, "Expectation Failed", true); - - /** - * 422 Unprocessable Entity (WebDAV, RFC4918) - */ - public static final HttpResponseStatus UNPROCESSABLE_ENTITY = - new HttpResponseStatus(422, "Unprocessable Entity", true); - - /** - * 423 Locked (WebDAV, RFC4918) - */ - public static final HttpResponseStatus LOCKED = - new HttpResponseStatus(423, "Locked", true); - - /** - * 424 Failed Dependency (WebDAV, RFC4918) - */ - public static final HttpResponseStatus FAILED_DEPENDENCY = new HttpResponseStatus(424, "Failed Dependency", true); - - /** - * 425 Unordered Collection (WebDAV, RFC3648) - */ - public static final HttpResponseStatus UNORDERED_COLLECTION = - new HttpResponseStatus(425, "Unordered Collection", true); - - /** - * 426 Upgrade Required (RFC2817) - */ - public static final HttpResponseStatus UPGRADE_REQUIRED = new HttpResponseStatus(426, "Upgrade Required", true); - - /** - * 428 Precondition Required (RFC6585) - */ - public static final HttpResponseStatus PRECONDITION_REQUIRED = - new HttpResponseStatus(428, "Precondition Required", true); - - /** - * 429 Too Many Requests (RFC6585) - */ - public static final HttpResponseStatus TOO_MANY_REQUESTS = new HttpResponseStatus(429, "Too Many Requests", true); - - /** - * 431 Request Header Fields Too Large (RFC6585) - */ - public static final HttpResponseStatus REQUEST_HEADER_FIELDS_TOO_LARGE = - new HttpResponseStatus(431, "Request Header Fields Too Large", true); - - /** - * 500 Internal Server Error - */ - public static final HttpResponseStatus INTERNAL_SERVER_ERROR = - new HttpResponseStatus(500, "Internal Server Error", true); - - /** - * 501 Not Implemented - */ - public static final HttpResponseStatus NOT_IMPLEMENTED = new HttpResponseStatus(501, "Not Implemented", true); - - /** - * 502 Bad Gateway - */ - public static final HttpResponseStatus BAD_GATEWAY = new HttpResponseStatus(502, "Bad Gateway", true); - - /** - * 503 Service Unavailable - */ - public static final HttpResponseStatus SERVICE_UNAVAILABLE = - new HttpResponseStatus(503, "Service Unavailable", true); - - /** - * 504 Gateway Timeout - */ - public static final HttpResponseStatus GATEWAY_TIMEOUT = new HttpResponseStatus(504, "Gateway Timeout", true); - - /** - * 505 HTTP Version Not Supported - */ - public static final HttpResponseStatus HTTP_VERSION_NOT_SUPPORTED = - new HttpResponseStatus(505, "HTTP Version Not Supported", true); - - /** - * 506 Variant Also Negotiates (RFC2295) - */ - public static final HttpResponseStatus VARIANT_ALSO_NEGOTIATES = - new HttpResponseStatus(506, "Variant Also Negotiates", true); - - /** - * 507 Insufficient Storage (WebDAV, RFC4918) - */ - public static final HttpResponseStatus INSUFFICIENT_STORAGE = - new HttpResponseStatus(507, "Insufficient Storage", true); - - /** - * 510 Not Extended (RFC2774) - */ - public static final HttpResponseStatus NOT_EXTENDED = new HttpResponseStatus(510, "Not Extended", true); - - /** - * 511 Network Authentication Required (RFC6585) - */ - public static final HttpResponseStatus NETWORK_AUTHENTICATION_REQUIRED = - new HttpResponseStatus(511, "Network Authentication Required", true); - - /** - * Returns the {@link HttpResponseStatus} represented by the specified code. - * If the specified code is a standard HTTP getStatus code, a cached instance - * will be returned. Otherwise, a new instance will be returned. - */ - public static HttpResponseStatus valueOf(int code) { - switch (code) { - case 100: - return CONTINUE; - case 101: - return SWITCHING_PROTOCOLS; - case 102: - return PROCESSING; - case 200: - return OK; - case 201: - return CREATED; - case 202: - return ACCEPTED; - case 203: - return NON_AUTHORITATIVE_INFORMATION; - case 204: - return NO_CONTENT; - case 205: - return RESET_CONTENT; - case 206: - return PARTIAL_CONTENT; - case 207: - return MULTI_STATUS; - case 300: - return MULTIPLE_CHOICES; - case 301: - return MOVED_PERMANENTLY; - case 302: - return FOUND; - case 303: - return SEE_OTHER; - case 304: - return NOT_MODIFIED; - case 305: - return USE_PROXY; - case 307: - return TEMPORARY_REDIRECT; - case 400: - return BAD_REQUEST; - case 401: - return UNAUTHORIZED; - case 402: - return PAYMENT_REQUIRED; - case 403: - return FORBIDDEN; - case 404: - return NOT_FOUND; - case 405: - return METHOD_NOT_ALLOWED; - case 406: - return NOT_ACCEPTABLE; - case 407: - return PROXY_AUTHENTICATION_REQUIRED; - case 408: - return REQUEST_TIMEOUT; - case 409: - return CONFLICT; - case 410: - return GONE; - case 411: - return LENGTH_REQUIRED; - case 412: - return PRECONDITION_FAILED; - case 413: - return REQUEST_ENTITY_TOO_LARGE; - case 414: - return REQUEST_URI_TOO_LONG; - case 415: - return UNSUPPORTED_MEDIA_TYPE; - case 416: - return REQUESTED_RANGE_NOT_SATISFIABLE; - case 417: - return EXPECTATION_FAILED; - case 422: - return UNPROCESSABLE_ENTITY; - case 423: - return LOCKED; - case 424: - return FAILED_DEPENDENCY; - case 425: - return UNORDERED_COLLECTION; - case 426: - return UPGRADE_REQUIRED; - case 428: - return PRECONDITION_REQUIRED; - case 429: - return TOO_MANY_REQUESTS; - case 431: - return REQUEST_HEADER_FIELDS_TOO_LARGE; - case 500: - return INTERNAL_SERVER_ERROR; - case 501: - return NOT_IMPLEMENTED; - case 502: - return BAD_GATEWAY; - case 503: - return SERVICE_UNAVAILABLE; - case 504: - return GATEWAY_TIMEOUT; - case 505: - return HTTP_VERSION_NOT_SUPPORTED; - case 506: - return VARIANT_ALSO_NEGOTIATES; - case 507: - return INSUFFICIENT_STORAGE; - case 510: - return NOT_EXTENDED; - case 511: - return NETWORK_AUTHENTICATION_REQUIRED; - } - - final String reasonPhrase; - - if (code < 100) { - reasonPhrase = "Unknown Status"; - } else if (code < 200) { - reasonPhrase = "Informational"; - } else if (code < 300) { - reasonPhrase = "Successful"; - } else if (code < 400) { - reasonPhrase = "Redirection"; - } else if (code < 500) { - reasonPhrase = "Client Error"; - } else if (code < 600) { - reasonPhrase = "Server Error"; - } else { - reasonPhrase = "Unknown Status"; - } - - return new HttpResponseStatus(code, reasonPhrase + " (" + code + ')'); - } - - private final int code; - - private final String reasonPhrase; - private final byte[] bytes; - - /** - * Creates a new instance with the specified {@code code} and its - * {@code reasonPhrase}. - */ - public HttpResponseStatus(int code, String reasonPhrase) { - this(code, reasonPhrase, false); - } - - private HttpResponseStatus(int code, String reasonPhrase, boolean bytes) { - if (code < 0) { - throw new IllegalArgumentException( - "code: " + code + " (expected: 0+)"); - } - - if (reasonPhrase == null) { - throw new NullPointerException("reasonPhrase"); - } - - for (int i = 0; i < reasonPhrase.length(); i ++) { - char c = reasonPhrase.charAt(i); - // Check prohibited characters. - switch (c) { - case '\n': case '\r': - throw new IllegalArgumentException( - "reasonPhrase contains one of the following prohibited characters: " + - "\\r\\n: " + reasonPhrase); - } - } - - this.code = code; - this.reasonPhrase = reasonPhrase; - if (bytes) { - this.bytes = (code + " " + reasonPhrase).getBytes(CharsetUtil.US_ASCII); - } else { - this.bytes = null; - } - } - - /** - * Returns the code of this {@link HttpResponseStatus}. - */ - public int code() { - return code; - } - - /** - * Returns the reason phrase of this {@link HttpResponseStatus}. - */ - public String reasonPhrase() { - return reasonPhrase; - } - - @Override - public int hashCode() { - return code(); - } - - /** - * Equality of {@link HttpResponseStatus} only depends on {@link #code()}. The - * reason phrase is not considered for equality. - */ - @Override - public boolean equals(Object o) { - if (!(o instanceof HttpResponseStatus)) { - return false; - } - - return code() == ((HttpResponseStatus) o).code(); - } - - /** - * Equality of {@link HttpResponseStatus} only depends on {@link #code()}. The - * reason phrase is not considered for equality. - */ - @Override - public int compareTo(HttpResponseStatus o) { - return code() - o.code(); - } - - @Override - public String toString() { - return new StringBuilder(reasonPhrase.length() + 5) - .append(code) - .append(' ') - .append(reasonPhrase) - .toString(); - } - - void encode(ByteBuf buf) { - if (bytes == null) { - HttpHeaders.encodeAscii0(String.valueOf(code()), buf); - buf.writeByte(SP); - HttpHeaders.encodeAscii0(String.valueOf(reasonPhrase()), buf); - } else { - buf.writeBytes(bytes); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpServerCodec.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpServerCodec.java deleted file mode 100755 index 6f48e2608c..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpServerCodec.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import com.ai.cloud.io.netty.channel.CombinedChannelDuplexHandler; - - -/** - * A combination of {@link HttpRequestDecoder} and {@link HttpResponseEncoder} - * which enables easier server side HTTP implementation. - * - * @see HttpClientCodec - */ -public final class HttpServerCodec - extends CombinedChannelDuplexHandler { - - /** - * Creates a new instance with the default decoder options - * ({@code maxInitialLineLength (4096}}, {@code maxHeaderSize (8192)}, and - * {@code maxChunkSize (8192)}). - */ - public HttpServerCodec() { - this(4096, 8192, 8192); - } - - /** - * Creates a new instance with the specified decoder options. - */ - public HttpServerCodec(int maxInitialLineLength, int maxHeaderSize, int maxChunkSize) { - super(new HttpRequestDecoder(maxInitialLineLength, maxHeaderSize, maxChunkSize), new HttpResponseEncoder()); - } - - /** - * Creates a new instance with the specified decoder options. - */ - public HttpServerCodec(int maxInitialLineLength, int maxHeaderSize, int maxChunkSize, boolean validateHeaders) { - super(new HttpRequestDecoder(maxInitialLineLength, maxHeaderSize, maxChunkSize, validateHeaders), - new HttpResponseEncoder()); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpUtil.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpUtil.java deleted file mode 100755 index 1e5fcf100d..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpUtil.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import java.net.URI; - -/** - * Utility methods useful in the HTTP context. - */ -public final class HttpUtil { - private HttpUtil() { } - - /** - * Determine if a uri is in origin-form according to - * rfc7230, 5.3. - */ - public static boolean isOriginForm(URI uri) { - return uri.getScheme() == null && uri.getSchemeSpecificPart() == null && - uri.getHost() == null && uri.getAuthority() == null; - } - - /** - * Determine if a uri is in asteric-form according to - * rfc7230, 5.3. - */ - public static boolean isAsteriskForm(URI uri) { - return "*".equals(uri.getPath()) && - uri.getScheme() == null && uri.getSchemeSpecificPart() == null && - uri.getHost() == null && uri.getAuthority() == null && uri.getQuery() == null && - uri.getFragment() == null; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpVersion.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpVersion.java deleted file mode 100755 index 1965d2e0b5..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/HttpVersion.java +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.util.CharsetUtil; - -/** - * The version of HTTP or its derived protocols, such as - * RTSP and - * ICAP. - */ -public class HttpVersion implements Comparable { - - private static final Pattern VERSION_PATTERN = - Pattern.compile("(\\S+)/(\\d+)\\.(\\d+)"); - - private static final String HTTP_1_0_STRING = "HTTP/1.0"; - private static final String HTTP_1_1_STRING = "HTTP/1.1"; - - /** - * HTTP/1.0 - */ - public static final HttpVersion HTTP_1_0 = new HttpVersion("HTTP", 1, 0, false, true); - - /** - * HTTP/1.1 - */ - public static final HttpVersion HTTP_1_1 = new HttpVersion("HTTP", 1, 1, true, true); - - /** - * Returns an existing or new {@link HttpVersion} instance which matches to - * the specified protocol version string. If the specified {@code text} is - * equal to {@code "HTTP/1.0"}, {@link #HTTP_1_0} will be returned. If the - * specified {@code text} is equal to {@code "HTTP/1.1"}, {@link #HTTP_1_1} - * will be returned. Otherwise, a new {@link HttpVersion} instance will be - * returned. - */ - public static HttpVersion valueOf(String text) { - if (text == null) { - throw new NullPointerException("text"); - } - - text = text.trim(); - - if (text.isEmpty()) { - throw new IllegalArgumentException("text is empty"); - } - - // Try to match without convert to uppercase first as this is what 99% of all clients - // will send anyway. Also there is a change to the RFC to make it clear that it is - // expected to be case-sensitive - // - // See: - // * http://trac.tools.ietf.org/wg/httpbis/trac/ticket/1 - // * http://trac.tools.ietf.org/wg/httpbis/trac/wiki - // - // TODO: Remove the uppercase conversion in 4.1.0 as the RFC state it must be HTTP (uppercase) - // See https://github.com/netty/netty/issues/1682 - - HttpVersion version = version0(text); - if (version == null) { - text = text.toUpperCase(); - // try again after convert to uppercase - version = version0(text); - if (version == null) { - // still no match, construct a new one - version = new HttpVersion(text, true); - } - } - return version; - } - - private static HttpVersion version0(String text) { - if (HTTP_1_1_STRING.equals(text)) { - return HTTP_1_1; - } - if (HTTP_1_0_STRING.equals(text)) { - return HTTP_1_0; - } - return null; - } - - private final String protocolName; - private final int majorVersion; - private final int minorVersion; - private final String text; - private final boolean keepAliveDefault; - private final byte[] bytes; - - /** - * Creates a new HTTP version with the specified version string. You will - * not need to create a new instance unless you are implementing a protocol - * derived from HTTP, such as - * RTSP and - * ICAP. - * - * @param keepAliveDefault - * {@code true} if and only if the connection is kept alive unless - * the {@code "Connection"} header is set to {@code "close"} explicitly. - */ - public HttpVersion(String text, boolean keepAliveDefault) { - if (text == null) { - throw new NullPointerException("text"); - } - - text = text.trim().toUpperCase(); - if (text.isEmpty()) { - throw new IllegalArgumentException("empty text"); - } - - Matcher m = VERSION_PATTERN.matcher(text); - if (!m.matches()) { - throw new IllegalArgumentException("invalid version format: " + text); - } - - protocolName = m.group(1); - majorVersion = Integer.parseInt(m.group(2)); - minorVersion = Integer.parseInt(m.group(3)); - this.text = protocolName + '/' + majorVersion + '.' + minorVersion; - this.keepAliveDefault = keepAliveDefault; - bytes = null; - } - - /** - * Creates a new HTTP version with the specified protocol name and version - * numbers. You will not need to create a new instance unless you are - * implementing a protocol derived from HTTP, such as - * RTSP and - * ICAP - * - * @param keepAliveDefault - * {@code true} if and only if the connection is kept alive unless - * the {@code "Connection"} header is set to {@code "close"} explicitly. - */ - public HttpVersion( - String protocolName, int majorVersion, int minorVersion, - boolean keepAliveDefault) { - this(protocolName, majorVersion, minorVersion, keepAliveDefault, false); - } - - private HttpVersion( - String protocolName, int majorVersion, int minorVersion, - boolean keepAliveDefault, boolean bytes) { - if (protocolName == null) { - throw new NullPointerException("protocolName"); - } - - protocolName = protocolName.trim().toUpperCase(); - if (protocolName.isEmpty()) { - throw new IllegalArgumentException("empty protocolName"); - } - - for (int i = 0; i < protocolName.length(); i ++) { - if (Character.isISOControl(protocolName.charAt(i)) || - Character.isWhitespace(protocolName.charAt(i))) { - throw new IllegalArgumentException("invalid character in protocolName"); - } - } - - if (majorVersion < 0) { - throw new IllegalArgumentException("negative majorVersion"); - } - if (minorVersion < 0) { - throw new IllegalArgumentException("negative minorVersion"); - } - - this.protocolName = protocolName; - this.majorVersion = majorVersion; - this.minorVersion = minorVersion; - text = protocolName + '/' + majorVersion + '.' + minorVersion; - this.keepAliveDefault = keepAliveDefault; - - if (bytes) { - this.bytes = text.getBytes(CharsetUtil.US_ASCII); - } else { - this.bytes = null; - } - } - - /** - * Returns the name of the protocol such as {@code "HTTP"} in {@code "HTTP/1.0"}. - */ - public String protocolName() { - return protocolName; - } - - /** - * Returns the name of the protocol such as {@code 1} in {@code "HTTP/1.0"}. - */ - public int majorVersion() { - return majorVersion; - } - - /** - * Returns the name of the protocol such as {@code 0} in {@code "HTTP/1.0"}. - */ - public int minorVersion() { - return minorVersion; - } - - /** - * Returns the full protocol version text such as {@code "HTTP/1.0"}. - */ - public String text() { - return text; - } - - /** - * Returns {@code true} if and only if the connection is kept alive unless - * the {@code "Connection"} header is set to {@code "close"} explicitly. - */ - public boolean isKeepAliveDefault() { - return keepAliveDefault; - } - - /** - * Returns the full protocol version text such as {@code "HTTP/1.0"}. - */ - @Override - public String toString() { - return text(); - } - - @Override - public int hashCode() { - return (protocolName().hashCode() * 31 + majorVersion()) * 31 + - minorVersion(); - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof HttpVersion)) { - return false; - } - - HttpVersion that = (HttpVersion) o; - return minorVersion() == that.minorVersion() && - majorVersion() == that.majorVersion() && - protocolName().equals(that.protocolName()); - } - - @Override - public int compareTo(HttpVersion o) { - int v = protocolName().compareTo(o.protocolName()); - if (v != 0) { - return v; - } - - v = majorVersion() - o.majorVersion(); - if (v != 0) { - return v; - } - - return minorVersion() - o.minorVersion(); - } - - void encode(ByteBuf buf) { - if (bytes == null) { - HttpHeaders.encodeAscii0(text, buf); - } else { - buf.writeBytes(bytes); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/LastHttpContent.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/LastHttpContent.java deleted file mode 100755 index 759765c99c..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/LastHttpContent.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.Unpooled; -import com.ai.cloud.io.netty.handler.codec.DecoderResult; - -/** - * The last {@link HttpContent} which has trailing headers. - */ -public interface LastHttpContent extends HttpContent { - - /** - * The 'end of content' marker in chunked encoding. - */ - LastHttpContent EMPTY_LAST_CONTENT = new LastHttpContent() { - - @Override - public ByteBuf content() { - return Unpooled.EMPTY_BUFFER; - } - - @Override - public LastHttpContent copy() { - return EMPTY_LAST_CONTENT; - } - - @Override - public LastHttpContent duplicate() { - return this; - } - - @Override - public HttpHeaders trailingHeaders() { - return HttpHeaders.EMPTY_HEADERS; - } - - @Override - public DecoderResult getDecoderResult() { - return DecoderResult.SUCCESS; - } - - @Override - public void setDecoderResult(DecoderResult result) { - throw new UnsupportedOperationException("read only"); - } - - @Override - public int refCnt() { - return 1; - } - - @Override - public LastHttpContent retain() { - return this; - } - - @Override - public LastHttpContent retain(int increment) { - return this; - } - - @Override - public boolean release() { - return false; - } - - @Override - public boolean release(int decrement) { - return false; - } - - @Override - public String toString() { - return "EmptyLastHttpContent"; - } - }; - - HttpHeaders trailingHeaders(); - - @Override - LastHttpContent copy(); - - @Override - LastHttpContent retain(int increment); - - @Override - LastHttpContent retain(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/QueryStringDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/QueryStringDecoder.java deleted file mode 100755 index 5d41a2b980..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/QueryStringDecoder.java +++ /dev/null @@ -1,385 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import java.net.URI; -import java.net.URLDecoder; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import com.ai.cloud.io.netty.util.CharsetUtil; - -/** - * Splits an HTTP query string into a path string and key-value parameter pairs. - * This decoder is for one time use only. Create a new instance for each URI: - *
- * {@link QueryStringDecoder} decoder = new {@link QueryStringDecoder}("/hello?recipient=world&x=1;y=2");
- * assert decoder.path().equals("/hello");
- * assert decoder.parameters().get("recipient").get(0).equals("world");
- * assert decoder.parameters().get("x").get(0).equals("1");
- * assert decoder.parameters().get("y").get(0).equals("2");
- * 
- * - * This decoder can also decode the content of an HTTP POST request whose - * content type is application/x-www-form-urlencoded: - *
- * {@link QueryStringDecoder} decoder = new {@link QueryStringDecoder}("recipient=world&x=1;y=2", false);
- * ...
- * 
- * - *

HashDOS vulnerability fix

- * - * As a workaround to the HashDOS vulnerability, the decoder - * limits the maximum number of decoded key-value parameter pairs, up to {@literal 1024} by - * default, and you can configure it when you construct the decoder by passing an additional - * integer parameter. - * - * @see QueryStringEncoder - */ -public class QueryStringDecoder { - - private static final int DEFAULT_MAX_PARAMS = 1024; - - private final Charset charset; - private final String uri; - private final boolean hasPath; - private final int maxParams; - private String path; - private Map> params; - private int nParams; - - /** - * Creates a new decoder that decodes the specified URI. The decoder will - * assume that the query string is encoded in UTF-8. - */ - public QueryStringDecoder(String uri) { - this(uri, HttpConstants.DEFAULT_CHARSET); - } - - /** - * Creates a new decoder that decodes the specified URI encoded in the - * specified charset. - */ - public QueryStringDecoder(String uri, boolean hasPath) { - this(uri, HttpConstants.DEFAULT_CHARSET, hasPath); - } - - /** - * Creates a new decoder that decodes the specified URI encoded in the - * specified charset. - */ - public QueryStringDecoder(String uri, Charset charset) { - this(uri, charset, true); - } - - /** - * Creates a new decoder that decodes the specified URI encoded in the - * specified charset. - */ - public QueryStringDecoder(String uri, Charset charset, boolean hasPath) { - this(uri, charset, hasPath, DEFAULT_MAX_PARAMS); - } - - /** - * Creates a new decoder that decodes the specified URI encoded in the - * specified charset. - */ - public QueryStringDecoder(String uri, Charset charset, boolean hasPath, int maxParams) { - if (uri == null) { - throw new NullPointerException("getUri"); - } - if (charset == null) { - throw new NullPointerException("charset"); - } - if (maxParams <= 0) { - throw new IllegalArgumentException( - "maxParams: " + maxParams + " (expected: a positive integer)"); - } - - this.uri = uri; - this.charset = charset; - this.maxParams = maxParams; - this.hasPath = hasPath; - } - - /** - * Creates a new decoder that decodes the specified URI. The decoder will - * assume that the query string is encoded in UTF-8. - */ - public QueryStringDecoder(URI uri) { - this(uri, HttpConstants.DEFAULT_CHARSET); - } - - /** - * Creates a new decoder that decodes the specified URI encoded in the - * specified charset. - */ - public QueryStringDecoder(URI uri, Charset charset) { - this(uri, charset, DEFAULT_MAX_PARAMS); - } - - /** - * Creates a new decoder that decodes the specified URI encoded in the - * specified charset. - */ - public QueryStringDecoder(URI uri, Charset charset, int maxParams) { - if (uri == null) { - throw new NullPointerException("getUri"); - } - if (charset == null) { - throw new NullPointerException("charset"); - } - if (maxParams <= 0) { - throw new IllegalArgumentException( - "maxParams: " + maxParams + " (expected: a positive integer)"); - } - - String rawPath = uri.getRawPath(); - if (rawPath != null) { - hasPath = true; - } else { - rawPath = ""; - hasPath = false; - } - // Also take care of cut of things like "http://localhost" - this.uri = rawPath + (uri.getRawQuery() == null? "" : '?' + uri.getRawQuery()); - - this.charset = charset; - this.maxParams = maxParams; - } - - /** - * Returns the uri used to initialize this {@link QueryStringDecoder}. - */ - public String uri() { - return uri; - } - - /** - * Returns the decoded path string of the URI. - */ - public String path() { - if (path == null) { - if (!hasPath) { - return path = ""; - } - - int pathEndPos = uri.indexOf('?'); - if (pathEndPos < 0) { - path = uri; - } else { - return path = uri.substring(0, pathEndPos); - } - } - return path; - } - - /** - * Returns the decoded key-value parameter pairs of the URI. - */ - public Map> parameters() { - if (params == null) { - if (hasPath) { - int pathLength = path().length(); - if (uri.length() == pathLength) { - return Collections.emptyMap(); - } - decodeParams(uri.substring(pathLength + 1)); - } else { - if (uri.isEmpty()) { - return Collections.emptyMap(); - } - decodeParams(uri); - } - } - return params; - } - - private void decodeParams(String s) { - Map> params = this.params = new LinkedHashMap>(); - nParams = 0; - String name = null; - int pos = 0; // Beginning of the unprocessed region - int i; // End of the unprocessed region - char c; // Current character - for (i = 0; i < s.length(); i++) { - c = s.charAt(i); - if (c == '=' && name == null) { - if (pos != i) { - name = decodeComponent(s.substring(pos, i), charset); - } - pos = i + 1; - // http://www.w3.org/TR/html401/appendix/notes.html#h-B.2.2 - } else if (c == '&' || c == ';') { - if (name == null && pos != i) { - // We haven't seen an `=' so far but moved forward. - // Must be a param of the form '&a&' so add it with - // an empty value. - if (!addParam(params, decodeComponent(s.substring(pos, i), charset), "")) { - return; - } - } else if (name != null) { - if (!addParam(params, name, decodeComponent(s.substring(pos, i), charset))) { - return; - } - name = null; - } - pos = i + 1; - } - } - - if (pos != i) { // Are there characters we haven't dealt with? - if (name == null) { // Yes and we haven't seen any `='. - addParam(params, decodeComponent(s.substring(pos, i), charset), ""); - } else { // Yes and this must be the last value. - addParam(params, name, decodeComponent(s.substring(pos, i), charset)); - } - } else if (name != null) { // Have we seen a name without value? - addParam(params, name, ""); - } - } - - private boolean addParam(Map> params, String name, String value) { - if (nParams >= maxParams) { - return false; - } - - List values = params.get(name); - if (values == null) { - values = new ArrayList(1); // Often there's only 1 value. - params.put(name, values); - } - values.add(value); - nParams ++; - return true; - } - - /** - * Decodes a bit of an URL encoded by a browser. - *

- * This is equivalent to calling {@link #decodeComponent(String, Charset)} - * with the UTF-8 charset (recommended to comply with RFC 3986, Section 2). - * @param s The string to decode (can be empty). - * @return The decoded string, or {@code s} if there's nothing to decode. - * If the string to decode is {@code null}, returns an empty string. - * @throws IllegalArgumentException if the string contains a malformed - * escape sequence. - */ - public static String decodeComponent(final String s) { - return decodeComponent(s, HttpConstants.DEFAULT_CHARSET); - } - - /** - * Decodes a bit of an URL encoded by a browser. - *

- * The string is expected to be encoded as per RFC 3986, Section 2. - * This is the encoding used by JavaScript functions {@code encodeURI} - * and {@code encodeURIComponent}, but not {@code escape}. For example - * in this encoding, é (in Unicode {@code U+00E9} or in UTF-8 - * {@code 0xC3 0xA9}) is encoded as {@code %C3%A9} or {@code %c3%a9}. - *

- * This is essentially equivalent to calling - * {@link URLDecoder#decode(String, String) URLDecoder.decode(s, charset.name())} - * except that it's over 2x faster and generates less garbage for the GC. - * Actually this function doesn't allocate any memory if there's nothing - * to decode, the argument itself is returned. - * @param s The string to decode (can be empty). - * @param charset The charset to use to decode the string (should really - * be {@link CharsetUtil#UTF_8}. - * @return The decoded string, or {@code s} if there's nothing to decode. - * If the string to decode is {@code null}, returns an empty string. - * @throws IllegalArgumentException if the string contains a malformed - * escape sequence. - */ - public static String decodeComponent(final String s, final Charset charset) { - if (s == null) { - return ""; - } - final int size = s.length(); - boolean modified = false; - for (int i = 0; i < size; i++) { - final char c = s.charAt(i); - if (c == '%' || c == '+') { - modified = true; - break; - } - } - if (!modified) { - return s; - } - final byte[] buf = new byte[size]; - int pos = 0; // position in `buf'. - for (int i = 0; i < size; i++) { - char c = s.charAt(i); - switch (c) { - case '+': - buf[pos++] = ' '; // "+" -> " " - break; - case '%': - if (i == size - 1) { - throw new IllegalArgumentException("unterminated escape" - + " sequence at end of string: " + s); - } - c = s.charAt(++i); - if (c == '%') { - buf[pos++] = '%'; // "%%" -> "%" - break; - } - if (i == size - 1) { - throw new IllegalArgumentException("partial escape" - + " sequence at end of string: " + s); - } - c = decodeHexNibble(c); - final char c2 = decodeHexNibble(s.charAt(++i)); - if (c == Character.MAX_VALUE || c2 == Character.MAX_VALUE) { - throw new IllegalArgumentException( - "invalid escape sequence `%" + s.charAt(i - 1) - + s.charAt(i) + "' at index " + (i - 2) - + " of: " + s); - } - c = (char) (c * 16 + c2); - // Fall through. - default: - buf[pos++] = (byte) c; - break; - } - } - return new String(buf, 0, pos, charset); - } - - /** - * Helper to decode half of a hexadecimal number from a string. - * @param c The ASCII character of the hexadecimal number to decode. - * Must be in the range {@code [0-9a-fA-F]}. - * @return The hexadecimal value represented in the ASCII character - * given, or {@link Character#MAX_VALUE} if the character is invalid. - */ - private static char decodeHexNibble(final char c) { - if ('0' <= c && c <= '9') { - return (char) (c - '0'); - } else if ('a' <= c && c <= 'f') { - return (char) (c - 'a' + 10); - } else if ('A' <= c && c <= 'F') { - return (char) (c - 'A' + 10); - } else { - return Character.MAX_VALUE; - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/QueryStringEncoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/QueryStringEncoder.java deleted file mode 100755 index 6bc5f1043c..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/QueryStringEncoder.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URLEncoder; -import java.nio.charset.Charset; -import java.nio.charset.UnsupportedCharsetException; -import java.util.ArrayList; -import java.util.List; - -/** - * Creates an URL-encoded URI from a path string and key-value parameter pairs. - * This encoder is for one time use only. Create a new instance for each URI. - * - *

- * {@link QueryStringEncoder} encoder = new {@link QueryStringEncoder}("/hello");
- * encoder.addParam("recipient", "world");
- * assert encoder.toString().equals("/hello?recipient=world");
- * 
- * @see QueryStringDecoder - */ -public class QueryStringEncoder { - - private final Charset charset; - private final String uri; - private final List params = new ArrayList(); - - /** - * Creates a new encoder that encodes a URI that starts with the specified - * path string. The encoder will encode the URI in UTF-8. - */ - public QueryStringEncoder(String uri) { - this(uri, HttpConstants.DEFAULT_CHARSET); - } - - /** - * Creates a new encoder that encodes a URI that starts with the specified - * path string in the specified charset. - */ - public QueryStringEncoder(String uri, Charset charset) { - if (uri == null) { - throw new NullPointerException("getUri"); - } - if (charset == null) { - throw new NullPointerException("charset"); - } - - this.uri = uri; - this.charset = charset; - } - - /** - * Adds a parameter with the specified name and value to this encoder. - */ - public void addParam(String name, String value) { - if (name == null) { - throw new NullPointerException("name"); - } - params.add(new Param(name, value)); - } - - /** - * Returns the URL-encoded URI object which was created from the path string - * specified in the constructor and the parameters added by - * {@link #addParam(String, String)} getMethod. - */ - public URI toUri() throws URISyntaxException { - return new URI(toString()); - } - - /** - * Returns the URL-encoded URI which was created from the path string - * specified in the constructor and the parameters added by - * {@link #addParam(String, String)} getMethod. - */ - @Override - public String toString() { - if (params.isEmpty()) { - return uri; - } else { - StringBuilder sb = new StringBuilder(uri).append('?'); - for (int i = 0; i < params.size(); i++) { - Param param = params.get(i); - sb.append(encodeComponent(param.name, charset)); - if (param.value != null) { - sb.append('='); - sb.append(encodeComponent(param.value, charset)); - } - if (i != params.size() - 1) { - sb.append('&'); - } - } - return sb.toString(); - } - } - - private static String encodeComponent(String s, Charset charset) { - // TODO: Optimize me. - try { - return URLEncoder.encode(s, charset.name()).replace("+", "%20"); - } catch (UnsupportedEncodingException ignored) { - throw new UnsupportedCharsetException(charset.name()); - } - } - - private static final class Param { - - final String name; - final String value; - - Param(String name, String value) { - this.value = value; - this.name = name; - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/ServerCookieEncoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/ServerCookieEncoder.java deleted file mode 100755 index 9276d9c076..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/ServerCookieEncoder.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http; - -import java.util.Collection; -import java.util.List; - -/** - * A RFC6265 compliant cookie encoder to be used server side, - * so some fields are sent (Version is typically ignored). - * - * As Netty's Cookie merges Expires and MaxAge into one single field, only Max-Age field is sent. - * - * Note that multiple cookies are supposed to be sent at once in a single "Set-Cookie" header. - * - *
- * // Example
- * {@link HttpRequest} req = ...;
- * res.setHeader("Cookie", {@link ServerCookieEncoder}.encode("JSESSIONID", "1234"));
- * 
- * - * @see ServerCookieDecoder - * - * @deprecated Use {@link com.ai.cloud.io.netty.handler.codec.http.cookie.ServerCookieEncoder} instead - */ -@Deprecated -public final class ServerCookieEncoder { - - /** - * Encodes the specified cookie name-value pair into a Set-Cookie header value. - * - * @param name the cookie name - * @param value the cookie value - * @return a single Set-Cookie header value - */ - @Deprecated - public static String encode(String name, String value) { - return com.ai.cloud.io.netty.handler.codec.http.cookie.ServerCookieEncoder.LAX.encode(name, value); - } - - /** - * Encodes the specified cookie into a Set-Cookie header value. - * - * @param cookie the cookie - * @return a single Set-Cookie header value - */ - @Deprecated - public static String encode(Cookie cookie) { - return com.ai.cloud.io.netty.handler.codec.http.cookie.ServerCookieEncoder.LAX.encode(cookie); - } - - /** - * Batch encodes cookies into Set-Cookie header values. - * - * @param cookies a bunch of cookies - * @return the corresponding bunch of Set-Cookie headers - */ - @Deprecated - public static List encode(Cookie... cookies) { - return com.ai.cloud.io.netty.handler.codec.http.cookie.ServerCookieEncoder.LAX.encode(cookies); - } - - /** - * Batch encodes cookies into Set-Cookie header values. - * - * @param cookies a bunch of cookies - * @return the corresponding bunch of Set-Cookie headers - */ - @Deprecated - public static List encode(Collection cookies) { - return com.ai.cloud.io.netty.handler.codec.http.cookie.ServerCookieEncoder.LAX.encode(cookies); - } - - /** - * Batch encodes cookies into Set-Cookie header values. - * - * @param cookies a bunch of cookies - * @return the corresponding bunch of Set-Cookie headers - */ - @Deprecated - public static List encode(Iterable cookies) { - return com.ai.cloud.io.netty.handler.codec.http.cookie.ServerCookieEncoder.LAX.encode(cookies); - } - - private ServerCookieEncoder() { - // Unused - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/ClientCookieDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/ClientCookieDecoder.java deleted file mode 100755 index fb4308b3a1..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/ClientCookieDecoder.java +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.cookie; - -import static com.ai.cloud.io.netty.util.internal.ObjectUtil.checkNotNull; - -import java.text.ParsePosition; -import java.util.Date; - -import com.ai.cloud.io.netty.handler.codec.http.HttpHeaderDateFormat; - -/** - * A RFC6265 compliant cookie decoder to be used client side. - * - * It will store the way the raw value was wrapped in {@link Cookie#setWrap(boolean)} so it can be - * eventually sent back to the Origin server as is. - * - * @see ClientCookieEncoder - */ -public final class ClientCookieDecoder extends CookieDecoder { - - /** - * Strict encoder that validates that name and value chars are in the valid scope - * defined in RFC6265 - */ - public static final ClientCookieDecoder STRICT = new ClientCookieDecoder(true); - - /** - * Lax instance that doesn't validate name and value - */ - public static final ClientCookieDecoder LAX = new ClientCookieDecoder(false); - - private ClientCookieDecoder(boolean strict) { - super(strict); - } - - /** - * Decodes the specified Set-Cookie HTTP header value into a {@link Cookie}. - * - * @return the decoded {@link Cookie} - */ - public Cookie decode(String header) { - final int headerLen = checkNotNull(header, "header").length(); - - if (headerLen == 0) { - return null; - } - - CookieBuilder cookieBuilder = null; - - loop: for (int i = 0;;) { - - // Skip spaces and separators. - for (;;) { - if (i == headerLen) { - break loop; - } - char c = header.charAt(i); - if (c == ',') { - // Having multiple cookies in a single Set-Cookie header is - // deprecated, modern browsers only parse the first one - break loop; - - } else if (c == '\t' || c == '\n' || c == 0x0b || c == '\f' - || c == '\r' || c == ' ' || c == ';') { - i++; - continue; - } - break; - } - - int nameBegin = i; - int nameEnd = i; - int valueBegin = -1; - int valueEnd = -1; - - if (i != headerLen) { - keyValLoop: for (;;) { - - char curChar = header.charAt(i); - if (curChar == ';') { - // NAME; (no value till ';') - nameEnd = i; - valueBegin = valueEnd = -1; - break keyValLoop; - - } else if (curChar == '=') { - // NAME=VALUE - nameEnd = i; - i++; - if (i == headerLen) { - // NAME= (empty value, i.e. nothing after '=') - valueBegin = valueEnd = 0; - break keyValLoop; - } - - valueBegin = i; - // NAME=VALUE; - int semiPos = header.indexOf(';', i); - valueEnd = i = semiPos > 0 ? semiPos : headerLen; - break keyValLoop; - } else { - i++; - } - - if (i == headerLen) { - // NAME (no value till the end of string) - nameEnd = headerLen; - valueBegin = valueEnd = -1; - break; - } - } - } - - if (valueEnd > 0 && header.charAt(valueEnd - 1) == ',') { - // old multiple cookies separator, skipping it - valueEnd--; - } - - if (cookieBuilder == null) { - // cookie name-value pair - DefaultCookie cookie = initCookie(header, nameBegin, nameEnd, valueBegin, valueEnd); - - if (cookie == null) { - return null; - } - - cookieBuilder = new CookieBuilder(cookie, header); - } else { - // cookie attribute - cookieBuilder.appendAttribute(nameBegin, nameEnd, valueBegin, valueEnd); - } - } - return cookieBuilder.cookie(); - } - - private static class CookieBuilder { - - private final String header; - private final DefaultCookie cookie; - private String domain; - private String path; - private long maxAge = Long.MIN_VALUE; - private int expiresStart; - private int expiresEnd; - private boolean secure; - private boolean httpOnly; - - public CookieBuilder(DefaultCookie cookie, String header) { - this.cookie = cookie; - this.header = header; - } - - private long mergeMaxAgeAndExpires() { - // max age has precedence over expires - if (maxAge != Long.MIN_VALUE) { - return maxAge; - } else { - String expires = computeValue(expiresStart, expiresEnd); - if (expires != null) { - Date expiresDate = HttpHeaderDateFormat.get().parse(expires, new ParsePosition(0)); - if (expiresDate != null) { - long maxAgeMillis = expiresDate.getTime() - System.currentTimeMillis(); - return maxAgeMillis / 1000 + (maxAgeMillis % 1000 != 0 ? 1 : 0); - } - } - } - return Long.MIN_VALUE; - } - - public Cookie cookie() { - cookie.setDomain(domain); - cookie.setPath(path); - cookie.setMaxAge(mergeMaxAgeAndExpires()); - cookie.setSecure(secure); - cookie.setHttpOnly(httpOnly); - return cookie; - } - - /** - * Parse and store a key-value pair. First one is considered to be the - * cookie name/value. Unknown attribute names are silently discarded. - * - * @param keyStart - * where the key starts in the header - * @param keyEnd - * where the key ends in the header - * @param valueStart - * where the value starts in the header - * @param valueEnd - * where the value ends in the header - */ - public void appendAttribute(int keyStart, int keyEnd, int valueStart, int valueEnd) { - int length = keyEnd - keyStart; - - if (length == 4) { - parse4(keyStart, valueStart, valueEnd); - } else if (length == 6) { - parse6(keyStart, valueStart, valueEnd); - } else if (length == 7) { - parse7(keyStart, valueStart, valueEnd); - } else if (length == 8) { - parse8(keyStart, valueStart, valueEnd); - } - } - - private void parse4(int nameStart, int valueStart, int valueEnd) { - if (header.regionMatches(true, nameStart, CookieHeaderNames.PATH, 0, 4)) { - path = computeValue(valueStart, valueEnd); - } - } - - private void parse6(int nameStart, int valueStart, int valueEnd) { - if (header.regionMatches(true, nameStart, CookieHeaderNames.DOMAIN, 0, 5)) { - domain = computeValue(valueStart, valueEnd); - } else if (header.regionMatches(true, nameStart, CookieHeaderNames.SECURE, 0, 5)) { - secure = true; - } - } - - private void setMaxAge(String value) { - try { - maxAge = Math.max(Long.valueOf(value), 0L); - } catch (NumberFormatException e1) { - // ignore failure to parse -> treat as session cookie - } - } - - private void parse7(int nameStart, int valueStart, int valueEnd) { - if (header.regionMatches(true, nameStart, CookieHeaderNames.EXPIRES, 0, 7)) { - expiresStart = valueStart; - expiresEnd = valueEnd; - } else if (header.regionMatches(true, nameStart, CookieHeaderNames.MAX_AGE, 0, 7)) { - setMaxAge(computeValue(valueStart, valueEnd)); - } - } - - private void parse8(int nameStart, int valueStart, int valueEnd) { - if (header.regionMatches(true, nameStart, CookieHeaderNames.HTTPONLY, 0, 8)) { - httpOnly = true; - } - } - - private String computeValue(int valueStart, int valueEnd) { - return valueStart == -1 || valueStart == valueEnd ? null : header.substring(valueStart, valueEnd); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/ClientCookieEncoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/ClientCookieEncoder.java deleted file mode 100755 index 5a149e7f9b..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/ClientCookieEncoder.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.cookie; - -import static com.ai.cloud.io.netty.handler.codec.http.cookie.CookieUtil.*; -import static com.ai.cloud.io.netty.util.internal.ObjectUtil.checkNotNull; - -import java.util.Iterator; - -import com.ai.cloud.io.netty.handler.codec.http.HttpRequest; - -/** - * A RFC6265 compliant cookie encoder to be used client side, - * so only name=value pairs are sent. - * - * User-Agents are not supposed to interpret cookies, so, if present, {@link Cookie#rawValue()} will be used. - * Otherwise, {@link Cookie#value()} will be used unquoted. - * - * Note that multiple cookies are supposed to be sent at once in a single "Cookie" header. - * - *
- * // Example
- * {@link HttpRequest} req = ...;
- * res.setHeader("Cookie", {@link ClientCookieEncoder}.encode("JSESSIONID", "1234"));
- * 
- * - * @see ClientCookieDecoder - */ -public final class ClientCookieEncoder extends CookieEncoder { - - /** - * Strict encoder that validates that name and value chars are in the valid scope - * defined in RFC6265 - */ - public static final ClientCookieEncoder STRICT = new ClientCookieEncoder(true); - - /** - * Lax instance that doesn't validate name and value - */ - public static final ClientCookieEncoder LAX = new ClientCookieEncoder(false); - - private ClientCookieEncoder(boolean strict) { - super(strict); - } - - /** - * Encodes the specified cookie into a Cookie header value. - * - * @param name the cookie name - * @param value the cookie value - * @return a Rfc6265 style Cookie header value - */ - public String encode(String name, String value) { - return encode(new DefaultCookie(name, value)); - } - - /** - * Encodes the specified cookie into a Cookie header value. - * - * @param specified the cookie - * @return a Rfc6265 style Cookie header value - */ - public String encode(Cookie cookie) { - StringBuilder buf = stringBuilder(); - encode(buf, checkNotNull(cookie, "cookie")); - return stripTrailingSeparator(buf); - } - - /** - * Encodes the specified cookies into a single Cookie header value. - * - * @param cookies some cookies - * @return a Rfc6265 style Cookie header value, null if no cookies are passed. - */ - public String encode(Cookie... cookies) { - if (checkNotNull(cookies, "cookies").length == 0) { - return null; - } - - StringBuilder buf = stringBuilder(); - for (Cookie c : cookies) { - if (c == null) { - break; - } - - encode(buf, c); - } - return stripTrailingSeparatorOrNull(buf); - } - - /** - * Encodes the specified cookies into a single Cookie header value. - * - * @param cookies some cookies - * @return a Rfc6265 style Cookie header value, null if no cookies are passed. - */ - public String encode(Iterable cookies) { - Iterator cookiesIt = checkNotNull(cookies, "cookies").iterator(); - if (!cookiesIt.hasNext()) { - return null; - } - - StringBuilder buf = stringBuilder(); - while (cookiesIt.hasNext()) { - Cookie c = cookiesIt.next(); - if (c == null) { - break; - } - - encode(buf, c); - } - return stripTrailingSeparatorOrNull(buf); - } - - private void encode(StringBuilder buf, Cookie c) { - final String name = c.name(); - final String value = c.value() != null ? c.value() : ""; - - validateCookie(name, value); - - if (c.wrap()) { - addQuoted(buf, name, value); - } else { - add(buf, name, value); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/Cookie.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/Cookie.java deleted file mode 100755 index 2a125d9790..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/Cookie.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.cookie; - -/** - * An interface defining an - * HTTP cookie. - */ -public interface Cookie extends Comparable { - - /** - * Returns the name of this {@link Cookie}. - * - * @return The name of this {@link Cookie} - */ - String name(); - - /** - * Returns the value of this {@link Cookie}. - * - * @return The value of this {@link Cookie} - */ - String value(); - - /** - * Sets the value of this {@link Cookie}. - * - * @param value The value to set - */ - void setValue(String value); - - /** - * Returns true if the raw value of this {@link Cookie}, - * was wrapped with double quotes in original Set-Cookie header. - * - * @return If the value of this {@link Cookie} is to be wrapped - */ - boolean wrap(); - - /** - * Sets true if the value of this {@link Cookie} - * is to be wrapped with double quotes. - * - * @param wrap true if wrap - */ - void setWrap(boolean wrap); - - /** - * Returns the domain of this {@link Cookie}. - * - * @return The domain of this {@link Cookie} - */ - String domain(); - - /** - * Sets the domain of this {@link Cookie}. - * - * @param domain The domain to use - */ - void setDomain(String domain); - - /** - * Returns the path of this {@link Cookie}. - * - * @return The {@link Cookie}'s path - */ - String path(); - - /** - * Sets the path of this {@link Cookie}. - * - * @param path The path to use for this {@link Cookie} - */ - void setPath(String path); - - /** - * Returns the maximum age of this {@link Cookie} in seconds or {@link Long#MIN_VALUE} if unspecified - * - * @return The maximum age of this {@link Cookie} - */ - long maxAge(); - - /** - * Sets the maximum age of this {@link Cookie} in seconds. - * If an age of {@code 0} is specified, this {@link Cookie} will be - * automatically removed by browser because it will expire immediately. - * If {@link Long#MIN_VALUE} is specified, this {@link Cookie} will be removed when the - * browser is closed. - * - * @param maxAge The maximum age of this {@link Cookie} in seconds - */ - void setMaxAge(long maxAge); - - /** - * Checks to see if this {@link Cookie} is secure - * - * @return True if this {@link Cookie} is secure, otherwise false - */ - boolean isSecure(); - - /** - * Sets the security getStatus of this {@link Cookie} - * - * @param secure True if this {@link Cookie} is to be secure, otherwise false - */ - void setSecure(boolean secure); - - /** - * Checks to see if this {@link Cookie} can only be accessed via HTTP. - * If this returns true, the {@link Cookie} cannot be accessed through - * client side script - But only if the browser supports it. - * For more information, please look here - * - * @return True if this {@link Cookie} is HTTP-only or false if it isn't - */ - boolean isHttpOnly(); - - /** - * Determines if this {@link Cookie} is HTTP only. - * If set to true, this {@link Cookie} cannot be accessed by a client - * side script. However, this works only if the browser supports it. - * For for information, please look - * here. - * - * @param httpOnly True if the {@link Cookie} is HTTP only, otherwise false. - */ - void setHttpOnly(boolean httpOnly); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/CookieDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/CookieDecoder.java deleted file mode 100755 index afe7722ddb..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/CookieDecoder.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.cookie; - -import static com.ai.cloud.io.netty.handler.codec.http.cookie.CookieUtil.firstInvalidCookieNameOctet; -import static com.ai.cloud.io.netty.handler.codec.http.cookie.CookieUtil.firstInvalidCookieValueOctet; -import static com.ai.cloud.io.netty.handler.codec.http.cookie.CookieUtil.unwrapValue; - -import java.nio.CharBuffer; - -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * Parent of Client and Server side cookie decoders - */ -public abstract class CookieDecoder { - - private final InternalLogger logger = InternalLoggerFactory.getInstance(getClass()); - - private final boolean strict; - - protected CookieDecoder(boolean strict) { - this.strict = strict; - } - - protected DefaultCookie initCookie(String header, int nameBegin, int nameEnd, int valueBegin, int valueEnd) { - if (nameBegin == -1 || nameBegin == nameEnd) { - logger.debug("Skipping cookie with null name"); - return null; - } - - if (valueBegin == -1) { - logger.debug("Skipping cookie with null value"); - return null; - } - - CharSequence wrappedValue = CharBuffer.wrap(header, valueBegin, valueEnd); - CharSequence unwrappedValue = unwrapValue(wrappedValue); - if (unwrappedValue == null) { - logger.debug("Skipping cookie because starting quotes are not properly balanced in '{}'", - wrappedValue); - return null; - } - - final String name = header.substring(nameBegin, nameEnd); - - int invalidOctetPos; - if (strict && (invalidOctetPos = firstInvalidCookieNameOctet(name)) >= 0) { - if (logger.isDebugEnabled()) { - logger.debug("Skipping cookie because name '{}' contains invalid char '{}'", - name, name.charAt(invalidOctetPos)); - } - return null; - } - - final boolean wrap = unwrappedValue.length() != valueEnd - valueBegin; - - if (strict && (invalidOctetPos = firstInvalidCookieValueOctet(unwrappedValue)) >= 0) { - if (logger.isDebugEnabled()) { - logger.debug("Skipping cookie because value '{}' contains invalid char '{}'", - unwrappedValue, unwrappedValue.charAt(invalidOctetPos)); - } - return null; - } - - DefaultCookie cookie = new DefaultCookie(name, unwrappedValue.toString()); - cookie.setWrap(wrap); - return cookie; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/CookieEncoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/CookieEncoder.java deleted file mode 100755 index 779cb0422b..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/CookieEncoder.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.cookie; - -import static com.ai.cloud.io.netty.handler.codec.http.cookie.CookieUtil.firstInvalidCookieNameOctet; -import static com.ai.cloud.io.netty.handler.codec.http.cookie.CookieUtil.firstInvalidCookieValueOctet; -import static com.ai.cloud.io.netty.handler.codec.http.cookie.CookieUtil.unwrapValue; - -/** - * Parent of Client and Server side cookie encoders - */ -public abstract class CookieEncoder { - - private final boolean strict; - - protected CookieEncoder(boolean strict) { - this.strict = strict; - } - - protected void validateCookie(String name, String value) { - if (strict) { - int pos; - - if ((pos = firstInvalidCookieNameOctet(name)) >= 0) { - throw new IllegalArgumentException("Cookie name contains an invalid char: " + name.charAt(pos)); - } - - CharSequence unwrappedValue = unwrapValue(value); - if (unwrappedValue == null) { - throw new IllegalArgumentException("Cookie value wrapping quotes are not balanced: " + value); - } - - if ((pos = firstInvalidCookieValueOctet(unwrappedValue)) >= 0) { - throw new IllegalArgumentException("Cookie value contains an invalid char: " + value.charAt(pos)); - } - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/CookieHeaderNames.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/CookieHeaderNames.java deleted file mode 100755 index 4dba13b389..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/CookieHeaderNames.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.cookie; - -public final class CookieHeaderNames { - public static final String PATH = "Path"; - - public static final String EXPIRES = "Expires"; - - public static final String MAX_AGE = "Max-Age"; - - public static final String DOMAIN = "Domain"; - - public static final String SECURE = "Secure"; - - public static final String HTTPONLY = "HTTPOnly"; - - private CookieHeaderNames() { - // Unused. - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/CookieUtil.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/CookieUtil.java deleted file mode 100755 index 261ae44867..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/CookieUtil.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.cookie; - -import java.util.BitSet; - -import com.ai.cloud.io.netty.handler.codec.http.HttpConstants; -import com.ai.cloud.io.netty.util.internal.InternalThreadLocalMap; - -final class CookieUtil { - - private static final BitSet VALID_COOKIE_VALUE_OCTETS = validCookieValueOctets(); - - private static final BitSet VALID_COOKIE_NAME_OCTETS = validCookieNameOctets(VALID_COOKIE_VALUE_OCTETS); - - // US-ASCII characters excluding CTLs, whitespace, DQUOTE, comma, semicolon, and backslash - private static BitSet validCookieValueOctets() { - BitSet bits = new BitSet(8); - for (int i = 35; i < 127; i++) { - // US-ASCII characters excluding CTLs (%x00-1F / %x7F) - bits.set(i); - } - bits.set('"', false); // exclude DQUOTE = %x22 - bits.set(',', false); // exclude comma = %x2C - bits.set(';', false); // exclude semicolon = %x3B - bits.set('\\', false); // exclude backslash = %x5C - return bits; - } - - // token = 1* - // separators = "(" | ")" | "<" | ">" | "@" - // | "," | ";" | ":" | "\" | <"> - // | "/" | "[" | "]" | "?" | "=" - // | "{" | "}" | SP | HT - private static BitSet validCookieNameOctets(BitSet validCookieValueOctets) { - BitSet bits = new BitSet(8); - bits.or(validCookieValueOctets); - bits.set('(', false); - bits.set(')', false); - bits.set('<', false); - bits.set('>', false); - bits.set('@', false); - bits.set(':', false); - bits.set('/', false); - bits.set('[', false); - bits.set(']', false); - bits.set('?', false); - bits.set('=', false); - bits.set('{', false); - bits.set('}', false); - bits.set(' ', false); - bits.set('\t', false); - return bits; - } - - static StringBuilder stringBuilder() { - return InternalThreadLocalMap.get().stringBuilder(); - } - - /** - * @param buf a buffer where some cookies were maybe encoded - * @return the buffer String without the trailing separator, or null if no cookie was appended. - */ - static String stripTrailingSeparatorOrNull(StringBuilder buf) { - return buf.length() == 0 ? null : stripTrailingSeparator(buf); - } - - static String stripTrailingSeparator(StringBuilder buf) { - if (buf.length() > 0) { - buf.setLength(buf.length() - 2); - } - return buf.toString(); - } - - static void add(StringBuilder sb, String name, long val) { - sb.append(name); - sb.append((char) HttpConstants.EQUALS); - sb.append(val); - sb.append((char) HttpConstants.SEMICOLON); - sb.append((char) HttpConstants.SP); - } - - static void add(StringBuilder sb, String name, String val) { - sb.append(name); - sb.append((char) HttpConstants.EQUALS); - sb.append(val); - sb.append((char) HttpConstants.SEMICOLON); - sb.append((char) HttpConstants.SP); - } - - static void add(StringBuilder sb, String name) { - sb.append(name); - sb.append((char) HttpConstants.SEMICOLON); - sb.append((char) HttpConstants.SP); - } - - static void addQuoted(StringBuilder sb, String name, String val) { - if (val == null) { - val = ""; - } - - sb.append(name); - sb.append((char) HttpConstants.EQUALS); - sb.append((char) HttpConstants.DOUBLE_QUOTE); - sb.append(val); - sb.append((char) HttpConstants.DOUBLE_QUOTE); - sb.append((char) HttpConstants.SEMICOLON); - sb.append((char) HttpConstants.SP); - } - - static int firstInvalidCookieNameOctet(CharSequence cs) { - return firstInvalidOctet(cs, VALID_COOKIE_NAME_OCTETS); - } - - static int firstInvalidCookieValueOctet(CharSequence cs) { - return firstInvalidOctet(cs, VALID_COOKIE_VALUE_OCTETS); - } - - static int firstInvalidOctet(CharSequence cs, BitSet bits) { - for (int i = 0; i < cs.length(); i++) { - char c = cs.charAt(i); - if (!bits.get(c)) { - return i; - } - } - return -1; - } - - static CharSequence unwrapValue(CharSequence cs) { - final int len = cs.length(); - if (len > 0 && cs.charAt(0) == '"') { - if (len >= 2 && cs.charAt(len - 1) == '"') { - // properly balanced - return len == 2 ? "" : cs.subSequence(1, len - 1); - } else { - return null; - } - } - return cs; - } - - private CookieUtil() { - // Unused - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/DefaultCookie.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/DefaultCookie.java deleted file mode 100755 index 6054d46493..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/DefaultCookie.java +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.cookie; - -import static com.ai.cloud.io.netty.handler.codec.http.cookie.CookieUtil.stringBuilder; -import static com.ai.cloud.io.netty.util.internal.ObjectUtil.checkNotNull; - -/** - * The default {@link Cookie} implementation. - */ -public class DefaultCookie implements Cookie { - - private final String name; - private String value; - private boolean wrap; - private String domain; - private String path; - private long maxAge = Long.MIN_VALUE; - private boolean secure; - private boolean httpOnly; - - /** - * Creates a new cookie with the specified name and value. - */ - public DefaultCookie(String name, String value) { - name = checkNotNull(name, "name").trim(); - if (name.isEmpty()) { - throw new IllegalArgumentException("empty name"); - } - - for (int i = 0; i < name.length(); i ++) { - char c = name.charAt(i); - if (c > 127) { - throw new IllegalArgumentException( - "name contains non-ascii character: " + name); - } - - // Check prohibited characters. - switch (c) { - case '\t': case '\n': case 0x0b: case '\f': case '\r': - case ' ': case ',': case ';': case '=': - throw new IllegalArgumentException( - "name contains one of the following prohibited characters: " + - "=,; \\t\\r\\n\\v\\f: " + name); - } - } - - if (name.charAt(0) == '$') { - throw new IllegalArgumentException("name starting with '$' not allowed: " + name); - } - - this.name = name; - setValue(value); - } - - @Override - public String name() { - return name; - } - - @Override - public String value() { - return value; - } - - @Override - public void setValue(String value) { - this.value = checkNotNull(value, "value"); - } - - @Override - public boolean wrap() { - return wrap; - } - - @Override - public void setWrap(boolean wrap) { - this.wrap = wrap; - } - - @Override - public String domain() { - return domain; - } - - @Override - public void setDomain(String domain) { - this.domain = validateValue("domain", domain); - } - - @Override - public String path() { - return path; - } - - @Override - public void setPath(String path) { - this.path = validateValue("path", path); - } - - @Override - public long maxAge() { - return maxAge; - } - - @Override - public void setMaxAge(long maxAge) { - this.maxAge = maxAge; - } - - @Override - public boolean isSecure() { - return secure; - } - - @Override - public void setSecure(boolean secure) { - this.secure = secure; - } - - @Override - public boolean isHttpOnly() { - return httpOnly; - } - - @Override - public void setHttpOnly(boolean httpOnly) { - this.httpOnly = httpOnly; - } - - @Override - public int hashCode() { - return name().hashCode(); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - - if (!(o instanceof Cookie)) { - return false; - } - - Cookie that = (Cookie) o; - if (!name().equalsIgnoreCase(that.name())) { - return false; - } - - if (path() == null) { - if (that.path() != null) { - return false; - } - } else if (that.path() == null) { - return false; - } else if (!path().equals(that.path())) { - return false; - } - - if (domain() == null) { - if (that.domain() != null) { - return false; - } - } else if (that.domain() == null) { - return false; - } else { - return domain().equalsIgnoreCase(that.domain()); - } - - return true; - } - - @Override - public int compareTo(Cookie c) { - int v = name().compareToIgnoreCase(c.name()); - if (v != 0) { - return v; - } - - if (path() == null) { - if (c.path() != null) { - return -1; - } - } else if (c.path() == null) { - return 1; - } else { - v = path().compareTo(c.path()); - if (v != 0) { - return v; - } - } - - if (domain() == null) { - if (c.domain() != null) { - return -1; - } - } else if (c.domain() == null) { - return 1; - } else { - v = domain().compareToIgnoreCase(c.domain()); - return v; - } - - return 0; - } - - @Override - public String toString() { - StringBuilder buf = stringBuilder() - .append(name()) - .append('=') - .append(value()); - if (domain() != null) { - buf.append(", domain=") - .append(domain()); - } - if (path() != null) { - buf.append(", path=") - .append(path()); - } - if (maxAge() >= 0) { - buf.append(", maxAge=") - .append(maxAge()) - .append('s'); - } - if (isSecure()) { - buf.append(", secure"); - } - if (isHttpOnly()) { - buf.append(", HTTPOnly"); - } - return buf.toString(); - } - - protected String validateValue(String name, String value) { - if (value == null) { - return null; - } - value = value.trim(); - if (value.isEmpty()) { - return null; - } - for (int i = 0; i < value.length(); i ++) { - char c = value.charAt(i); - switch (c) { - case '\r': case '\n': case '\f': case 0x0b: case ';': - throw new IllegalArgumentException( - name + " contains one of the following prohibited characters: " + - ";\\r\\n\\f\\v (" + value + ')'); - } - } - return value; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/ServerCookieDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/ServerCookieDecoder.java deleted file mode 100755 index 10a47365b8..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/ServerCookieDecoder.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.cookie; - -import static com.ai.cloud.io.netty.util.internal.ObjectUtil.checkNotNull; - -import java.util.Collections; -import java.util.Set; -import java.util.TreeSet; - -/** - * A RFC6265 compliant cookie decoder to be used server side. - * - * Only name and value fields are expected, so old fields are not populated (path, domain, etc). - * - * Old RFC2965 cookies are still supported, - * old fields will simply be ignored. - * - * @see ServerCookieEncoder - */ -public final class ServerCookieDecoder extends CookieDecoder { - - private static final String RFC2965_VERSION = "$Version"; - - private static final String RFC2965_PATH = "$" + CookieHeaderNames.PATH; - - private static final String RFC2965_DOMAIN = "$" + CookieHeaderNames.DOMAIN; - - private static final String RFC2965_PORT = "$Port"; - - /** - * Strict encoder that validates that name and value chars are in the valid scope - * defined in RFC6265 - */ - public static final ServerCookieDecoder STRICT = new ServerCookieDecoder(true); - - /** - * Lax instance that doesn't validate name and value - */ - public static final ServerCookieDecoder LAX = new ServerCookieDecoder(false); - - private ServerCookieDecoder(boolean strict) { - super(strict); - } - - /** - * Decodes the specified Set-Cookie HTTP header value into a {@link Cookie}. - * - * @return the decoded {@link Cookie} - */ - public Set decode(String header) { - final int headerLen = checkNotNull(header, "header").length(); - - if (headerLen == 0) { - return Collections.emptySet(); - } - - Set cookies = new TreeSet(); - - int i = 0; - - boolean rfc2965Style = false; - if (header.regionMatches(true, 0, RFC2965_VERSION, 0, RFC2965_VERSION.length())) { - // RFC 2965 style cookie, move to after version value - i = header.indexOf(';') + 1; - rfc2965Style = true; - } - - loop: for (;;) { - - // Skip spaces and separators. - for (;;) { - if (i == headerLen) { - break loop; - } - char c = header.charAt(i); - if (c == '\t' || c == '\n' || c == 0x0b || c == '\f' - || c == '\r' || c == ' ' || c == ',' || c == ';') { - i++; - continue; - } - break; - } - - int nameBegin = i; - int nameEnd = i; - int valueBegin = -1; - int valueEnd = -1; - - if (i != headerLen) { - keyValLoop: for (;;) { - - char curChar = header.charAt(i); - if (curChar == ';') { - // NAME; (no value till ';') - nameEnd = i; - valueBegin = valueEnd = -1; - break keyValLoop; - - } else if (curChar == '=') { - // NAME=VALUE - nameEnd = i; - i++; - if (i == headerLen) { - // NAME= (empty value, i.e. nothing after '=') - valueBegin = valueEnd = 0; - break keyValLoop; - } - - valueBegin = i; - // NAME=VALUE; - int semiPos = header.indexOf(';', i); - valueEnd = i = semiPos > 0 ? semiPos : headerLen; - break keyValLoop; - } else { - i++; - } - - if (i == headerLen) { - // NAME (no value till the end of string) - nameEnd = headerLen; - valueBegin = valueEnd = -1; - break; - } - } - } - - if (rfc2965Style && (header.regionMatches(nameBegin, RFC2965_PATH, 0, RFC2965_PATH.length()) || - header.regionMatches(nameBegin, RFC2965_DOMAIN, 0, RFC2965_DOMAIN.length()) || - header.regionMatches(nameBegin, RFC2965_PORT, 0, RFC2965_PORT.length()))) { - - // skip obsolete RFC2965 fields - continue; - } - - DefaultCookie cookie = initCookie(header, nameBegin, nameEnd, valueBegin, valueEnd); - if (cookie != null) { - cookies.add(cookie); - } - } - - return cookies; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/ServerCookieEncoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/ServerCookieEncoder.java deleted file mode 100755 index 56f8d2a1e7..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/ServerCookieEncoder.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.cookie; - -import static com.ai.cloud.io.netty.handler.codec.http.cookie.CookieUtil.*; -import static com.ai.cloud.io.netty.util.internal.ObjectUtil.checkNotNull; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.List; - -import com.ai.cloud.io.netty.handler.codec.http.HttpHeaderDateFormat; -import com.ai.cloud.io.netty.handler.codec.http.HttpRequest; - -/** - * A RFC6265 compliant cookie encoder to be used server side, - * so some fields are sent (Version is typically ignored). - * - * As Netty's Cookie merges Expires and MaxAge into one single field, only Max-Age field is sent. - * - * Note that multiple cookies are supposed to be sent at once in a single "Set-Cookie" header. - * - *
- * // Example
- * {@link HttpRequest} req = ...;
- * res.setHeader("Cookie", {@link ServerCookieEncoder}.encode("JSESSIONID", "1234"));
- * 
- * - * @see ServerCookieDecoder - */ -public final class ServerCookieEncoder extends CookieEncoder { - - /** - * Strict encoder that validates that name and value chars are in the valid scope - * defined in RFC6265 - */ - public static final ServerCookieEncoder STRICT = new ServerCookieEncoder(true); - - /** - * Lax instance that doesn't validate name and value - */ - public static final ServerCookieEncoder LAX = new ServerCookieEncoder(false); - - private ServerCookieEncoder(boolean strict) { - super(strict); - } - - /** - * Encodes the specified cookie name-value pair into a Set-Cookie header value. - * - * @param name the cookie name - * @param value the cookie value - * @return a single Set-Cookie header value - */ - public String encode(String name, String value) { - return encode(new DefaultCookie(name, value)); - } - - /** - * Encodes the specified cookie into a Set-Cookie header value. - * - * @param cookie the cookie - * @return a single Set-Cookie header value - */ - public String encode(Cookie cookie) { - final String name = checkNotNull(cookie, "cookie").name(); - final String value = cookie.value() != null ? cookie.value() : ""; - - validateCookie(name, value); - - StringBuilder buf = stringBuilder(); - - if (cookie.wrap()) { - addQuoted(buf, name, value); - } else { - add(buf, name, value); - } - - if (cookie.maxAge() != Long.MIN_VALUE) { - add(buf, CookieHeaderNames.MAX_AGE, cookie.maxAge()); - Date expires = new Date(cookie.maxAge() * 1000 + System.currentTimeMillis()); - add(buf, CookieHeaderNames.EXPIRES, HttpHeaderDateFormat.get().format(expires)); - } - - if (cookie.path() != null) { - add(buf, CookieHeaderNames.PATH, cookie.path()); - } - - if (cookie.domain() != null) { - add(buf, CookieHeaderNames.DOMAIN, cookie.domain()); - } - if (cookie.isSecure()) { - add(buf, CookieHeaderNames.SECURE); - } - if (cookie.isHttpOnly()) { - add(buf, CookieHeaderNames.HTTPONLY); - } - - return stripTrailingSeparator(buf); - } - - /** - * Batch encodes cookies into Set-Cookie header values. - * - * @param cookies a bunch of cookies - * @return the corresponding bunch of Set-Cookie headers - */ - public List encode(Cookie... cookies) { - if (checkNotNull(cookies, "cookies").length == 0) { - return Collections.emptyList(); - } - - List encoded = new ArrayList(cookies.length); - for (Cookie c : cookies) { - if (c == null) { - break; - } - encoded.add(encode(c)); - } - return encoded; - } - - /** - * Batch encodes cookies into Set-Cookie header values. - * - * @param cookies a bunch of cookies - * @return the corresponding bunch of Set-Cookie headers - */ - public List encode(Collection cookies) { - if (checkNotNull(cookies, "cookies").isEmpty()) { - return Collections.emptyList(); - } - - List encoded = new ArrayList(cookies.size()); - for (Cookie c : cookies) { - if (c == null) { - break; - } - encoded.add(encode(c)); - } - return encoded; - } - - /** - * Batch encodes cookies into Set-Cookie header values. - * - * @param cookies a bunch of cookies - * @return the corresponding bunch of Set-Cookie headers - */ - public List encode(Iterable cookies) { - if (!checkNotNull(cookies, "cookies").iterator().hasNext()) { - return Collections.emptyList(); - } - - List encoded = new ArrayList(); - for (Cookie c : cookies) { - if (c == null) { - break; - } - encoded.add(encode(c)); - } - return encoded; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/package-info.java deleted file mode 100755 index 13d02110e9..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cookie/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * This package contains Cookie related classes. - */ -package com.ai.cloud.io.netty.handler.codec.http.cookie; diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cors/CorsConfig.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cors/CorsConfig.java deleted file mode 100755 index 3f6ed624a2..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cors/CorsConfig.java +++ /dev/null @@ -1,575 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, version - * 2.0 (the "License"); you may not use this file except in compliance with the - * License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.cors; - -import java.util.Arrays; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.concurrent.Callable; - -import com.ai.cloud.io.netty.handler.codec.http.DefaultHttpHeaders; -import com.ai.cloud.io.netty.handler.codec.http.HttpHeaders; -import com.ai.cloud.io.netty.handler.codec.http.HttpMethod; -import com.ai.cloud.io.netty.handler.codec.http.HttpHeaders.Names; -import com.ai.cloud.io.netty.util.internal.StringUtil; - -/** - * Configuration for Cross-Origin Resource Sharing (CORS). - */ -public final class CorsConfig { - - private final Set origins; - private final boolean anyOrigin; - private final boolean enabled; - private final Set exposeHeaders; - private final boolean allowCredentials; - private final long maxAge; - private final Set allowedRequestMethods; - private final Set allowedRequestHeaders; - private final boolean allowNullOrigin; - private final Map> preflightHeaders; - private final boolean shortCurcuit; - - private CorsConfig(final Builder builder) { - origins = new LinkedHashSet(builder.origins); - anyOrigin = builder.anyOrigin; - enabled = builder.enabled; - exposeHeaders = builder.exposeHeaders; - allowCredentials = builder.allowCredentials; - maxAge = builder.maxAge; - allowedRequestMethods = builder.requestMethods; - allowedRequestHeaders = builder.requestHeaders; - allowNullOrigin = builder.allowNullOrigin; - preflightHeaders = builder.preflightHeaders; - shortCurcuit = builder.shortCurcuit; - } - - /** - * Determines if support for CORS is enabled. - * - * @return {@code true} if support for CORS is enabled, false otherwise. - */ - public boolean isCorsSupportEnabled() { - return enabled; - } - - /** - * Determines whether a wildcard origin, '*', is supported. - * - * @return {@code boolean} true if any origin is allowed. - */ - public boolean isAnyOriginSupported() { - return anyOrigin; - } - - /** - * Returns the allowed origin. This can either be a wildcard or an origin value. - * - * @return the value that will be used for the CORS response header 'Access-Control-Allow-Origin' - */ - public String origin() { - return origins.isEmpty() ? "*" : origins.iterator().next(); - } - - /** - * Returns the set of allowed origins. - * - * @return {@code Set} the allowed origins. - */ - public Set origins() { - return origins; - } - - /** - * Web browsers may set the 'Origin' request header to 'null' if a resource is loaded - * from the local file system. - * - * If isNullOriginAllowed is true then the server will response with the wildcard for the - * the CORS response header 'Access-Control-Allow-Origin'. - * - * @return {@code true} if a 'null' origin should be supported. - */ - public boolean isNullOriginAllowed() { - return allowNullOrigin; - } - - /** - * Returns a set of headers to be exposed to calling clients. - * - * During a simple CORS request only certain response headers are made available by the - * browser, for example using: - *
-     * xhr.getResponseHeader("Content-Type");
-     * 
- * The headers that are available by default are: - *
    - *
  • Cache-Control
  • - *
  • Content-Language
  • - *
  • Content-Type
  • - *
  • Expires
  • - *
  • Last-Modified
  • - *
  • Pragma
  • - *
- * To expose other headers they need to be specified, which is what this method enables by - * adding the headers names to the CORS 'Access-Control-Expose-Headers' response header. - * - * @return {@code List} a list of the headers to expose. - */ - public Set exposedHeaders() { - return Collections.unmodifiableSet(exposeHeaders); - } - - /** - * Determines if cookies are supported for CORS requests. - * - * By default cookies are not included in CORS requests but if isCredentialsAllowed returns - * true cookies will be added to CORS requests. Setting this value to true will set the - * CORS 'Access-Control-Allow-Credentials' response header to true. - * - * Please note that cookie support needs to be enabled on the client side as well. - * The client needs to opt-in to send cookies by calling: - *
-     * xhr.withCredentials = true;
-     * 
- * The default value for 'withCredentials' is false in which case no cookies are sent. - * Settning this to true will included cookies in cross origin requests. - * - * @return {@code true} if cookies are supported. - */ - public boolean isCredentialsAllowed() { - return allowCredentials; - } - - /** - * Gets the maxAge setting. - * - * When making a preflight request the client has to perform two request with can be inefficient. - * This setting will set the CORS 'Access-Control-Max-Age' response header and enables the - * caching of the preflight response for the specified time. During this time no preflight - * request will be made. - * - * @return {@code long} the time in seconds that a preflight request may be cached. - */ - public long maxAge() { - return maxAge; - } - - /** - * Returns the allowed set of Request Methods. The Http methods that should be returned in the - * CORS 'Access-Control-Request-Method' response header. - * - * @return {@code Set} of {@link HttpMethod}s that represent the allowed Request Methods. - */ - public Set allowedRequestMethods() { - return Collections.unmodifiableSet(allowedRequestMethods); - } - - /** - * Returns the allowed set of Request Headers. - * - * The header names returned from this method will be used to set the CORS - * 'Access-Control-Allow-Headers' response header. - * - * @return {@code Set} of strings that represent the allowed Request Headers. - */ - public Set allowedRequestHeaders() { - return Collections.unmodifiableSet(allowedRequestHeaders); - } - - /** - * Returns HTTP response headers that should be added to a CORS preflight response. - * - * @return {@link HttpHeaders} the HTTP response headers to be added. - */ - public HttpHeaders preflightResponseHeaders() { - if (preflightHeaders.isEmpty()) { - return HttpHeaders.EMPTY_HEADERS; - } - final HttpHeaders preflightHeaders = new DefaultHttpHeaders(); - for (Entry> entry : this.preflightHeaders.entrySet()) { - final Object value = getValue(entry.getValue()); - if (value instanceof Iterable) { - preflightHeaders.add(entry.getKey(), (Iterable) value); - } else { - preflightHeaders.add(entry.getKey(), value); - } - } - return preflightHeaders; - } - - /** - * Determines whether a CORS request should be rejected if it's invalid before being - * further processing. - * - * CORS headers are set after a request is processed. This may not always be desired - * and this setting will check that the Origin is valid and if it is not valid no - * further processing will take place, and a error will be returned to the calling client. - * - * @return {@code true} if a CORS request should short-curcuit upon receiving an invalid Origin header. - */ - public boolean isShortCurcuit() { - return shortCurcuit; - } - - private static T getValue(final Callable callable) { - try { - return callable.call(); - } catch (final Exception e) { - throw new IllegalStateException("Could not generate value for callable [" + callable + ']', e); - } - } - - @Override - public String toString() { - return StringUtil.simpleClassName(this) + "[enabled=" + enabled + - ", origins=" + origins + - ", anyOrigin=" + anyOrigin + - ", exposedHeaders=" + exposeHeaders + - ", isCredentialsAllowed=" + allowCredentials + - ", maxAge=" + maxAge + - ", allowedRequestMethods=" + allowedRequestMethods + - ", allowedRequestHeaders=" + allowedRequestHeaders + - ", preflightHeaders=" + preflightHeaders + ']'; - } - - /** - * Creates a Builder instance with it's origin set to '*'. - * - * @return Builder to support method chaining. - */ - public static Builder withAnyOrigin() { - return new Builder(); - } - - /** - * Creates a {@link Builder} instance with the specified origin. - * - * @return {@link Builder} to support method chaining. - */ - public static Builder withOrigin(final String origin) { - if ("*".equals(origin)) { - return new Builder(); - } - return new Builder(origin); - } - - /** - * Creates a {@link Builder} instance with the specified origins. - * - * @return {@link Builder} to support method chaining. - */ - public static Builder withOrigins(final String... origins) { - return new Builder(origins); - } - - /** - * Builder used to configure and build a CorsConfig instance. - */ - public static class Builder { - - private final Set origins; - private final boolean anyOrigin; - private boolean allowNullOrigin; - private boolean enabled = true; - private boolean allowCredentials; - private final Set exposeHeaders = new HashSet(); - private long maxAge; - private final Set requestMethods = new HashSet(); - private final Set requestHeaders = new HashSet(); - private final Map> preflightHeaders = new HashMap>(); - private boolean noPreflightHeaders; - private boolean shortCurcuit; - - /** - * Creates a new Builder instance with the origin passed in. - * - * @param origins the origin to be used for this builder. - */ - public Builder(final String... origins) { - this.origins = new LinkedHashSet(Arrays.asList(origins)); - anyOrigin = false; - } - - /** - * Creates a new Builder instance allowing any origin, "*" which is the - * wildcard origin. - * - */ - public Builder() { - anyOrigin = true; - origins = Collections.emptySet(); - } - - /** - * Web browsers may set the 'Origin' request header to 'null' if a resource is loaded - * from the local file system. Calling this method will enable a successful CORS response - * with a wildcard for the the CORS response header 'Access-Control-Allow-Origin'. - * - * @return {@link Builder} to support method chaining. - */ - public Builder allowNullOrigin() { - allowNullOrigin = true; - return this; - } - - /** - * Disables CORS support. - * - * @return {@link Builder} to support method chaining. - */ - public Builder disable() { - enabled = false; - return this; - } - - /** - * Specifies the headers to be exposed to calling clients. - * - * During a simple CORS request, only certain response headers are made available by the - * browser, for example using: - *
-         * xhr.getResponseHeader("Content-Type");
-         * 
- * - * The headers that are available by default are: - *
    - *
  • Cache-Control
  • - *
  • Content-Language
  • - *
  • Content-Type
  • - *
  • Expires
  • - *
  • Last-Modified
  • - *
  • Pragma
  • - *
- * - * To expose other headers they need to be specified which is what this method enables by - * adding the headers to the CORS 'Access-Control-Expose-Headers' response header. - * - * @param headers the values to be added to the 'Access-Control-Expose-Headers' response header - * @return {@link Builder} to support method chaining. - */ - public Builder exposeHeaders(final String... headers) { - exposeHeaders.addAll(Arrays.asList(headers)); - return this; - } - - /** - * By default cookies are not included in CORS requests, but this method will enable cookies to - * be added to CORS requests. Calling this method will set the CORS 'Access-Control-Allow-Credentials' - * response header to true. - * - * Please note, that cookie support needs to be enabled on the client side as well. - * The client needs to opt-in to send cookies by calling: - *
-         * xhr.withCredentials = true;
-         * 
- * The default value for 'withCredentials' is false in which case no cookies are sent. - * Settning this to true will included cookies in cross origin requests. - * - * @return {@link Builder} to support method chaining. - */ - public Builder allowCredentials() { - allowCredentials = true; - return this; - } - - /** - * When making a preflight request the client has to perform two request with can be inefficient. - * This setting will set the CORS 'Access-Control-Max-Age' response header and enables the - * caching of the preflight response for the specified time. During this time no preflight - * request will be made. - * - * @param max the maximum time, in seconds, that the preflight response may be cached. - * @return {@link Builder} to support method chaining. - */ - public Builder maxAge(final long max) { - maxAge = max; - return this; - } - - /** - * Specifies the allowed set of HTTP Request Methods that should be returned in the - * CORS 'Access-Control-Request-Method' response header. - * - * @param methods the {@link HttpMethod}s that should be allowed. - * @return {@link Builder} to support method chaining. - */ - public Builder allowedRequestMethods(final HttpMethod... methods) { - requestMethods.addAll(Arrays.asList(methods)); - return this; - } - - /** - * Specifies the if headers that should be returned in the CORS 'Access-Control-Allow-Headers' - * response header. - * - * If a client specifies headers on the request, for example by calling: - *
-         * xhr.setRequestHeader('My-Custom-Header', "SomeValue");
-         * 
- * the server will recieve the above header name in the 'Access-Control-Request-Headers' of the - * preflight request. The server will then decide if it allows this header to be sent for the - * real request (remember that a preflight is not the real request but a request asking the server - * if it allow a request). - * - * @param headers the headers to be added to the preflight 'Access-Control-Allow-Headers' response header. - * @return {@link Builder} to support method chaining. - */ - public Builder allowedRequestHeaders(final String... headers) { - requestHeaders.addAll(Arrays.asList(headers)); - return this; - } - - /** - * Returns HTTP response headers that should be added to a CORS preflight response. - * - * An intermediary like a load balancer might require that a CORS preflight request - * have certain headers set. This enables such headers to be added. - * - * @param name the name of the HTTP header. - * @param values the values for the HTTP header. - * @return {@link Builder} to support method chaining. - */ - public Builder preflightResponseHeader(final CharSequence name, final Object... values) { - if (values.length == 1) { - preflightHeaders.put(name, new ConstantValueGenerator(values[0])); - } else { - preflightResponseHeader(name, Arrays.asList(values)); - } - return this; - } - - /** - * Returns HTTP response headers that should be added to a CORS preflight response. - * - * An intermediary like a load balancer might require that a CORS preflight request - * have certain headers set. This enables such headers to be added. - * - * @param name the name of the HTTP header. - * @param value the values for the HTTP header. - * @param the type of values that the Iterable contains. - * @return {@link Builder} to support method chaining. - */ - public Builder preflightResponseHeader(final CharSequence name, final Iterable value) { - preflightHeaders.put(name, new ConstantValueGenerator(value)); - return this; - } - - /** - * Returns HTTP response headers that should be added to a CORS preflight response. - * - * An intermediary like a load balancer might require that a CORS preflight request - * have certain headers set. This enables such headers to be added. - * - * Some values must be dynamically created when the HTTP response is created, for - * example the 'Date' response header. This can be occomplished by using a Callable - * which will have its 'call' method invoked when the HTTP response is created. - * - * @param name the name of the HTTP header. - * @param valueGenerator a Callable which will be invoked at HTTP response creation. - * @param the type of the value that the Callable can return. - * @return {@link Builder} to support method chaining. - */ - public Builder preflightResponseHeader(final String name, final Callable valueGenerator) { - preflightHeaders.put(name, valueGenerator); - return this; - } - - /** - * Specifies that no preflight response headers should be added to a preflight response. - * - * @return {@link Builder} to support method chaining. - */ - public Builder noPreflightResponseHeaders() { - noPreflightHeaders = true; - return this; - } - - /** - * Builds a {@link CorsConfig} with settings specified by previous method calls. - * - * @return {@link CorsConfig} the configured CorsConfig instance. - */ - public CorsConfig build() { - if (preflightHeaders.isEmpty() && !noPreflightHeaders) { - preflightHeaders.put(Names.DATE, new DateValueGenerator()); - preflightHeaders.put(Names.CONTENT_LENGTH, new ConstantValueGenerator("0")); - } - return new CorsConfig(this); - } - - /** - * Specifies that a CORS request should be rejected if it's invalid before being - * further processing. - * - * CORS headers are set after a request is processed. This may not always be desired - * and this setting will check that the Origin is valid and if it is not valid no - * further processing will take place, and a error will be returned to the calling client. - * - * @return {@link Builder} to support method chaining. - */ - public Builder shortCurcuit() { - shortCurcuit = true; - return this; - } - } - - /** - * This class is used for preflight HTTP response values that do not need to be - * generated, but instead the value is "static" in that the same value will be returned - * for each call. - */ - private static final class ConstantValueGenerator implements Callable { - - private final Object value; - - /** - * Sole constructor. - * - * @param value the value that will be returned when the call method is invoked. - */ - private ConstantValueGenerator(final Object value) { - if (value == null) { - throw new IllegalArgumentException("value must not be null"); - } - this.value = value; - } - - @Override - public Object call() { - return value; - } - } - - /** - * This callable is used for the DATE preflight HTTP response HTTP header. - * It's value must be generated when the response is generated, hence will be - * different for every call. - */ - public static final class DateValueGenerator implements Callable { - - @Override - public Date call() throws Exception { - return new Date(); - } - } - -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cors/CorsHandler.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cors/CorsHandler.java deleted file mode 100755 index b15c4726d5..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cors/CorsHandler.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, version - * 2.0 (the "License"); you may not use this file except in compliance with the - * License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.cors; - -import com.ai.cloud.io.netty.channel.ChannelDuplexHandler; -import com.ai.cloud.io.netty.channel.ChannelFutureListener; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelPromise; -import com.ai.cloud.io.netty.handler.codec.http.DefaultFullHttpResponse; -import com.ai.cloud.io.netty.handler.codec.http.HttpHeaders; -import com.ai.cloud.io.netty.handler.codec.http.HttpRequest; -import com.ai.cloud.io.netty.handler.codec.http.HttpResponse; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -import static com.ai.cloud.io.netty.handler.codec.http.HttpHeaders.Names.*; -import static com.ai.cloud.io.netty.handler.codec.http.HttpMethod.*; -import static com.ai.cloud.io.netty.handler.codec.http.HttpResponseStatus.*; -import static com.ai.cloud.io.netty.util.ReferenceCountUtil.release; - -/** - * Handles Cross Origin Resource Sharing (CORS) requests. - *

- * This handler can be configured using a {@link CorsConfig}, please - * refer to this class for details about the configuration options available. - */ -public class CorsHandler extends ChannelDuplexHandler { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(CorsHandler.class); - private static final String ANY_ORIGIN = "*"; - private final CorsConfig config; - - private HttpRequest request; - - public CorsHandler(final CorsConfig config) { - this.config = config; - } - - @Override - public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception { - if (config.isCorsSupportEnabled() && msg instanceof HttpRequest) { - request = (HttpRequest) msg; - if (isPreflightRequest(request)) { - handlePreflight(ctx, request); - return; - } - if (config.isShortCurcuit() && !validateOrigin()) { - forbidden(ctx, request); - return; - } - } - ctx.fireChannelRead(msg); - } - - private void handlePreflight(final ChannelHandlerContext ctx, final HttpRequest request) { - final HttpResponse response = new DefaultFullHttpResponse(request.getProtocolVersion(), OK); - if (setOrigin(response)) { - setAllowMethods(response); - setAllowHeaders(response); - setAllowCredentials(response); - setMaxAge(response); - setPreflightHeaders(response); - } - release(request); - ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); - } - - /** - * This is a non CORS specification feature which enables the setting of preflight - * response headers that might be required by intermediaries. - * - * @param response the HttpResponse to which the preflight response headers should be added. - */ - private void setPreflightHeaders(final HttpResponse response) { - response.headers().add(config.preflightResponseHeaders()); - } - - private boolean setOrigin(final HttpResponse response) { - final String origin = request.headers().get(ORIGIN); - if (origin != null) { - if ("null".equals(origin) && config.isNullOriginAllowed()) { - setAnyOrigin(response); - return true; - } - if (config.isAnyOriginSupported()) { - if (config.isCredentialsAllowed()) { - echoRequestOrigin(response); - setVaryHeader(response); - } else { - setAnyOrigin(response); - } - return true; - } - if (config.origins().contains(origin)) { - setOrigin(response, origin); - setVaryHeader(response); - return true; - } - logger.debug("Request origin [" + origin + "] was not among the configured origins " + config.origins()); - } - return false; - } - - private boolean validateOrigin() { - if (config.isAnyOriginSupported()) { - return true; - } - - final String origin = request.headers().get(ORIGIN); - if (origin == null) { - // Not a CORS request so we cannot validate it. It may be a non CORS request. - return true; - } - - if ("null".equals(origin) && config.isNullOriginAllowed()) { - return true; - } - - return config.origins().contains(origin); - } - - private void echoRequestOrigin(final HttpResponse response) { - setOrigin(response, request.headers().get(ORIGIN)); - } - - private static void setVaryHeader(final HttpResponse response) { - response.headers().set(VARY, ORIGIN); - } - - private static void setAnyOrigin(final HttpResponse response) { - setOrigin(response, ANY_ORIGIN); - } - - private static void setOrigin(final HttpResponse response, final String origin) { - response.headers().set(ACCESS_CONTROL_ALLOW_ORIGIN, origin); - } - - private void setAllowCredentials(final HttpResponse response) { - if (config.isCredentialsAllowed() - && !response.headers().get(ACCESS_CONTROL_ALLOW_ORIGIN).equals(ANY_ORIGIN)) { - response.headers().set(ACCESS_CONTROL_ALLOW_CREDENTIALS, "true"); - } - } - - private static boolean isPreflightRequest(final HttpRequest request) { - final HttpHeaders headers = request.headers(); - return request.getMethod().equals(OPTIONS) && - headers.contains(ORIGIN) && - headers.contains(ACCESS_CONTROL_REQUEST_METHOD); - } - - private void setExposeHeaders(final HttpResponse response) { - if (!config.exposedHeaders().isEmpty()) { - response.headers().set(ACCESS_CONTROL_EXPOSE_HEADERS, config.exposedHeaders()); - } - } - - private void setAllowMethods(final HttpResponse response) { - response.headers().set(ACCESS_CONTROL_ALLOW_METHODS, config.allowedRequestMethods()); - } - - private void setAllowHeaders(final HttpResponse response) { - response.headers().set(ACCESS_CONTROL_ALLOW_HEADERS, config.allowedRequestHeaders()); - } - - private void setMaxAge(final HttpResponse response) { - response.headers().set(ACCESS_CONTROL_MAX_AGE, config.maxAge()); - } - - @Override - public void write(final ChannelHandlerContext ctx, final Object msg, final ChannelPromise promise) - throws Exception { - if (config.isCorsSupportEnabled() && msg instanceof HttpResponse) { - final HttpResponse response = (HttpResponse) msg; - if (setOrigin(response)) { - setAllowCredentials(response); - setAllowHeaders(response); - setExposeHeaders(response); - } - } - ctx.writeAndFlush(msg, promise); - } - - @Override - public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) throws Exception { - logger.error("Caught error in CorsHandler", cause); - ctx.fireExceptionCaught(cause); - } - - private static void forbidden(final ChannelHandlerContext ctx, final HttpRequest request) { - ctx.writeAndFlush(new DefaultFullHttpResponse(request.getProtocolVersion(), FORBIDDEN)) - .addListener(ChannelFutureListener.CLOSE); - release(request); - } -} - diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cors/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cors/package-info.java deleted file mode 100755 index 2fd7855d22..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/cors/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * This package contains Cross Origin Resource Sharing (CORS) related classes. - */ -package com.ai.cloud.io.netty.handler.codec.http.cors; diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/AbstractDiskHttpData.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/AbstractDiskHttpData.java deleted file mode 100755 index 7fdec730ee..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/AbstractDiskHttpData.java +++ /dev/null @@ -1,424 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.multipart; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.nio.charset.Charset; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.handler.codec.http.HttpConstants; -import com.ai.cloud.io.netty.util.internal.EmptyArrays; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -import static com.ai.cloud.io.netty.buffer.Unpooled.*; - -/** - * Abstract Disk HttpData implementation - */ -public abstract class AbstractDiskHttpData extends AbstractHttpData { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(AbstractDiskHttpData.class); - - protected File file; - private boolean isRenamed; - private FileChannel fileChannel; - - protected AbstractDiskHttpData(String name, Charset charset, long size) { - super(name, charset, size); - } - - /** - * - * @return the real DiskFilename (basename) - */ - protected abstract String getDiskFilename(); - /** - * - * @return the default prefix - */ - protected abstract String getPrefix(); - /** - * - * @return the default base Directory - */ - protected abstract String getBaseDirectory(); - /** - * - * @return the default postfix - */ - protected abstract String getPostfix(); - /** - * - * @return True if the file should be deleted on Exit by default - */ - protected abstract boolean deleteOnExit(); - - /** - * @return a new Temp File from getDiskFilename(), default prefix, postfix and baseDirectory - */ - private File tempFile() throws IOException { - String newpostfix; - String diskFilename = getDiskFilename(); - if (diskFilename != null) { - newpostfix = '_' + diskFilename; - } else { - newpostfix = getPostfix(); - } - File tmpFile; - if (getBaseDirectory() == null) { - // create a temporary file - tmpFile = File.createTempFile(getPrefix(), newpostfix); - } else { - tmpFile = File.createTempFile(getPrefix(), newpostfix, new File( - getBaseDirectory())); - } - if (deleteOnExit()) { - tmpFile.deleteOnExit(); - } - return tmpFile; - } - - @Override - public void setContent(ByteBuf buffer) throws IOException { - if (buffer == null) { - throw new NullPointerException("buffer"); - } - try { - size = buffer.readableBytes(); - if (definedSize > 0 && definedSize < size) { - throw new IOException("Out of size: " + size + " > " + definedSize); - } - if (file == null) { - file = tempFile(); - } - if (buffer.readableBytes() == 0) { - // empty file - file.createNewFile(); - return; - } - FileOutputStream outputStream = new FileOutputStream(file); - try { - FileChannel localfileChannel = outputStream.getChannel(); - ByteBuffer byteBuffer = buffer.nioBuffer(); - int written = 0; - while (written < size) { - written += localfileChannel.write(byteBuffer); - } - buffer.readerIndex(buffer.readerIndex() + written); - localfileChannel.force(false); - } finally { - outputStream.close(); - } - completed = true; - } finally { - // Release the buffer as it was retained before and we not need a reference to it at all - // See https://github.com/netty/netty/issues/1516 - buffer.release(); - } - } - - @Override - public void addContent(ByteBuf buffer, boolean last) - throws IOException { - if (buffer != null) { - try { - int localsize = buffer.readableBytes(); - if (definedSize > 0 && definedSize < size + localsize) { - throw new IOException("Out of size: " + (size + localsize) + - " > " + definedSize); - } - ByteBuffer byteBuffer = buffer.nioBufferCount() == 1 ? buffer.nioBuffer() : buffer.copy().nioBuffer(); - int written = 0; - if (file == null) { - file = tempFile(); - } - if (fileChannel == null) { - FileOutputStream outputStream = new FileOutputStream(file); - fileChannel = outputStream.getChannel(); - } - while (written < localsize) { - written += fileChannel.write(byteBuffer); - } - size += localsize; - buffer.readerIndex(buffer.readerIndex() + written); - } finally { - // Release the buffer as it was retained before and we not need a reference to it at all - // See https://github.com/netty/netty/issues/1516 - buffer.release(); - } - } - if (last) { - if (file == null) { - file = tempFile(); - } - if (fileChannel == null) { - FileOutputStream outputStream = new FileOutputStream(file); - fileChannel = outputStream.getChannel(); - } - fileChannel.force(false); - fileChannel.close(); - fileChannel = null; - completed = true; - } else { - if (buffer == null) { - throw new NullPointerException("buffer"); - } - } - } - - @Override - public void setContent(File file) throws IOException { - if (this.file != null) { - delete(); - } - this.file = file; - size = file.length(); - isRenamed = true; - completed = true; - } - - @Override - public void setContent(InputStream inputStream) throws IOException { - if (inputStream == null) { - throw new NullPointerException("inputStream"); - } - if (file != null) { - delete(); - } - file = tempFile(); - FileOutputStream outputStream = new FileOutputStream(file); - int written = 0; - try { - FileChannel localfileChannel = outputStream.getChannel(); - byte[] bytes = new byte[4096 * 4]; - ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); - int read = inputStream.read(bytes); - while (read > 0) { - byteBuffer.position(read).flip(); - written += localfileChannel.write(byteBuffer); - read = inputStream.read(bytes); - } - localfileChannel.force(false); - } finally { - outputStream.close(); - } - size = written; - if (definedSize > 0 && definedSize < size) { - file.delete(); - file = null; - throw new IOException("Out of size: " + size + " > " + definedSize); - } - isRenamed = true; - completed = true; - } - - @Override - public void delete() { - if (fileChannel != null) { - try { - fileChannel.force(false); - fileChannel.close(); - } catch (IOException e) { - logger.warn("Failed to close a file.", e); - } - fileChannel = null; - } - if (! isRenamed) { - if (file != null && file.exists()) { - file.delete(); - } - file = null; - } - } - - @Override - public byte[] get() throws IOException { - if (file == null) { - return EmptyArrays.EMPTY_BYTES; - } - return readFrom(file); - } - - @Override - public ByteBuf getByteBuf() throws IOException { - if (file == null) { - return EMPTY_BUFFER; - } - byte[] array = readFrom(file); - return wrappedBuffer(array); - } - - @Override - public ByteBuf getChunk(int length) throws IOException { - if (file == null || length == 0) { - return EMPTY_BUFFER; - } - if (fileChannel == null) { - FileInputStream inputStream = new FileInputStream(file); - fileChannel = inputStream.getChannel(); - } - int read = 0; - ByteBuffer byteBuffer = ByteBuffer.allocate(length); - while (read < length) { - int readnow = fileChannel.read(byteBuffer); - if (readnow == -1) { - fileChannel.close(); - fileChannel = null; - break; - } else { - read += readnow; - } - } - if (read == 0) { - return EMPTY_BUFFER; - } - byteBuffer.flip(); - ByteBuf buffer = wrappedBuffer(byteBuffer); - buffer.readerIndex(0); - buffer.writerIndex(read); - return buffer; - } - - @Override - public String getString() throws IOException { - return getString(HttpConstants.DEFAULT_CHARSET); - } - - @Override - public String getString(Charset encoding) throws IOException { - if (file == null) { - return ""; - } - if (encoding == null) { - byte[] array = readFrom(file); - return new String(array, HttpConstants.DEFAULT_CHARSET.name()); - } - byte[] array = readFrom(file); - return new String(array, encoding.name()); - } - - @Override - public boolean isInMemory() { - return false; - } - - @Override - public boolean renameTo(File dest) throws IOException { - if (dest == null) { - throw new NullPointerException("dest"); - } - if (file == null) { - throw new IOException("No file defined so cannot be renamed"); - } - if (!file.renameTo(dest)) { - // must copy - IOException exception = null; - FileInputStream inputStream = null; - FileOutputStream outputStream = null; - long chunkSize = 8196; - long position = 0; - try { - inputStream = new FileInputStream(file); - outputStream = new FileOutputStream(dest); - FileChannel in = inputStream.getChannel(); - FileChannel out = outputStream.getChannel(); - while (position < size) { - if (chunkSize < size - position) { - chunkSize = size - position; - } - position += in.transferTo(position, chunkSize , out); - } - } catch (IOException e) { - exception = e; - } finally { - if (inputStream != null) { - try { - inputStream.close(); - } catch (IOException e) { - if (exception == null) { // Choose to report the first exception - exception = e; - } else { - logger.warn("Multiple exceptions detected, the following will be suppressed {}", e); - } - } - } - if (outputStream != null) { - try { - outputStream.close(); - } catch (IOException e) { - if (exception == null) { // Choose to report the first exception - exception = e; - } else { - logger.warn("Multiple exceptions detected, the following will be suppressed {}", e); - } - } - } - } - if (exception != null) { - throw exception; - } - if (position == size) { - file.delete(); - file = dest; - isRenamed = true; - return true; - } else { - dest.delete(); - return false; - } - } - file = dest; - isRenamed = true; - return true; - } - - /** - * Utility function - * @return the array of bytes - */ - private static byte[] readFrom(File src) throws IOException { - long srcsize = src.length(); - if (srcsize > Integer.MAX_VALUE) { - throw new IllegalArgumentException( - "File too big to be loaded in memory"); - } - FileInputStream inputStream = new FileInputStream(src); - byte[] array = new byte[(int) srcsize]; - try { - FileChannel fileChannel = inputStream.getChannel(); - ByteBuffer byteBuffer = ByteBuffer.wrap(array); - int read = 0; - while (read < srcsize) { - read += fileChannel.read(byteBuffer); - } - } finally { - inputStream.close(); - } - return array; - } - - @Override - public File getFile() throws IOException { - return file; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/AbstractHttpData.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/AbstractHttpData.java deleted file mode 100755 index 60e4a480eb..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/AbstractHttpData.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.multipart; - -import java.io.IOException; -import java.nio.charset.Charset; -import java.util.regex.Pattern; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelException; -import com.ai.cloud.io.netty.handler.codec.http.HttpConstants; -import com.ai.cloud.io.netty.util.AbstractReferenceCounted; - -/** - * Abstract HttpData implementation - */ -public abstract class AbstractHttpData extends AbstractReferenceCounted implements HttpData { - - private static final Pattern STRIP_PATTERN = Pattern.compile("(?:^\\s+|\\s+$|\\n)"); - private static final Pattern REPLACE_PATTERN = Pattern.compile("[\\r\\t]"); - - protected final String name; - protected long definedSize; - protected long size; - protected Charset charset = HttpConstants.DEFAULT_CHARSET; - protected boolean completed; - - protected AbstractHttpData(String name, Charset charset, long size) { - if (name == null) { - throw new NullPointerException("name"); - } - - name = REPLACE_PATTERN.matcher(name).replaceAll(" "); - name = STRIP_PATTERN.matcher(name).replaceAll(""); - - if (name.isEmpty()) { - throw new IllegalArgumentException("empty name"); - } - - this.name = name; - if (charset != null) { - setCharset(charset); - } - definedSize = size; - } - - @Override - public String getName() { - return name; - } - - @Override - public boolean isCompleted() { - return completed; - } - - @Override - public Charset getCharset() { - return charset; - } - - @Override - public void setCharset(Charset charset) { - if (charset == null) { - throw new NullPointerException("charset"); - } - this.charset = charset; - } - - @Override - public long length() { - return size; - } - - @Override - public ByteBuf content() { - try { - return getByteBuf(); - } catch (IOException e) { - throw new ChannelException(e); - } - } - - @Override - protected void deallocate() { - delete(); - } - - @Override - public HttpData retain() { - super.retain(); - return this; - } - - @Override - public HttpData retain(int increment) { - super.retain(increment); - return this; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/AbstractMemoryHttpData.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/AbstractMemoryHttpData.java deleted file mode 100755 index 1b2b0e62d4..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/AbstractMemoryHttpData.java +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.multipart; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.nio.charset.Charset; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.CompositeByteBuf; -import com.ai.cloud.io.netty.handler.codec.http.HttpConstants; - -import static com.ai.cloud.io.netty.buffer.Unpooled.*; - -/** - * Abstract Memory HttpData implementation - */ -public abstract class AbstractMemoryHttpData extends AbstractHttpData { - - private ByteBuf byteBuf; - private int chunkPosition; - protected boolean isRenamed; - - protected AbstractMemoryHttpData(String name, Charset charset, long size) { - super(name, charset, size); - } - - @Override - public void setContent(ByteBuf buffer) throws IOException { - if (buffer == null) { - throw new NullPointerException("buffer"); - } - long localsize = buffer.readableBytes(); - if (definedSize > 0 && definedSize < localsize) { - throw new IOException("Out of size: " + localsize + " > " + - definedSize); - } - if (byteBuf != null) { - byteBuf.release(); - } - byteBuf = buffer; - size = localsize; - completed = true; - } - - @Override - public void setContent(InputStream inputStream) throws IOException { - if (inputStream == null) { - throw new NullPointerException("inputStream"); - } - ByteBuf buffer = buffer(); - byte[] bytes = new byte[4096 * 4]; - int read = inputStream.read(bytes); - int written = 0; - while (read > 0) { - buffer.writeBytes(bytes, 0, read); - written += read; - read = inputStream.read(bytes); - } - size = written; - if (definedSize > 0 && definedSize < size) { - throw new IOException("Out of size: " + size + " > " + definedSize); - } - if (byteBuf != null) { - byteBuf.release(); - } - byteBuf = buffer; - completed = true; - } - - @Override - public void addContent(ByteBuf buffer, boolean last) - throws IOException { - if (buffer != null) { - long localsize = buffer.readableBytes(); - if (definedSize > 0 && definedSize < size + localsize) { - throw new IOException("Out of size: " + (size + localsize) + - " > " + definedSize); - } - size += localsize; - if (byteBuf == null) { - byteBuf = buffer; - } else if (byteBuf instanceof CompositeByteBuf) { - CompositeByteBuf cbb = (CompositeByteBuf) byteBuf; - cbb.addComponent(buffer); - cbb.writerIndex(cbb.writerIndex() + buffer.readableBytes()); - } else { - CompositeByteBuf cbb = compositeBuffer(Integer.MAX_VALUE); - cbb.addComponents(byteBuf, buffer); - cbb.writerIndex(byteBuf.readableBytes() + buffer.readableBytes()); - byteBuf = cbb; - } - } - if (last) { - completed = true; - } else { - if (buffer == null) { - throw new NullPointerException("buffer"); - } - } - } - - @Override - public void setContent(File file) throws IOException { - if (file == null) { - throw new NullPointerException("file"); - } - long newsize = file.length(); - if (newsize > Integer.MAX_VALUE) { - throw new IllegalArgumentException( - "File too big to be loaded in memory"); - } - FileInputStream inputStream = new FileInputStream(file); - FileChannel fileChannel = inputStream.getChannel(); - byte[] array = new byte[(int) newsize]; - ByteBuffer byteBuffer = ByteBuffer.wrap(array); - int read = 0; - while (read < newsize) { - read += fileChannel.read(byteBuffer); - } - fileChannel.close(); - inputStream.close(); - byteBuffer.flip(); - if (byteBuf != null) { - byteBuf.release(); - } - byteBuf = wrappedBuffer(Integer.MAX_VALUE, byteBuffer); - size = newsize; - completed = true; - } - - @Override - public void delete() { - if (byteBuf != null) { - byteBuf.release(); - byteBuf = null; - } - } - - @Override - public byte[] get() { - if (byteBuf == null) { - return EMPTY_BUFFER.array(); - } - byte[] array = new byte[byteBuf.readableBytes()]; - byteBuf.getBytes(byteBuf.readerIndex(), array); - return array; - } - - @Override - public String getString() { - return getString(HttpConstants.DEFAULT_CHARSET); - } - - @Override - public String getString(Charset encoding) { - if (byteBuf == null) { - return ""; - } - if (encoding == null) { - encoding = HttpConstants.DEFAULT_CHARSET; - } - return byteBuf.toString(encoding); - } - - /** - * Utility to go from a In Memory FileUpload - * to a Disk (or another implementation) FileUpload - * @return the attached ByteBuf containing the actual bytes - */ - @Override - public ByteBuf getByteBuf() { - return byteBuf; - } - - @Override - public ByteBuf getChunk(int length) throws IOException { - if (byteBuf == null || length == 0 || byteBuf.readableBytes() == 0) { - chunkPosition = 0; - return EMPTY_BUFFER; - } - int sizeLeft = byteBuf.readableBytes() - chunkPosition; - if (sizeLeft == 0) { - chunkPosition = 0; - return EMPTY_BUFFER; - } - int sliceLength = length; - if (sizeLeft < length) { - sliceLength = sizeLeft; - } - ByteBuf chunk = byteBuf.slice(chunkPosition, sliceLength).retain(); - chunkPosition += sliceLength; - return chunk; - } - - @Override - public boolean isInMemory() { - return true; - } - - @Override - public boolean renameTo(File dest) throws IOException { - if (dest == null) { - throw new NullPointerException("dest"); - } - if (byteBuf == null) { - // empty file - dest.createNewFile(); - isRenamed = true; - return true; - } - int length = byteBuf.readableBytes(); - FileOutputStream outputStream = new FileOutputStream(dest); - FileChannel fileChannel = outputStream.getChannel(); - int written = 0; - if (byteBuf.nioBufferCount() == 1) { - ByteBuffer byteBuffer = byteBuf.nioBuffer(); - while (written < length) { - written += fileChannel.write(byteBuffer); - } - } else { - ByteBuffer[] byteBuffers = byteBuf.nioBuffers(); - while (written < length) { - written += fileChannel.write(byteBuffers); - } - } - - fileChannel.force(false); - fileChannel.close(); - outputStream.close(); - isRenamed = true; - return written == length; - } - - @Override - public File getFile() throws IOException { - throw new IOException("Not represented by a file"); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/Attribute.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/Attribute.java deleted file mode 100755 index 18f659681c..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/Attribute.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.multipart; - -import java.io.IOException; - -/** - * Attribute interface - */ -public interface Attribute extends HttpData { - /** - * Returns the value of this HttpData. - */ - String getValue() throws IOException; - - /** - * Sets the value of this HttpData. - */ - void setValue(String value) throws IOException; - - @Override - Attribute copy(); - - @Override - Attribute duplicate(); - - @Override - Attribute retain(); - - @Override - Attribute retain(int increment); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/CaseIgnoringComparator.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/CaseIgnoringComparator.java deleted file mode 100755 index 8529378923..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/CaseIgnoringComparator.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.multipart; - -import java.io.Serializable; -import java.util.Comparator; - -final class CaseIgnoringComparator implements Comparator, Serializable { - - private static final long serialVersionUID = 4582133183775373862L; - - static final CaseIgnoringComparator INSTANCE = new CaseIgnoringComparator(); - - private CaseIgnoringComparator() { - } - - @Override - public int compare(CharSequence o1, CharSequence o2) { - int o1Length = o1.length(); - int o2Length = o2.length(); - int min = Math.min(o1Length, o2Length); - for (int i = 0; i < min; i++) { - char c1 = o1.charAt(i); - char c2 = o2.charAt(i); - if (c1 != c2) { - c1 = Character.toUpperCase(c1); - c2 = Character.toUpperCase(c2); - if (c1 != c2) { - c1 = Character.toLowerCase(c1); - c2 = Character.toLowerCase(c2); - if (c1 != c2) { - return c1 - c2; - } - } - } - } - return o1Length - o2Length; - } - - private Object readResolve() { - return INSTANCE; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/DefaultHttpDataFactory.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/DefaultHttpDataFactory.java deleted file mode 100755 index 4c5d577e98..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/DefaultHttpDataFactory.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.multipart; - -import java.io.IOException; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import com.ai.cloud.io.netty.handler.codec.http.HttpRequest; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - -/** - * Default factory giving Attribute and FileUpload according to constructor - * - * Attribute and FileUpload could be :
- * - MemoryAttribute, DiskAttribute or MixedAttribute
- * - MemoryFileUpload, DiskFileUpload or MixedFileUpload
- * according to the constructor. - */ -public class DefaultHttpDataFactory implements HttpDataFactory { - /** - * Proposed default MINSIZE as 16 KB. - */ - public static final long MINSIZE = 0x4000; - - private final boolean useDisk; - - private final boolean checkSize; - - private long minSize; - - /** - * Keep all HttpDatas until cleanAllHttpDatas() is called. - */ - private final Map> requestFileDeleteMap = PlatformDependent.newConcurrentHashMap(); - - /** - * HttpData will be in memory if less than default size (16KB). - * The type will be Mixed. - */ - public DefaultHttpDataFactory() { - useDisk = false; - checkSize = true; - minSize = MINSIZE; - } - - /** - * HttpData will be always on Disk if useDisk is True, else always in Memory if False - */ - public DefaultHttpDataFactory(boolean useDisk) { - this.useDisk = useDisk; - checkSize = false; - } - - /** - * HttpData will be on Disk if the size of the file is greater than minSize, else it - * will be in memory. The type will be Mixed. - */ - public DefaultHttpDataFactory(long minSize) { - useDisk = false; - checkSize = true; - this.minSize = minSize; - } - - /** - * @return the associated list of Files for the request - */ - private List getList(HttpRequest request) { - List list = requestFileDeleteMap.get(request); - if (list == null) { - list = new ArrayList(); - requestFileDeleteMap.put(request, list); - } - return list; - } - - @Override - public Attribute createAttribute(HttpRequest request, String name) { - if (useDisk) { - Attribute attribute = new DiskAttribute(name); - List fileToDelete = getList(request); - fileToDelete.add(attribute); - return attribute; - } - if (checkSize) { - Attribute attribute = new MixedAttribute(name, minSize); - List fileToDelete = getList(request); - fileToDelete.add(attribute); - return attribute; - } - return new MemoryAttribute(name); - } - - @Override - public Attribute createAttribute(HttpRequest request, String name, String value) { - if (useDisk) { - Attribute attribute; - try { - attribute = new DiskAttribute(name, value); - } catch (IOException e) { - // revert to Mixed mode - attribute = new MixedAttribute(name, value, minSize); - } - List fileToDelete = getList(request); - fileToDelete.add(attribute); - return attribute; - } - if (checkSize) { - Attribute attribute = new MixedAttribute(name, value, minSize); - List fileToDelete = getList(request); - fileToDelete.add(attribute); - return attribute; - } - try { - return new MemoryAttribute(name, value); - } catch (IOException e) { - throw new IllegalArgumentException(e); - } - } - - @Override - public FileUpload createFileUpload(HttpRequest request, String name, String filename, - String contentType, String contentTransferEncoding, Charset charset, - long size) { - if (useDisk) { - FileUpload fileUpload = new DiskFileUpload(name, filename, contentType, - contentTransferEncoding, charset, size); - List fileToDelete = getList(request); - fileToDelete.add(fileUpload); - return fileUpload; - } - if (checkSize) { - FileUpload fileUpload = new MixedFileUpload(name, filename, contentType, - contentTransferEncoding, charset, size, minSize); - List fileToDelete = getList(request); - fileToDelete.add(fileUpload); - return fileUpload; - } - return new MemoryFileUpload(name, filename, contentType, - contentTransferEncoding, charset, size); - } - - @Override - public void removeHttpDataFromClean(HttpRequest request, InterfaceHttpData data) { - if (data instanceof HttpData) { - List fileToDelete = getList(request); - fileToDelete.remove(data); - } - } - - @Override - public void cleanRequestHttpDatas(HttpRequest request) { - List fileToDelete = requestFileDeleteMap.remove(request); - if (fileToDelete != null) { - for (HttpData data: fileToDelete) { - data.delete(); - } - fileToDelete.clear(); - } - } - - @Override - public void cleanAllHttpDatas() { - Iterator>> i = requestFileDeleteMap.entrySet().iterator(); - while (i.hasNext()) { - Entry> e = i.next(); - i.remove(); - - List fileToDelete = e.getValue(); - if (fileToDelete != null) { - for (HttpData data : fileToDelete) { - data.delete(); - } - fileToDelete.clear(); - } - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/DiskAttribute.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/DiskAttribute.java deleted file mode 100755 index 7ea573a90c..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/DiskAttribute.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.multipart; - -import java.io.IOException; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelException; -import com.ai.cloud.io.netty.handler.codec.http.HttpConstants; - -import static com.ai.cloud.io.netty.buffer.Unpooled.*; - -/** - * Disk implementation of Attributes - */ -public class DiskAttribute extends AbstractDiskHttpData implements Attribute { - public static String baseDirectory; - - public static boolean deleteOnExitTemporaryFile = true; - - public static final String prefix = "Attr_"; - - public static final String postfix = ".att"; - - /** - * Constructor used for huge Attribute - */ - public DiskAttribute(String name) { - super(name, HttpConstants.DEFAULT_CHARSET, 0); - } - - public DiskAttribute(String name, String value) throws IOException { - super(name, HttpConstants.DEFAULT_CHARSET, 0); // Attribute have no default size - setValue(value); - } - - @Override - public HttpDataType getHttpDataType() { - return HttpDataType.Attribute; - } - - @Override - public String getValue() throws IOException { - byte [] bytes = get(); - return new String(bytes, charset.name()); - } - - @Override - public void setValue(String value) throws IOException { - if (value == null) { - throw new NullPointerException("value"); - } - byte [] bytes = value.getBytes(charset.name()); - ByteBuf buffer = wrappedBuffer(bytes); - if (definedSize > 0) { - definedSize = buffer.readableBytes(); - } - setContent(buffer); - } - - @Override - public void addContent(ByteBuf buffer, boolean last) throws IOException { - int localsize = buffer.readableBytes(); - if (definedSize > 0 && definedSize < size + localsize) { - definedSize = size + localsize; - } - super.addContent(buffer, last); - } - @Override - public int hashCode() { - return getName().hashCode(); - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof Attribute)) { - return false; - } - Attribute attribute = (Attribute) o; - return getName().equalsIgnoreCase(attribute.getName()); - } - - @Override - public int compareTo(InterfaceHttpData o) { - if (!(o instanceof Attribute)) { - throw new ClassCastException("Cannot compare " + getHttpDataType() + - " with " + o.getHttpDataType()); - } - return compareTo((Attribute) o); - } - - public int compareTo(Attribute o) { - return getName().compareToIgnoreCase(o.getName()); - } - - @Override - public String toString() { - try { - return getName() + '=' + getValue(); - } catch (IOException e) { - return getName() + "=IoException"; - } - } - - @Override - protected boolean deleteOnExit() { - return deleteOnExitTemporaryFile; - } - - @Override - protected String getBaseDirectory() { - return baseDirectory; - } - - @Override - protected String getDiskFilename() { - return getName() + postfix; - } - - @Override - protected String getPostfix() { - return postfix; - } - - @Override - protected String getPrefix() { - return prefix; - } - - @Override - public Attribute copy() { - DiskAttribute attr = new DiskAttribute(getName()); - attr.setCharset(getCharset()); - ByteBuf content = content(); - if (content != null) { - try { - attr.setContent(content.copy()); - } catch (IOException e) { - throw new ChannelException(e); - } - } - return attr; - } - - @Override - public Attribute duplicate() { - DiskAttribute attr = new DiskAttribute(getName()); - attr.setCharset(getCharset()); - ByteBuf content = content(); - if (content != null) { - try { - attr.setContent(content.duplicate()); - } catch (IOException e) { - throw new ChannelException(e); - } - } - return attr; - } - - @Override - public Attribute retain(int increment) { - super.retain(increment); - return this; - } - - @Override - public Attribute retain() { - super.retain(); - return this; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/DiskFileUpload.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/DiskFileUpload.java deleted file mode 100755 index 2ff57f64a8..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/DiskFileUpload.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.multipart; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.Charset; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelException; -import com.ai.cloud.io.netty.handler.codec.http.HttpHeaders; - -/** - * Disk FileUpload implementation that stores file into real files - */ -public class DiskFileUpload extends AbstractDiskHttpData implements FileUpload { - public static String baseDirectory; - - public static boolean deleteOnExitTemporaryFile = true; - - public static final String prefix = "FUp_"; - - public static final String postfix = ".tmp"; - - private String filename; - - private String contentType; - - private String contentTransferEncoding; - - public DiskFileUpload(String name, String filename, String contentType, - String contentTransferEncoding, Charset charset, long size) { - super(name, charset, size); - setFilename(filename); - setContentType(contentType); - setContentTransferEncoding(contentTransferEncoding); - } - - @Override - public HttpDataType getHttpDataType() { - return HttpDataType.FileUpload; - } - - @Override - public String getFilename() { - return filename; - } - - @Override - public void setFilename(String filename) { - if (filename == null) { - throw new NullPointerException("filename"); - } - this.filename = filename; - } - - @Override - public int hashCode() { - return getName().hashCode(); - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof Attribute)) { - return false; - } - Attribute attribute = (Attribute) o; - return getName().equalsIgnoreCase(attribute.getName()); - } - - @Override - public int compareTo(InterfaceHttpData o) { - if (!(o instanceof FileUpload)) { - throw new ClassCastException("Cannot compare " + getHttpDataType() + - " with " + o.getHttpDataType()); - } - return compareTo((FileUpload) o); - } - - public int compareTo(FileUpload o) { - int v; - v = getName().compareToIgnoreCase(o.getName()); - if (v != 0) { - return v; - } - // TODO should we compare size ? - return v; - } - - @Override - public void setContentType(String contentType) { - if (contentType == null) { - throw new NullPointerException("contentType"); - } - this.contentType = contentType; - } - - @Override - public String getContentType() { - return contentType; - } - - @Override - public String getContentTransferEncoding() { - return contentTransferEncoding; - } - - @Override - public void setContentTransferEncoding(String contentTransferEncoding) { - this.contentTransferEncoding = contentTransferEncoding; - } - - @Override - public String toString() { - return HttpPostBodyUtil.CONTENT_DISPOSITION + ": " + - HttpPostBodyUtil.FORM_DATA + "; " + HttpPostBodyUtil.NAME + "=\"" + getName() + - "\"; " + HttpPostBodyUtil.FILENAME + "=\"" + filename + "\"\r\n" + - HttpHeaders.Names.CONTENT_TYPE + ": " + contentType + - (charset != null? "; " + HttpHeaders.Values.CHARSET + '=' + charset.name() + "\r\n" : "\r\n") + - HttpHeaders.Names.CONTENT_LENGTH + ": " + length() + "\r\n" + - "Completed: " + isCompleted() + - "\r\nIsInMemory: " + isInMemory() + "\r\nRealFile: " + - (file != null ? file.getAbsolutePath() : "null") + " DefaultDeleteAfter: " + - deleteOnExitTemporaryFile; - } - - @Override - protected boolean deleteOnExit() { - return deleteOnExitTemporaryFile; - } - - @Override - protected String getBaseDirectory() { - return baseDirectory; - } - - @Override - protected String getDiskFilename() { - File file = new File(filename); - return file.getName(); - } - - @Override - protected String getPostfix() { - return postfix; - } - - @Override - protected String getPrefix() { - return prefix; - } - - @Override - public FileUpload copy() { - DiskFileUpload upload = new DiskFileUpload(getName(), - getFilename(), getContentType(), getContentTransferEncoding(), getCharset(), size); - ByteBuf buf = content(); - if (buf != null) { - try { - upload.setContent(buf.copy()); - } catch (IOException e) { - throw new ChannelException(e); - } - } - return upload; - } - - @Override - public FileUpload duplicate() { - DiskFileUpload upload = new DiskFileUpload(getName(), - getFilename(), getContentType(), getContentTransferEncoding(), getCharset(), size); - ByteBuf buf = content(); - if (buf != null) { - try { - upload.setContent(buf.duplicate()); - } catch (IOException e) { - throw new ChannelException(e); - } - } - return upload; - } - - @Override - public FileUpload retain(int increment) { - super.retain(increment); - return this; - } - - @Override - public FileUpload retain() { - super.retain(); - return this; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/FileUpload.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/FileUpload.java deleted file mode 100755 index 242f9af88d..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/FileUpload.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.multipart; - -/** - * FileUpload interface that could be in memory, on temporary file or any other implementations. - * - * Most methods are inspired from java.io.File API. - */ -public interface FileUpload extends HttpData { - /** - * Returns the original filename in the client's filesystem, - * as provided by the browser (or other client software). - * @return the original filename - */ - String getFilename(); - - /** - * Set the original filename - */ - void setFilename(String filename); - - /** - * Set the Content Type passed by the browser if defined - * @param contentType Content Type to set - must be not null - */ - void setContentType(String contentType); - - /** - * Returns the content type passed by the browser or null if not defined. - * @return the content type passed by the browser or null if not defined. - */ - String getContentType(); - - /** - * Set the Content-Transfer-Encoding type from String as 7bit, 8bit or binary - */ - void setContentTransferEncoding(String contentTransferEncoding); - - /** - * Returns the Content-Transfer-Encoding - * @return the Content-Transfer-Encoding - */ - String getContentTransferEncoding(); - - @Override - FileUpload copy(); - - @Override - FileUpload duplicate(); - - @Override - FileUpload retain(); - - @Override - FileUpload retain(int increment); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/HttpData.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/HttpData.java deleted file mode 100755 index 9af4d68c43..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/HttpData.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.multipart; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.Charset; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.ByteBufHolder; - -/** - * Extended interface for InterfaceHttpData - */ -public interface HttpData extends InterfaceHttpData, ByteBufHolder { - /** - * Set the content from the ChannelBuffer (erase any previous data) - * - * @param buffer - * must be not null - * @exception IOException - */ - void setContent(ByteBuf buffer) throws IOException; - - /** - * Add the content from the ChannelBuffer - * - * @param buffer - * must be not null except if last is set to False - * @param last - * True of the buffer is the last one - * @exception IOException - */ - void addContent(ByteBuf buffer, boolean last) throws IOException; - - /** - * Set the content from the file (erase any previous data) - * - * @param file - * must be not null - * @exception IOException - */ - void setContent(File file) throws IOException; - - /** - * Set the content from the inputStream (erase any previous data) - * - * @param inputStream - * must be not null - * @exception IOException - */ - void setContent(InputStream inputStream) throws IOException; - - /** - * - * @return True if the InterfaceHttpData is completed (all data are stored) - */ - boolean isCompleted(); - - /** - * Returns the size in byte of the InterfaceHttpData - * - * @return the size of the InterfaceHttpData - */ - long length(); - - /** - * Deletes the underlying storage for a file item, including deleting any - * associated temporary disk file. - */ - void delete(); - - /** - * Returns the contents of the file item as an array of bytes. - * - * @return the contents of the file item as an array of bytes. - * @exception IOException - */ - byte[] get() throws IOException; - - /** - * Returns the content of the file item as a ByteBuf - * - * @return the content of the file item as a ByteBuf - * @throws IOException - */ - ByteBuf getByteBuf() throws IOException; - - /** - * Returns a ChannelBuffer for the content from the current position with at - * most length read bytes, increasing the current position of the Bytes - * read. Once it arrives at the end, it returns an EMPTY_BUFFER and it - * resets the current position to 0. - * - * @return a ChannelBuffer for the content from the current position or an - * EMPTY_BUFFER if there is no more data to return - */ - ByteBuf getChunk(int length) throws IOException; - - /** - * Returns the contents of the file item as a String, using the default - * character encoding. - * - * @return the contents of the file item as a String, using the default - * character encoding. - * @exception IOException - */ - String getString() throws IOException; - - /** - * Returns the contents of the file item as a String, using the specified - * charset. - * - * @param encoding - * the charset to use - * @return the contents of the file item as a String, using the specified - * charset. - * @exception IOException - */ - String getString(Charset encoding) throws IOException; - - /** - * Set the Charset passed by the browser if defined - * - * @param charset - * Charset to set - must be not null - */ - void setCharset(Charset charset); - - /** - * Returns the Charset passed by the browser or null if not defined. - * - * @return the Charset passed by the browser or null if not defined. - */ - Charset getCharset(); - - /** - * A convenience getMethod to write an uploaded item to disk. If a previous one - * exists, it will be deleted. Once this getMethod is called, if successful, - * the new file will be out of the cleaner of the factory that creates the - * original InterfaceHttpData object. - * - * @param dest - * destination file - must be not null - * @return True if the write is successful - * @exception IOException - */ - boolean renameTo(File dest) throws IOException; - - /** - * Provides a hint as to whether or not the file contents will be read from - * memory. - * - * @return True if the file contents is in memory. - */ - boolean isInMemory(); - - /** - * - * @return the associated File if this data is represented in a file - * @exception IOException - * if this data is not represented by a file - */ - File getFile() throws IOException; - - @Override - HttpData copy(); - - @Override - HttpData duplicate(); - - @Override - HttpData retain(); - - @Override - HttpData retain(int increment); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/HttpDataFactory.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/HttpDataFactory.java deleted file mode 100755 index b8e0084b00..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/HttpDataFactory.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.multipart; - -import java.nio.charset.Charset; - -import com.ai.cloud.io.netty.handler.codec.http.HttpRequest; - -/** - * Interface to enable creation of InterfaceHttpData objects - */ -public interface HttpDataFactory { - /** - * - * @param request associated request - * @return a new Attribute with no value - */ - Attribute createAttribute(HttpRequest request, String name); - - /** - * @param request associated request - * @return a new Attribute - */ - Attribute createAttribute(HttpRequest request, String name, String value); - - /** - * @param request associated request - * @param size the size of the Uploaded file - * @return a new FileUpload - */ - FileUpload createFileUpload(HttpRequest request, String name, String filename, - String contentType, String contentTransferEncoding, Charset charset, - long size); - - /** - * Remove the given InterfaceHttpData from clean list (will not delete the file, except if the file - * is still a temporary one as setup at construction) - * @param request associated request - */ - void removeHttpDataFromClean(HttpRequest request, InterfaceHttpData data); - - /** - * Remove all InterfaceHttpData from virtual File storage from clean list for the request - * - * @param request associated request - */ - void cleanRequestHttpDatas(HttpRequest request); - - /** - * Remove all InterfaceHttpData from virtual File storage from clean list for all requests - */ - void cleanAllHttpDatas(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/HttpPostBodyUtil.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/HttpPostBodyUtil.java deleted file mode 100755 index 248702b385..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/HttpPostBodyUtil.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.multipart; - -import java.nio.charset.Charset; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.util.CharsetUtil; - -/** - * Shared Static object between HttpMessageDecoder, HttpPostRequestDecoder and HttpPostRequestEncoder - */ -final class HttpPostBodyUtil { - - public static final int chunkSize = 8096; - /** - * HTTP content disposition header name. - */ - public static final String CONTENT_DISPOSITION = "Content-Disposition"; - - public static final String NAME = "name"; - - public static final String FILENAME = "filename"; - - /** - * Content-disposition value for form data. - */ - public static final String FORM_DATA = "form-data"; - - /** - * Content-disposition value for file attachment. - */ - public static final String ATTACHMENT = "attachment"; - - /** - * Content-disposition value for file attachment. - */ - public static final String FILE = "file"; - - /** - * HTTP content type body attribute for multiple uploads. - */ - public static final String MULTIPART_MIXED = "multipart/mixed"; - - /** - * Charset for 8BIT - */ - public static final Charset ISO_8859_1 = CharsetUtil.ISO_8859_1; - - /** - * Charset for 7BIT - */ - public static final Charset US_ASCII = CharsetUtil.US_ASCII; - - /** - * Default Content-Type in binary form - */ - public static final String DEFAULT_BINARY_CONTENT_TYPE = "application/octet-stream"; - - /** - * Default Content-Type in Text form - */ - public static final String DEFAULT_TEXT_CONTENT_TYPE = "text/plain"; - - /** - * Allowed mechanism for multipart - * mechanism := "7bit" - / "8bit" - / "binary" - Not allowed: "quoted-printable" - / "base64" - */ - public enum TransferEncodingMechanism { - /** - * Default encoding - */ - BIT7("7bit"), - /** - * Short lines but not in ASCII - no encoding - */ - BIT8("8bit"), - /** - * Could be long text not in ASCII - no encoding - */ - BINARY("binary"); - - private final String value; - - TransferEncodingMechanism(String value) { - this.value = value; - } - - TransferEncodingMechanism() { - value = name(); - } - - public String value() { - return value; - } - - @Override - public String toString() { - return value; - } - } - - private HttpPostBodyUtil() { - } - - /** - * Exception when NO Backend Array is found - */ - static class SeekAheadNoBackArrayException extends Exception { - private static final long serialVersionUID = -630418804938699495L; - } - - /** - * This class intends to decrease the CPU in seeking ahead some bytes in - * HttpPostRequestDecoder - */ - static class SeekAheadOptimize { - byte[] bytes; - int readerIndex; - int pos; - int origPos; - int limit; - ByteBuf buffer; - - SeekAheadOptimize(ByteBuf buffer) throws SeekAheadNoBackArrayException { - if (!buffer.hasArray()) { - throw new SeekAheadNoBackArrayException(); - } - this.buffer = buffer; - bytes = buffer.array(); - readerIndex = buffer.readerIndex(); - origPos = pos = buffer.arrayOffset() + readerIndex; - limit = buffer.arrayOffset() + buffer.writerIndex(); - } - - /** - * - * @param minus this value will be used as (currentPos - minus) to set - * the current readerIndex in the buffer. - */ - void setReadPosition(int minus) { - pos -= minus; - readerIndex = getReadPosition(pos); - buffer.readerIndex(readerIndex); - } - - /** - * - * @param index raw index of the array (pos in general) - * @return the value equivalent of raw index to be used in readerIndex(value) - */ - int getReadPosition(int index) { - return index - origPos + readerIndex; - } - - void clear() { - buffer = null; - bytes = null; - limit = 0; - pos = 0; - readerIndex = 0; - } - } - - /** - * Find the first non whitespace - * @return the rank of the first non whitespace - */ - static int findNonWhitespace(String sb, int offset) { - int result; - for (result = offset; result < sb.length(); result ++) { - if (!Character.isWhitespace(sb.charAt(result))) { - break; - } - } - return result; - } - - /** - * Find the first whitespace - * @return the rank of the first whitespace - */ - static int findWhitespace(String sb, int offset) { - int result; - for (result = offset; result < sb.length(); result ++) { - if (Character.isWhitespace(sb.charAt(result))) { - break; - } - } - return result; - } - - /** - * Find the end of String - * @return the rank of the end of string - */ - static int findEndOfString(String sb) { - int result; - for (result = sb.length(); result > 0; result --) { - if (!Character.isWhitespace(sb.charAt(result - 1))) { - break; - } - } - return result; - } - -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/HttpPostMultipartRequestDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/HttpPostMultipartRequestDecoder.java deleted file mode 100755 index caff6620fc..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/HttpPostMultipartRequestDecoder.java +++ /dev/null @@ -1,1835 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.multipart; - -import java.io.IOException; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.handler.codec.http.HttpConstants; -import com.ai.cloud.io.netty.handler.codec.http.HttpContent; -import com.ai.cloud.io.netty.handler.codec.http.HttpHeaders; -import com.ai.cloud.io.netty.handler.codec.http.HttpRequest; -import com.ai.cloud.io.netty.handler.codec.http.LastHttpContent; -import com.ai.cloud.io.netty.handler.codec.http.multipart.HttpPostBodyUtil.SeekAheadNoBackArrayException; -import com.ai.cloud.io.netty.handler.codec.http.multipart.HttpPostBodyUtil.SeekAheadOptimize; -import com.ai.cloud.io.netty.handler.codec.http.multipart.HttpPostBodyUtil.TransferEncodingMechanism; -import com.ai.cloud.io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.EndOfDataDecoderException; -import com.ai.cloud.io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.ErrorDataDecoderException; -import com.ai.cloud.io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.MultiPartStatus; -import com.ai.cloud.io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.NotEnoughDataDecoderException; -import com.ai.cloud.io.netty.util.internal.StringUtil; - -import static com.ai.cloud.io.netty.buffer.Unpooled.*; - -/** - * This decoder will decode Body and can handle POST BODY. - * - * You MUST call {@link #destroy()} after completion to release all resources. - * - */ -public class HttpPostMultipartRequestDecoder implements InterfaceHttpPostRequestDecoder { - - /** - * Factory used to create InterfaceHttpData - */ - private final HttpDataFactory factory; - - /** - * Request to decode - */ - private final HttpRequest request; - - /** - * Default charset to use - */ - private Charset charset; - - /** - * Does the last chunk already received - */ - private boolean isLastChunk; - - /** - * HttpDatas from Body - */ - private final List bodyListHttpData = new ArrayList(); - - /** - * HttpDatas as Map from Body - */ - private final Map> bodyMapHttpData = new TreeMap>( - CaseIgnoringComparator.INSTANCE); - - /** - * The current channelBuffer - */ - private ByteBuf undecodedChunk; - - /** - * Body HttpDatas current position - */ - private int bodyListHttpDataRank; - - /** - * If multipart, this is the boundary for the flobal multipart - */ - private String multipartDataBoundary; - - /** - * If multipart, there could be internal multiparts (mixed) to the global - * multipart. Only one level is allowed. - */ - private String multipartMixedBoundary; - - /** - * Current getStatus - */ - private MultiPartStatus currentStatus = MultiPartStatus.NOTSTARTED; - - /** - * Used in Multipart - */ - private Map currentFieldAttributes; - - /** - * The current FileUpload that is currently in decode process - */ - private FileUpload currentFileUpload; - - /** - * The current Attribute that is currently in decode process - */ - private Attribute currentAttribute; - - private boolean destroyed; - - private int discardThreshold = HttpPostRequestDecoder.DEFAULT_DISCARD_THRESHOLD; - - /** - * - * @param request - * the request to decode - * @throws NullPointerException - * for request - * @throws ErrorDataDecoderException - * if the default charset was wrong when decoding or other - * errors - */ - public HttpPostMultipartRequestDecoder(HttpRequest request) { - this(new DefaultHttpDataFactory(DefaultHttpDataFactory.MINSIZE), request, HttpConstants.DEFAULT_CHARSET); - } - - /** - * - * @param factory - * the factory used to create InterfaceHttpData - * @param request - * the request to decode - * @throws NullPointerException - * for request or factory - * @throws ErrorDataDecoderException - * if the default charset was wrong when decoding or other - * errors - */ - public HttpPostMultipartRequestDecoder(HttpDataFactory factory, HttpRequest request) { - this(factory, request, HttpConstants.DEFAULT_CHARSET); - } - - /** - * - * @param factory - * the factory used to create InterfaceHttpData - * @param request - * the request to decode - * @param charset - * the charset to use as default - * @throws NullPointerException - * for request or charset or factory - * @throws ErrorDataDecoderException - * if the default charset was wrong when decoding or other - * errors - */ - public HttpPostMultipartRequestDecoder(HttpDataFactory factory, HttpRequest request, Charset charset) { - if (factory == null) { - throw new NullPointerException("factory"); - } - if (request == null) { - throw new NullPointerException("request"); - } - if (charset == null) { - throw new NullPointerException("charset"); - } - this.request = request; - this.charset = charset; - this.factory = factory; - // Fill default values - - setMultipart(this.request.headers().get(HttpHeaders.Names.CONTENT_TYPE)); - if (request instanceof HttpContent) { - // Offer automatically if the given request is als type of HttpContent - // See #1089 - offer((HttpContent) request); - } else { - undecodedChunk = buffer(); - parseBody(); - } - } - - /** - * Set from the request ContentType the multipartDataBoundary and the possible charset. - */ - private void setMultipart(String contentType) { - String[] dataBoundary = HttpPostRequestDecoder.getMultipartDataBoundary(contentType); - if (dataBoundary != null) { - multipartDataBoundary = dataBoundary[0]; - if (dataBoundary.length > 1 && dataBoundary[1] != null) { - charset = Charset.forName(dataBoundary[1]); - } - } else { - multipartDataBoundary = null; - } - currentStatus = MultiPartStatus.HEADERDELIMITER; - } - - private void checkDestroyed() { - if (destroyed) { - throw new IllegalStateException(HttpPostMultipartRequestDecoder.class.getSimpleName() - + " was destroyed already"); - } - } - - /** - * True if this request is a Multipart request - * - * @return True if this request is a Multipart request - */ - @Override - public boolean isMultipart() { - checkDestroyed(); - return true; - } - - /** - * Set the amount of bytes after which read bytes in the buffer should be discarded. - * Setting this lower gives lower memory usage but with the overhead of more memory copies. - * Use {@code 0} to disable it. - */ - @Override - public void setDiscardThreshold(int discardThreshold) { - if (discardThreshold < 0) { - throw new IllegalArgumentException("discardThreshold must be >= 0"); - } - this.discardThreshold = discardThreshold; - } - - /** - * Return the threshold in bytes after which read data in the buffer should be discarded. - */ - @Override - public int getDiscardThreshold() { - return discardThreshold; - } - - /** - * This getMethod returns a List of all HttpDatas from body.
- * - * If chunked, all chunks must have been offered using offer() getMethod. If - * not, NotEnoughDataDecoderException will be raised. - * - * @return the list of HttpDatas from Body part for POST getMethod - * @throws NotEnoughDataDecoderException - * Need more chunks - */ - @Override - public List getBodyHttpDatas() { - checkDestroyed(); - - if (!isLastChunk) { - throw new NotEnoughDataDecoderException(); - } - return bodyListHttpData; - } - - /** - * This getMethod returns a List of all HttpDatas with the given name from - * body.
- * - * If chunked, all chunks must have been offered using offer() getMethod. If - * not, NotEnoughDataDecoderException will be raised. - * - * @return All Body HttpDatas with the given name (ignore case) - * @throws NotEnoughDataDecoderException - * need more chunks - */ - @Override - public List getBodyHttpDatas(String name) { - checkDestroyed(); - - if (!isLastChunk) { - throw new NotEnoughDataDecoderException(); - } - return bodyMapHttpData.get(name); - } - - /** - * This getMethod returns the first InterfaceHttpData with the given name from - * body.
- * - * If chunked, all chunks must have been offered using offer() getMethod. If - * not, NotEnoughDataDecoderException will be raised. - * - * @return The first Body InterfaceHttpData with the given name (ignore - * case) - * @throws NotEnoughDataDecoderException - * need more chunks - */ - @Override - public InterfaceHttpData getBodyHttpData(String name) { - checkDestroyed(); - - if (!isLastChunk) { - throw new NotEnoughDataDecoderException(); - } - List list = bodyMapHttpData.get(name); - if (list != null) { - return list.get(0); - } - return null; - } - - /** - * Initialized the internals from a new chunk - * - * @param content - * the new received chunk - * @throws ErrorDataDecoderException - * if there is a problem with the charset decoding or other - * errors - */ - @Override - public HttpPostMultipartRequestDecoder offer(HttpContent content) { - checkDestroyed(); - - // Maybe we should better not copy here for performance reasons but this will need - // more care by the caller to release the content in a correct manner later - // So maybe something to optimize on a later stage - ByteBuf buf = content.content(); - if (undecodedChunk == null) { - undecodedChunk = buf.copy(); - } else { - undecodedChunk.writeBytes(buf); - } - if (content instanceof LastHttpContent) { - isLastChunk = true; - } - parseBody(); - if (undecodedChunk != null && undecodedChunk.writerIndex() > discardThreshold) { - undecodedChunk.discardReadBytes(); - } - return this; - } - - /** - * True if at current getStatus, there is an available decoded - * InterfaceHttpData from the Body. - * - * This getMethod works for chunked and not chunked request. - * - * @return True if at current getStatus, there is a decoded InterfaceHttpData - * @throws EndOfDataDecoderException - * No more data will be available - */ - @Override - public boolean hasNext() { - checkDestroyed(); - - if (currentStatus == MultiPartStatus.EPILOGUE) { - // OK except if end of list - if (bodyListHttpDataRank >= bodyListHttpData.size()) { - throw new EndOfDataDecoderException(); - } - } - return !bodyListHttpData.isEmpty() && bodyListHttpDataRank < bodyListHttpData.size(); - } - - /** - * Returns the next available InterfaceHttpData or null if, at the time it - * is called, there is no more available InterfaceHttpData. A subsequent - * call to offer(httpChunk) could enable more data. - * - * Be sure to call {@link InterfaceHttpData#release()} after you are done - * with processing to make sure to not leak any resources - * - * @return the next available InterfaceHttpData or null if none - * @throws EndOfDataDecoderException - * No more data will be available - */ - @Override - public InterfaceHttpData next() { - checkDestroyed(); - - if (hasNext()) { - return bodyListHttpData.get(bodyListHttpDataRank++); - } - return null; - } - - /** - * This getMethod will parse as much as possible data and fill the list and map - * - * @throws ErrorDataDecoderException - * if there is a problem with the charset decoding or other - * errors - */ - private void parseBody() { - if (currentStatus == MultiPartStatus.PREEPILOGUE || currentStatus == MultiPartStatus.EPILOGUE) { - if (isLastChunk) { - currentStatus = MultiPartStatus.EPILOGUE; - } - return; - } - parseBodyMultipart(); - } - - /** - * Utility function to add a new decoded data - */ - protected void addHttpData(InterfaceHttpData data) { - if (data == null) { - return; - } - List datas = bodyMapHttpData.get(data.getName()); - if (datas == null) { - datas = new ArrayList(1); - bodyMapHttpData.put(data.getName(), datas); - } - datas.add(data); - bodyListHttpData.add(data); - } - - /** - * Parse the Body for multipart - * - * @throws ErrorDataDecoderException - * if there is a problem with the charset decoding or other - * errors - */ - private void parseBodyMultipart() { - if (undecodedChunk == null || undecodedChunk.readableBytes() == 0) { - // nothing to decode - return; - } - InterfaceHttpData data = decodeMultipart(currentStatus); - while (data != null) { - addHttpData(data); - if (currentStatus == MultiPartStatus.PREEPILOGUE || currentStatus == MultiPartStatus.EPILOGUE) { - break; - } - data = decodeMultipart(currentStatus); - } - } - - /** - * Decode a multipart request by pieces
- *
- * NOTSTARTED PREAMBLE (
- * (HEADERDELIMITER DISPOSITION (FIELD | FILEUPLOAD))*
- * (HEADERDELIMITER DISPOSITION MIXEDPREAMBLE
- * (MIXEDDELIMITER MIXEDDISPOSITION MIXEDFILEUPLOAD)+
- * MIXEDCLOSEDELIMITER)*
- * CLOSEDELIMITER)+ EPILOGUE
- * - * Inspired from HttpMessageDecoder - * - * @return the next decoded InterfaceHttpData or null if none until now. - * @throws ErrorDataDecoderException - * if an error occurs - */ - private InterfaceHttpData decodeMultipart(MultiPartStatus state) { - switch (state) { - case NOTSTARTED: - throw new ErrorDataDecoderException("Should not be called with the current getStatus"); - case PREAMBLE: - // Content-type: multipart/form-data, boundary=AaB03x - throw new ErrorDataDecoderException("Should not be called with the current getStatus"); - case HEADERDELIMITER: { - // --AaB03x or --AaB03x-- - return findMultipartDelimiter(multipartDataBoundary, MultiPartStatus.DISPOSITION, - MultiPartStatus.PREEPILOGUE); - } - case DISPOSITION: { - // content-disposition: form-data; name="field1" - // content-disposition: form-data; name="pics"; filename="file1.txt" - // and other immediate values like - // Content-type: image/gif - // Content-Type: text/plain - // Content-Type: text/plain; charset=ISO-8859-1 - // Content-Transfer-Encoding: binary - // The following line implies a change of mode (mixed mode) - // Content-type: multipart/mixed, boundary=BbC04y - return findMultipartDisposition(); - } - case FIELD: { - // Now get value according to Content-Type and Charset - Charset localCharset = null; - Attribute charsetAttribute = currentFieldAttributes.get(HttpHeaders.Values.CHARSET); - if (charsetAttribute != null) { - try { - localCharset = Charset.forName(charsetAttribute.getValue()); - } catch (IOException e) { - throw new ErrorDataDecoderException(e); - } - } - Attribute nameAttribute = currentFieldAttributes.get(HttpPostBodyUtil.NAME); - if (currentAttribute == null) { - try { - currentAttribute = factory.createAttribute(request, - cleanString(nameAttribute.getValue())); - } catch (NullPointerException e) { - throw new ErrorDataDecoderException(e); - } catch (IllegalArgumentException e) { - throw new ErrorDataDecoderException(e); - } catch (IOException e) { - throw new ErrorDataDecoderException(e); - } - if (localCharset != null) { - currentAttribute.setCharset(localCharset); - } - } - // load data - try { - loadFieldMultipart(multipartDataBoundary); - } catch (NotEnoughDataDecoderException ignored) { - return null; - } - Attribute finalAttribute = currentAttribute; - currentAttribute = null; - currentFieldAttributes = null; - // ready to load the next one - currentStatus = MultiPartStatus.HEADERDELIMITER; - return finalAttribute; - } - case FILEUPLOAD: { - // eventually restart from existing FileUpload - return getFileUpload(multipartDataBoundary); - } - case MIXEDDELIMITER: { - // --AaB03x or --AaB03x-- - // Note that currentFieldAttributes exists - return findMultipartDelimiter(multipartMixedBoundary, MultiPartStatus.MIXEDDISPOSITION, - MultiPartStatus.HEADERDELIMITER); - } - case MIXEDDISPOSITION: { - return findMultipartDisposition(); - } - case MIXEDFILEUPLOAD: { - // eventually restart from existing FileUpload - return getFileUpload(multipartMixedBoundary); - } - case PREEPILOGUE: - return null; - case EPILOGUE: - return null; - default: - throw new ErrorDataDecoderException("Shouldn't reach here."); - } - } - - /** - * Skip control Characters - * - * @throws NotEnoughDataDecoderException - */ - void skipControlCharacters() { - SeekAheadOptimize sao; - try { - sao = new SeekAheadOptimize(undecodedChunk); - } catch (SeekAheadNoBackArrayException ignored) { - try { - skipControlCharactersStandard(); - } catch (IndexOutOfBoundsException e1) { - throw new NotEnoughDataDecoderException(e1); - } - return; - } - - while (sao.pos < sao.limit) { - char c = (char) (sao.bytes[sao.pos++] & 0xFF); - if (!Character.isISOControl(c) && !Character.isWhitespace(c)) { - sao.setReadPosition(1); - return; - } - } - throw new NotEnoughDataDecoderException("Access out of bounds"); - } - - void skipControlCharactersStandard() { - for (;;) { - char c = (char) undecodedChunk.readUnsignedByte(); - if (!Character.isISOControl(c) && !Character.isWhitespace(c)) { - undecodedChunk.readerIndex(undecodedChunk.readerIndex() - 1); - break; - } - } - } - - /** - * Find the next Multipart Delimiter - * - * @param delimiter - * delimiter to find - * @param dispositionStatus - * the next getStatus if the delimiter is a start - * @param closeDelimiterStatus - * the next getStatus if the delimiter is a close delimiter - * @return the next InterfaceHttpData if any - * @throws ErrorDataDecoderException - */ - private InterfaceHttpData findMultipartDelimiter(String delimiter, MultiPartStatus dispositionStatus, - MultiPartStatus closeDelimiterStatus) { - // --AaB03x or --AaB03x-- - int readerIndex = undecodedChunk.readerIndex(); - try { - skipControlCharacters(); - } catch (NotEnoughDataDecoderException ignored) { - undecodedChunk.readerIndex(readerIndex); - return null; - } - skipOneLine(); - String newline; - try { - newline = readDelimiter(delimiter); - } catch (NotEnoughDataDecoderException ignored) { - undecodedChunk.readerIndex(readerIndex); - return null; - } - if (newline.equals(delimiter)) { - currentStatus = dispositionStatus; - return decodeMultipart(dispositionStatus); - } - if (newline.equals(delimiter + "--")) { - // CLOSEDELIMITER or MIXED CLOSEDELIMITER found - currentStatus = closeDelimiterStatus; - if (currentStatus == MultiPartStatus.HEADERDELIMITER) { - // MIXEDCLOSEDELIMITER - // end of the Mixed part - currentFieldAttributes = null; - return decodeMultipart(MultiPartStatus.HEADERDELIMITER); - } - return null; - } - undecodedChunk.readerIndex(readerIndex); - throw new ErrorDataDecoderException("No Multipart delimiter found"); - } - - /** - * Find the next Disposition - * - * @return the next InterfaceHttpData if any - * @throws ErrorDataDecoderException - */ - private InterfaceHttpData findMultipartDisposition() { - int readerIndex = undecodedChunk.readerIndex(); - if (currentStatus == MultiPartStatus.DISPOSITION) { - currentFieldAttributes = new TreeMap(CaseIgnoringComparator.INSTANCE); - } - // read many lines until empty line with newline found! Store all data - while (!skipOneLine()) { - String newline; - try { - skipControlCharacters(); - newline = readLine(); - } catch (NotEnoughDataDecoderException ignored) { - undecodedChunk.readerIndex(readerIndex); - return null; - } - String[] contents = splitMultipartHeader(newline); - if (contents[0].equalsIgnoreCase(HttpPostBodyUtil.CONTENT_DISPOSITION)) { - boolean checkSecondArg; - if (currentStatus == MultiPartStatus.DISPOSITION) { - checkSecondArg = contents[1].equalsIgnoreCase(HttpPostBodyUtil.FORM_DATA); - } else { - checkSecondArg = contents[1].equalsIgnoreCase(HttpPostBodyUtil.ATTACHMENT) - || contents[1].equalsIgnoreCase(HttpPostBodyUtil.FILE); - } - if (checkSecondArg) { - // read next values and store them in the map as Attribute - for (int i = 2; i < contents.length; i++) { - String[] values = StringUtil.split(contents[i], '=', 2); - Attribute attribute; - try { - String name = cleanString(values[0]); - String value = values[1]; - - // See http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html - if (HttpPostBodyUtil.FILENAME.equals(name)) { - // filename value is quoted string so strip them - value = value.substring(1, value.length() - 1); - } else { - // otherwise we need to clean the value - value = cleanString(value); - } - attribute = factory.createAttribute(request, name, value); - } catch (NullPointerException e) { - throw new ErrorDataDecoderException(e); - } catch (IllegalArgumentException e) { - throw new ErrorDataDecoderException(e); - } - currentFieldAttributes.put(attribute.getName(), attribute); - } - } - } else if (contents[0].equalsIgnoreCase(HttpHeaders.Names.CONTENT_TRANSFER_ENCODING)) { - Attribute attribute; - try { - attribute = factory.createAttribute(request, HttpHeaders.Names.CONTENT_TRANSFER_ENCODING, - cleanString(contents[1])); - } catch (NullPointerException e) { - throw new ErrorDataDecoderException(e); - } catch (IllegalArgumentException e) { - throw new ErrorDataDecoderException(e); - } - currentFieldAttributes.put(HttpHeaders.Names.CONTENT_TRANSFER_ENCODING, attribute); - } else if (contents[0].equalsIgnoreCase(HttpHeaders.Names.CONTENT_LENGTH)) { - Attribute attribute; - try { - attribute = factory.createAttribute(request, HttpHeaders.Names.CONTENT_LENGTH, - cleanString(contents[1])); - } catch (NullPointerException e) { - throw new ErrorDataDecoderException(e); - } catch (IllegalArgumentException e) { - throw new ErrorDataDecoderException(e); - } - currentFieldAttributes.put(HttpHeaders.Names.CONTENT_LENGTH, attribute); - } else if (contents[0].equalsIgnoreCase(HttpHeaders.Names.CONTENT_TYPE)) { - // Take care of possible "multipart/mixed" - if (contents[1].equalsIgnoreCase(HttpPostBodyUtil.MULTIPART_MIXED)) { - if (currentStatus == MultiPartStatus.DISPOSITION) { - String values = StringUtil.substringAfter(contents[2], '='); - multipartMixedBoundary = "--" + values; - currentStatus = MultiPartStatus.MIXEDDELIMITER; - return decodeMultipart(MultiPartStatus.MIXEDDELIMITER); - } else { - throw new ErrorDataDecoderException("Mixed Multipart found in a previous Mixed Multipart"); - } - } else { - for (int i = 1; i < contents.length; i++) { - if (contents[i].toLowerCase().startsWith(HttpHeaders.Values.CHARSET)) { - String values = StringUtil.substringAfter(contents[i], '='); - Attribute attribute; - try { - attribute = factory.createAttribute(request, HttpHeaders.Values.CHARSET, - cleanString(values)); - } catch (NullPointerException e) { - throw new ErrorDataDecoderException(e); - } catch (IllegalArgumentException e) { - throw new ErrorDataDecoderException(e); - } - currentFieldAttributes.put(HttpHeaders.Values.CHARSET, attribute); - } else { - Attribute attribute; - try { - attribute = factory.createAttribute(request, - cleanString(contents[0]), contents[i]); - } catch (NullPointerException e) { - throw new ErrorDataDecoderException(e); - } catch (IllegalArgumentException e) { - throw new ErrorDataDecoderException(e); - } - currentFieldAttributes.put(attribute.getName(), attribute); - } - } - } - } else { - throw new ErrorDataDecoderException("Unknown Params: " + newline); - } - } - // Is it a FileUpload - Attribute filenameAttribute = currentFieldAttributes.get(HttpPostBodyUtil.FILENAME); - if (currentStatus == MultiPartStatus.DISPOSITION) { - if (filenameAttribute != null) { - // FileUpload - currentStatus = MultiPartStatus.FILEUPLOAD; - // do not change the buffer position - return decodeMultipart(MultiPartStatus.FILEUPLOAD); - } else { - // Field - currentStatus = MultiPartStatus.FIELD; - // do not change the buffer position - return decodeMultipart(MultiPartStatus.FIELD); - } - } else { - if (filenameAttribute != null) { - // FileUpload - currentStatus = MultiPartStatus.MIXEDFILEUPLOAD; - // do not change the buffer position - return decodeMultipart(MultiPartStatus.MIXEDFILEUPLOAD); - } else { - // Field is not supported in MIXED mode - throw new ErrorDataDecoderException("Filename not found"); - } - } - } - - /** - * Get the FileUpload (new one or current one) - * - * @param delimiter - * the delimiter to use - * @return the InterfaceHttpData if any - * @throws ErrorDataDecoderException - */ - protected InterfaceHttpData getFileUpload(String delimiter) { - // eventually restart from existing FileUpload - // Now get value according to Content-Type and Charset - Attribute encoding = currentFieldAttributes.get(HttpHeaders.Names.CONTENT_TRANSFER_ENCODING); - Charset localCharset = charset; - // Default - TransferEncodingMechanism mechanism = TransferEncodingMechanism.BIT7; - if (encoding != null) { - String code; - try { - code = encoding.getValue().toLowerCase(); - } catch (IOException e) { - throw new ErrorDataDecoderException(e); - } - if (code.equals(HttpPostBodyUtil.TransferEncodingMechanism.BIT7.value())) { - localCharset = HttpPostBodyUtil.US_ASCII; - } else if (code.equals(HttpPostBodyUtil.TransferEncodingMechanism.BIT8.value())) { - localCharset = HttpPostBodyUtil.ISO_8859_1; - mechanism = TransferEncodingMechanism.BIT8; - } else if (code.equals(HttpPostBodyUtil.TransferEncodingMechanism.BINARY.value())) { - // no real charset, so let the default - mechanism = TransferEncodingMechanism.BINARY; - } else { - throw new ErrorDataDecoderException("TransferEncoding Unknown: " + code); - } - } - Attribute charsetAttribute = currentFieldAttributes.get(HttpHeaders.Values.CHARSET); - if (charsetAttribute != null) { - try { - localCharset = Charset.forName(charsetAttribute.getValue()); - } catch (IOException e) { - throw new ErrorDataDecoderException(e); - } - } - if (currentFileUpload == null) { - Attribute filenameAttribute = currentFieldAttributes.get(HttpPostBodyUtil.FILENAME); - Attribute nameAttribute = currentFieldAttributes.get(HttpPostBodyUtil.NAME); - Attribute contentTypeAttribute = currentFieldAttributes.get(HttpHeaders.Names.CONTENT_TYPE); - if (contentTypeAttribute == null) { - throw new ErrorDataDecoderException("Content-Type is absent but required"); - } - Attribute lengthAttribute = currentFieldAttributes.get(HttpHeaders.Names.CONTENT_LENGTH); - long size; - try { - size = lengthAttribute != null ? Long.parseLong(lengthAttribute.getValue()) : 0L; - } catch (IOException e) { - throw new ErrorDataDecoderException(e); - } catch (NumberFormatException ignored) { - size = 0; - } - try { - currentFileUpload = factory.createFileUpload(request, - cleanString(nameAttribute.getValue()), cleanString(filenameAttribute.getValue()), - contentTypeAttribute.getValue(), mechanism.value(), localCharset, - size); - } catch (NullPointerException e) { - throw new ErrorDataDecoderException(e); - } catch (IllegalArgumentException e) { - throw new ErrorDataDecoderException(e); - } catch (IOException e) { - throw new ErrorDataDecoderException(e); - } - } - // load data as much as possible - try { - readFileUploadByteMultipart(delimiter); - } catch (NotEnoughDataDecoderException e) { - // do not change the buffer position - // since some can be already saved into FileUpload - // So do not change the currentStatus - return null; - } - if (currentFileUpload.isCompleted()) { - // ready to load the next one - if (currentStatus == MultiPartStatus.FILEUPLOAD) { - currentStatus = MultiPartStatus.HEADERDELIMITER; - currentFieldAttributes = null; - } else { - currentStatus = MultiPartStatus.MIXEDDELIMITER; - cleanMixedAttributes(); - } - FileUpload fileUpload = currentFileUpload; - currentFileUpload = null; - return fileUpload; - } - // do not change the buffer position - // since some can be already saved into FileUpload - // So do not change the currentStatus - return null; - } - - /** - * Destroy the {@link HttpPostMultipartRequestDecoder} and release all it resources. After this method - * was called it is not possible to operate on it anymore. - */ - @Override - public void destroy() { - checkDestroyed(); - cleanFiles(); - destroyed = true; - - if (undecodedChunk != null && undecodedChunk.refCnt() > 0) { - undecodedChunk.release(); - undecodedChunk = null; - } - - // release all data which was not yet pulled - for (int i = bodyListHttpDataRank; i < bodyListHttpData.size(); i++) { - bodyListHttpData.get(i).release(); - } - } - - /** - * Clean all HttpDatas (on Disk) for the current request. - */ - @Override - public void cleanFiles() { - checkDestroyed(); - - factory.cleanRequestHttpDatas(request); - } - - /** - * Remove the given FileUpload from the list of FileUploads to clean - */ - @Override - public void removeHttpDataFromClean(InterfaceHttpData data) { - checkDestroyed(); - - factory.removeHttpDataFromClean(request, data); - } - - /** - * Remove all Attributes that should be cleaned between two FileUpload in - * Mixed mode - */ - private void cleanMixedAttributes() { - currentFieldAttributes.remove(HttpHeaders.Values.CHARSET); - currentFieldAttributes.remove(HttpHeaders.Names.CONTENT_LENGTH); - currentFieldAttributes.remove(HttpHeaders.Names.CONTENT_TRANSFER_ENCODING); - currentFieldAttributes.remove(HttpHeaders.Names.CONTENT_TYPE); - currentFieldAttributes.remove(HttpPostBodyUtil.FILENAME); - } - - /** - * Read one line up to the CRLF or LF - * - * @return the String from one line - * @throws NotEnoughDataDecoderException - * Need more chunks and reset the readerInder to the previous - * value - */ - private String readLineStandard() { - int readerIndex = undecodedChunk.readerIndex(); - try { - ByteBuf line = buffer(64); - - while (undecodedChunk.isReadable()) { - byte nextByte = undecodedChunk.readByte(); - if (nextByte == HttpConstants.CR) { - // check but do not changed readerIndex - nextByte = undecodedChunk.getByte(undecodedChunk.readerIndex()); - if (nextByte == HttpConstants.LF) { - // force read - undecodedChunk.readByte(); - return line.toString(charset); - } else { - // Write CR (not followed by LF) - line.writeByte(HttpConstants.CR); - } - } else if (nextByte == HttpConstants.LF) { - return line.toString(charset); - } else { - line.writeByte(nextByte); - } - } - } catch (IndexOutOfBoundsException e) { - undecodedChunk.readerIndex(readerIndex); - throw new NotEnoughDataDecoderException(e); - } - undecodedChunk.readerIndex(readerIndex); - throw new NotEnoughDataDecoderException(); - } - - /** - * Read one line up to the CRLF or LF - * - * @return the String from one line - * @throws NotEnoughDataDecoderException - * Need more chunks and reset the readerInder to the previous - * value - */ - private String readLine() { - SeekAheadOptimize sao; - try { - sao = new SeekAheadOptimize(undecodedChunk); - } catch (SeekAheadNoBackArrayException ignored) { - return readLineStandard(); - } - int readerIndex = undecodedChunk.readerIndex(); - try { - ByteBuf line = buffer(64); - - while (sao.pos < sao.limit) { - byte nextByte = sao.bytes[sao.pos++]; - if (nextByte == HttpConstants.CR) { - if (sao.pos < sao.limit) { - nextByte = sao.bytes[sao.pos++]; - if (nextByte == HttpConstants.LF) { - sao.setReadPosition(0); - return line.toString(charset); - } else { - // Write CR (not followed by LF) - sao.pos--; - line.writeByte(HttpConstants.CR); - } - } else { - line.writeByte(nextByte); - } - } else if (nextByte == HttpConstants.LF) { - sao.setReadPosition(0); - return line.toString(charset); - } else { - line.writeByte(nextByte); - } - } - } catch (IndexOutOfBoundsException e) { - undecodedChunk.readerIndex(readerIndex); - throw new NotEnoughDataDecoderException(e); - } - undecodedChunk.readerIndex(readerIndex); - throw new NotEnoughDataDecoderException(); - } - - /** - * Read one line up to --delimiter or --delimiter-- and if existing the CRLF - * or LF Read one line up to --delimiter or --delimiter-- and if existing - * the CRLF or LF. Note that CRLF or LF are mandatory for opening delimiter - * (--delimiter) but not for closing delimiter (--delimiter--) since some - * clients does not include CRLF in this case. - * - * @param delimiter - * of the form --string, such that '--' is already included - * @return the String from one line as the delimiter searched (opening or - * closing) - * @throws NotEnoughDataDecoderException - * Need more chunks and reset the readerInder to the previous - * value - */ - private String readDelimiterStandard(String delimiter) { - int readerIndex = undecodedChunk.readerIndex(); - try { - StringBuilder sb = new StringBuilder(64); - int delimiterPos = 0; - int len = delimiter.length(); - while (undecodedChunk.isReadable() && delimiterPos < len) { - byte nextByte = undecodedChunk.readByte(); - if (nextByte == delimiter.charAt(delimiterPos)) { - delimiterPos++; - sb.append((char) nextByte); - } else { - // delimiter not found so break here ! - undecodedChunk.readerIndex(readerIndex); - throw new NotEnoughDataDecoderException(); - } - } - // Now check if either opening delimiter or closing delimiter - if (undecodedChunk.isReadable()) { - byte nextByte = undecodedChunk.readByte(); - // first check for opening delimiter - if (nextByte == HttpConstants.CR) { - nextByte = undecodedChunk.readByte(); - if (nextByte == HttpConstants.LF) { - return sb.toString(); - } else { - // error since CR must be followed by LF - // delimiter not found so break here ! - undecodedChunk.readerIndex(readerIndex); - throw new NotEnoughDataDecoderException(); - } - } else if (nextByte == HttpConstants.LF) { - return sb.toString(); - } else if (nextByte == '-') { - sb.append('-'); - // second check for closing delimiter - nextByte = undecodedChunk.readByte(); - if (nextByte == '-') { - sb.append('-'); - // now try to find if CRLF or LF there - if (undecodedChunk.isReadable()) { - nextByte = undecodedChunk.readByte(); - if (nextByte == HttpConstants.CR) { - nextByte = undecodedChunk.readByte(); - if (nextByte == HttpConstants.LF) { - return sb.toString(); - } else { - // error CR without LF - // delimiter not found so break here ! - undecodedChunk.readerIndex(readerIndex); - throw new NotEnoughDataDecoderException(); - } - } else if (nextByte == HttpConstants.LF) { - return sb.toString(); - } else { - // No CRLF but ok however (Adobe Flash uploader) - // minus 1 since we read one char ahead but - // should not - undecodedChunk.readerIndex(undecodedChunk.readerIndex() - 1); - return sb.toString(); - } - } - // FIXME what do we do here? - // either considering it is fine, either waiting for - // more data to come? - // lets try considering it is fine... - return sb.toString(); - } - // only one '-' => not enough - // whatever now => error since incomplete - } - } - } catch (IndexOutOfBoundsException e) { - undecodedChunk.readerIndex(readerIndex); - throw new NotEnoughDataDecoderException(e); - } - undecodedChunk.readerIndex(readerIndex); - throw new NotEnoughDataDecoderException(); - } - - /** - * Read one line up to --delimiter or --delimiter-- and if existing the CRLF - * or LF. Note that CRLF or LF are mandatory for opening delimiter - * (--delimiter) but not for closing delimiter (--delimiter--) since some - * clients does not include CRLF in this case. - * - * @param delimiter - * of the form --string, such that '--' is already included - * @return the String from one line as the delimiter searched (opening or - * closing) - * @throws NotEnoughDataDecoderException - * Need more chunks and reset the readerInder to the previous - * value - */ - private String readDelimiter(String delimiter) { - SeekAheadOptimize sao; - try { - sao = new SeekAheadOptimize(undecodedChunk); - } catch (SeekAheadNoBackArrayException ignored) { - return readDelimiterStandard(delimiter); - } - int readerIndex = undecodedChunk.readerIndex(); - int delimiterPos = 0; - int len = delimiter.length(); - try { - StringBuilder sb = new StringBuilder(64); - // check conformity with delimiter - while (sao.pos < sao.limit && delimiterPos < len) { - byte nextByte = sao.bytes[sao.pos++]; - if (nextByte == delimiter.charAt(delimiterPos)) { - delimiterPos++; - sb.append((char) nextByte); - } else { - // delimiter not found so break here ! - undecodedChunk.readerIndex(readerIndex); - throw new NotEnoughDataDecoderException(); - } - } - // Now check if either opening delimiter or closing delimiter - if (sao.pos < sao.limit) { - byte nextByte = sao.bytes[sao.pos++]; - if (nextByte == HttpConstants.CR) { - // first check for opening delimiter - if (sao.pos < sao.limit) { - nextByte = sao.bytes[sao.pos++]; - if (nextByte == HttpConstants.LF) { - sao.setReadPosition(0); - return sb.toString(); - } else { - // error CR without LF - // delimiter not found so break here ! - undecodedChunk.readerIndex(readerIndex); - throw new NotEnoughDataDecoderException(); - } - } else { - // error since CR must be followed by LF - // delimiter not found so break here ! - undecodedChunk.readerIndex(readerIndex); - throw new NotEnoughDataDecoderException(); - } - } else if (nextByte == HttpConstants.LF) { - // same first check for opening delimiter where LF used with - // no CR - sao.setReadPosition(0); - return sb.toString(); - } else if (nextByte == '-') { - sb.append('-'); - // second check for closing delimiter - if (sao.pos < sao.limit) { - nextByte = sao.bytes[sao.pos++]; - if (nextByte == '-') { - sb.append('-'); - // now try to find if CRLF or LF there - if (sao.pos < sao.limit) { - nextByte = sao.bytes[sao.pos++]; - if (nextByte == HttpConstants.CR) { - if (sao.pos < sao.limit) { - nextByte = sao.bytes[sao.pos++]; - if (nextByte == HttpConstants.LF) { - sao.setReadPosition(0); - return sb.toString(); - } else { - // error CR without LF - // delimiter not found so break here ! - undecodedChunk.readerIndex(readerIndex); - throw new NotEnoughDataDecoderException(); - } - } else { - // error CR without LF - // delimiter not found so break here ! - undecodedChunk.readerIndex(readerIndex); - throw new NotEnoughDataDecoderException(); - } - } else if (nextByte == HttpConstants.LF) { - sao.setReadPosition(0); - return sb.toString(); - } else { - // No CRLF but ok however (Adobe Flash - // uploader) - // minus 1 since we read one char ahead but - // should not - sao.setReadPosition(1); - return sb.toString(); - } - } - // FIXME what do we do here? - // either considering it is fine, either waiting for - // more data to come? - // lets try considering it is fine... - sao.setReadPosition(0); - return sb.toString(); - } - // whatever now => error since incomplete - // only one '-' => not enough or whatever not enough - // element - } - } - } - } catch (IndexOutOfBoundsException e) { - undecodedChunk.readerIndex(readerIndex); - throw new NotEnoughDataDecoderException(e); - } - undecodedChunk.readerIndex(readerIndex); - throw new NotEnoughDataDecoderException(); - } - - /** - * Read a FileUpload data as Byte (Binary) and add the bytes directly to the - * FileUpload. If the delimiter is found, the FileUpload is completed. - * - * @throws NotEnoughDataDecoderException - * Need more chunks but do not reset the readerInder since some - * values will be already added to the FileOutput - * @throws ErrorDataDecoderException - * write IO error occurs with the FileUpload - */ - private void readFileUploadByteMultipartStandard(String delimiter) { - int readerIndex = undecodedChunk.readerIndex(); - // found the decoder limit - boolean newLine = true; - int index = 0; - int lastPosition = undecodedChunk.readerIndex(); - boolean found = false; - while (undecodedChunk.isReadable()) { - byte nextByte = undecodedChunk.readByte(); - if (newLine) { - // Check the delimiter - if (nextByte == delimiter.codePointAt(index)) { - index++; - if (delimiter.length() == index) { - found = true; - break; - } - continue; - } else { - newLine = false; - index = 0; - // continue until end of line - if (nextByte == HttpConstants.CR) { - if (undecodedChunk.isReadable()) { - nextByte = undecodedChunk.readByte(); - if (nextByte == HttpConstants.LF) { - newLine = true; - index = 0; - lastPosition = undecodedChunk.readerIndex() - 2; - } else { - // save last valid position - lastPosition = undecodedChunk.readerIndex() - 1; - - // Unread next byte. - undecodedChunk.readerIndex(lastPosition); - } - } - } else if (nextByte == HttpConstants.LF) { - newLine = true; - index = 0; - lastPosition = undecodedChunk.readerIndex() - 1; - } else { - // save last valid position - lastPosition = undecodedChunk.readerIndex(); - } - } - } else { - // continue until end of line - if (nextByte == HttpConstants.CR) { - if (undecodedChunk.isReadable()) { - nextByte = undecodedChunk.readByte(); - if (nextByte == HttpConstants.LF) { - newLine = true; - index = 0; - lastPosition = undecodedChunk.readerIndex() - 2; - } else { - // save last valid position - lastPosition = undecodedChunk.readerIndex() - 1; - - // Unread next byte. - undecodedChunk.readerIndex(lastPosition); - } - } - } else if (nextByte == HttpConstants.LF) { - newLine = true; - index = 0; - lastPosition = undecodedChunk.readerIndex() - 1; - } else { - // save last valid position - lastPosition = undecodedChunk.readerIndex(); - } - } - } - ByteBuf buffer = undecodedChunk.copy(readerIndex, lastPosition - readerIndex); - if (found) { - // found so lastPosition is correct and final - try { - currentFileUpload.addContent(buffer, true); - // just before the CRLF and delimiter - undecodedChunk.readerIndex(lastPosition); - } catch (IOException e) { - throw new ErrorDataDecoderException(e); - } - } else { - // possibly the delimiter is partially found but still the last - // position is OK - try { - currentFileUpload.addContent(buffer, false); - // last valid char (not CR, not LF, not beginning of delimiter) - undecodedChunk.readerIndex(lastPosition); - throw new NotEnoughDataDecoderException(); - } catch (IOException e) { - throw new ErrorDataDecoderException(e); - } - } - } - - /** - * Read a FileUpload data as Byte (Binary) and add the bytes directly to the - * FileUpload. If the delimiter is found, the FileUpload is completed. - * - * @throws NotEnoughDataDecoderException - * Need more chunks but do not reset the readerInder since some - * values will be already added to the FileOutput - * @throws ErrorDataDecoderException - * write IO error occurs with the FileUpload - */ - private void readFileUploadByteMultipart(String delimiter) { - SeekAheadOptimize sao; - try { - sao = new SeekAheadOptimize(undecodedChunk); - } catch (SeekAheadNoBackArrayException ignored) { - readFileUploadByteMultipartStandard(delimiter); - return; - } - int readerIndex = undecodedChunk.readerIndex(); - // found the decoder limit - boolean newLine = true; - int index = 0; - int lastrealpos = sao.pos; - int lastPosition; - boolean found = false; - - while (sao.pos < sao.limit) { - byte nextByte = sao.bytes[sao.pos++]; - if (newLine) { - // Check the delimiter - if (nextByte == delimiter.codePointAt(index)) { - index++; - if (delimiter.length() == index) { - found = true; - break; - } - continue; - } else { - newLine = false; - index = 0; - // continue until end of line - if (nextByte == HttpConstants.CR) { - if (sao.pos < sao.limit) { - nextByte = sao.bytes[sao.pos++]; - if (nextByte == HttpConstants.LF) { - newLine = true; - index = 0; - lastrealpos = sao.pos - 2; - } else { - // unread next byte - sao.pos--; - - // save last valid position - lastrealpos = sao.pos; - } - } - } else if (nextByte == HttpConstants.LF) { - newLine = true; - index = 0; - lastrealpos = sao.pos - 1; - } else { - // save last valid position - lastrealpos = sao.pos; - } - } - } else { - // continue until end of line - if (nextByte == HttpConstants.CR) { - if (sao.pos < sao.limit) { - nextByte = sao.bytes[sao.pos++]; - if (nextByte == HttpConstants.LF) { - newLine = true; - index = 0; - lastrealpos = sao.pos - 2; - } else { - // unread next byte - sao.pos--; - - // save last valid position - lastrealpos = sao.pos; - } - } - } else if (nextByte == HttpConstants.LF) { - newLine = true; - index = 0; - lastrealpos = sao.pos - 1; - } else { - // save last valid position - lastrealpos = sao.pos; - } - } - } - lastPosition = sao.getReadPosition(lastrealpos); - ByteBuf buffer = undecodedChunk.copy(readerIndex, lastPosition - readerIndex); - if (found) { - // found so lastPosition is correct and final - try { - currentFileUpload.addContent(buffer, true); - // just before the CRLF and delimiter - undecodedChunk.readerIndex(lastPosition); - } catch (IOException e) { - throw new ErrorDataDecoderException(e); - } - } else { - // possibly the delimiter is partially found but still the last - // position is OK - try { - currentFileUpload.addContent(buffer, false); - // last valid char (not CR, not LF, not beginning of delimiter) - undecodedChunk.readerIndex(lastPosition); - throw new NotEnoughDataDecoderException(); - } catch (IOException e) { - throw new ErrorDataDecoderException(e); - } - } - } - - /** - * Load the field value from a Multipart request - * - * @throws NotEnoughDataDecoderException - * Need more chunks - * @throws ErrorDataDecoderException - */ - private void loadFieldMultipartStandard(String delimiter) { - int readerIndex = undecodedChunk.readerIndex(); - try { - // found the decoder limit - boolean newLine = true; - int index = 0; - int lastPosition = undecodedChunk.readerIndex(); - boolean found = false; - while (undecodedChunk.isReadable()) { - byte nextByte = undecodedChunk.readByte(); - if (newLine) { - // Check the delimiter - if (nextByte == delimiter.codePointAt(index)) { - index++; - if (delimiter.length() == index) { - found = true; - break; - } - continue; - } else { - newLine = false; - index = 0; - // continue until end of line - if (nextByte == HttpConstants.CR) { - if (undecodedChunk.isReadable()) { - nextByte = undecodedChunk.readByte(); - if (nextByte == HttpConstants.LF) { - newLine = true; - index = 0; - lastPosition = undecodedChunk.readerIndex() - 2; - } else { - // Unread second nextByte - lastPosition = undecodedChunk.readerIndex() - 1; - undecodedChunk.readerIndex(lastPosition); - } - } else { - lastPosition = undecodedChunk.readerIndex() - 1; - } - } else if (nextByte == HttpConstants.LF) { - newLine = true; - index = 0; - lastPosition = undecodedChunk.readerIndex() - 1; - } else { - lastPosition = undecodedChunk.readerIndex(); - } - } - } else { - // continue until end of line - if (nextByte == HttpConstants.CR) { - if (undecodedChunk.isReadable()) { - nextByte = undecodedChunk.readByte(); - if (nextByte == HttpConstants.LF) { - newLine = true; - index = 0; - lastPosition = undecodedChunk.readerIndex() - 2; - } else { - // Unread second nextByte - lastPosition = undecodedChunk.readerIndex() - 1; - undecodedChunk.readerIndex(lastPosition); - } - } else { - lastPosition = undecodedChunk.readerIndex() - 1; - } - } else if (nextByte == HttpConstants.LF) { - newLine = true; - index = 0; - lastPosition = undecodedChunk.readerIndex() - 1; - } else { - lastPosition = undecodedChunk.readerIndex(); - } - } - } - if (found) { - // found so lastPosition is correct - // but position is just after the delimiter (either close - // delimiter or simple one) - // so go back of delimiter size - try { - currentAttribute.addContent( - undecodedChunk.copy(readerIndex, lastPosition - readerIndex), true); - } catch (IOException e) { - throw new ErrorDataDecoderException(e); - } - undecodedChunk.readerIndex(lastPosition); - } else { - try { - currentAttribute.addContent( - undecodedChunk.copy(readerIndex, lastPosition - readerIndex), false); - } catch (IOException e) { - throw new ErrorDataDecoderException(e); - } - undecodedChunk.readerIndex(lastPosition); - throw new NotEnoughDataDecoderException(); - } - } catch (IndexOutOfBoundsException e) { - undecodedChunk.readerIndex(readerIndex); - throw new NotEnoughDataDecoderException(e); - } - } - - /** - * Load the field value from a Multipart request - * - * @throws NotEnoughDataDecoderException - * Need more chunks - * @throws ErrorDataDecoderException - */ - private void loadFieldMultipart(String delimiter) { - SeekAheadOptimize sao; - try { - sao = new SeekAheadOptimize(undecodedChunk); - } catch (SeekAheadNoBackArrayException ignored) { - loadFieldMultipartStandard(delimiter); - return; - } - int readerIndex = undecodedChunk.readerIndex(); - try { - // found the decoder limit - boolean newLine = true; - int index = 0; - int lastPosition; - int lastrealpos = sao.pos; - boolean found = false; - - while (sao.pos < sao.limit) { - byte nextByte = sao.bytes[sao.pos++]; - if (newLine) { - // Check the delimiter - if (nextByte == delimiter.codePointAt(index)) { - index++; - if (delimiter.length() == index) { - found = true; - break; - } - continue; - } else { - newLine = false; - index = 0; - // continue until end of line - if (nextByte == HttpConstants.CR) { - if (sao.pos < sao.limit) { - nextByte = sao.bytes[sao.pos++]; - if (nextByte == HttpConstants.LF) { - newLine = true; - index = 0; - lastrealpos = sao.pos - 2; - } else { - // Unread last nextByte - sao.pos--; - lastrealpos = sao.pos; - } - } - } else if (nextByte == HttpConstants.LF) { - newLine = true; - index = 0; - lastrealpos = sao.pos - 1; - } else { - lastrealpos = sao.pos; - } - } - } else { - // continue until end of line - if (nextByte == HttpConstants.CR) { - if (sao.pos < sao.limit) { - nextByte = sao.bytes[sao.pos++]; - if (nextByte == HttpConstants.LF) { - newLine = true; - index = 0; - lastrealpos = sao.pos - 2; - } else { - // Unread last nextByte - sao.pos--; - lastrealpos = sao.pos; - } - } - } else if (nextByte == HttpConstants.LF) { - newLine = true; - index = 0; - lastrealpos = sao.pos - 1; - } else { - lastrealpos = sao.pos; - } - } - } - lastPosition = sao.getReadPosition(lastrealpos); - if (found) { - // found so lastPosition is correct - // but position is just after the delimiter (either close - // delimiter or simple one) - // so go back of delimiter size - try { - currentAttribute.addContent( - undecodedChunk.copy(readerIndex, lastPosition - readerIndex), true); - } catch (IOException e) { - throw new ErrorDataDecoderException(e); - } - undecodedChunk.readerIndex(lastPosition); - } else { - try { - currentAttribute.addContent( - undecodedChunk.copy(readerIndex, lastPosition - readerIndex), false); - } catch (IOException e) { - throw new ErrorDataDecoderException(e); - } - undecodedChunk.readerIndex(lastPosition); - throw new NotEnoughDataDecoderException(); - } - } catch (IndexOutOfBoundsException e) { - undecodedChunk.readerIndex(readerIndex); - throw new NotEnoughDataDecoderException(e); - } - } - - /** - * Clean the String from any unallowed character - * - * @return the cleaned String - */ - @SuppressWarnings("IfStatementWithIdenticalBranches") - private static String cleanString(String field) { - StringBuilder sb = new StringBuilder(field.length()); - for (int i = 0; i < field.length(); i++) { - char nextChar = field.charAt(i); - if (nextChar == HttpConstants.COLON) { - sb.append(HttpConstants.SP_CHAR); - } else if (nextChar == HttpConstants.COMMA) { - sb.append(HttpConstants.SP_CHAR); - } else if (nextChar == HttpConstants.EQUALS) { - sb.append(HttpConstants.SP_CHAR); - } else if (nextChar == HttpConstants.SEMICOLON) { - sb.append(HttpConstants.SP_CHAR); - } else if (nextChar == HttpConstants.HT) { - sb.append(HttpConstants.SP_CHAR); - } else if (nextChar == HttpConstants.DOUBLE_QUOTE) { - // nothing added, just removes it - } else { - sb.append(nextChar); - } - } - return sb.toString().trim(); - } - - /** - * Skip one empty line - * - * @return True if one empty line was skipped - */ - private boolean skipOneLine() { - if (!undecodedChunk.isReadable()) { - return false; - } - byte nextByte = undecodedChunk.readByte(); - if (nextByte == HttpConstants.CR) { - if (!undecodedChunk.isReadable()) { - undecodedChunk.readerIndex(undecodedChunk.readerIndex() - 1); - return false; - } - nextByte = undecodedChunk.readByte(); - if (nextByte == HttpConstants.LF) { - return true; - } - undecodedChunk.readerIndex(undecodedChunk.readerIndex() - 2); - return false; - } - if (nextByte == HttpConstants.LF) { - return true; - } - undecodedChunk.readerIndex(undecodedChunk.readerIndex() - 1); - return false; - } - - /** - * Split one header in Multipart - * - * @return an array of String where rank 0 is the name of the header, - * follows by several values that were separated by ';' or ',' - */ - private static String[] splitMultipartHeader(String sb) { - ArrayList headers = new ArrayList(1); - int nameStart; - int nameEnd; - int colonEnd; - int valueStart; - int valueEnd; - nameStart = HttpPostBodyUtil.findNonWhitespace(sb, 0); - for (nameEnd = nameStart; nameEnd < sb.length(); nameEnd++) { - char ch = sb.charAt(nameEnd); - if (ch == ':' || Character.isWhitespace(ch)) { - break; - } - } - for (colonEnd = nameEnd; colonEnd < sb.length(); colonEnd++) { - if (sb.charAt(colonEnd) == ':') { - colonEnd++; - break; - } - } - valueStart = HttpPostBodyUtil.findNonWhitespace(sb, colonEnd); - valueEnd = HttpPostBodyUtil.findEndOfString(sb); - headers.add(sb.substring(nameStart, nameEnd)); - String svalue = sb.substring(valueStart, valueEnd); - String[] values; - if (svalue.indexOf(';') >= 0) { - values = splitMultipartHeaderValues(svalue); - } else { - values = StringUtil.split(svalue, ','); - } - for (String value : values) { - headers.add(value.trim()); - } - String[] array = new String[headers.size()]; - for (int i = 0; i < headers.size(); i++) { - array[i] = headers.get(i); - } - return array; - } - - /** - * Split one header value in Multipart - * @return an array of String where values that were separated by ';' or ',' - */ - private static String[] splitMultipartHeaderValues(String svalue) { - List values = new ArrayList(1); - boolean inQuote = false; - boolean escapeNext = false; - int start = 0; - for (int i = 0; i < svalue.length(); i++) { - char c = svalue.charAt(i); - if (inQuote) { - if (escapeNext) { - escapeNext = false; - } else { - if (c == '\\') { - escapeNext = true; - } else if (c == '"') { - inQuote = false; - } - } - } else { - if (c == '"') { - inQuote = true; - } else if (c == ';') { - values.add(svalue.substring(start, i)); - start = i + 1; - } - } - } - values.add(svalue.substring(start)); - return values.toArray(new String[values.size()]); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/HttpPostRequestDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/HttpPostRequestDecoder.java deleted file mode 100755 index 9360c69754..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/HttpPostRequestDecoder.java +++ /dev/null @@ -1,393 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.multipart; - -import java.nio.charset.Charset; -import java.util.List; - -import com.ai.cloud.io.netty.handler.codec.DecoderException; -import com.ai.cloud.io.netty.handler.codec.http.HttpConstants; -import com.ai.cloud.io.netty.handler.codec.http.HttpContent; -import com.ai.cloud.io.netty.handler.codec.http.HttpHeaders; -import com.ai.cloud.io.netty.handler.codec.http.HttpRequest; -import com.ai.cloud.io.netty.util.internal.StringUtil; - -/** - * This decoder will decode Body and can handle POST BODY. - * - * You MUST call {@link #destroy()} after completion to release all resources. - * - */ -public class HttpPostRequestDecoder implements InterfaceHttpPostRequestDecoder { - - static final int DEFAULT_DISCARD_THRESHOLD = 10 * 1024 * 1024; - - private final InterfaceHttpPostRequestDecoder decoder; - - /** - * - * @param request - * the request to decode - * @throws NullPointerException - * for request - * @throws ErrorDataDecoderException - * if the default charset was wrong when decoding or other - * errors - * @throws IncompatibleDataDecoderException - * This exception is deprecated - */ - public HttpPostRequestDecoder(HttpRequest request) - throws ErrorDataDecoderException, IncompatibleDataDecoderException { - this(new DefaultHttpDataFactory(DefaultHttpDataFactory.MINSIZE), request, HttpConstants.DEFAULT_CHARSET); - } - - /** - * - * @param factory - * the factory used to create InterfaceHttpData - * @param request - * the request to decode - * @throws NullPointerException - * for request or factory - * @throws ErrorDataDecoderException - * if the default charset was wrong when decoding or other - * errors - * @throws IncompatibleDataDecoderException - * This exception is deprecated - */ - public HttpPostRequestDecoder(HttpDataFactory factory, HttpRequest request) - throws ErrorDataDecoderException, IncompatibleDataDecoderException { - this(factory, request, HttpConstants.DEFAULT_CHARSET); - } - - /** - * - * @param factory - * the factory used to create InterfaceHttpData - * @param request - * the request to decode - * @param charset - * the charset to use as default - * @throws NullPointerException - * for request or charset or factory - * @throws ErrorDataDecoderException - * if the default charset was wrong when decoding or other - * errors - * @throws IncompatibleDataDecoderException - * This exception is deprecated - */ - public HttpPostRequestDecoder(HttpDataFactory factory, HttpRequest request, Charset charset) - throws ErrorDataDecoderException, IncompatibleDataDecoderException { - if (factory == null) { - throw new NullPointerException("factory"); - } - if (request == null) { - throw new NullPointerException("request"); - } - if (charset == null) { - throw new NullPointerException("charset"); - } - // Fill default values - if (isMultipart(request)) { - decoder = new HttpPostMultipartRequestDecoder(factory, request, charset); - } else { - decoder = new HttpPostStandardRequestDecoder(factory, request, charset); - } - } - - /** - * states follow NOTSTARTED PREAMBLE ( (HEADERDELIMITER DISPOSITION (FIELD | - * FILEUPLOAD))* (HEADERDELIMITER DISPOSITION MIXEDPREAMBLE (MIXEDDELIMITER - * MIXEDDISPOSITION MIXEDFILEUPLOAD)+ MIXEDCLOSEDELIMITER)* CLOSEDELIMITER)+ - * EPILOGUE - * - * First getStatus is: NOSTARTED - * - * Content-type: multipart/form-data, boundary=AaB03x => PREAMBLE in Header - * - * --AaB03x => HEADERDELIMITER content-disposition: form-data; name="field1" - * => DISPOSITION - * - * Joe Blow => FIELD --AaB03x => HEADERDELIMITER content-disposition: - * form-data; name="pics" => DISPOSITION Content-type: multipart/mixed, - * boundary=BbC04y - * - * --BbC04y => MIXEDDELIMITER Content-disposition: attachment; - * filename="file1.txt" => MIXEDDISPOSITION Content-Type: text/plain - * - * ... contents of file1.txt ... => MIXEDFILEUPLOAD --BbC04y => - * MIXEDDELIMITER Content-disposition: file; filename="file2.gif" => - * MIXEDDISPOSITION Content-type: image/gif Content-Transfer-Encoding: - * binary - * - * ...contents of file2.gif... => MIXEDFILEUPLOAD --BbC04y-- => - * MIXEDCLOSEDELIMITER --AaB03x-- => CLOSEDELIMITER - * - * Once CLOSEDELIMITER is found, last getStatus is EPILOGUE - */ - protected enum MultiPartStatus { - NOTSTARTED, PREAMBLE, HEADERDELIMITER, DISPOSITION, FIELD, FILEUPLOAD, MIXEDPREAMBLE, MIXEDDELIMITER, - MIXEDDISPOSITION, MIXEDFILEUPLOAD, MIXEDCLOSEDELIMITER, CLOSEDELIMITER, PREEPILOGUE, EPILOGUE - } - - /** - * Check if the given request is a multipart request - * @return True if the request is a Multipart request - */ - public static boolean isMultipart(HttpRequest request) { - if (request.headers().contains(HttpHeaders.Names.CONTENT_TYPE)) { - return getMultipartDataBoundary(request.headers().get(HttpHeaders.Names.CONTENT_TYPE)) != null; - } else { - return false; - } - } - - /** - * Check from the request ContentType if this request is a Multipart request. - * @return an array of String if multipartDataBoundary exists with the multipartDataBoundary - * as first element, charset if any as second (missing if not set), else null - */ - protected static String[] getMultipartDataBoundary(String contentType) { - // Check if Post using "multipart/form-data; boundary=--89421926422648 [; charset=xxx]" - String[] headerContentType = splitHeaderContentType(contentType); - if (headerContentType[0].toLowerCase().startsWith( - HttpHeaders.Values.MULTIPART_FORM_DATA)) { - int mrank; - int crank; - if (headerContentType[1].toLowerCase().startsWith( - HttpHeaders.Values.BOUNDARY)) { - mrank = 1; - crank = 2; - } else if (headerContentType[2].toLowerCase().startsWith( - HttpHeaders.Values.BOUNDARY)) { - mrank = 2; - crank = 1; - } else { - return null; - } - String boundary = StringUtil.substringAfter(headerContentType[mrank], '='); - if (boundary == null) { - throw new ErrorDataDecoderException("Needs a boundary value"); - } - if (boundary.charAt(0) == '"') { - String bound = boundary.trim(); - int index = bound.length() - 1; - if (bound.charAt(index) == '"') { - boundary = bound.substring(1, index); - } - } - if (headerContentType[crank].toLowerCase().startsWith( - HttpHeaders.Values.CHARSET)) { - String charset = StringUtil.substringAfter(headerContentType[crank], '='); - if (charset != null) { - return new String[] {"--" + boundary, charset}; - } - } - return new String[] {"--" + boundary}; - } - return null; - } - - @Override - public boolean isMultipart() { - return decoder.isMultipart(); - } - - @Override - public void setDiscardThreshold(int discardThreshold) { - decoder.setDiscardThreshold(discardThreshold); - } - - @Override - public int getDiscardThreshold() { - return decoder.getDiscardThreshold(); - } - - @Override - public List getBodyHttpDatas() { - return decoder.getBodyHttpDatas(); - } - - @Override - public List getBodyHttpDatas(String name) { - return decoder.getBodyHttpDatas(name); - } - - @Override - public InterfaceHttpData getBodyHttpData(String name) { - return decoder.getBodyHttpData(name); - } - - @Override - public InterfaceHttpPostRequestDecoder offer(HttpContent content) { - return decoder.offer(content); - } - - @Override - public boolean hasNext() { - return decoder.hasNext(); - } - - @Override - public InterfaceHttpData next() { - return decoder.next(); - } - - @Override - public void destroy() { - decoder.destroy(); - } - - @Override - public void cleanFiles() { - decoder.cleanFiles(); - } - - @Override - public void removeHttpDataFromClean(InterfaceHttpData data) { - decoder.removeHttpDataFromClean(data); - } - /** - * Utility function to add a new decoded data - */ - protected void addHttpData(InterfaceHttpData data) { - if (decoder instanceof HttpPostMultipartRequestDecoder) { - ((HttpPostMultipartRequestDecoder) decoder).addHttpData(data); - } else { - ((HttpPostStandardRequestDecoder) decoder).addHttpData(data); - } - } - /** - * Get the FileUpload (new one or current one) - * - * @param delimiter - * the delimiter to use - * @return the InterfaceHttpData if any - * @throws ErrorDataDecoderException - */ - protected InterfaceHttpData getFileUpload(String delimiter) { - if (decoder instanceof HttpPostMultipartRequestDecoder) { - ((HttpPostMultipartRequestDecoder) decoder).getFileUpload(delimiter); - } - return null; - } - /** - * Split the very first line (Content-Type value) in 3 Strings - * - * @return the array of 3 Strings - */ - private static String[] splitHeaderContentType(String sb) { - int aStart; - int aEnd; - int bStart; - int bEnd; - int cStart; - int cEnd; - aStart = HttpPostBodyUtil.findNonWhitespace(sb, 0); - aEnd = sb.indexOf(';'); - if (aEnd == -1) { - return new String[] { sb, "", "" }; - } - bStart = HttpPostBodyUtil.findNonWhitespace(sb, aEnd + 1); - if (sb.charAt(aEnd - 1) == ' ') { - aEnd--; - } - bEnd = sb.indexOf(';', bStart); - if (bEnd == -1) { - bEnd = HttpPostBodyUtil.findEndOfString(sb); - return new String[] { sb.substring(aStart, aEnd), sb.substring(bStart, bEnd), "" }; - } - cStart = HttpPostBodyUtil.findNonWhitespace(sb, bEnd + 1); - if (sb.charAt(bEnd - 1) == ' ') { - bEnd--; - } - cEnd = HttpPostBodyUtil.findEndOfString(sb); - return new String[] { sb.substring(aStart, aEnd), sb.substring(bStart, bEnd), sb.substring(cStart, cEnd) }; - } - - /** - * Exception when try reading data from request in chunked format, and not - * enough data are available (need more chunks) - */ - public static class NotEnoughDataDecoderException extends DecoderException { - private static final long serialVersionUID = -7846841864603865638L; - - public NotEnoughDataDecoderException() { - } - - public NotEnoughDataDecoderException(String msg) { - super(msg); - } - - public NotEnoughDataDecoderException(Throwable cause) { - super(cause); - } - - public NotEnoughDataDecoderException(String msg, Throwable cause) { - super(msg, cause); - } - } - - /** - * Exception when the body is fully decoded, even if there is still data - */ - public static class EndOfDataDecoderException extends DecoderException { - private static final long serialVersionUID = 1336267941020800769L; - } - - /** - * Exception when an error occurs while decoding - */ - public static class ErrorDataDecoderException extends DecoderException { - private static final long serialVersionUID = 5020247425493164465L; - - public ErrorDataDecoderException() { - } - - public ErrorDataDecoderException(String msg) { - super(msg); - } - - public ErrorDataDecoderException(Throwable cause) { - super(cause); - } - - public ErrorDataDecoderException(String msg, Throwable cause) { - super(msg, cause); - } - } - /** - * Exception when an unappropriated getMethod was called on a request - */ - public static class IncompatibleDataDecoderException extends DecoderException { - private static final long serialVersionUID = -953268047926250267L; - - public IncompatibleDataDecoderException() { - } - - public IncompatibleDataDecoderException(String msg) { - super(msg); - } - - public IncompatibleDataDecoderException(Throwable cause) { - super(cause); - } - - public IncompatibleDataDecoderException(String msg, Throwable cause) { - super(msg, cause); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/HttpPostRequestEncoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/HttpPostRequestEncoder.java deleted file mode 100755 index 4ec08c5cec..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/HttpPostRequestEncoder.java +++ /dev/null @@ -1,1234 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.multipart; - -import java.io.File; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; -import java.util.regex.Pattern; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.handler.codec.DecoderResult; -import com.ai.cloud.io.netty.handler.codec.http.DefaultFullHttpRequest; -import com.ai.cloud.io.netty.handler.codec.http.DefaultHttpContent; -import com.ai.cloud.io.netty.handler.codec.http.FullHttpRequest; -import com.ai.cloud.io.netty.handler.codec.http.HttpConstants; -import com.ai.cloud.io.netty.handler.codec.http.HttpContent; -import com.ai.cloud.io.netty.handler.codec.http.HttpHeaders; -import com.ai.cloud.io.netty.handler.codec.http.HttpMethod; -import com.ai.cloud.io.netty.handler.codec.http.HttpRequest; -import com.ai.cloud.io.netty.handler.codec.http.HttpVersion; -import com.ai.cloud.io.netty.handler.codec.http.LastHttpContent; -import com.ai.cloud.io.netty.handler.stream.ChunkedInput; -import com.ai.cloud.io.netty.util.internal.ThreadLocalRandom; - -import static com.ai.cloud.io.netty.buffer.Unpooled.*; - -/** - * This encoder will help to encode Request for a FORM as POST. - */ -public class HttpPostRequestEncoder implements ChunkedInput { - /** - * Different modes to use to encode form data. - */ - public enum EncoderMode { - /** - * Legacy mode which should work for most. It is known to not work with OAUTH. For OAUTH use - * {@link EncoderMode#RFC3986}. The W3C form recommentations this for submitting post form data. - */ - RFC1738, - - /** - * Mode which is more new and is used for OAUTH - */ - RFC3986 - } - - private static final Map percentEncodings = new HashMap(); - - static { - percentEncodings.put(Pattern.compile("\\*"), "%2A"); - percentEncodings.put(Pattern.compile("\\+"), "%20"); - percentEncodings.put(Pattern.compile("%7E"), "~"); - } - - /** - * Factory used to create InterfaceHttpData - */ - private final HttpDataFactory factory; - - /** - * Request to encode - */ - private final HttpRequest request; - - /** - * Default charset to use - */ - private final Charset charset; - - /** - * Chunked false by default - */ - private boolean isChunked; - - /** - * InterfaceHttpData for Body (without encoding) - */ - private final List bodyListDatas; - /** - * The final Multipart List of InterfaceHttpData including encoding - */ - final List multipartHttpDatas; - - /** - * Does this request is a Multipart request - */ - private final boolean isMultipart; - - /** - * If multipart, this is the boundary for the flobal multipart - */ - String multipartDataBoundary; - - /** - * If multipart, there could be internal multiparts (mixed) to the global multipart. Only one level is allowed. - */ - String multipartMixedBoundary; - /** - * To check if the header has been finalized - */ - private boolean headerFinalized; - - private final EncoderMode encoderMode; - - /** - * - * @param request - * the request to encode - * @param multipart - * True if the FORM is a ENCTYPE="multipart/form-data" - * @throws NullPointerException - * for request - * @throws ErrorDataEncoderException - * if the request is not a POST - */ - public HttpPostRequestEncoder(HttpRequest request, boolean multipart) throws ErrorDataEncoderException { - this(new DefaultHttpDataFactory(DefaultHttpDataFactory.MINSIZE), request, multipart, - HttpConstants.DEFAULT_CHARSET, EncoderMode.RFC1738); - } - - /** - * - * @param factory - * the factory used to create InterfaceHttpData - * @param request - * the request to encode - * @param multipart - * True if the FORM is a ENCTYPE="multipart/form-data" - * @throws NullPointerException - * for request and factory - * @throws ErrorDataEncoderException - * if the request is not a POST - */ - public HttpPostRequestEncoder(HttpDataFactory factory, HttpRequest request, boolean multipart) - throws ErrorDataEncoderException { - this(factory, request, multipart, HttpConstants.DEFAULT_CHARSET, EncoderMode.RFC1738); - } - - /** - * - * @param factory - * the factory used to create InterfaceHttpData - * @param request - * the request to encode - * @param multipart - * True if the FORM is a ENCTYPE="multipart/form-data" - * @param charset - * the charset to use as default - * @param encoderMode - * the mode for the encoder to use. See {@link EncoderMode} for the details. - * @throws NullPointerException - * for request or charset or factory - * @throws ErrorDataEncoderException - * if the request is not a POST - */ - public HttpPostRequestEncoder( - HttpDataFactory factory, HttpRequest request, boolean multipart, Charset charset, - EncoderMode encoderMode) - throws ErrorDataEncoderException { - if (factory == null) { - throw new NullPointerException("factory"); - } - if (request == null) { - throw new NullPointerException("request"); - } - if (charset == null) { - throw new NullPointerException("charset"); - } - if (request.getMethod() != HttpMethod.POST) { - throw new ErrorDataEncoderException("Cannot create a Encoder if not a POST"); - } - this.request = request; - this.charset = charset; - this.factory = factory; - // Fill default values - bodyListDatas = new ArrayList(); - // default mode - isLastChunk = false; - isLastChunkSent = false; - isMultipart = multipart; - multipartHttpDatas = new ArrayList(); - this.encoderMode = encoderMode; - if (isMultipart) { - initDataMultipart(); - } - } - - /** - * Clean all HttpDatas (on Disk) for the current request. - */ - public void cleanFiles() { - factory.cleanRequestHttpDatas(request); - } - - /** - * Does the last non empty chunk already encoded so that next chunk will be empty (last chunk) - */ - private boolean isLastChunk; - /** - * Last chunk already sent - */ - private boolean isLastChunkSent; - /** - * The current FileUpload that is currently in encode process - */ - private FileUpload currentFileUpload; - /** - * While adding a FileUpload, is the multipart currently in Mixed Mode - */ - private boolean duringMixedMode; - - /** - * Global Body size - */ - private long globalBodySize; - - /** - * True if this request is a Multipart request - * - * @return True if this request is a Multipart request - */ - public boolean isMultipart() { - return isMultipart; - } - - /** - * Init the delimiter for Global Part (Data). - */ - private void initDataMultipart() { - multipartDataBoundary = getNewMultipartDelimiter(); - } - - /** - * Init the delimiter for Mixed Part (Mixed). - */ - private void initMixedMultipart() { - multipartMixedBoundary = getNewMultipartDelimiter(); - } - - /** - * - * @return a newly generated Delimiter (either for DATA or MIXED) - */ - private static String getNewMultipartDelimiter() { - // construct a generated delimiter - return Long.toHexString(ThreadLocalRandom.current().nextLong()).toLowerCase(); - } - - /** - * This getMethod returns a List of all InterfaceHttpData from body part.
- - * @return the list of InterfaceHttpData from Body part - */ - public List getBodyListAttributes() { - return bodyListDatas; - } - - /** - * Set the Body HttpDatas list - * - * @throws NullPointerException - * for datas - * @throws ErrorDataEncoderException - * if the encoding is in error or if the finalize were already done - */ - public void setBodyHttpDatas(List datas) throws ErrorDataEncoderException { - if (datas == null) { - throw new NullPointerException("datas"); - } - globalBodySize = 0; - bodyListDatas.clear(); - currentFileUpload = null; - duringMixedMode = false; - multipartHttpDatas.clear(); - for (InterfaceHttpData data : datas) { - addBodyHttpData(data); - } - } - - /** - * Add a simple attribute in the body as Name=Value - * - * @param name - * name of the parameter - * @param value - * the value of the parameter - * @throws NullPointerException - * for name - * @throws ErrorDataEncoderException - * if the encoding is in error or if the finalize were already done - */ - public void addBodyAttribute(String name, String value) throws ErrorDataEncoderException { - if (name == null) { - throw new NullPointerException("name"); - } - String svalue = value; - if (value == null) { - svalue = ""; - } - Attribute data = factory.createAttribute(request, name, svalue); - addBodyHttpData(data); - } - - /** - * Add a file as a FileUpload - * - * @param name - * the name of the parameter - * @param file - * the file to be uploaded (if not Multipart mode, only the filename will be included) - * @param contentType - * the associated contentType for the File - * @param isText - * True if this file should be transmitted in Text format (else binary) - * @throws NullPointerException - * for name and file - * @throws ErrorDataEncoderException - * if the encoding is in error or if the finalize were already done - */ - public void addBodyFileUpload(String name, File file, String contentType, boolean isText) - throws ErrorDataEncoderException { - if (name == null) { - throw new NullPointerException("name"); - } - if (file == null) { - throw new NullPointerException("file"); - } - String scontentType = contentType; - String contentTransferEncoding = null; - if (contentType == null) { - if (isText) { - scontentType = HttpPostBodyUtil.DEFAULT_TEXT_CONTENT_TYPE; - } else { - scontentType = HttpPostBodyUtil.DEFAULT_BINARY_CONTENT_TYPE; - } - } - if (!isText) { - contentTransferEncoding = HttpPostBodyUtil.TransferEncodingMechanism.BINARY.value(); - } - FileUpload fileUpload = factory.createFileUpload(request, name, file.getName(), scontentType, - contentTransferEncoding, null, file.length()); - try { - fileUpload.setContent(file); - } catch (IOException e) { - throw new ErrorDataEncoderException(e); - } - addBodyHttpData(fileUpload); - } - - /** - * Add a series of Files associated with one File parameter (implied Mixed mode in Multipart) - * - * @param name - * the name of the parameter - * @param file - * the array of files - * @param contentType - * the array of content Types associated with each file - * @param isText - * the array of isText attribute (False meaning binary mode) for each file - * @throws NullPointerException - * also throws if array have different sizes - * @throws ErrorDataEncoderException - * if the encoding is in error or if the finalize were already done - */ - public void addBodyFileUploads(String name, File[] file, String[] contentType, boolean[] isText) - throws ErrorDataEncoderException { - if (file.length != contentType.length && file.length != isText.length) { - throw new NullPointerException("Different array length"); - } - for (int i = 0; i < file.length; i++) { - addBodyFileUpload(name, file[i], contentType[i], isText[i]); - } - } - - /** - * Add the InterfaceHttpData to the Body list - * - * @throws NullPointerException - * for data - * @throws ErrorDataEncoderException - * if the encoding is in error or if the finalize were already done - */ - public void addBodyHttpData(InterfaceHttpData data) throws ErrorDataEncoderException { - if (headerFinalized) { - throw new ErrorDataEncoderException("Cannot add value once finalized"); - } - if (data == null) { - throw new NullPointerException("data"); - } - bodyListDatas.add(data); - if (!isMultipart) { - if (data instanceof Attribute) { - Attribute attribute = (Attribute) data; - try { - // name=value& with encoded name and attribute - String key = encodeAttribute(attribute.getName(), charset); - String value = encodeAttribute(attribute.getValue(), charset); - Attribute newattribute = factory.createAttribute(request, key, value); - multipartHttpDatas.add(newattribute); - globalBodySize += newattribute.getName().length() + 1 + newattribute.length() + 1; - } catch (IOException e) { - throw new ErrorDataEncoderException(e); - } - } else if (data instanceof FileUpload) { - // since not Multipart, only name=filename => Attribute - FileUpload fileUpload = (FileUpload) data; - // name=filename& with encoded name and filename - String key = encodeAttribute(fileUpload.getName(), charset); - String value = encodeAttribute(fileUpload.getFilename(), charset); - Attribute newattribute = factory.createAttribute(request, key, value); - multipartHttpDatas.add(newattribute); - globalBodySize += newattribute.getName().length() + 1 + newattribute.length() + 1; - } - return; - } - /* - * Logic: - * if not Attribute: - * add Data to body list - * if (duringMixedMode) - * add endmixedmultipart delimiter - * currentFileUpload = null - * duringMixedMode = false; - * add multipart delimiter, multipart body header and Data to multipart list - * reset currentFileUpload, duringMixedMode - * if FileUpload: take care of multiple file for one field => mixed mode - * if (duringMixeMode) - * if (currentFileUpload.name == data.name) - * add mixedmultipart delimiter, mixedmultipart body header and Data to multipart list - * else - * add endmixedmultipart delimiter, multipart body header and Data to multipart list - * currentFileUpload = data - * duringMixedMode = false; - * else - * if (currentFileUpload.name == data.name) - * change multipart body header of previous file into multipart list to - * mixedmultipart start, mixedmultipart body header - * add mixedmultipart delimiter, mixedmultipart body header and Data to multipart list - * duringMixedMode = true - * else - * add multipart delimiter, multipart body header and Data to multipart list - * currentFileUpload = data - * duringMixedMode = false; - * Do not add last delimiter! Could be: - * if duringmixedmode: endmixedmultipart + endmultipart - * else only endmultipart - */ - if (data instanceof Attribute) { - if (duringMixedMode) { - InternalAttribute internal = new InternalAttribute(charset); - internal.addValue("\r\n--" + multipartMixedBoundary + "--"); - multipartHttpDatas.add(internal); - multipartMixedBoundary = null; - currentFileUpload = null; - duringMixedMode = false; - } - InternalAttribute internal = new InternalAttribute(charset); - if (!multipartHttpDatas.isEmpty()) { - // previously a data field so CRLF - internal.addValue("\r\n"); - } - internal.addValue("--" + multipartDataBoundary + "\r\n"); - // content-disposition: form-data; name="field1" - Attribute attribute = (Attribute) data; - internal.addValue(HttpPostBodyUtil.CONTENT_DISPOSITION + ": " + HttpPostBodyUtil.FORM_DATA + "; " - + HttpPostBodyUtil.NAME + "=\"" + attribute.getName() + "\"\r\n"); - Charset localcharset = attribute.getCharset(); - if (localcharset != null) { - // Content-Type: text/plain; charset=charset - internal.addValue(HttpHeaders.Names.CONTENT_TYPE + ": " + - HttpPostBodyUtil.DEFAULT_TEXT_CONTENT_TYPE + "; " + - HttpHeaders.Values.CHARSET + '=' - + localcharset.name() + "\r\n"); - } - // CRLF between body header and data - internal.addValue("\r\n"); - multipartHttpDatas.add(internal); - multipartHttpDatas.add(data); - globalBodySize += attribute.length() + internal.size(); - } else if (data instanceof FileUpload) { - FileUpload fileUpload = (FileUpload) data; - InternalAttribute internal = new InternalAttribute(charset); - if (!multipartHttpDatas.isEmpty()) { - // previously a data field so CRLF - internal.addValue("\r\n"); - } - boolean localMixed; - if (duringMixedMode) { - if (currentFileUpload != null && currentFileUpload.getName().equals(fileUpload.getName())) { - // continue a mixed mode - - localMixed = true; - } else { - // end a mixed mode - - // add endmixedmultipart delimiter, multipart body header - // and - // Data to multipart list - internal.addValue("--" + multipartMixedBoundary + "--"); - multipartHttpDatas.add(internal); - multipartMixedBoundary = null; - // start a new one (could be replaced if mixed start again - // from here - internal = new InternalAttribute(charset); - internal.addValue("\r\n"); - localMixed = false; - // new currentFileUpload and no more in Mixed mode - currentFileUpload = fileUpload; - duringMixedMode = false; - } - } else { - if (currentFileUpload != null && currentFileUpload.getName().equals(fileUpload.getName())) { - // create a new mixed mode (from previous file) - - // change multipart body header of previous file into - // multipart list to - // mixedmultipart start, mixedmultipart body header - - // change Internal (size()-2 position in multipartHttpDatas) - // from (line starting with *) - // --AaB03x - // * Content-Disposition: form-data; name="files"; - // filename="file1.txt" - // Content-Type: text/plain - // to (lines starting with *) - // --AaB03x - // * Content-Disposition: form-data; name="files" - // * Content-Type: multipart/mixed; boundary=BbC04y - // * - // * --BbC04y - // * Content-Disposition: file; filename="file1.txt" - // Content-Type: text/plain - initMixedMultipart(); - InternalAttribute pastAttribute = (InternalAttribute) multipartHttpDatas.get(multipartHttpDatas - .size() - 2); - // remove past size - globalBodySize -= pastAttribute.size(); - StringBuilder replacement = new StringBuilder( - 139 + multipartDataBoundary.length() + multipartMixedBoundary.length() * 2 + - - fileUpload.getFilename().length() + fileUpload.getName().length()); - - replacement.append("--") - .append(multipartDataBoundary) - .append("\r\n") - - .append(HttpPostBodyUtil.CONTENT_DISPOSITION) - .append(": ") - .append(HttpPostBodyUtil.FORM_DATA) - .append("; ") - .append(HttpPostBodyUtil.NAME) - .append("=\"") - .append(fileUpload.getName()) - .append("\"\r\n") - - .append(HttpHeaders.Names.CONTENT_TYPE) - .append(": ") - .append(HttpPostBodyUtil.MULTIPART_MIXED) - .append("; ") - .append(HttpHeaders.Values.BOUNDARY) - .append('=') - .append(multipartMixedBoundary) - .append("\r\n\r\n") - - .append("--") - .append(multipartMixedBoundary) - .append("\r\n") - - .append(HttpPostBodyUtil.CONTENT_DISPOSITION) - .append(": ") - .append(HttpPostBodyUtil.ATTACHMENT) - .append("; ") - .append(HttpPostBodyUtil.FILENAME) - .append("=\"") - .append(fileUpload.getFilename()) - .append("\"\r\n"); - - pastAttribute.setValue(replacement.toString(), 1); - pastAttribute.setValue("", 2); - - // update past size - globalBodySize += pastAttribute.size(); - - // now continue - // add mixedmultipart delimiter, mixedmultipart body header - // and - // Data to multipart list - localMixed = true; - duringMixedMode = true; - } else { - // a simple new multipart - // add multipart delimiter, multipart body header and Data - // to multipart list - localMixed = false; - currentFileUpload = fileUpload; - duringMixedMode = false; - } - } - - if (localMixed) { - // add mixedmultipart delimiter, mixedmultipart body header and - // Data to multipart list - internal.addValue("--" + multipartMixedBoundary + "\r\n"); - // Content-Disposition: file; filename="file1.txt" - internal.addValue(HttpPostBodyUtil.CONTENT_DISPOSITION + ": " + HttpPostBodyUtil.ATTACHMENT + "; " - + HttpPostBodyUtil.FILENAME + "=\"" + fileUpload.getFilename() + "\"\r\n"); - } else { - internal.addValue("--" + multipartDataBoundary + "\r\n"); - // Content-Disposition: form-data; name="files"; - // filename="file1.txt" - internal.addValue(HttpPostBodyUtil.CONTENT_DISPOSITION + ": " + HttpPostBodyUtil.FORM_DATA + "; " - + HttpPostBodyUtil.NAME + "=\"" + fileUpload.getName() + "\"; " - + HttpPostBodyUtil.FILENAME + "=\"" + fileUpload.getFilename() + "\"\r\n"); - } - // Content-Type: image/gif - // Content-Type: text/plain; charset=ISO-8859-1 - // Content-Transfer-Encoding: binary - internal.addValue(HttpHeaders.Names.CONTENT_TYPE + ": " + fileUpload.getContentType()); - String contentTransferEncoding = fileUpload.getContentTransferEncoding(); - if (contentTransferEncoding != null - && contentTransferEncoding.equals(HttpPostBodyUtil.TransferEncodingMechanism.BINARY.value())) { - internal.addValue("\r\n" + HttpHeaders.Names.CONTENT_TRANSFER_ENCODING + ": " - + HttpPostBodyUtil.TransferEncodingMechanism.BINARY.value() + "\r\n\r\n"); - } else if (fileUpload.getCharset() != null) { - internal.addValue("; " + HttpHeaders.Values.CHARSET + '=' - + fileUpload.getCharset().name() + "\r\n\r\n"); - } else { - internal.addValue("\r\n\r\n"); - } - multipartHttpDatas.add(internal); - multipartHttpDatas.add(data); - globalBodySize += fileUpload.length() + internal.size(); - } - } - - /** - * Iterator to be used when encoding will be called chunk after chunk - */ - private ListIterator iterator; - - /** - * Finalize the request by preparing the Header in the request and returns the request ready to be sent.
- * Once finalized, no data must be added.
- * If the request does not need chunk (isChunked() == false), this request is the only object to send to the remote - * server. - * - * @return the request object (chunked or not according to size of body) - * @throws ErrorDataEncoderException - * if the encoding is in error or if the finalize were already done - */ - public HttpRequest finalizeRequest() throws ErrorDataEncoderException { - // Finalize the multipartHttpDatas - if (!headerFinalized) { - if (isMultipart) { - InternalAttribute internal = new InternalAttribute(charset); - if (duringMixedMode) { - internal.addValue("\r\n--" + multipartMixedBoundary + "--"); - } - internal.addValue("\r\n--" + multipartDataBoundary + "--\r\n"); - multipartHttpDatas.add(internal); - multipartMixedBoundary = null; - currentFileUpload = null; - duringMixedMode = false; - globalBodySize += internal.size(); - } - headerFinalized = true; - } else { - throw new ErrorDataEncoderException("Header already encoded"); - } - - HttpHeaders headers = request.headers(); - List contentTypes = headers.getAll(HttpHeaders.Names.CONTENT_TYPE); - List transferEncoding = headers.getAll(HttpHeaders.Names.TRANSFER_ENCODING); - if (contentTypes != null) { - headers.remove(HttpHeaders.Names.CONTENT_TYPE); - for (String contentType : contentTypes) { - // "multipart/form-data; boundary=--89421926422648" - String lowercased = contentType.toLowerCase(); - if (lowercased.startsWith(HttpHeaders.Values.MULTIPART_FORM_DATA) || - lowercased.startsWith(HttpHeaders.Values.APPLICATION_X_WWW_FORM_URLENCODED)) { - // ignore - } else { - headers.add(HttpHeaders.Names.CONTENT_TYPE, contentType); - } - } - } - if (isMultipart) { - String value = HttpHeaders.Values.MULTIPART_FORM_DATA + "; " + HttpHeaders.Values.BOUNDARY + '=' - + multipartDataBoundary; - headers.add(HttpHeaders.Names.CONTENT_TYPE, value); - } else { - // Not multipart - headers.add(HttpHeaders.Names.CONTENT_TYPE, HttpHeaders.Values.APPLICATION_X_WWW_FORM_URLENCODED); - } - // Now consider size for chunk or not - long realSize = globalBodySize; - if (isMultipart) { - iterator = multipartHttpDatas.listIterator(); - } else { - realSize -= 1; // last '&' removed - iterator = multipartHttpDatas.listIterator(); - } - headers.set(HttpHeaders.Names.CONTENT_LENGTH, String.valueOf(realSize)); - if (realSize > HttpPostBodyUtil.chunkSize || isMultipart) { - isChunked = true; - if (transferEncoding != null) { - headers.remove(HttpHeaders.Names.TRANSFER_ENCODING); - for (String v : transferEncoding) { - if (v.equalsIgnoreCase(HttpHeaders.Values.CHUNKED)) { - // ignore - } else { - headers.add(HttpHeaders.Names.TRANSFER_ENCODING, v); - } - } - } - HttpHeaders.setTransferEncodingChunked(request); - - // wrap to hide the possible content - return new WrappedHttpRequest(request); - } else { - // get the only one body and set it to the request - HttpContent chunk = nextChunk(); - if (request instanceof FullHttpRequest) { - FullHttpRequest fullRequest = (FullHttpRequest) request; - ByteBuf chunkContent = chunk.content(); - if (fullRequest.content() != chunkContent) { - fullRequest.content().clear().writeBytes(chunkContent); - chunkContent.release(); - } - return fullRequest; - } else { - return new WrappedFullHttpRequest(request, chunk); - } - } - } - - /** - * @return True if the request is by Chunk - */ - public boolean isChunked() { - return isChunked; - } - - /** - * Encode one attribute - * - * @return the encoded attribute - * @throws ErrorDataEncoderException - * if the encoding is in error - */ - private String encodeAttribute(String s, Charset charset) throws ErrorDataEncoderException { - if (s == null) { - return ""; - } - try { - String encoded = URLEncoder.encode(s, charset.name()); - if (encoderMode == EncoderMode.RFC3986) { - for (Map.Entry entry : percentEncodings.entrySet()) { - String replacement = entry.getValue(); - encoded = entry.getKey().matcher(encoded).replaceAll(replacement); - } - } - return encoded; - } catch (UnsupportedEncodingException e) { - throw new ErrorDataEncoderException(charset.name(), e); - } - } - - /** - * The ByteBuf currently used by the encoder - */ - private ByteBuf currentBuffer; - /** - * The current InterfaceHttpData to encode (used if more chunks are available) - */ - private InterfaceHttpData currentData; - /** - * If not multipart, does the currentBuffer stands for the Key or for the Value - */ - private boolean isKey = true; - - /** - * - * @return the next ByteBuf to send as a HttpChunk and modifying currentBuffer accordingly - */ - private ByteBuf fillByteBuf() { - int length = currentBuffer.readableBytes(); - if (length > HttpPostBodyUtil.chunkSize) { - ByteBuf slice = currentBuffer.slice(currentBuffer.readerIndex(), HttpPostBodyUtil.chunkSize); - currentBuffer.retain(); - currentBuffer.skipBytes(HttpPostBodyUtil.chunkSize); - return slice; - } else { - // to continue - ByteBuf slice = currentBuffer; - currentBuffer = null; - return slice; - } - } - - /** - * From the current context (currentBuffer and currentData), returns the next HttpChunk (if possible) trying to get - * sizeleft bytes more into the currentBuffer. This is the Multipart version. - * - * @param sizeleft - * the number of bytes to try to get from currentData - * @return the next HttpChunk or null if not enough bytes were found - * @throws ErrorDataEncoderException - * if the encoding is in error - */ - private HttpContent encodeNextChunkMultipart(int sizeleft) throws ErrorDataEncoderException { - if (currentData == null) { - return null; - } - ByteBuf buffer; - if (currentData instanceof InternalAttribute) { - buffer = ((InternalAttribute) currentData).toByteBuf(); - currentData = null; - } else { - if (currentData instanceof Attribute) { - try { - buffer = ((Attribute) currentData).getChunk(sizeleft); - } catch (IOException e) { - throw new ErrorDataEncoderException(e); - } - } else { - try { - buffer = ((HttpData) currentData).getChunk(sizeleft); - } catch (IOException e) { - throw new ErrorDataEncoderException(e); - } - } - if (buffer.capacity() == 0) { - // end for current InterfaceHttpData, need more data - currentData = null; - return null; - } - } - if (currentBuffer == null) { - currentBuffer = buffer; - } else { - currentBuffer = wrappedBuffer(currentBuffer, buffer); - } - if (currentBuffer.readableBytes() < HttpPostBodyUtil.chunkSize) { - currentData = null; - return null; - } - buffer = fillByteBuf(); - return new DefaultHttpContent(buffer); - } - - /** - * From the current context (currentBuffer and currentData), returns the next HttpChunk (if possible) trying to get - * sizeleft bytes more into the currentBuffer. This is the UrlEncoded version. - * - * @param sizeleft - * the number of bytes to try to get from currentData - * @return the next HttpChunk or null if not enough bytes were found - * @throws ErrorDataEncoderException - * if the encoding is in error - */ - private HttpContent encodeNextChunkUrlEncoded(int sizeleft) throws ErrorDataEncoderException { - if (currentData == null) { - return null; - } - int size = sizeleft; - ByteBuf buffer; - - // Set name= - if (isKey) { - String key = currentData.getName(); - buffer = wrappedBuffer(key.getBytes()); - isKey = false; - if (currentBuffer == null) { - currentBuffer = wrappedBuffer(buffer, wrappedBuffer("=".getBytes())); - // continue - size -= buffer.readableBytes() + 1; - } else { - currentBuffer = wrappedBuffer(currentBuffer, buffer, wrappedBuffer("=".getBytes())); - // continue - size -= buffer.readableBytes() + 1; - } - if (currentBuffer.readableBytes() >= HttpPostBodyUtil.chunkSize) { - buffer = fillByteBuf(); - return new DefaultHttpContent(buffer); - } - } - - // Put value into buffer - try { - buffer = ((HttpData) currentData).getChunk(size); - } catch (IOException e) { - throw new ErrorDataEncoderException(e); - } - - // Figure out delimiter - ByteBuf delimiter = null; - if (buffer.readableBytes() < size) { - isKey = true; - delimiter = iterator.hasNext() ? wrappedBuffer("&".getBytes()) : null; - } - - // End for current InterfaceHttpData, need potentially more data - if (buffer.capacity() == 0) { - currentData = null; - if (currentBuffer == null) { - currentBuffer = delimiter; - } else { - if (delimiter != null) { - currentBuffer = wrappedBuffer(currentBuffer, delimiter); - } - } - if (currentBuffer.readableBytes() >= HttpPostBodyUtil.chunkSize) { - buffer = fillByteBuf(); - return new DefaultHttpContent(buffer); - } - return null; - } - - // Put it all together: name=value& - if (currentBuffer == null) { - if (delimiter != null) { - currentBuffer = wrappedBuffer(buffer, delimiter); - } else { - currentBuffer = buffer; - } - } else { - if (delimiter != null) { - currentBuffer = wrappedBuffer(currentBuffer, buffer, delimiter); - } else { - currentBuffer = wrappedBuffer(currentBuffer, buffer); - } - } - - // end for current InterfaceHttpData, need more data - if (currentBuffer.readableBytes() < HttpPostBodyUtil.chunkSize) { - currentData = null; - isKey = true; - return null; - } - - buffer = fillByteBuf(); - return new DefaultHttpContent(buffer); - } - - @Override - public void close() throws Exception { - // NO since the user can want to reuse (broadcast for instance) - // cleanFiles(); - } - - /** - * Returns the next available HttpChunk. The caller is responsible to test if this chunk is the last one (isLast()), - * in order to stop calling this getMethod. - * - * @return the next available HttpChunk - * @throws ErrorDataEncoderException - * if the encoding is in error - */ - @Override - public HttpContent readChunk(ChannelHandlerContext ctx) throws Exception { - if (isLastChunkSent) { - return null; - } else { - return nextChunk(); - } - } - - /** - * Returns the next available HttpChunk. The caller is responsible to test if this chunk is the last one (isLast()), - * in order to stop calling this getMethod. - * - * @return the next available HttpChunk - * @throws ErrorDataEncoderException - * if the encoding is in error - */ - private HttpContent nextChunk() throws ErrorDataEncoderException { - if (isLastChunk) { - isLastChunkSent = true; - return LastHttpContent.EMPTY_LAST_CONTENT; - } - ByteBuf buffer; - int size = HttpPostBodyUtil.chunkSize; - // first test if previous buffer is not empty - if (currentBuffer != null) { - size -= currentBuffer.readableBytes(); - } - if (size <= 0) { - // NextChunk from buffer - buffer = fillByteBuf(); - return new DefaultHttpContent(buffer); - } - // size > 0 - if (currentData != null) { - // continue to read data - if (isMultipart) { - HttpContent chunk = encodeNextChunkMultipart(size); - if (chunk != null) { - return chunk; - } - } else { - HttpContent chunk = encodeNextChunkUrlEncoded(size); - if (chunk != null) { - // NextChunk Url from currentData - return chunk; - } - } - size = HttpPostBodyUtil.chunkSize - currentBuffer.readableBytes(); - } - if (!iterator.hasNext()) { - isLastChunk = true; - // NextChunk as last non empty from buffer - buffer = currentBuffer; - currentBuffer = null; - return new DefaultHttpContent(buffer); - } - while (size > 0 && iterator.hasNext()) { - currentData = iterator.next(); - HttpContent chunk; - if (isMultipart) { - chunk = encodeNextChunkMultipart(size); - } else { - chunk = encodeNextChunkUrlEncoded(size); - } - if (chunk == null) { - // not enough - size = HttpPostBodyUtil.chunkSize - currentBuffer.readableBytes(); - continue; - } - // NextChunk from data - return chunk; - } - // end since no more data - isLastChunk = true; - if (currentBuffer == null) { - isLastChunkSent = true; - // LastChunk with no more data - return LastHttpContent.EMPTY_LAST_CONTENT; - } - // Previous LastChunk with no more data - buffer = currentBuffer; - currentBuffer = null; - return new DefaultHttpContent(buffer); - } - - @Override - public boolean isEndOfInput() throws Exception { - return isLastChunkSent; - } - - /** - * Exception when an error occurs while encoding - */ - public static class ErrorDataEncoderException extends Exception { - private static final long serialVersionUID = 5020247425493164465L; - - public ErrorDataEncoderException() { - } - - public ErrorDataEncoderException(String msg) { - super(msg); - } - - public ErrorDataEncoderException(Throwable cause) { - super(cause); - } - - public ErrorDataEncoderException(String msg, Throwable cause) { - super(msg, cause); - } - } - - private static class WrappedHttpRequest implements HttpRequest { - private final HttpRequest request; - WrappedHttpRequest(HttpRequest request) { - this.request = request; - } - - @Override - public HttpRequest setProtocolVersion(HttpVersion version) { - request.setProtocolVersion(version); - return this; - } - - @Override - public HttpRequest setMethod(HttpMethod method) { - request.setMethod(method); - return this; - } - - @Override - public HttpRequest setUri(String uri) { - request.setUri(uri); - return this; - } - - @Override - public HttpMethod getMethod() { - return request.getMethod(); - } - - @Override - public String getUri() { - return request.getUri(); - } - - @Override - public HttpVersion getProtocolVersion() { - return request.getProtocolVersion(); - } - - @Override - public HttpHeaders headers() { - return request.headers(); - } - - @Override - public DecoderResult getDecoderResult() { - return request.getDecoderResult(); - } - - @Override - public void setDecoderResult(DecoderResult result) { - request.setDecoderResult(result); - } - } - - private static final class WrappedFullHttpRequest extends WrappedHttpRequest implements FullHttpRequest { - private final HttpContent content; - private WrappedFullHttpRequest(HttpRequest request, HttpContent content) { - super(request); - this.content = content; - } - - @Override - public FullHttpRequest setProtocolVersion(HttpVersion version) { - super.setProtocolVersion(version); - return this; - } - - @Override - public FullHttpRequest setMethod(HttpMethod method) { - super.setMethod(method); - return this; - } - - @Override - public FullHttpRequest setUri(String uri) { - super.setUri(uri); - return this; - } - - @Override - public FullHttpRequest copy() { - DefaultFullHttpRequest copy = new DefaultFullHttpRequest( - getProtocolVersion(), getMethod(), getUri(), content().copy()); - copy.headers().set(headers()); - copy.trailingHeaders().set(trailingHeaders()); - return copy; - } - - @Override - public FullHttpRequest duplicate() { - DefaultFullHttpRequest duplicate = new DefaultFullHttpRequest( - getProtocolVersion(), getMethod(), getUri(), content().duplicate()); - duplicate.headers().set(headers()); - duplicate.trailingHeaders().set(trailingHeaders()); - return duplicate; - } - - @Override - public FullHttpRequest retain(int increment) { - content.retain(increment); - return this; - } - - @Override - public FullHttpRequest retain() { - content.retain(); - return this; - } - - @Override - public ByteBuf content() { - return content.content(); - } - - @Override - public HttpHeaders trailingHeaders() { - if (content instanceof LastHttpContent) { - return ((LastHttpContent) content).trailingHeaders(); - } else { - return HttpHeaders.EMPTY_HEADERS; - } - } - - @Override - public int refCnt() { - return content.refCnt(); - } - - @Override - public boolean release() { - return content.release(); - } - - @Override - public boolean release(int decrement) { - return content.release(decrement); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/HttpPostStandardRequestDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/HttpPostStandardRequestDecoder.java deleted file mode 100755 index 1dd27d0f3f..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/HttpPostStandardRequestDecoder.java +++ /dev/null @@ -1,731 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.multipart; - -import java.io.IOException; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.handler.codec.http.HttpConstants; -import com.ai.cloud.io.netty.handler.codec.http.HttpContent; -import com.ai.cloud.io.netty.handler.codec.http.HttpRequest; -import com.ai.cloud.io.netty.handler.codec.http.LastHttpContent; -import com.ai.cloud.io.netty.handler.codec.http.QueryStringDecoder; -import com.ai.cloud.io.netty.handler.codec.http.multipart.HttpPostBodyUtil.SeekAheadNoBackArrayException; -import com.ai.cloud.io.netty.handler.codec.http.multipart.HttpPostBodyUtil.SeekAheadOptimize; -import com.ai.cloud.io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.EndOfDataDecoderException; -import com.ai.cloud.io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.ErrorDataDecoderException; -import com.ai.cloud.io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.MultiPartStatus; -import com.ai.cloud.io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.NotEnoughDataDecoderException; - -import static com.ai.cloud.io.netty.buffer.Unpooled.*; - -/** - * This decoder will decode Body and can handle POST BODY. - * - * You MUST call {@link #destroy()} after completion to release all resources. - * - */ -public class HttpPostStandardRequestDecoder implements InterfaceHttpPostRequestDecoder { - - /** - * Factory used to create InterfaceHttpData - */ - private final HttpDataFactory factory; - - /** - * Request to decode - */ - private final HttpRequest request; - - /** - * Default charset to use - */ - private final Charset charset; - - /** - * Does the last chunk already received - */ - private boolean isLastChunk; - - /** - * HttpDatas from Body - */ - private final List bodyListHttpData = new ArrayList(); - - /** - * HttpDatas as Map from Body - */ - private final Map> bodyMapHttpData = new TreeMap>( - CaseIgnoringComparator.INSTANCE); - - /** - * The current channelBuffer - */ - private ByteBuf undecodedChunk; - - /** - * Body HttpDatas current position - */ - private int bodyListHttpDataRank; - - /** - * Current getStatus - */ - private MultiPartStatus currentStatus = MultiPartStatus.NOTSTARTED; - - /** - * The current Attribute that is currently in decode process - */ - private Attribute currentAttribute; - - private boolean destroyed; - - private int discardThreshold = HttpPostRequestDecoder.DEFAULT_DISCARD_THRESHOLD; - - /** - * - * @param request - * the request to decode - * @throws NullPointerException - * for request - * @throws ErrorDataDecoderException - * if the default charset was wrong when decoding or other - * errors - */ - public HttpPostStandardRequestDecoder(HttpRequest request) { - this(new DefaultHttpDataFactory(DefaultHttpDataFactory.MINSIZE), request, HttpConstants.DEFAULT_CHARSET); - } - - /** - * - * @param factory - * the factory used to create InterfaceHttpData - * @param request - * the request to decode - * @throws NullPointerException - * for request or factory - * @throws ErrorDataDecoderException - * if the default charset was wrong when decoding or other - * errors - */ - public HttpPostStandardRequestDecoder(HttpDataFactory factory, HttpRequest request) { - this(factory, request, HttpConstants.DEFAULT_CHARSET); - } - - /** - * - * @param factory - * the factory used to create InterfaceHttpData - * @param request - * the request to decode - * @param charset - * the charset to use as default - * @throws NullPointerException - * for request or charset or factory - * @throws ErrorDataDecoderException - * if the default charset was wrong when decoding or other - * errors - */ - public HttpPostStandardRequestDecoder(HttpDataFactory factory, HttpRequest request, Charset charset) { - if (factory == null) { - throw new NullPointerException("factory"); - } - if (request == null) { - throw new NullPointerException("request"); - } - if (charset == null) { - throw new NullPointerException("charset"); - } - this.request = request; - this.charset = charset; - this.factory = factory; - if (request instanceof HttpContent) { - // Offer automatically if the given request is als type of HttpContent - // See #1089 - offer((HttpContent) request); - } else { - undecodedChunk = buffer(); - parseBody(); - } - } - - private void checkDestroyed() { - if (destroyed) { - throw new IllegalStateException(HttpPostStandardRequestDecoder.class.getSimpleName() - + " was destroyed already"); - } - } - - /** - * True if this request is a Multipart request - * - * @return True if this request is a Multipart request - */ - @Override - public boolean isMultipart() { - checkDestroyed(); - return false; - } - - /** - * Set the amount of bytes after which read bytes in the buffer should be discarded. - * Setting this lower gives lower memory usage but with the overhead of more memory copies. - * Use {@code 0} to disable it. - */ - @Override - public void setDiscardThreshold(int discardThreshold) { - if (discardThreshold < 0) { - throw new IllegalArgumentException("discardThreshold must be >= 0"); - } - this.discardThreshold = discardThreshold; - } - - /** - * Return the threshold in bytes after which read data in the buffer should be discarded. - */ - @Override - public int getDiscardThreshold() { - return discardThreshold; - } - - /** - * This getMethod returns a List of all HttpDatas from body.
- * - * If chunked, all chunks must have been offered using offer() getMethod. If - * not, NotEnoughDataDecoderException will be raised. - * - * @return the list of HttpDatas from Body part for POST getMethod - * @throws NotEnoughDataDecoderException - * Need more chunks - */ - @Override - public List getBodyHttpDatas() { - checkDestroyed(); - - if (!isLastChunk) { - throw new NotEnoughDataDecoderException(); - } - return bodyListHttpData; - } - - /** - * This getMethod returns a List of all HttpDatas with the given name from - * body.
- * - * If chunked, all chunks must have been offered using offer() getMethod. If - * not, NotEnoughDataDecoderException will be raised. - * - * @return All Body HttpDatas with the given name (ignore case) - * @throws NotEnoughDataDecoderException - * need more chunks - */ - @Override - public List getBodyHttpDatas(String name) { - checkDestroyed(); - - if (!isLastChunk) { - throw new NotEnoughDataDecoderException(); - } - return bodyMapHttpData.get(name); - } - - /** - * This getMethod returns the first InterfaceHttpData with the given name from - * body.
- * - * If chunked, all chunks must have been offered using offer() getMethod. If - * not, NotEnoughDataDecoderException will be raised. - * - * @return The first Body InterfaceHttpData with the given name (ignore - * case) - * @throws NotEnoughDataDecoderException - * need more chunks - */ - @Override - public InterfaceHttpData getBodyHttpData(String name) { - checkDestroyed(); - - if (!isLastChunk) { - throw new NotEnoughDataDecoderException(); - } - List list = bodyMapHttpData.get(name); - if (list != null) { - return list.get(0); - } - return null; - } - - /** - * Initialized the internals from a new chunk - * - * @param content - * the new received chunk - * @throws ErrorDataDecoderException - * if there is a problem with the charset decoding or other - * errors - */ - @Override - public HttpPostStandardRequestDecoder offer(HttpContent content) { - checkDestroyed(); - - // Maybe we should better not copy here for performance reasons but this will need - // more care by the caller to release the content in a correct manner later - // So maybe something to optimize on a later stage - ByteBuf buf = content.content(); - if (undecodedChunk == null) { - undecodedChunk = buf.copy(); - } else { - undecodedChunk.writeBytes(buf); - } - if (content instanceof LastHttpContent) { - isLastChunk = true; - } - parseBody(); - if (undecodedChunk != null && undecodedChunk.writerIndex() > discardThreshold) { - undecodedChunk.discardReadBytes(); - } - return this; - } - - /** - * True if at current getStatus, there is an available decoded - * InterfaceHttpData from the Body. - * - * This getMethod works for chunked and not chunked request. - * - * @return True if at current getStatus, there is a decoded InterfaceHttpData - * @throws EndOfDataDecoderException - * No more data will be available - */ - @Override - public boolean hasNext() { - checkDestroyed(); - - if (currentStatus == MultiPartStatus.EPILOGUE) { - // OK except if end of list - if (bodyListHttpDataRank >= bodyListHttpData.size()) { - throw new EndOfDataDecoderException(); - } - } - return !bodyListHttpData.isEmpty() && bodyListHttpDataRank < bodyListHttpData.size(); - } - - /** - * Returns the next available InterfaceHttpData or null if, at the time it - * is called, there is no more available InterfaceHttpData. A subsequent - * call to offer(httpChunk) could enable more data. - * - * Be sure to call {@link InterfaceHttpData#release()} after you are done - * with processing to make sure to not leak any resources - * - * @return the next available InterfaceHttpData or null if none - * @throws EndOfDataDecoderException - * No more data will be available - */ - @Override - public InterfaceHttpData next() { - checkDestroyed(); - - if (hasNext()) { - return bodyListHttpData.get(bodyListHttpDataRank++); - } - return null; - } - - /** - * This getMethod will parse as much as possible data and fill the list and map - * - * @throws ErrorDataDecoderException - * if there is a problem with the charset decoding or other - * errors - */ - private void parseBody() { - if (currentStatus == MultiPartStatus.PREEPILOGUE || currentStatus == MultiPartStatus.EPILOGUE) { - if (isLastChunk) { - currentStatus = MultiPartStatus.EPILOGUE; - } - return; - } - parseBodyAttributes(); - } - - /** - * Utility function to add a new decoded data - */ - protected void addHttpData(InterfaceHttpData data) { - if (data == null) { - return; - } - List datas = bodyMapHttpData.get(data.getName()); - if (datas == null) { - datas = new ArrayList(1); - bodyMapHttpData.put(data.getName(), datas); - } - datas.add(data); - bodyListHttpData.add(data); - } - - /** - * This getMethod fill the map and list with as much Attribute as possible from - * Body in not Multipart mode. - * - * @throws ErrorDataDecoderException - * if there is a problem with the charset decoding or other - * errors - */ - private void parseBodyAttributesStandard() { - int firstpos = undecodedChunk.readerIndex(); - int currentpos = firstpos; - int equalpos; - int ampersandpos; - if (currentStatus == MultiPartStatus.NOTSTARTED) { - currentStatus = MultiPartStatus.DISPOSITION; - } - boolean contRead = true; - try { - while (undecodedChunk.isReadable() && contRead) { - char read = (char) undecodedChunk.readUnsignedByte(); - currentpos++; - switch (currentStatus) { - case DISPOSITION:// search '=' - if (read == '=') { - currentStatus = MultiPartStatus.FIELD; - equalpos = currentpos - 1; - String key = decodeAttribute(undecodedChunk.toString(firstpos, equalpos - firstpos, charset), - charset); - currentAttribute = factory.createAttribute(request, key); - firstpos = currentpos; - } else if (read == '&') { // special empty FIELD - currentStatus = MultiPartStatus.DISPOSITION; - ampersandpos = currentpos - 1; - String key = decodeAttribute( - undecodedChunk.toString(firstpos, ampersandpos - firstpos, charset), charset); - currentAttribute = factory.createAttribute(request, key); - currentAttribute.setValue(""); // empty - addHttpData(currentAttribute); - currentAttribute = null; - firstpos = currentpos; - contRead = true; - } - break; - case FIELD:// search '&' or end of line - if (read == '&') { - currentStatus = MultiPartStatus.DISPOSITION; - ampersandpos = currentpos - 1; - setFinalBuffer(undecodedChunk.copy(firstpos, ampersandpos - firstpos)); - firstpos = currentpos; - contRead = true; - } else if (read == HttpConstants.CR) { - if (undecodedChunk.isReadable()) { - read = (char) undecodedChunk.readUnsignedByte(); - currentpos++; - if (read == HttpConstants.LF) { - currentStatus = MultiPartStatus.PREEPILOGUE; - ampersandpos = currentpos - 2; - setFinalBuffer(undecodedChunk.copy(firstpos, ampersandpos - firstpos)); - firstpos = currentpos; - contRead = false; - } else { - // Error - throw new ErrorDataDecoderException("Bad end of line"); - } - } else { - currentpos--; - } - } else if (read == HttpConstants.LF) { - currentStatus = MultiPartStatus.PREEPILOGUE; - ampersandpos = currentpos - 1; - setFinalBuffer(undecodedChunk.copy(firstpos, ampersandpos - firstpos)); - firstpos = currentpos; - contRead = false; - } - break; - default: - // just stop - contRead = false; - } - } - if (isLastChunk && currentAttribute != null) { - // special case - ampersandpos = currentpos; - if (ampersandpos > firstpos) { - setFinalBuffer(undecodedChunk.copy(firstpos, ampersandpos - firstpos)); - } else if (!currentAttribute.isCompleted()) { - setFinalBuffer(EMPTY_BUFFER); - } - firstpos = currentpos; - currentStatus = MultiPartStatus.EPILOGUE; - undecodedChunk.readerIndex(firstpos); - return; - } - if (contRead && currentAttribute != null) { - // reset index except if to continue in case of FIELD getStatus - if (currentStatus == MultiPartStatus.FIELD) { - currentAttribute.addContent(undecodedChunk.copy(firstpos, currentpos - firstpos), - false); - firstpos = currentpos; - } - undecodedChunk.readerIndex(firstpos); - } else { - // end of line or end of block so keep index to last valid position - undecodedChunk.readerIndex(firstpos); - } - } catch (ErrorDataDecoderException e) { - // error while decoding - undecodedChunk.readerIndex(firstpos); - throw e; - } catch (IOException e) { - // error while decoding - undecodedChunk.readerIndex(firstpos); - throw new ErrorDataDecoderException(e); - } - } - - /** - * This getMethod fill the map and list with as much Attribute as possible from - * Body in not Multipart mode. - * - * @throws ErrorDataDecoderException - * if there is a problem with the charset decoding or other - * errors - */ - private void parseBodyAttributes() { - SeekAheadOptimize sao; - try { - sao = new SeekAheadOptimize(undecodedChunk); - } catch (SeekAheadNoBackArrayException ignored) { - parseBodyAttributesStandard(); - return; - } - int firstpos = undecodedChunk.readerIndex(); - int currentpos = firstpos; - int equalpos; - int ampersandpos; - if (currentStatus == MultiPartStatus.NOTSTARTED) { - currentStatus = MultiPartStatus.DISPOSITION; - } - boolean contRead = true; - try { - loop: while (sao.pos < sao.limit) { - char read = (char) (sao.bytes[sao.pos++] & 0xFF); - currentpos++; - switch (currentStatus) { - case DISPOSITION:// search '=' - if (read == '=') { - currentStatus = MultiPartStatus.FIELD; - equalpos = currentpos - 1; - String key = decodeAttribute(undecodedChunk.toString(firstpos, equalpos - firstpos, charset), - charset); - currentAttribute = factory.createAttribute(request, key); - firstpos = currentpos; - } else if (read == '&') { // special empty FIELD - currentStatus = MultiPartStatus.DISPOSITION; - ampersandpos = currentpos - 1; - String key = decodeAttribute( - undecodedChunk.toString(firstpos, ampersandpos - firstpos, charset), charset); - currentAttribute = factory.createAttribute(request, key); - currentAttribute.setValue(""); // empty - addHttpData(currentAttribute); - currentAttribute = null; - firstpos = currentpos; - contRead = true; - } - break; - case FIELD:// search '&' or end of line - if (read == '&') { - currentStatus = MultiPartStatus.DISPOSITION; - ampersandpos = currentpos - 1; - setFinalBuffer(undecodedChunk.copy(firstpos, ampersandpos - firstpos)); - firstpos = currentpos; - contRead = true; - } else if (read == HttpConstants.CR) { - if (sao.pos < sao.limit) { - read = (char) (sao.bytes[sao.pos++] & 0xFF); - currentpos++; - if (read == HttpConstants.LF) { - currentStatus = MultiPartStatus.PREEPILOGUE; - ampersandpos = currentpos - 2; - sao.setReadPosition(0); - setFinalBuffer(undecodedChunk.copy(firstpos, ampersandpos - firstpos)); - firstpos = currentpos; - contRead = false; - break loop; - } else { - // Error - sao.setReadPosition(0); - throw new ErrorDataDecoderException("Bad end of line"); - } - } else { - if (sao.limit > 0) { - currentpos--; - } - } - } else if (read == HttpConstants.LF) { - currentStatus = MultiPartStatus.PREEPILOGUE; - ampersandpos = currentpos - 1; - sao.setReadPosition(0); - setFinalBuffer(undecodedChunk.copy(firstpos, ampersandpos - firstpos)); - firstpos = currentpos; - contRead = false; - break loop; - } - break; - default: - // just stop - sao.setReadPosition(0); - contRead = false; - break loop; - } - } - if (isLastChunk && currentAttribute != null) { - // special case - ampersandpos = currentpos; - if (ampersandpos > firstpos) { - setFinalBuffer(undecodedChunk.copy(firstpos, ampersandpos - firstpos)); - } else if (!currentAttribute.isCompleted()) { - setFinalBuffer(EMPTY_BUFFER); - } - firstpos = currentpos; - currentStatus = MultiPartStatus.EPILOGUE; - undecodedChunk.readerIndex(firstpos); - return; - } - if (contRead && currentAttribute != null) { - // reset index except if to continue in case of FIELD getStatus - if (currentStatus == MultiPartStatus.FIELD) { - currentAttribute.addContent(undecodedChunk.copy(firstpos, currentpos - firstpos), - false); - firstpos = currentpos; - } - undecodedChunk.readerIndex(firstpos); - } else { - // end of line or end of block so keep index to last valid position - undecodedChunk.readerIndex(firstpos); - } - } catch (ErrorDataDecoderException e) { - // error while decoding - undecodedChunk.readerIndex(firstpos); - throw e; - } catch (IOException e) { - // error while decoding - undecodedChunk.readerIndex(firstpos); - throw new ErrorDataDecoderException(e); - } - } - - private void setFinalBuffer(ByteBuf buffer) throws IOException { - currentAttribute.addContent(buffer, true); - String value = decodeAttribute(currentAttribute.getByteBuf().toString(charset), charset); - currentAttribute.setValue(value); - addHttpData(currentAttribute); - currentAttribute = null; - } - - /** - * Decode component - * - * @return the decoded component - */ - private static String decodeAttribute(String s, Charset charset) { - try { - return QueryStringDecoder.decodeComponent(s, charset); - } catch (IllegalArgumentException e) { - throw new ErrorDataDecoderException("Bad string: '" + s + '\'', e); - } - } - - /** - * Skip control Characters - */ - void skipControlCharacters() { - SeekAheadOptimize sao; - try { - sao = new SeekAheadOptimize(undecodedChunk); - } catch (SeekAheadNoBackArrayException ignored) { - try { - skipControlCharactersStandard(); - } catch (IndexOutOfBoundsException e) { - throw new NotEnoughDataDecoderException(e); - } - return; - } - - while (sao.pos < sao.limit) { - char c = (char) (sao.bytes[sao.pos++] & 0xFF); - if (!Character.isISOControl(c) && !Character.isWhitespace(c)) { - sao.setReadPosition(1); - return; - } - } - throw new NotEnoughDataDecoderException("Access out of bounds"); - } - - void skipControlCharactersStandard() { - for (;;) { - char c = (char) undecodedChunk.readUnsignedByte(); - if (!Character.isISOControl(c) && !Character.isWhitespace(c)) { - undecodedChunk.readerIndex(undecodedChunk.readerIndex() - 1); - break; - } - } - } - - /** - * Destroy the {@link HttpPostStandardRequestDecoder} and release all it resources. After this method - * was called it is not possible to operate on it anymore. - */ - @Override - public void destroy() { - checkDestroyed(); - cleanFiles(); - destroyed = true; - - if (undecodedChunk != null && undecodedChunk.refCnt() > 0) { - undecodedChunk.release(); - undecodedChunk = null; - } - - // release all data which was not yet pulled - for (int i = bodyListHttpDataRank; i < bodyListHttpData.size(); i++) { - bodyListHttpData.get(i).release(); - } - } - - /** - * Clean all HttpDatas (on Disk) for the current request. - */ - @Override - public void cleanFiles() { - checkDestroyed(); - - factory.cleanRequestHttpDatas(request); - } - - /** - * Remove the given FileUpload from the list of FileUploads to clean - */ - @Override - public void removeHttpDataFromClean(InterfaceHttpData data) { - checkDestroyed(); - - factory.removeHttpDataFromClean(request, data); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/InterfaceHttpData.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/InterfaceHttpData.java deleted file mode 100755 index 8a42e84e9a..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/InterfaceHttpData.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.multipart; - -import com.ai.cloud.io.netty.util.ReferenceCounted; - -/** - * Interface for all Objects that could be encoded/decoded using HttpPostRequestEncoder/Decoder - */ -public interface InterfaceHttpData extends Comparable, ReferenceCounted { - enum HttpDataType { - Attribute, FileUpload, InternalAttribute - } - - /** - * Returns the name of this InterfaceHttpData. - */ - String getName(); - - /** - * - * @return The HttpDataType - */ - HttpDataType getHttpDataType(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/InterfaceHttpPostRequestDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/InterfaceHttpPostRequestDecoder.java deleted file mode 100755 index c85fbe089a..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/InterfaceHttpPostRequestDecoder.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.multipart; - -import java.util.List; - -import com.ai.cloud.io.netty.handler.codec.http.HttpContent; - -/** - * This decoder will decode Body and can handle POST BODY (or for PUT, PATCH or OPTIONS). - * - * You MUST call {@link #destroy()} after completion to release all resources. - * - */ -public interface InterfaceHttpPostRequestDecoder { - /** - * True if this request is a Multipart request - * - * @return True if this request is a Multipart request - */ - boolean isMultipart(); - - /** - * Set the amount of bytes after which read bytes in the buffer should be discarded. - * Setting this lower gives lower memory usage but with the overhead of more memory copies. - * Use {@code 0} to disable it. - */ - void setDiscardThreshold(int discardThreshold); - - /** - * Return the threshold in bytes after which read data in the buffer should be discarded. - */ - int getDiscardThreshold(); - - /** - * This getMethod returns a List of all HttpDatas from body.
- * - * If chunked, all chunks must have been offered using offer() getMethod. If - * not, NotEnoughDataDecoderException will be raised. - * - * @return the list of HttpDatas from Body part for POST getMethod - * @throws HttpPostRequestDecoder.NotEnoughDataDecoderException - * Need more chunks - */ - List getBodyHttpDatas(); - - /** - * This getMethod returns a List of all HttpDatas with the given name from - * body.
- * - * If chunked, all chunks must have been offered using offer() getMethod. If - * not, NotEnoughDataDecoderException will be raised. - * - * @return All Body HttpDatas with the given name (ignore case) - * @throws HttpPostRequestDecoder.NotEnoughDataDecoderException - * need more chunks - */ - List getBodyHttpDatas(String name); - - /** - * This getMethod returns the first InterfaceHttpData with the given name from - * body.
- * - * If chunked, all chunks must have been offered using offer() getMethod. If - * not, NotEnoughDataDecoderException will be raised. - * - * @return The first Body InterfaceHttpData with the given name (ignore - * case) - * @throws HttpPostRequestDecoder.NotEnoughDataDecoderException - * need more chunks - */ - InterfaceHttpData getBodyHttpData(String name); - - /** - * Initialized the internals from a new chunk - * - * @param content - * the new received chunk - * @throws HttpPostRequestDecoder.ErrorDataDecoderException - * if there is a problem with the charset decoding or other - * errors - */ - InterfaceHttpPostRequestDecoder offer(HttpContent content); - - /** - * True if at current getStatus, there is an available decoded - * InterfaceHttpData from the Body. - * - * This getMethod works for chunked and not chunked request. - * - * @return True if at current getStatus, there is a decoded InterfaceHttpData - * @throws HttpPostRequestDecoder.EndOfDataDecoderException - * No more data will be available - */ - boolean hasNext(); - - /** - * Returns the next available InterfaceHttpData or null if, at the time it - * is called, there is no more available InterfaceHttpData. A subsequent - * call to offer(httpChunk) could enable more data. - * - * Be sure to call {@link InterfaceHttpData#release()} after you are done - * with processing to make sure to not leak any resources - * - * @return the next available InterfaceHttpData or null if none - * @throws HttpPostRequestDecoder.EndOfDataDecoderException - * No more data will be available - */ - InterfaceHttpData next(); - - /** - * Destroy the {@link InterfaceHttpPostRequestDecoder} and release all it resources. After this method - * was called it is not possible to operate on it anymore. - */ - void destroy(); - - /** - * Clean all HttpDatas (on Disk) for the current request. - */ - void cleanFiles(); - - /** - * Remove the given FileUpload from the list of FileUploads to clean - */ - void removeHttpDataFromClean(InterfaceHttpData data); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/InternalAttribute.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/InternalAttribute.java deleted file mode 100755 index 99b51b08b0..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/InternalAttribute.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.multipart; - -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.List; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.Unpooled; -import com.ai.cloud.io.netty.util.AbstractReferenceCounted; - -/** - * This Attribute is only for Encoder use to insert special command between object if needed - * (like Multipart Mixed mode) - */ -final class InternalAttribute extends AbstractReferenceCounted implements InterfaceHttpData { - private final List value = new ArrayList(); - private final Charset charset; - private int size; - - InternalAttribute(Charset charset) { - this.charset = charset; - } - - @Override - public HttpDataType getHttpDataType() { - return HttpDataType.InternalAttribute; - } - - public void addValue(String value) { - if (value == null) { - throw new NullPointerException("value"); - } - ByteBuf buf = Unpooled.copiedBuffer(value, charset); - this.value.add(buf); - size += buf.readableBytes(); - } - - public void addValue(String value, int rank) { - if (value == null) { - throw new NullPointerException("value"); - } - ByteBuf buf = Unpooled.copiedBuffer(value, charset); - this.value.add(rank, buf); - size += buf.readableBytes(); - } - - public void setValue(String value, int rank) { - if (value == null) { - throw new NullPointerException("value"); - } - ByteBuf buf = Unpooled.copiedBuffer(value, charset); - ByteBuf old = this.value.set(rank, buf); - if (old != null) { - size -= old.readableBytes(); - old.release(); - } - size += buf.readableBytes(); - } - - @Override - public int hashCode() { - return getName().hashCode(); - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof Attribute)) { - return false; - } - Attribute attribute = (Attribute) o; - return getName().equalsIgnoreCase(attribute.getName()); - } - - @Override - public int compareTo(InterfaceHttpData o) { - if (!(o instanceof InternalAttribute)) { - throw new ClassCastException("Cannot compare " + getHttpDataType() + - " with " + o.getHttpDataType()); - } - return compareTo((InternalAttribute) o); - } - - public int compareTo(InternalAttribute o) { - return getName().compareToIgnoreCase(o.getName()); - } - - @Override - public String toString() { - StringBuilder result = new StringBuilder(); - for (ByteBuf elt : value) { - result.append(elt.toString(charset)); - } - return result.toString(); - } - - public int size() { - return size; - } - - public ByteBuf toByteBuf() { - return Unpooled.compositeBuffer().addComponents(value).writerIndex(size()).readerIndex(0); - } - - @Override - public String getName() { - return "InternalAttribute"; - } - - @Override - protected void deallocate() { - // Do nothing - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/MemoryAttribute.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/MemoryAttribute.java deleted file mode 100755 index 6251ce9148..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/MemoryAttribute.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.multipart; - -import java.io.IOException; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelException; -import com.ai.cloud.io.netty.handler.codec.http.HttpConstants; - -import static com.ai.cloud.io.netty.buffer.Unpooled.*; - -/** - * Memory implementation of Attributes - */ -public class MemoryAttribute extends AbstractMemoryHttpData implements Attribute { - - public MemoryAttribute(String name) { - super(name, HttpConstants.DEFAULT_CHARSET, 0); - } - - public MemoryAttribute(String name, String value) throws IOException { - super(name, HttpConstants.DEFAULT_CHARSET, 0); // Attribute have no default size - setValue(value); - } - - @Override - public HttpDataType getHttpDataType() { - return HttpDataType.Attribute; - } - - @Override - public String getValue() { - return getByteBuf().toString(charset); - } - - @Override - public void setValue(String value) throws IOException { - if (value == null) { - throw new NullPointerException("value"); - } - byte [] bytes = value.getBytes(charset.name()); - ByteBuf buffer = wrappedBuffer(bytes); - if (definedSize > 0) { - definedSize = buffer.readableBytes(); - } - setContent(buffer); - } - - @Override - public void addContent(ByteBuf buffer, boolean last) throws IOException { - int localsize = buffer.readableBytes(); - if (definedSize > 0 && definedSize < size + localsize) { - definedSize = size + localsize; - } - super.addContent(buffer, last); - } - - @Override - public int hashCode() { - return getName().hashCode(); - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof Attribute)) { - return false; - } - Attribute attribute = (Attribute) o; - return getName().equalsIgnoreCase(attribute.getName()); - } - - @Override - public int compareTo(InterfaceHttpData other) { - if (!(other instanceof Attribute)) { - throw new ClassCastException("Cannot compare " + getHttpDataType() + - " with " + other.getHttpDataType()); - } - return compareTo((Attribute) other); - } - - public int compareTo(Attribute o) { - return getName().compareToIgnoreCase(o.getName()); - } - - @Override - public String toString() { - return getName() + '=' + getValue(); - } - - @Override - public Attribute copy() { - MemoryAttribute attr = new MemoryAttribute(getName()); - attr.setCharset(getCharset()); - ByteBuf content = content(); - if (content != null) { - try { - attr.setContent(content.copy()); - } catch (IOException e) { - throw new ChannelException(e); - } - } - return attr; - } - - @Override - public Attribute duplicate() { - MemoryAttribute attr = new MemoryAttribute(getName()); - attr.setCharset(getCharset()); - ByteBuf content = content(); - if (content != null) { - try { - attr.setContent(content.duplicate()); - } catch (IOException e) { - throw new ChannelException(e); - } - } - return attr; - } - - @Override - public Attribute retain() { - super.retain(); - return this; - } - - @Override - public Attribute retain(int increment) { - super.retain(increment); - return this; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/MemoryFileUpload.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/MemoryFileUpload.java deleted file mode 100755 index 1892d4d697..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/MemoryFileUpload.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.multipart; - -import java.io.IOException; -import java.nio.charset.Charset; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelException; -import com.ai.cloud.io.netty.handler.codec.http.HttpHeaders; - -/** - * Default FileUpload implementation that stores file into memory.

- * - * Warning: be aware of the memory limitation. - */ -public class MemoryFileUpload extends AbstractMemoryHttpData implements FileUpload { - - private String filename; - - private String contentType; - - private String contentTransferEncoding; - - public MemoryFileUpload(String name, String filename, String contentType, - String contentTransferEncoding, Charset charset, long size) { - super(name, charset, size); - setFilename(filename); - setContentType(contentType); - setContentTransferEncoding(contentTransferEncoding); - } - - @Override - public HttpDataType getHttpDataType() { - return HttpDataType.FileUpload; - } - - @Override - public String getFilename() { - return filename; - } - - @Override - public void setFilename(String filename) { - if (filename == null) { - throw new NullPointerException("filename"); - } - this.filename = filename; - } - - @Override - public int hashCode() { - return getName().hashCode(); - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof Attribute)) { - return false; - } - Attribute attribute = (Attribute) o; - return getName().equalsIgnoreCase(attribute.getName()); - } - - @Override - public int compareTo(InterfaceHttpData o) { - if (!(o instanceof FileUpload)) { - throw new ClassCastException("Cannot compare " + getHttpDataType() + - " with " + o.getHttpDataType()); - } - return compareTo((FileUpload) o); - } - - public int compareTo(FileUpload o) { - int v; - v = getName().compareToIgnoreCase(o.getName()); - if (v != 0) { - return v; - } - // TODO should we compare size for instance ? - return v; - } - - @Override - public void setContentType(String contentType) { - if (contentType == null) { - throw new NullPointerException("contentType"); - } - this.contentType = contentType; - } - - @Override - public String getContentType() { - return contentType; - } - - @Override - public String getContentTransferEncoding() { - return contentTransferEncoding; - } - - @Override - public void setContentTransferEncoding(String contentTransferEncoding) { - this.contentTransferEncoding = contentTransferEncoding; - } - - @Override - public String toString() { - return HttpPostBodyUtil.CONTENT_DISPOSITION + ": " + - HttpPostBodyUtil.FORM_DATA + "; " + HttpPostBodyUtil.NAME + "=\"" + getName() + - "\"; " + HttpPostBodyUtil.FILENAME + "=\"" + filename + "\"\r\n" + - HttpHeaders.Names.CONTENT_TYPE + ": " + contentType + - (charset != null? "; " + HttpHeaders.Values.CHARSET + '=' + charset.name() + "\r\n" : "\r\n") + - HttpHeaders.Names.CONTENT_LENGTH + ": " + length() + "\r\n" + - "Completed: " + isCompleted() + - "\r\nIsInMemory: " + isInMemory(); - } - - @Override - public FileUpload copy() { - MemoryFileUpload upload = new MemoryFileUpload(getName(), getFilename(), getContentType(), - getContentTransferEncoding(), getCharset(), size); - ByteBuf buf = content(); - if (buf != null) { - try { - upload.setContent(buf.copy()); - return upload; - } catch (IOException e) { - throw new ChannelException(e); - } - } - return upload; - } - - @Override - public FileUpload duplicate() { - MemoryFileUpload upload = new MemoryFileUpload(getName(), getFilename(), getContentType(), - getContentTransferEncoding(), getCharset(), size); - ByteBuf buf = content(); - if (buf != null) { - try { - upload.setContent(buf.duplicate()); - return upload; - } catch (IOException e) { - throw new ChannelException(e); - } - } - return upload; - } - @Override - public FileUpload retain() { - super.retain(); - return this; - } - - @Override - public FileUpload retain(int increment) { - super.retain(increment); - return this; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/MixedAttribute.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/MixedAttribute.java deleted file mode 100755 index 1f443e7eb1..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/MixedAttribute.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.multipart; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.Charset; - -import com.ai.cloud.io.netty.buffer.ByteBuf; - -/** - * Mixed implementation using both in Memory and in File with a limit of size - */ -public class MixedAttribute implements Attribute { - private Attribute attribute; - - private final long limitSize; - - public MixedAttribute(String name, long limitSize) { - this.limitSize = limitSize; - attribute = new MemoryAttribute(name); - } - - public MixedAttribute(String name, String value, long limitSize) { - this.limitSize = limitSize; - if (value.length() > this.limitSize) { - try { - attribute = new DiskAttribute(name, value); - } catch (IOException e) { - // revert to Memory mode - try { - attribute = new MemoryAttribute(name, value); - } catch (IOException e1) { - throw new IllegalArgumentException(e); - } - } - } else { - try { - attribute = new MemoryAttribute(name, value); - } catch (IOException e) { - throw new IllegalArgumentException(e); - } - } - } - - @Override - public void addContent(ByteBuf buffer, boolean last) throws IOException { - if (attribute instanceof MemoryAttribute) { - if (attribute.length() + buffer.readableBytes() > limitSize) { - DiskAttribute diskAttribute = new DiskAttribute(attribute - .getName()); - if (((MemoryAttribute) attribute).getByteBuf() != null) { - diskAttribute.addContent(((MemoryAttribute) attribute) - .getByteBuf(), false); - } - attribute = diskAttribute; - } - } - attribute.addContent(buffer, last); - } - - @Override - public void delete() { - attribute.delete(); - } - - @Override - public byte[] get() throws IOException { - return attribute.get(); - } - - @Override - public ByteBuf getByteBuf() throws IOException { - return attribute.getByteBuf(); - } - - @Override - public Charset getCharset() { - return attribute.getCharset(); - } - - @Override - public String getString() throws IOException { - return attribute.getString(); - } - - @Override - public String getString(Charset encoding) throws IOException { - return attribute.getString(encoding); - } - - @Override - public boolean isCompleted() { - return attribute.isCompleted(); - } - - @Override - public boolean isInMemory() { - return attribute.isInMemory(); - } - - @Override - public long length() { - return attribute.length(); - } - - @Override - public boolean renameTo(File dest) throws IOException { - return attribute.renameTo(dest); - } - - @Override - public void setCharset(Charset charset) { - attribute.setCharset(charset); - } - - @Override - public void setContent(ByteBuf buffer) throws IOException { - if (buffer.readableBytes() > limitSize) { - if (attribute instanceof MemoryAttribute) { - // change to Disk - attribute = new DiskAttribute(attribute.getName()); - } - } - attribute.setContent(buffer); - } - - @Override - public void setContent(File file) throws IOException { - if (file.length() > limitSize) { - if (attribute instanceof MemoryAttribute) { - // change to Disk - attribute = new DiskAttribute(attribute.getName()); - } - } - attribute.setContent(file); - } - - @Override - public void setContent(InputStream inputStream) throws IOException { - if (attribute instanceof MemoryAttribute) { - // change to Disk even if we don't know the size - attribute = new DiskAttribute(attribute.getName()); - } - attribute.setContent(inputStream); - } - - @Override - public HttpDataType getHttpDataType() { - return attribute.getHttpDataType(); - } - - @Override - public String getName() { - return attribute.getName(); - } - - @Override - public int compareTo(InterfaceHttpData o) { - return attribute.compareTo(o); - } - - @Override - public String toString() { - return "Mixed: " + attribute.toString(); - } - - @Override - public String getValue() throws IOException { - return attribute.getValue(); - } - - @Override - public void setValue(String value) throws IOException { - attribute.setValue(value); - } - - @Override - public ByteBuf getChunk(int length) throws IOException { - return attribute.getChunk(length); - } - - @Override - public File getFile() throws IOException { - return attribute.getFile(); - } - - @Override - public Attribute copy() { - return attribute.copy(); - } - - @Override - public Attribute duplicate() { - return attribute.duplicate(); - } - - @Override - public ByteBuf content() { - return attribute.content(); - } - - @Override - public int refCnt() { - return attribute.refCnt(); - } - - @Override - public Attribute retain() { - attribute.retain(); - return this; - } - - @Override - public Attribute retain(int increment) { - attribute.retain(increment); - return this; - } - - @Override - public boolean release() { - return attribute.release(); - } - - @Override - public boolean release(int decrement) { - return attribute.release(decrement); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/MixedFileUpload.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/MixedFileUpload.java deleted file mode 100755 index 027f0cae16..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/MixedFileUpload.java +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.http.multipart; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.Charset; - -import com.ai.cloud.io.netty.buffer.ByteBuf; - -/** - * Mixed implementation using both in Memory and in File with a limit of size - */ -public class MixedFileUpload implements FileUpload { - - private FileUpload fileUpload; - - private final long limitSize; - - private final long definedSize; - - public MixedFileUpload(String name, String filename, String contentType, - String contentTransferEncoding, Charset charset, long size, - long limitSize) { - this.limitSize = limitSize; - if (size > this.limitSize) { - fileUpload = new DiskFileUpload(name, filename, contentType, - contentTransferEncoding, charset, size); - } else { - fileUpload = new MemoryFileUpload(name, filename, contentType, - contentTransferEncoding, charset, size); - } - definedSize = size; - } - - @Override - public void addContent(ByteBuf buffer, boolean last) - throws IOException { - if (fileUpload instanceof MemoryFileUpload) { - if (fileUpload.length() + buffer.readableBytes() > limitSize) { - DiskFileUpload diskFileUpload = new DiskFileUpload(fileUpload - .getName(), fileUpload.getFilename(), fileUpload - .getContentType(), fileUpload - .getContentTransferEncoding(), fileUpload.getCharset(), - definedSize); - - ByteBuf data = fileUpload.getByteBuf(); - if (data != null && data.isReadable()) { - diskFileUpload.addContent(data.retain(), false); - } - // release old upload - fileUpload.release(); - - fileUpload = diskFileUpload; - } - } - fileUpload.addContent(buffer, last); - } - - @Override - public void delete() { - fileUpload.delete(); - } - - @Override - public byte[] get() throws IOException { - return fileUpload.get(); - } - - @Override - public ByteBuf getByteBuf() throws IOException { - return fileUpload.getByteBuf(); - } - - @Override - public Charset getCharset() { - return fileUpload.getCharset(); - } - - @Override - public String getContentType() { - return fileUpload.getContentType(); - } - - @Override - public String getContentTransferEncoding() { - return fileUpload.getContentTransferEncoding(); - } - - @Override - public String getFilename() { - return fileUpload.getFilename(); - } - - @Override - public String getString() throws IOException { - return fileUpload.getString(); - } - - @Override - public String getString(Charset encoding) throws IOException { - return fileUpload.getString(encoding); - } - - @Override - public boolean isCompleted() { - return fileUpload.isCompleted(); - } - - @Override - public boolean isInMemory() { - return fileUpload.isInMemory(); - } - - @Override - public long length() { - return fileUpload.length(); - } - - @Override - public boolean renameTo(File dest) throws IOException { - return fileUpload.renameTo(dest); - } - - @Override - public void setCharset(Charset charset) { - fileUpload.setCharset(charset); - } - - @Override - public void setContent(ByteBuf buffer) throws IOException { - if (buffer.readableBytes() > limitSize) { - if (fileUpload instanceof MemoryFileUpload) { - FileUpload memoryUpload = fileUpload; - // change to Disk - fileUpload = new DiskFileUpload(memoryUpload - .getName(), memoryUpload.getFilename(), memoryUpload - .getContentType(), memoryUpload - .getContentTransferEncoding(), memoryUpload.getCharset(), - definedSize); - - // release old upload - memoryUpload.release(); - } - } - fileUpload.setContent(buffer); - } - - @Override - public void setContent(File file) throws IOException { - if (file.length() > limitSize) { - if (fileUpload instanceof MemoryFileUpload) { - FileUpload memoryUpload = fileUpload; - - // change to Disk - fileUpload = new DiskFileUpload(memoryUpload - .getName(), memoryUpload.getFilename(), memoryUpload - .getContentType(), memoryUpload - .getContentTransferEncoding(), memoryUpload.getCharset(), - definedSize); - - // release old upload - memoryUpload.release(); - } - } - fileUpload.setContent(file); - } - - @Override - public void setContent(InputStream inputStream) throws IOException { - if (fileUpload instanceof MemoryFileUpload) { - FileUpload memoryUpload = fileUpload; - - // change to Disk - fileUpload = new DiskFileUpload(fileUpload - .getName(), fileUpload.getFilename(), fileUpload - .getContentType(), fileUpload - .getContentTransferEncoding(), fileUpload.getCharset(), - definedSize); - - // release old upload - memoryUpload.release(); - } - fileUpload.setContent(inputStream); - } - - @Override - public void setContentType(String contentType) { - fileUpload.setContentType(contentType); - } - - @Override - public void setContentTransferEncoding(String contentTransferEncoding) { - fileUpload.setContentTransferEncoding(contentTransferEncoding); - } - - @Override - public void setFilename(String filename) { - fileUpload.setFilename(filename); - } - - @Override - public HttpDataType getHttpDataType() { - return fileUpload.getHttpDataType(); - } - - @Override - public String getName() { - return fileUpload.getName(); - } - - @Override - public int compareTo(InterfaceHttpData o) { - return fileUpload.compareTo(o); - } - - @Override - public String toString() { - return "Mixed: " + fileUpload.toString(); - } - - @Override - public ByteBuf getChunk(int length) throws IOException { - return fileUpload.getChunk(length); - } - - @Override - public File getFile() throws IOException { - return fileUpload.getFile(); - } - - @Override - public FileUpload copy() { - return fileUpload.copy(); - } - - @Override - public FileUpload duplicate() { - return fileUpload.duplicate(); - } - - @Override - public ByteBuf content() { - return fileUpload.content(); - } - - @Override - public int refCnt() { - return fileUpload.refCnt(); - } - - @Override - public FileUpload retain() { - fileUpload.retain(); - return this; - } - - @Override - public FileUpload retain(int increment) { - fileUpload.retain(increment); - return this; - } - - @Override - public boolean release() { - return fileUpload.release(); - } - - @Override - public boolean release(int decrement) { - return fileUpload.release(decrement); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/package-info.java deleted file mode 100755 index 8afb9798f5..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/multipart/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * HTTP multipart support. - */ -package com.ai.cloud.io.netty.handler.codec.http.multipart; diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/package-info.java deleted file mode 100755 index 824874c1f5..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/http/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * Encoder, decoder and their related message types for HTTP. - */ -package com.ai.cloud.io.netty.handler.codec.http; diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/package-info.java deleted file mode 100755 index a8520c339e..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/package-info.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * Extensible decoder and its common implementations which deal with the - * packet fragmentation and reassembly issue found in a stream-based transport - * such as TCP/IP. - */ -package com.ai.cloud.io.netty.handler.codec; diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspDecoder.java deleted file mode 100755 index 78fbe113b4..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspDecoder.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.rtsp; - -import java.util.regex.Pattern; - -import com.ai.cloud.io.netty.buffer.Unpooled; -import com.ai.cloud.io.netty.handler.codec.http.DefaultFullHttpRequest; -import com.ai.cloud.io.netty.handler.codec.http.DefaultFullHttpResponse; -import com.ai.cloud.io.netty.handler.codec.http.DefaultHttpRequest; -import com.ai.cloud.io.netty.handler.codec.http.DefaultHttpResponse; -import com.ai.cloud.io.netty.handler.codec.http.HttpMessage; -import com.ai.cloud.io.netty.handler.codec.http.HttpObjectDecoder; -import com.ai.cloud.io.netty.handler.codec.http.HttpResponseStatus; - -/** - * Decodes {@link ByteBuf}s into RTSP messages represented in - * {@link HttpMessage}s. - *

- *

Parameters that prevents excessive memory consumption

- * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
NameMeaning
{@code maxInitialLineLength}The maximum length of the initial line - * (e.g. {@code "SETUP / RTSP/1.0"} or {@code "RTSP/1.0 200 OK"}) - * If the length of the initial line exceeds this value, a - * {@link TooLongFrameException} will be raised.
{@code maxHeaderSize}The maximum length of all headers. If the sum of the length of each - * header exceeds this value, a {@link TooLongFrameException} will be - * raised.
{@code maxContentLength}The maximum length of the content. If the content length exceeds this - * value, a {@link TooLongFrameException} will be raised.
- */ -public class RtspDecoder extends HttpObjectDecoder { - /** - * Status code for unknown responses. - */ - private static final HttpResponseStatus UNKNOWN_STATUS = - new HttpResponseStatus(999, "Unknown"); - /** - * True if the message to decode is a request. - * False if the message to decode is a response. - */ - private boolean isDecodingRequest; - - /** - * Regex used on first line in message to detect if it is a response. - */ - private static final Pattern versionPattern = Pattern.compile("RTSP/\\d\\.\\d"); - - /** - * Constant for default max initial line length. - */ - public static final int DEFAULT_MAX_INITIAL_LINE_LENGTH = 4096; - - /** - * Constant for default max header size. - */ - public static final int DEFAULT_MAX_HEADER_SIZE = 8192; - - /** - * Constant for default max content length. - */ - public static final int DEFAULT_MAX_CONTENT_LENGTH = 8192; - - /** - * Creates a new instance with the default - * {@code maxInitialLineLength (4096)}, {@code maxHeaderSize (8192)}, and - * {@code maxContentLength (8192)}. - */ - public RtspDecoder() { - this(DEFAULT_MAX_INITIAL_LINE_LENGTH, - DEFAULT_MAX_HEADER_SIZE, - DEFAULT_MAX_CONTENT_LENGTH); - } - - /** - * Creates a new instance with the specified parameters. - * @param maxInitialLineLength The max allowed length of initial line - * @param maxHeaderSize The max allowed size of header - * @param maxContentLength The max allowed content length - */ - public RtspDecoder(final int maxInitialLineLength, - final int maxHeaderSize, - final int maxContentLength) { - super(maxInitialLineLength, maxHeaderSize, maxContentLength * 2, false); - } - - /** - * Creates a new instance with the specified parameters. - * @param maxInitialLineLength The max allowed length of initial line - * @param maxHeaderSize The max allowed size of header - * @param maxContentLength The max allowed content length - * @param validateHeaders Set to true if headers should be validated - */ - public RtspDecoder(final int maxInitialLineLength, - final int maxHeaderSize, - final int maxContentLength, - final boolean validateHeaders) { - super(maxInitialLineLength, - maxHeaderSize, - maxContentLength * 2, - false, - validateHeaders); - } - - @Override - protected HttpMessage createMessage(final String[] initialLine) - throws Exception { - // If the first element of the initial line is a version string then - // this is a response - if (versionPattern.matcher(initialLine[0]).matches()) { - isDecodingRequest = false; - return new DefaultHttpResponse(RtspVersions.valueOf(initialLine[0]), - new HttpResponseStatus(Integer.parseInt(initialLine[1]), - initialLine[2]), - validateHeaders); - } else { - isDecodingRequest = true; - return new DefaultHttpRequest(RtspVersions.valueOf(initialLine[2]), - RtspMethods.valueOf(initialLine[0]), - initialLine[1], - validateHeaders); - } - } - - @Override - protected boolean isContentAlwaysEmpty(final HttpMessage msg) { - // Unlike HTTP, RTSP always assumes zero-length body if Content-Length - // header is absent. - return super.isContentAlwaysEmpty(msg) || !msg.headers().contains(RtspHeaders.Names.CONTENT_LENGTH); - } - - @Override - protected HttpMessage createInvalidMessage() { - if (isDecodingRequest) { - return new DefaultFullHttpRequest(RtspVersions.RTSP_1_0, - RtspMethods.OPTIONS, "/bad-request", Unpooled.EMPTY_BUFFER, validateHeaders); - } else { - return new DefaultFullHttpResponse(RtspVersions.RTSP_1_0, - UNKNOWN_STATUS, Unpooled.EMPTY_BUFFER, - validateHeaders); - } - } - - @Override - protected boolean isDecodingRequest() { - return isDecodingRequest; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspEncoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspEncoder.java deleted file mode 100755 index a8d85e5098..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspEncoder.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.rtsp; - -import static com.ai.cloud.io.netty.handler.codec.http.HttpConstants.CR; -import static com.ai.cloud.io.netty.handler.codec.http.HttpConstants.LF; -import static com.ai.cloud.io.netty.handler.codec.http.HttpConstants.SP; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.handler.codec.UnsupportedMessageTypeException; -import com.ai.cloud.io.netty.handler.codec.http.HttpContent; -import com.ai.cloud.io.netty.handler.codec.http.HttpHeaders; -import com.ai.cloud.io.netty.handler.codec.http.HttpMessage; -import com.ai.cloud.io.netty.handler.codec.http.HttpObjectEncoder; -import com.ai.cloud.io.netty.handler.codec.http.HttpRequest; -import com.ai.cloud.io.netty.handler.codec.http.HttpResponse; -import com.ai.cloud.io.netty.util.CharsetUtil; -import com.ai.cloud.io.netty.util.internal.StringUtil; - -/** - * Encodes an RTSP message represented in {@link HttpMessage} or an {@link HttpContent} into - * a {@link ByteBuf}. - */ -public class RtspEncoder extends HttpObjectEncoder { - /** - * Constant for CRLF. - */ - private static final byte[] CRLF = {CR, LF}; - - @Override - public boolean acceptOutboundMessage(final Object msg) - throws Exception { - return super.acceptOutboundMessage(msg) && ((msg instanceof HttpRequest) || (msg instanceof HttpResponse)); - } - - @Override - protected void encodeInitialLine(final ByteBuf buf, final HttpMessage message) - throws Exception { - if (message instanceof HttpRequest) { - HttpRequest request = (HttpRequest) message; - HttpHeaders.encodeAscii(request.getMethod().toString(), buf); - buf.writeByte(SP); - buf.writeBytes(request.getUri().getBytes(CharsetUtil.UTF_8)); - buf.writeByte(SP); - HttpHeaders.encodeAscii(request.getProtocolVersion().toString(), buf); - buf.writeBytes(CRLF); - } else if (message instanceof HttpResponse) { - HttpResponse response = (HttpResponse) message; - HttpHeaders.encodeAscii(response.getProtocolVersion().toString(), - buf); - buf.writeByte(SP); - buf.writeBytes(String.valueOf(response.getStatus().code()) - .getBytes(CharsetUtil.US_ASCII)); - buf.writeByte(SP); - HttpHeaders.encodeAscii(String.valueOf(response.getStatus().reasonPhrase()), - buf); - buf.writeBytes(CRLF); - } else { - throw new UnsupportedMessageTypeException("Unsupported type " - + StringUtil.simpleClassName(message)); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspHeaders.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspHeaders.java deleted file mode 100755 index 7bf518b170..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspHeaders.java +++ /dev/null @@ -1,388 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.rtsp; - -import com.ai.cloud.io.netty.handler.codec.http.HttpHeaders; - - -/** - * Standard RTSP header names and values. - */ -public final class RtspHeaders { - - /** - * Standard RTSP header names. - */ - public static final class Names { - /** - * {@code "Accept"} - */ - public static final String ACCEPT = HttpHeaders.Names.ACCEPT; - /** - * {@code "Accept-Encoding"} - */ - public static final String ACCEPT_ENCODING = HttpHeaders.Names.ACCEPT_ENCODING; - /** - * {@code "Accept-Lanugage"} - */ - public static final String ACCEPT_LANGUAGE = HttpHeaders.Names.ACCEPT_LANGUAGE; - /** - * {@code "Allow"} - */ - public static final String ALLOW = "Allow"; - /** - * {@code "Authorization"} - */ - public static final String AUTHORIZATION = HttpHeaders.Names.AUTHORIZATION; - /** - * {@code "Bandwidth"} - */ - public static final String BANDWIDTH = "Bandwidth"; - /** - * {@code "Blocksize"} - */ - public static final String BLOCKSIZE = "Blocksize"; - /** - * {@code "Cache-Control"} - */ - public static final String CACHE_CONTROL = HttpHeaders.Names.CACHE_CONTROL; - /** - * {@code "Conference"} - */ - public static final String CONFERENCE = "Conference"; - /** - * {@code "Connection"} - */ - public static final String CONNECTION = HttpHeaders.Names.CONNECTION; - /** - * {@code "Content-Base"} - */ - public static final String CONTENT_BASE = HttpHeaders.Names.CONTENT_BASE; - /** - * {@code "Content-Encoding"} - */ - public static final String CONTENT_ENCODING = HttpHeaders.Names.CONTENT_ENCODING; - /** - * {@code "Content-Language"} - */ - public static final String CONTENT_LANGUAGE = HttpHeaders.Names.CONTENT_LANGUAGE; - /** - * {@code "Content-Length"} - */ - public static final String CONTENT_LENGTH = HttpHeaders.Names.CONTENT_LENGTH; - /** - * {@code "Content-Location"} - */ - public static final String CONTENT_LOCATION = HttpHeaders.Names.CONTENT_LOCATION; - /** - * {@code "Content-Type"} - */ - public static final String CONTENT_TYPE = HttpHeaders.Names.CONTENT_TYPE; - /** - * {@code "CSeq"} - */ - public static final String CSEQ = "CSeq"; - /** - * {@code "Date"} - */ - public static final String DATE = HttpHeaders.Names.DATE; - /** - * {@code "Expires"} - */ - public static final String EXPIRES = HttpHeaders.Names.EXPIRES; - /** - * {@code "From"} - */ - public static final String FROM = HttpHeaders.Names.FROM; - /** - * {@code "Host"} - */ - public static final String HOST = HttpHeaders.Names.HOST; - /** - * {@code "If-Match"} - */ - public static final String IF_MATCH = HttpHeaders.Names.IF_MATCH; - /** - * {@code "If-Modified-Since"} - */ - public static final String IF_MODIFIED_SINCE = HttpHeaders.Names.IF_MODIFIED_SINCE; - /** - * {@code "KeyMgmt"} - */ - public static final String KEYMGMT = "KeyMgmt"; - /** - * {@code "Last-Modified"} - */ - public static final String LAST_MODIFIED = HttpHeaders.Names.LAST_MODIFIED; - /** - * {@code "Proxy-Authenticate"} - */ - public static final String PROXY_AUTHENTICATE = HttpHeaders.Names.PROXY_AUTHENTICATE; - /** - * {@code "Proxy-Require"} - */ - public static final String PROXY_REQUIRE = "Proxy-Require"; - /** - * {@code "Public"} - */ - public static final String PUBLIC = "Public"; - /** - * {@code "Range"} - */ - public static final String RANGE = HttpHeaders.Names.RANGE; - /** - * {@code "Referer"} - */ - public static final String REFERER = HttpHeaders.Names.REFERER; - /** - * {@code "Require"} - */ - public static final String REQUIRE = "Require"; - /** - * {@code "Retry-After"} - */ - public static final String RETRT_AFTER = HttpHeaders.Names.RETRY_AFTER; - /** - * {@code "RTP-Info"} - */ - public static final String RTP_INFO = "RTP-Info"; - /** - * {@code "Scale"} - */ - public static final String SCALE = "Scale"; - /** - * {@code "Session"} - */ - public static final String SESSION = "Session"; - /** - * {@code "Server"} - */ - public static final String SERVER = HttpHeaders.Names.SERVER; - /** - * {@code "Speed"} - */ - public static final String SPEED = "Speed"; - /** - * {@code "Timestamp"} - */ - public static final String TIMESTAMP = "Timestamp"; - /** - * {@code "Transport"} - */ - public static final String TRANSPORT = "Transport"; - /** - * {@code "Unsupported"} - */ - public static final String UNSUPPORTED = "Unsupported"; - /** - * {@code "User-Agent"} - */ - public static final String USER_AGENT = HttpHeaders.Names.USER_AGENT; - /** - * {@code "Vary"} - */ - public static final String VARY = HttpHeaders.Names.VARY; - /** - * {@code "Via"} - */ - public static final String VIA = HttpHeaders.Names.VIA; - /** - * {@code "WWW-Authenticate"} - */ - public static final String WWW_AUTHENTICATE = HttpHeaders.Names.WWW_AUTHENTICATE; - - private Names() { - } - } - - /** - * Standard RTSP header values. - */ - public static final class Values { - /** - * {@code "append"} - */ - public static final String APPEND = "append"; - /** - * {@code "AVP"} - */ - public static final String AVP = "AVP"; - /** - * {@code "bytes"} - */ - public static final String BYTES = HttpHeaders.Values.BYTES; - /** - * {@code "charset"} - */ - public static final String CHARSET = HttpHeaders.Values.CHARSET; - /** - * {@code "client_port"} - */ - public static final String CLIENT_PORT = "client_port"; - /** - * {@code "clock"} - */ - public static final String CLOCK = "clock"; - /** - * {@code "close"} - */ - public static final String CLOSE = HttpHeaders.Values.CLOSE; - /** - * {@code "compress"} - */ - public static final String COMPRESS = HttpHeaders.Values.COMPRESS; - /** - * {@code "100-continue"} - */ - public static final String CONTINUE = HttpHeaders.Values.CONTINUE; - /** - * {@code "deflate"} - */ - public static final String DEFLATE = HttpHeaders.Values.DEFLATE; - /** - * {@code "destination"} - */ - public static final String DESTINATION = "destination"; - /** - * {@code "gzip"} - */ - public static final String GZIP = HttpHeaders.Values.GZIP; - /** - * {@code "identity"} - */ - public static final String IDENTITY = HttpHeaders.Values.IDENTITY; - /** - * {@code "interleaved"} - */ - public static final String INTERLEAVED = "interleaved"; - /** - * {@code "keep-alive"} - */ - public static final String KEEP_ALIVE = HttpHeaders.Values.KEEP_ALIVE; - /** - * {@code "layers"} - */ - public static final String LAYERS = "layers"; - /** - * {@code "max-age"} - */ - public static final String MAX_AGE = HttpHeaders.Values.MAX_AGE; - /** - * {@code "max-stale"} - */ - public static final String MAX_STALE = HttpHeaders.Values.MAX_STALE; - /** - * {@code "min-fresh"} - */ - public static final String MIN_FRESH = HttpHeaders.Values.MIN_FRESH; - /** - * {@code "mode"} - */ - public static final String MODE = "mode"; - /** - * {@code "multicast"} - */ - public static final String MULTICAST = "multicast"; - /** - * {@code "must-revalidate"} - */ - public static final String MUST_REVALIDATE = HttpHeaders.Values.MUST_REVALIDATE; - /** - * {@code "none"} - */ - public static final String NONE = HttpHeaders.Values.NONE; - /** - * {@code "no-cache"} - */ - public static final String NO_CACHE = HttpHeaders.Values.NO_CACHE; - /** - * {@code "no-transform"} - */ - public static final String NO_TRANSFORM = HttpHeaders.Values.NO_TRANSFORM; - /** - * {@code "only-if-cached"} - */ - public static final String ONLY_IF_CACHED = HttpHeaders.Values.ONLY_IF_CACHED; - /** - * {@code "port"} - */ - public static final String PORT = "port"; - /** - * {@code "private"} - */ - public static final String PRIVATE = HttpHeaders.Values.PRIVATE; - /** - * {@code "proxy-revalidate"} - */ - public static final String PROXY_REVALIDATE = HttpHeaders.Values.PROXY_REVALIDATE; - /** - * {@code "public"} - */ - public static final String PUBLIC = HttpHeaders.Values.PUBLIC; - /** - * {@code "RTP"} - */ - public static final String RTP = "RTP"; - /** - * {@code "rtptime"} - */ - public static final String RTPTIME = "rtptime"; - /** - * {@code "seq"} - */ - public static final String SEQ = "seq"; - /** - * {@code "server_port"} - */ - public static final String SERVER_PORT = "server_port"; - /** - * {@code "ssrc"} - */ - public static final String SSRC = "ssrc"; - /** - * {@code "TCP"} - */ - public static final String TCP = "TCP"; - /** - * {@code "time"} - */ - public static final String TIME = "time"; - /** - * {@code "timeout"} - */ - public static final String TIMEOUT = "timeout"; - /** - * {@code "ttl"} - */ - public static final String TTL = "ttl"; - /** - * {@code "UDP"} - */ - public static final String UDP = "UDP"; - /** - * {@code "unicast"} - */ - public static final String UNICAST = "unicast"; - /** - * {@code "url"} - */ - public static final String URL = "url"; - - private Values() { } - } - - private RtspHeaders() { } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspMethods.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspMethods.java deleted file mode 100755 index c966d24d94..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspMethods.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.rtsp; - -import java.util.HashMap; -import java.util.Map; - -import com.ai.cloud.io.netty.handler.codec.http.HttpMethod; - -/** - * The request getMethod of RTSP. - */ -public final class RtspMethods { - - /** - * The OPTIONS getMethod represents a request for information about the communication options - * available on the request/response chain identified by the Request-URI. This getMethod allows - * the client to determine the options and/or requirements associated with a resource, or the - * capabilities of a server, without implying a resource action or initiating a resource - * retrieval. - */ - public static final HttpMethod OPTIONS = HttpMethod.OPTIONS; - - /** - * The DESCRIBE getMethod retrieves the description of a presentation or - * media object identified by the request URL from a server. - */ - public static final HttpMethod DESCRIBE = new HttpMethod("DESCRIBE"); - - /** - * The ANNOUNCE posts the description of a presentation or media object - * identified by the request URL to a server, or updates the client-side - * session description in real-time. - */ - public static final HttpMethod ANNOUNCE = new HttpMethod("ANNOUNCE"); - - /** - * The SETUP request for a URI specifies the transport mechanism to be - * used for the streamed media. - */ - public static final HttpMethod SETUP = new HttpMethod("SETUP"); - - /** - * The PLAY getMethod tells the server to start sending data via the - * mechanism specified in SETUP. - */ - public static final HttpMethod PLAY = new HttpMethod("PLAY"); - - /** - * The PAUSE request causes the stream delivery to be interrupted - * (halted) temporarily. - */ - public static final HttpMethod PAUSE = new HttpMethod("PAUSE"); - - /** - * The TEARDOWN request stops the stream delivery for the given URI, - * freeing the resources associated with it. - */ - public static final HttpMethod TEARDOWN = new HttpMethod("TEARDOWN"); - - /** - * The GET_PARAMETER request retrieves the value of a parameter of a - * presentation or stream specified in the URI. - */ - public static final HttpMethod GET_PARAMETER = new HttpMethod("GET_PARAMETER"); - - /** - * The SET_PARAMETER requests to set the value of a parameter for a - * presentation or stream specified by the URI. - */ - public static final HttpMethod SET_PARAMETER = new HttpMethod("SET_PARAMETER"); - - /** - * The REDIRECT request informs the client that it must connect to another - * server location. - */ - public static final HttpMethod REDIRECT = new HttpMethod("REDIRECT"); - - /** - * The RECORD getMethod initiates recording a range of media data according to - * the presentation description. - */ - public static final HttpMethod RECORD = new HttpMethod("RECORD"); - - private static final Map methodMap = new HashMap(); - - static { - methodMap.put(DESCRIBE.toString(), DESCRIBE); - methodMap.put(ANNOUNCE.toString(), ANNOUNCE); - methodMap.put(GET_PARAMETER.toString(), GET_PARAMETER); - methodMap.put(OPTIONS.toString(), OPTIONS); - methodMap.put(PAUSE.toString(), PAUSE); - methodMap.put(PLAY.toString(), PLAY); - methodMap.put(RECORD.toString(), RECORD); - methodMap.put(REDIRECT.toString(), REDIRECT); - methodMap.put(SETUP.toString(), SETUP); - methodMap.put(SET_PARAMETER.toString(), SET_PARAMETER); - methodMap.put(TEARDOWN.toString(), TEARDOWN); - } - - /** - * Returns the {@link HttpMethod} represented by the specified name. - * If the specified name is a standard RTSP getMethod name, a cached instance - * will be returned. Otherwise, a new instance will be returned. - */ - public static HttpMethod valueOf(String name) { - if (name == null) { - throw new NullPointerException("name"); - } - - name = name.trim().toUpperCase(); - if (name.isEmpty()) { - throw new IllegalArgumentException("empty name"); - } - - HttpMethod result = methodMap.get(name); - if (result != null) { - return result; - } else { - return new HttpMethod(name); - } - } - - private RtspMethods() { - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspObjectDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspObjectDecoder.java deleted file mode 100755 index 6763d12ac6..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspObjectDecoder.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.rtsp; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.handler.codec.TooLongFrameException; -import com.ai.cloud.io.netty.handler.codec.http.HttpMessage; -import com.ai.cloud.io.netty.handler.codec.http.HttpObjectDecoder; - -/** - * Decodes {@link ByteBuf}s into RTSP messages represented in - * {@link HttpMessage}s. - *

- *

Parameters that prevents excessive memory consumption

- * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
NameMeaning
{@code maxInitialLineLength}The maximum length of the initial line - * (e.g. {@code "SETUP / RTSP/1.0"} or {@code "RTSP/1.0 200 OK"}) - * If the length of the initial line exceeds this value, a - * {@link TooLongFrameException} will be raised.
{@code maxHeaderSize}The maximum length of all headers. If the sum of the length of each - * header exceeds this value, a {@link TooLongFrameException} will be raised.
{@code maxContentLength}The maximum length of the content. If the content length exceeds this - * value, a {@link TooLongFrameException} will be raised.
- * - * @deprecated Use {@link RtspDecoder} instead. - */ -@Deprecated -public abstract class RtspObjectDecoder extends HttpObjectDecoder { - - /** - * Creates a new instance with the default - * {@code maxInitialLineLength (4096)}, {@code maxHeaderSize (8192)}, and - * {@code maxContentLength (8192)}. - */ - protected RtspObjectDecoder() { - this(4096, 8192, 8192); - } - - /** - * Creates a new instance with the specified parameters. - */ - protected RtspObjectDecoder(int maxInitialLineLength, int maxHeaderSize, int maxContentLength) { - super(maxInitialLineLength, maxHeaderSize, maxContentLength * 2, false); - } - - protected RtspObjectDecoder( - int maxInitialLineLength, int maxHeaderSize, int maxContentLength, boolean validateHeaders) { - super(maxInitialLineLength, maxHeaderSize, maxContentLength * 2, false, validateHeaders); - } - - @Override - protected boolean isContentAlwaysEmpty(HttpMessage msg) { - // Unlike HTTP, RTSP always assumes zero-length body if Content-Length - // header is absent. - boolean empty = super.isContentAlwaysEmpty(msg); - if (empty) { - return true; - } - if (!msg.headers().contains(RtspHeaders.Names.CONTENT_LENGTH)) { - return true; - } - return empty; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspObjectEncoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspObjectEncoder.java deleted file mode 100755 index fc74349f7b..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspObjectEncoder.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.rtsp; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelHandler.Sharable; -import com.ai.cloud.io.netty.handler.codec.http.FullHttpMessage; -import com.ai.cloud.io.netty.handler.codec.http.HttpMessage; -import com.ai.cloud.io.netty.handler.codec.http.HttpObjectEncoder; - -/** - * Encodes an RTSP message represented in {@link FullHttpMessage} into - * a {@link ByteBuf}. - * - * @deprecated Use {@link RtspEncoder} instead. - */ -@Sharable -@Deprecated -public abstract class RtspObjectEncoder extends HttpObjectEncoder { - - /** - * Creates a new instance. - */ - protected RtspObjectEncoder() { - } - - @Override - public boolean acceptOutboundMessage(Object msg) throws Exception { - return msg instanceof FullHttpMessage; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspRequestDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspRequestDecoder.java deleted file mode 100755 index cf67191ed5..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspRequestDecoder.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.rtsp; - -/** - * @deprecated Use {@link RtspDecoder} directly instead - */ -@Deprecated -public class RtspRequestDecoder extends RtspDecoder { -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspRequestEncoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspRequestEncoder.java deleted file mode 100755 index 52391a3213..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspRequestEncoder.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.rtsp; - -/** - * @deprecated Use {@link RtspEncoder} directly instead - */ -@Deprecated -public class RtspRequestEncoder extends RtspEncoder { -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspResponseDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspResponseDecoder.java deleted file mode 100755 index 6bd732d0d6..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspResponseDecoder.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.rtsp; - -/** - * @deprecated Use {@link RtspDecoder} directly instead - */ -@Deprecated -public class RtspResponseDecoder extends RtspDecoder { -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspResponseEncoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspResponseEncoder.java deleted file mode 100755 index 77bc3a6a42..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspResponseEncoder.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.rtsp; - -/** - * @deprecated Use {@link RtspEncoder} directly instead - */ -@Deprecated -public class RtspResponseEncoder extends RtspEncoder { -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspResponseStatuses.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspResponseStatuses.java deleted file mode 100755 index 8e8f26999b..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspResponseStatuses.java +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.rtsp; - -import com.ai.cloud.io.netty.handler.codec.http.HttpResponseStatus; - -/** - * The getStatus code and its description of a RTSP response. - */ -public final class RtspResponseStatuses { - - /** - * 100 Continue - */ - public static final HttpResponseStatus CONTINUE = HttpResponseStatus.CONTINUE; - - /** - * 200 OK - */ - public static final HttpResponseStatus OK = HttpResponseStatus.OK; - - /** - * 201 Created - */ - public static final HttpResponseStatus CREATED = HttpResponseStatus.CREATED; - - /** - * 250 Low on Storage Space - */ - public static final HttpResponseStatus LOW_STORAGE_SPACE = new HttpResponseStatus( - 250, "Low on Storage Space"); - - /** - * 300 Multiple Choices - */ - public static final HttpResponseStatus MULTIPLE_CHOICES = HttpResponseStatus.MULTIPLE_CHOICES; - - /** - * 301 Moved Permanently - */ - public static final HttpResponseStatus MOVED_PERMANENTLY = HttpResponseStatus.MOVED_PERMANENTLY; - - /** - * 302 Moved Temporarily - */ - public static final HttpResponseStatus MOVED_TEMPORARILY = new HttpResponseStatus( - 302, "Moved Temporarily"); - /** - * 304 Not Modified - */ - public static final HttpResponseStatus NOT_MODIFIED = HttpResponseStatus.NOT_MODIFIED; - - /** - * 305 Use Proxy - */ - public static final HttpResponseStatus USE_PROXY = HttpResponseStatus.USE_PROXY; - - /** - * 400 Bad Request - */ - public static final HttpResponseStatus BAD_REQUEST = HttpResponseStatus.BAD_REQUEST; - - /** - * 401 Unauthorized - */ - public static final HttpResponseStatus UNAUTHORIZED = HttpResponseStatus.UNAUTHORIZED; - - /** - * 402 Payment Required - */ - public static final HttpResponseStatus PAYMENT_REQUIRED = HttpResponseStatus.PAYMENT_REQUIRED; - - /** - * 403 Forbidden - */ - public static final HttpResponseStatus FORBIDDEN = HttpResponseStatus.FORBIDDEN; - - /** - * 404 Not Found - */ - public static final HttpResponseStatus NOT_FOUND = HttpResponseStatus.NOT_FOUND; - - /** - * 405 Method Not Allowed - */ - public static final HttpResponseStatus METHOD_NOT_ALLOWED = HttpResponseStatus.METHOD_NOT_ALLOWED; - - /** - * 406 Not Acceptable - */ - public static final HttpResponseStatus NOT_ACCEPTABLE = HttpResponseStatus.NOT_ACCEPTABLE; - - /** - * 407 Proxy Authentication Required - */ - public static final HttpResponseStatus PROXY_AUTHENTICATION_REQUIRED = - HttpResponseStatus.PROXY_AUTHENTICATION_REQUIRED; - - /** - * 408 Request Timeout - */ - public static final HttpResponseStatus REQUEST_TIMEOUT = HttpResponseStatus.REQUEST_TIMEOUT; - - /** - * 410 Gone - */ - public static final HttpResponseStatus GONE = HttpResponseStatus.GONE; - - /** - * 411 Length Required - */ - public static final HttpResponseStatus LENGTH_REQUIRED = HttpResponseStatus.LENGTH_REQUIRED; - - /** - * 412 Precondition Failed - */ - public static final HttpResponseStatus PRECONDITION_FAILED = HttpResponseStatus.PRECONDITION_FAILED; - - /** - * 413 Request Entity Too Large - */ - public static final HttpResponseStatus REQUEST_ENTITY_TOO_LARGE = HttpResponseStatus.REQUEST_ENTITY_TOO_LARGE; - - /** - * 414 Request-URI Too Long - */ - public static final HttpResponseStatus REQUEST_URI_TOO_LONG = HttpResponseStatus.REQUEST_URI_TOO_LONG; - - /** - * 415 Unsupported Media Type - */ - public static final HttpResponseStatus UNSUPPORTED_MEDIA_TYPE = HttpResponseStatus.UNSUPPORTED_MEDIA_TYPE; - - /** - * 451 Parameter Not Understood - */ - public static final HttpResponseStatus PARAMETER_NOT_UNDERSTOOD = new HttpResponseStatus( - 451, "Parameter Not Understood"); - - /** - * 452 Conference Not Found - */ - public static final HttpResponseStatus CONFERENCE_NOT_FOUND = new HttpResponseStatus( - 452, "Conference Not Found"); - - /** - * 453 Not Enough Bandwidth - */ - public static final HttpResponseStatus NOT_ENOUGH_BANDWIDTH = new HttpResponseStatus( - 453, "Not Enough Bandwidth"); - - /** - * 454 Session Not Found - */ - public static final HttpResponseStatus SESSION_NOT_FOUND = new HttpResponseStatus( - 454, "Session Not Found"); - - /** - * 455 Method Not Valid in This State - */ - public static final HttpResponseStatus METHOD_NOT_VALID = new HttpResponseStatus( - 455, "Method Not Valid in This State"); - - /** - * 456 Header Field Not Valid for Resource - */ - public static final HttpResponseStatus HEADER_FIELD_NOT_VALID = new HttpResponseStatus( - 456, "Header Field Not Valid for Resource"); - - /** - * 457 Invalid Range - */ - public static final HttpResponseStatus INVALID_RANGE = new HttpResponseStatus( - 457, "Invalid Range"); - - /** - * 458 Parameter Is Read-Only - */ - public static final HttpResponseStatus PARAMETER_IS_READONLY = new HttpResponseStatus( - 458, "Parameter Is Read-Only"); - - /** - * 459 Aggregate operation not allowed - */ - public static final HttpResponseStatus AGGREGATE_OPERATION_NOT_ALLOWED = new HttpResponseStatus( - 459, "Aggregate operation not allowed"); - - /** - * 460 Only Aggregate operation allowed - */ - public static final HttpResponseStatus ONLY_AGGREGATE_OPERATION_ALLOWED = new HttpResponseStatus( - 460, "Only Aggregate operation allowed"); - - /** - * 461 Unsupported transport - */ - public static final HttpResponseStatus UNSUPPORTED_TRANSPORT = new HttpResponseStatus( - 461, "Unsupported transport"); - - /** - * 462 Destination unreachable - */ - public static final HttpResponseStatus DESTINATION_UNREACHABLE = new HttpResponseStatus( - 462, "Destination unreachable"); - - /** - * 463 Key management failure - */ - public static final HttpResponseStatus KEY_MANAGEMENT_FAILURE = new HttpResponseStatus( - 463, "Key management failure"); - - /** - * 500 Internal Server Error - */ - public static final HttpResponseStatus INTERNAL_SERVER_ERROR = HttpResponseStatus.INTERNAL_SERVER_ERROR; - - /** - * 501 Not Implemented - */ - public static final HttpResponseStatus NOT_IMPLEMENTED = HttpResponseStatus.NOT_IMPLEMENTED; - - /** - * 502 Bad Gateway - */ - public static final HttpResponseStatus BAD_GATEWAY = HttpResponseStatus.BAD_GATEWAY; - - /** - * 503 Service Unavailable - */ - public static final HttpResponseStatus SERVICE_UNAVAILABLE = HttpResponseStatus.SERVICE_UNAVAILABLE; - - /** - * 504 Gateway Timeout - */ - public static final HttpResponseStatus GATEWAY_TIMEOUT = HttpResponseStatus.GATEWAY_TIMEOUT; - - /** - * 505 RTSP Version not supported - */ - public static final HttpResponseStatus RTSP_VERSION_NOT_SUPPORTED = new HttpResponseStatus( - 505, "RTSP Version not supported"); - - /** - * 551 Option not supported - */ - public static final HttpResponseStatus OPTION_NOT_SUPPORTED = new HttpResponseStatus( - 551, "Option not supported"); - - /** - * Returns the {@link HttpResponseStatus} represented by the specified code. - * If the specified code is a standard RTSP getStatus code, a cached instance - * will be returned. Otherwise, a new instance will be returned. - */ - public static HttpResponseStatus valueOf(int code) { - switch (code) { - case 250: return LOW_STORAGE_SPACE; - case 302: return MOVED_TEMPORARILY; - case 451: return PARAMETER_NOT_UNDERSTOOD; - case 452: return CONFERENCE_NOT_FOUND; - case 453: return NOT_ENOUGH_BANDWIDTH; - case 454: return SESSION_NOT_FOUND; - case 455: return METHOD_NOT_VALID; - case 456: return HEADER_FIELD_NOT_VALID; - case 457: return INVALID_RANGE; - case 458: return PARAMETER_IS_READONLY; - case 459: return AGGREGATE_OPERATION_NOT_ALLOWED; - case 460: return ONLY_AGGREGATE_OPERATION_ALLOWED; - case 461: return UNSUPPORTED_TRANSPORT; - case 462: return DESTINATION_UNREACHABLE; - case 463: return KEY_MANAGEMENT_FAILURE; - case 505: return RTSP_VERSION_NOT_SUPPORTED; - case 551: return OPTION_NOT_SUPPORTED; - default: return HttpResponseStatus.valueOf(code); - } - } - - private RtspResponseStatuses() { - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspVersions.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspVersions.java deleted file mode 100755 index d47878f619..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/RtspVersions.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.rtsp; - -import com.ai.cloud.io.netty.handler.codec.http.HttpVersion; - -/** - * The version of RTSP. - */ -public final class RtspVersions { - - /** - * RTSP/1.0 - */ - public static final HttpVersion RTSP_1_0 = new HttpVersion("RTSP", 1, 0, true); - - /** - * Returns an existing or new {@link HttpVersion} instance which matches to - * the specified RTSP version string. If the specified {@code text} is - * equal to {@code "RTSP/1.0"}, {@link #RTSP_1_0} will be returned. - * Otherwise, a new {@link HttpVersion} instance will be returned. - */ - public static HttpVersion valueOf(String text) { - if (text == null) { - throw new NullPointerException("text"); - } - - text = text.trim().toUpperCase(); - if ("RTSP/1.0".equals(text)) { - return RTSP_1_0; - } - - return new HttpVersion(text, true); - } - - private RtspVersions() { - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/package-info.java deleted file mode 100755 index 0a50b3f8c5..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/rtsp/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * An RTSP - * extension based on the HTTP codec. - */ -package com.ai.cloud.io.netty.handler.codec.rtsp; diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/CachingClassResolver.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/CachingClassResolver.java deleted file mode 100755 index 7c14f928c3..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/CachingClassResolver.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.serialization; - -import java.util.Map; - -class CachingClassResolver implements ClassResolver { - - private final Map> classCache; - private final ClassResolver delegate; - - CachingClassResolver(ClassResolver delegate, Map> classCache) { - this.delegate = delegate; - this.classCache = classCache; - } - - @Override - public Class resolve(String className) throws ClassNotFoundException { - // Query the cache first. - Class clazz; - clazz = classCache.get(className); - if (clazz != null) { - return clazz; - } - - // And then try to load. - clazz = delegate.resolve(className); - - classCache.put(className, clazz); - return clazz; - } - -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/ClassLoaderClassResolver.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/ClassLoaderClassResolver.java deleted file mode 100755 index 812598edbd..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/ClassLoaderClassResolver.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.serialization; - -class ClassLoaderClassResolver implements ClassResolver { - - private final ClassLoader classLoader; - - ClassLoaderClassResolver(ClassLoader classLoader) { - this.classLoader = classLoader; - } - - @Override - public Class resolve(String className) throws ClassNotFoundException { - try { - return classLoader.loadClass(className); - } catch (ClassNotFoundException ignored) { - return Class.forName(className, false, classLoader); - } - } - -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/ClassResolver.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/ClassResolver.java deleted file mode 100755 index 94ae7fcba0..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/ClassResolver.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.serialization; - -/** - * please use {@link ClassResolvers} as instance factory - */ -public interface ClassResolver { - - Class resolve(String className) throws ClassNotFoundException; - -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/ClassResolvers.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/ClassResolvers.java deleted file mode 100755 index c26bf3c7af..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/ClassResolvers.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.serialization; - -import java.lang.ref.Reference; -import java.util.HashMap; - -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - -public final class ClassResolvers { - - /** - * cache disabled - * @param classLoader - specific classLoader to use, or null if you want to revert to default - * @return new instance of class resolver - */ - public static ClassResolver cacheDisabled(ClassLoader classLoader) { - return new ClassLoaderClassResolver(defaultClassLoader(classLoader)); - } - - /** - * non-agressive non-concurrent cache - * good for non-shared default cache - * - * @param classLoader - specific classLoader to use, or null if you want to revert to default - * @return new instance of class resolver - */ - public static ClassResolver weakCachingResolver(ClassLoader classLoader) { - return new CachingClassResolver( - new ClassLoaderClassResolver(defaultClassLoader(classLoader)), - new WeakReferenceMap>(new HashMap>>())); - } - - /** - * agressive non-concurrent cache - * good for non-shared cache, when we're not worried about class unloading - * - * @param classLoader - specific classLoader to use, or null if you want to revert to default - * @return new instance of class resolver - */ - public static ClassResolver softCachingResolver(ClassLoader classLoader) { - return new CachingClassResolver( - new ClassLoaderClassResolver(defaultClassLoader(classLoader)), - new SoftReferenceMap>(new HashMap>>())); - } - - /** - * non-agressive concurrent cache - * good for shared cache, when we're worried about class unloading - * - * @param classLoader - specific classLoader to use, or null if you want to revert to default - * @return new instance of class resolver - */ - public static ClassResolver weakCachingConcurrentResolver(ClassLoader classLoader) { - return new CachingClassResolver( - new ClassLoaderClassResolver(defaultClassLoader(classLoader)), - new WeakReferenceMap>( - PlatformDependent.>>newConcurrentHashMap())); - } - - /** - * agressive concurrent cache - * good for shared cache, when we're not worried about class unloading - * - * @param classLoader - specific classLoader to use, or null if you want to revert to default - * @return new instance of class resolver - */ - public static ClassResolver softCachingConcurrentResolver(ClassLoader classLoader) { - return new CachingClassResolver( - new ClassLoaderClassResolver(defaultClassLoader(classLoader)), - new SoftReferenceMap>( - PlatformDependent.>>newConcurrentHashMap())); - } - - static ClassLoader defaultClassLoader(ClassLoader classLoader) { - if (classLoader != null) { - return classLoader; - } - - final ClassLoader contextClassLoader = PlatformDependent.getContextClassLoader(); - if (contextClassLoader != null) { - return contextClassLoader; - } - - return PlatformDependent.getClassLoader(ClassResolvers.class); - } - - private ClassResolvers() { - // Unused - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/CompactObjectInputStream.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/CompactObjectInputStream.java deleted file mode 100755 index 3f7f55ebd8..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/CompactObjectInputStream.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.serialization; - -import java.io.EOFException; -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInputStream; -import java.io.ObjectStreamClass; -import java.io.StreamCorruptedException; - -class CompactObjectInputStream extends ObjectInputStream { - - private final ClassResolver classResolver; - - CompactObjectInputStream(InputStream in, ClassResolver classResolver) throws IOException { - super(in); - this.classResolver = classResolver; - } - - @Override - protected void readStreamHeader() throws IOException { - int version = readByte() & 0xFF; - if (version != STREAM_VERSION) { - throw new StreamCorruptedException( - "Unsupported version: " + version); - } - } - - @Override - protected ObjectStreamClass readClassDescriptor() - throws IOException, ClassNotFoundException { - int type = read(); - if (type < 0) { - throw new EOFException(); - } - switch (type) { - case CompactObjectOutputStream.TYPE_FAT_DESCRIPTOR: - return super.readClassDescriptor(); - case CompactObjectOutputStream.TYPE_THIN_DESCRIPTOR: - String className = readUTF(); - Class clazz = classResolver.resolve(className); - return ObjectStreamClass.lookupAny(clazz); - default: - throw new StreamCorruptedException( - "Unexpected class descriptor type: " + type); - } - } - - @Override - protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { - Class clazz; - try { - clazz = classResolver.resolve(desc.getName()); - } catch (ClassNotFoundException ignored) { - clazz = super.resolveClass(desc); - } - - return clazz; - } - -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/CompactObjectOutputStream.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/CompactObjectOutputStream.java deleted file mode 100755 index f123e250b5..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/CompactObjectOutputStream.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.serialization; - -import java.io.IOException; -import java.io.ObjectOutputStream; -import java.io.ObjectStreamClass; -import java.io.OutputStream; - -class CompactObjectOutputStream extends ObjectOutputStream { - - static final int TYPE_FAT_DESCRIPTOR = 0; - static final int TYPE_THIN_DESCRIPTOR = 1; - - CompactObjectOutputStream(OutputStream out) throws IOException { - super(out); - } - - @Override - protected void writeStreamHeader() throws IOException { - writeByte(STREAM_VERSION); - } - - @Override - protected void writeClassDescriptor(ObjectStreamClass desc) throws IOException { - Class clazz = desc.forClass(); - if (clazz.isPrimitive() || clazz.isArray() || clazz.isInterface() || - desc.getSerialVersionUID() == 0) { - write(TYPE_FAT_DESCRIPTOR); - super.writeClassDescriptor(desc); - } else { - write(TYPE_THIN_DESCRIPTOR); - writeUTF(desc.getName()); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/CompatibleObjectEncoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/CompatibleObjectEncoder.java deleted file mode 100755 index cef6593832..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/CompatibleObjectEncoder.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.serialization; - -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.OutputStream; -import java.io.Serializable; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.ByteBufOutputStream; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.handler.codec.MessageToByteEncoder; -import com.ai.cloud.io.netty.util.Attribute; -import com.ai.cloud.io.netty.util.AttributeKey; - -/** - * An encoder which serializes a Java object into a {@link ByteBuf} - * (interoperability version). - *

- * This encoder is interoperable with the standard Java object streams such as - * {@link ObjectInputStream} and {@link ObjectOutputStream}. - */ -public class CompatibleObjectEncoder extends MessageToByteEncoder { - - private static final AttributeKey OOS = - AttributeKey.valueOf(CompatibleObjectEncoder.class.getName() + ".OOS"); - - private final int resetInterval; - private int writtenObjects; - - /** - * Creates a new instance with the reset interval of {@code 16}. - */ - public CompatibleObjectEncoder() { - this(16); // Reset at every sixteen writes - } - - /** - * Creates a new instance. - * - * @param resetInterval - * the number of objects between {@link ObjectOutputStream#reset()}. - * {@code 0} will disable resetting the stream, but the remote - * peer will be at the risk of getting {@link OutOfMemoryError} in - * the long term. - */ - public CompatibleObjectEncoder(int resetInterval) { - if (resetInterval < 0) { - throw new IllegalArgumentException( - "resetInterval: " + resetInterval); - } - this.resetInterval = resetInterval; - } - - /** - * Creates a new {@link ObjectOutputStream} which wraps the specified - * {@link OutputStream}. Override this method to use a subclass of the - * {@link ObjectOutputStream}. - */ - protected ObjectOutputStream newObjectOutputStream(OutputStream out) throws Exception { - return new ObjectOutputStream(out); - } - - @Override - protected void encode(ChannelHandlerContext ctx, Serializable msg, ByteBuf out) throws Exception { - Attribute oosAttr = ctx.attr(OOS); - ObjectOutputStream oos = oosAttr.get(); - if (oos == null) { - oos = newObjectOutputStream(new ByteBufOutputStream(out)); - ObjectOutputStream newOos = oosAttr.setIfAbsent(oos); - if (newOos != null) { - oos = newOos; - } - } - - synchronized (oos) { - if (resetInterval != 0) { - // Resetting will prevent OOM on the receiving side. - writtenObjects ++; - if (writtenObjects % resetInterval == 0) { - oos.reset(); - } - } - - oos.writeObject(msg); - oos.flush(); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/ObjectDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/ObjectDecoder.java deleted file mode 100755 index 3fa79bd4fb..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/ObjectDecoder.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.serialization; - -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.StreamCorruptedException; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.ByteBufInputStream; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.handler.codec.LengthFieldBasedFrameDecoder; - -/** - * A decoder which deserializes the received {@link ByteBuf}s into Java - * objects. - *

- * Please note that the serialized form this decoder expects is not - * compatible with the standard {@link ObjectOutputStream}. Please use - * {@link ObjectEncoder} or {@link ObjectEncoderOutputStream} to ensure the - * interoperability with this decoder. - */ -public class ObjectDecoder extends LengthFieldBasedFrameDecoder { - - private final ClassResolver classResolver; - - /** - * Creates a new decoder whose maximum object size is {@code 1048576} - * bytes. If the size of the received object is greater than - * {@code 1048576} bytes, a {@link StreamCorruptedException} will be - * raised. - * - * @param classResolver the {@link ClassResolver} to use for this decoder - */ - public ObjectDecoder(ClassResolver classResolver) { - this(1048576, classResolver); - } - - /** - * Creates a new decoder with the specified maximum object size. - * - * @param maxObjectSize the maximum byte length of the serialized object. - * if the length of the received object is greater - * than this value, {@link StreamCorruptedException} - * will be raised. - * @param classResolver the {@link ClassResolver} which will load the class - * of the serialized object - */ - public ObjectDecoder(int maxObjectSize, ClassResolver classResolver) { - super(maxObjectSize, 0, 4, 0, 4); - this.classResolver = classResolver; - } - - @Override - protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception { - ByteBuf frame = (ByteBuf) super.decode(ctx, in); - if (frame == null) { - return null; - } - - ObjectInputStream is = new CompactObjectInputStream(new ByteBufInputStream(frame), classResolver); - Object result = is.readObject(); - is.close(); - return result; - } - - @Override - protected ByteBuf extractFrame(ChannelHandlerContext ctx, ByteBuf buffer, int index, int length) { - return buffer.slice(index, length); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/ObjectDecoderInputStream.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/ObjectDecoderInputStream.java deleted file mode 100755 index bfebfc0d58..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/ObjectDecoderInputStream.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.serialization; - -import java.io.BufferedReader; -import java.io.DataInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInput; -import java.io.StreamCorruptedException; - -/** - * An {@link ObjectInput} which is interoperable with {@link ObjectEncoder} - * and {@link ObjectEncoderOutputStream}. - */ -public class ObjectDecoderInputStream extends InputStream implements - ObjectInput { - - private final DataInputStream in; - private final int maxObjectSize; - private final ClassResolver classResolver; - - /** - * Creates a new {@link ObjectInput}. - * - * @param in - * the {@link InputStream} where the serialized form will be - * read from - */ - public ObjectDecoderInputStream(InputStream in) { - this(in, null); - } - - /** - * Creates a new {@link ObjectInput}. - * - * @param in - * the {@link InputStream} where the serialized form will be - * read from - * @param classLoader - * the {@link ClassLoader} which will load the class of the - * serialized object - */ - public ObjectDecoderInputStream(InputStream in, ClassLoader classLoader) { - this(in, classLoader, 1048576); - } - - /** - * Creates a new {@link ObjectInput}. - * - * @param in - * the {@link InputStream} where the serialized form will be - * read from - * @param maxObjectSize - * the maximum byte length of the serialized object. if the length - * of the received object is greater than this value, - * a {@link StreamCorruptedException} will be raised. - */ - public ObjectDecoderInputStream(InputStream in, int maxObjectSize) { - this(in, null, maxObjectSize); - } - - /** - * Creates a new {@link ObjectInput}. - * - * @param in - * the {@link InputStream} where the serialized form will be - * read from - * @param classLoader - * the {@link ClassLoader} which will load the class of the - * serialized object - * @param maxObjectSize - * the maximum byte length of the serialized object. if the length - * of the received object is greater than this value, - * a {@link StreamCorruptedException} will be raised. - */ - public ObjectDecoderInputStream(InputStream in, ClassLoader classLoader, int maxObjectSize) { - if (in == null) { - throw new NullPointerException("in"); - } - if (maxObjectSize <= 0) { - throw new IllegalArgumentException("maxObjectSize: " + maxObjectSize); - } - if (in instanceof DataInputStream) { - this.in = (DataInputStream) in; - } else { - this.in = new DataInputStream(in); - } - classResolver = ClassResolvers.weakCachingResolver(classLoader); - this.maxObjectSize = maxObjectSize; - } - - @Override - public Object readObject() throws ClassNotFoundException, IOException { - int dataLen = readInt(); - if (dataLen <= 0) { - throw new StreamCorruptedException("invalid data length: " + dataLen); - } - if (dataLen > maxObjectSize) { - throw new StreamCorruptedException( - "data length too big: " + dataLen + " (max: " + maxObjectSize + ')'); - } - - return new CompactObjectInputStream(in, classResolver).readObject(); - } - - @Override - public int available() throws IOException { - return in.available(); - } - - @Override - public void close() throws IOException { - in.close(); - } - - @Override - public void mark(int readlimit) { - in.mark(readlimit); - } - - @Override - public boolean markSupported() { - return in.markSupported(); - } - - @Override - public int read() throws IOException { - return in.read(); - } - - @Override - public final int read(byte[] b, int off, int len) throws IOException { - return in.read(b, off, len); - } - - @Override - public final int read(byte[] b) throws IOException { - return in.read(b); - } - - @Override - public final boolean readBoolean() throws IOException { - return in.readBoolean(); - } - - @Override - public final byte readByte() throws IOException { - return in.readByte(); - } - - @Override - public final char readChar() throws IOException { - return in.readChar(); - } - - @Override - public final double readDouble() throws IOException { - return in.readDouble(); - } - - @Override - public final float readFloat() throws IOException { - return in.readFloat(); - } - - @Override - public final void readFully(byte[] b, int off, int len) throws IOException { - in.readFully(b, off, len); - } - - @Override - public final void readFully(byte[] b) throws IOException { - in.readFully(b); - } - - @Override - public final int readInt() throws IOException { - return in.readInt(); - } - - /** - * @deprecated Use {@link BufferedReader#readLine()} instead. - */ - @Override - @Deprecated - public final String readLine() throws IOException { - return in.readLine(); - } - - @Override - public final long readLong() throws IOException { - return in.readLong(); - } - - @Override - public final short readShort() throws IOException { - return in.readShort(); - } - - @Override - public final int readUnsignedByte() throws IOException { - return in.readUnsignedByte(); - } - - @Override - public final int readUnsignedShort() throws IOException { - return in.readUnsignedShort(); - } - - @Override - public final String readUTF() throws IOException { - return in.readUTF(); - } - - @Override - public void reset() throws IOException { - in.reset(); - } - - @Override - public long skip(long n) throws IOException { - return in.skip(n); - } - - @Override - public final int skipBytes(int n) throws IOException { - return in.skipBytes(n); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/ObjectEncoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/ObjectEncoder.java deleted file mode 100755 index 55c93eb197..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/ObjectEncoder.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.serialization; - -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.ByteBufOutputStream; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelHandler.Sharable; -import com.ai.cloud.io.netty.handler.codec.MessageToByteEncoder; - -/** - * An encoder which serializes a Java object into a {@link ByteBuf}. - *

- * Please note that the serialized form this encoder produces is not - * compatible with the standard {@link ObjectInputStream}. Please use - * {@link ObjectDecoder} or {@link ObjectDecoderInputStream} to ensure the - * interoperability with this encoder. - */ -@Sharable -public class ObjectEncoder extends MessageToByteEncoder { - private static final byte[] LENGTH_PLACEHOLDER = new byte[4]; - - @Override - protected void encode(ChannelHandlerContext ctx, Serializable msg, ByteBuf out) throws Exception { - int startIdx = out.writerIndex(); - - ByteBufOutputStream bout = new ByteBufOutputStream(out); - bout.write(LENGTH_PLACEHOLDER); - ObjectOutputStream oout = new CompactObjectOutputStream(bout); - oout.writeObject(msg); - oout.flush(); - oout.close(); - - int endIdx = out.writerIndex(); - - out.setInt(startIdx, endIdx - startIdx - 4); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/ObjectEncoderOutputStream.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/ObjectEncoderOutputStream.java deleted file mode 100755 index c680ce0e4d..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/ObjectEncoderOutputStream.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.serialization; - -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.ObjectOutput; -import java.io.ObjectOutputStream; -import java.io.OutputStream; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.ByteBufOutputStream; -import com.ai.cloud.io.netty.buffer.Unpooled; - -/** - * An {@link ObjectOutput} which is interoperable with {@link ObjectDecoder} - * and {@link ObjectDecoderInputStream}. - */ -public class ObjectEncoderOutputStream extends OutputStream implements - ObjectOutput { - - private final DataOutputStream out; - private final int estimatedLength; - - /** - * Creates a new {@link ObjectOutput} with the estimated length of 512 - * bytes. - * - * @param out - * the {@link OutputStream} where the serialized form will be - * written out - */ - public ObjectEncoderOutputStream(OutputStream out) { - this(out, 512); - } - - /** - * Creates a new {@link ObjectOutput}. - * - * @param out - * the {@link OutputStream} where the serialized form will be - * written out - * - * @param estimatedLength - * the estimated byte length of the serialized form of an object. - * If the length of the serialized form exceeds this value, the - * internal buffer will be expanded automatically at the cost of - * memory bandwidth. If this value is too big, it will also waste - * memory bandwidth. To avoid unnecessary memory copy or allocation - * cost, please specify the properly estimated value. - */ - public ObjectEncoderOutputStream(OutputStream out, int estimatedLength) { - if (out == null) { - throw new NullPointerException("out"); - } - if (estimatedLength < 0) { - throw new IllegalArgumentException("estimatedLength: " + estimatedLength); - } - - if (out instanceof DataOutputStream) { - this.out = (DataOutputStream) out; - } else { - this.out = new DataOutputStream(out); - } - this.estimatedLength = estimatedLength; - } - - @Override - public void writeObject(Object obj) throws IOException { - ByteBufOutputStream bout = new ByteBufOutputStream(Unpooled.buffer(estimatedLength)); - ObjectOutputStream oout = new CompactObjectOutputStream(bout); - oout.writeObject(obj); - oout.flush(); - oout.close(); - - ByteBuf buffer = bout.buffer(); - int objectSize = buffer.readableBytes(); - writeInt(objectSize); - buffer.getBytes(0, this, objectSize); - } - - @Override - public void write(int b) throws IOException { - out.write(b); - } - - @Override - public void close() throws IOException { - out.close(); - } - - @Override - public void flush() throws IOException { - out.flush(); - } - - public final int size() { - return out.size(); - } - - @Override - public void write(byte[] b, int off, int len) throws IOException { - out.write(b, off, len); - } - - @Override - public void write(byte[] b) throws IOException { - out.write(b); - } - - @Override - public final void writeBoolean(boolean v) throws IOException { - out.writeBoolean(v); - } - - @Override - public final void writeByte(int v) throws IOException { - out.writeByte(v); - } - - @Override - public final void writeBytes(String s) throws IOException { - out.writeBytes(s); - } - - @Override - public final void writeChar(int v) throws IOException { - out.writeChar(v); - } - - @Override - public final void writeChars(String s) throws IOException { - out.writeChars(s); - } - - @Override - public final void writeDouble(double v) throws IOException { - out.writeDouble(v); - } - - @Override - public final void writeFloat(float v) throws IOException { - out.writeFloat(v); - } - - @Override - public final void writeInt(int v) throws IOException { - out.writeInt(v); - } - - @Override - public final void writeLong(long v) throws IOException { - out.writeLong(v); - } - - @Override - public final void writeShort(int v) throws IOException { - out.writeShort(v); - } - - @Override - public final void writeUTF(String str) throws IOException { - out.writeUTF(str); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/ReferenceMap.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/ReferenceMap.java deleted file mode 100755 index d88491e065..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/ReferenceMap.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.serialization; - -import java.lang.ref.Reference; -import java.util.Collection; -import java.util.Map; -import java.util.Set; - -abstract class ReferenceMap implements Map { - - private final Map> delegate; - - protected ReferenceMap(Map> delegate) { - this.delegate = delegate; - } - - abstract Reference fold(V value); - - private V unfold(Reference ref) { - if (ref == null) { - return null; - } - - return ref.get(); - } - - @Override - public int size() { - return delegate.size(); - } - - @Override - public boolean isEmpty() { - return delegate.isEmpty(); - } - - @Override - public boolean containsKey(Object key) { - return delegate.containsKey(key); - } - - @Override - public boolean containsValue(Object value) { - throw new UnsupportedOperationException(); - } - - @Override - public V get(Object key) { - return unfold(delegate.get(key)); - } - - @Override - public V put(K key, V value) { - return unfold(delegate.put(key, fold(value))); - } - - @Override - public V remove(Object key) { - return unfold(delegate.remove(key)); - } - - @Override - public void putAll(Map m) { - for (Entry entry : m.entrySet()) { - delegate.put(entry.getKey(), fold(entry.getValue())); - } - } - - @Override - public void clear() { - delegate.clear(); - } - - @Override - public Set keySet() { - return delegate.keySet(); - } - - @Override - public Collection values() { - throw new UnsupportedOperationException(); - } - - @Override - public Set> entrySet() { - throw new UnsupportedOperationException(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/SoftReferenceMap.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/SoftReferenceMap.java deleted file mode 100755 index 77116a066d..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/SoftReferenceMap.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.serialization; - -import java.lang.ref.Reference; -import java.lang.ref.SoftReference; -import java.util.Map; - -final class SoftReferenceMap extends ReferenceMap { - - SoftReferenceMap(Map> delegate) { - super(delegate); - } - - @Override - Reference fold(V value) { - return new SoftReference(value); - } - -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/WeakReferenceMap.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/WeakReferenceMap.java deleted file mode 100755 index cf8c66df1f..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/WeakReferenceMap.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.serialization; - -import java.lang.ref.Reference; -import java.lang.ref.WeakReference; -import java.util.Map; - -final class WeakReferenceMap extends ReferenceMap { - - WeakReferenceMap(Map> delegate) { - super(delegate); - } - - @Override - Reference fold(V value) { - return new WeakReference(value); - } - -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/package-info.java deleted file mode 100755 index ddb4b65487..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/serialization/package-info.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * Encoder, decoder and their compatibility stream implementations which - * transform a {@link java.io.Serializable} object into a byte buffer and - * vice versa. - */ -package com.ai.cloud.io.netty.handler.codec.serialization; diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksAddressType.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksAddressType.java deleted file mode 100755 index d8e9792b2b..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksAddressType.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.handler.codec.socks; - -public enum SocksAddressType { - IPv4((byte) 0x01), - DOMAIN((byte) 0x03), - IPv6((byte) 0x04), - UNKNOWN((byte) 0xff); - - private final byte b; - - SocksAddressType(byte b) { - this.b = b; - } - - /** - * @deprecated Use {@link #valueOf(byte)} instead. - */ - @Deprecated - public static SocksAddressType fromByte(byte b) { - return valueOf(b); - } - - public static SocksAddressType valueOf(byte b) { - for (SocksAddressType code : values()) { - if (code.b == b) { - return code; - } - } - return UNKNOWN; - } - - public byte byteValue() { - return b; - } -} - diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksAuthRequest.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksAuthRequest.java deleted file mode 100755 index d1395b6394..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksAuthRequest.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.socks; - -import java.nio.charset.CharsetEncoder; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.util.CharsetUtil; - -/** - * An socks auth request. - * - * @see SocksAuthResponse - * @see SocksAuthRequestDecoder - */ -public final class SocksAuthRequest extends SocksRequest { - private static final CharsetEncoder asciiEncoder = CharsetUtil.getEncoder(CharsetUtil.US_ASCII); - private static final SocksSubnegotiationVersion SUBNEGOTIATION_VERSION = SocksSubnegotiationVersion.AUTH_PASSWORD; - private final String username; - private final String password; - - public SocksAuthRequest(String username, String password) { - super(SocksRequestType.AUTH); - if (username == null) { - throw new NullPointerException("username"); - } - if (password == null) { - throw new NullPointerException("username"); - } - if (!asciiEncoder.canEncode(username) || !asciiEncoder.canEncode(password)) { - throw new IllegalArgumentException( - "username: " + username + " or password: **** values should be in pure ascii"); - } - if (username.length() > 255) { - throw new IllegalArgumentException("username: " + username + " exceeds 255 char limit"); - } - if (password.length() > 255) { - throw new IllegalArgumentException("password: **** exceeds 255 char limit"); - } - this.username = username; - this.password = password; - } - - /** - * Returns username that needs to be authenticated - * - * @return username that needs to be authenticated - */ - public String username() { - return username; - } - - /** - * Returns password that needs to be validated - * - * @return password that needs to be validated - */ - public String password() { - return password; - } - - @Override - public void encodeAsByteBuf(ByteBuf byteBuf) { - byteBuf.writeByte(SUBNEGOTIATION_VERSION.byteValue()); - byteBuf.writeByte(username.length()); - byteBuf.writeBytes(username.getBytes(CharsetUtil.US_ASCII)); - byteBuf.writeByte(password.length()); - byteBuf.writeBytes(password.getBytes(CharsetUtil.US_ASCII)); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksAuthRequestDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksAuthRequestDecoder.java deleted file mode 100755 index 575f6203a6..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksAuthRequestDecoder.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.socks; - -import java.util.List; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.handler.codec.ReplayingDecoder; -import com.ai.cloud.io.netty.handler.codec.socks.SocksAuthRequestDecoder.State; -import com.ai.cloud.io.netty.util.CharsetUtil; - -/** - * Decodes {@link ByteBuf}s into {@link SocksAuthRequest}. - * Before returning SocksRequest decoder removes itself from pipeline. - */ -public class SocksAuthRequestDecoder extends ReplayingDecoder { - private static final String name = "SOCKS_AUTH_REQUEST_DECODER"; - - /** - * @deprecated Will be removed at the next minor version bump. - */ - @Deprecated - public static String getName() { - return name; - } - - private SocksSubnegotiationVersion version; - private int fieldLength; - private String username; - private String password; - private SocksRequest msg = SocksCommonUtils.UNKNOWN_SOCKS_REQUEST; - - public SocksAuthRequestDecoder() { - super(State.CHECK_PROTOCOL_VERSION); - } - - @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuf, List out) throws Exception { - switch (state()) { - case CHECK_PROTOCOL_VERSION: { - version = SocksSubnegotiationVersion.valueOf(byteBuf.readByte()); - if (version != SocksSubnegotiationVersion.AUTH_PASSWORD) { - break; - } - checkpoint(State.READ_USERNAME); - } - case READ_USERNAME: { - fieldLength = byteBuf.readByte(); - username = byteBuf.readBytes(fieldLength).toString(CharsetUtil.US_ASCII); - checkpoint(State.READ_PASSWORD); - } - case READ_PASSWORD: { - fieldLength = byteBuf.readByte(); - password = byteBuf.readBytes(fieldLength).toString(CharsetUtil.US_ASCII); - msg = new SocksAuthRequest(username, password); - } - } - ctx.pipeline().remove(this); - out.add(msg); - } - - enum State { - CHECK_PROTOCOL_VERSION, - READ_USERNAME, - READ_PASSWORD - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksAuthResponse.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksAuthResponse.java deleted file mode 100755 index 3d72ec5f05..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksAuthResponse.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.socks; - -import com.ai.cloud.io.netty.buffer.ByteBuf; - -/** - * An socks auth response. - * - * @see SocksAuthRequest - * @see SocksAuthResponseDecoder - */ -public final class SocksAuthResponse extends SocksResponse { - private static final SocksSubnegotiationVersion SUBNEGOTIATION_VERSION = SocksSubnegotiationVersion.AUTH_PASSWORD; - private final SocksAuthStatus authStatus; - - public SocksAuthResponse(SocksAuthStatus authStatus) { - super(SocksResponseType.AUTH); - if (authStatus == null) { - throw new NullPointerException("authStatus"); - } - this.authStatus = authStatus; - } - - /** - * Returns the {@link SocksAuthStatus} of this {@link SocksAuthResponse} - * - * @return The {@link SocksAuthStatus} of this {@link SocksAuthResponse} - */ - public SocksAuthStatus authStatus() { - return authStatus; - } - - @Override - public void encodeAsByteBuf(ByteBuf byteBuf) { - byteBuf.writeByte(SUBNEGOTIATION_VERSION.byteValue()); - byteBuf.writeByte(authStatus.byteValue()); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksAuthResponseDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksAuthResponseDecoder.java deleted file mode 100755 index b27bcf0f39..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksAuthResponseDecoder.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.socks; - -import java.util.List; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.handler.codec.ReplayingDecoder; -import com.ai.cloud.io.netty.handler.codec.socks.SocksAuthResponseDecoder.State; - -/** - * Decodes {@link ByteBuf}s into {@link SocksAuthResponse}. - * Before returning SocksResponse decoder removes itself from pipeline. - */ -public class SocksAuthResponseDecoder extends ReplayingDecoder { - private static final String name = "SOCKS_AUTH_RESPONSE_DECODER"; - - /** - * @deprecated Will be removed at the next minor version bump. - */ - @Deprecated - public static String getName() { - return name; - } - - private SocksSubnegotiationVersion version; - private SocksAuthStatus authStatus; - private SocksResponse msg = SocksCommonUtils.UNKNOWN_SOCKS_RESPONSE; - - public SocksAuthResponseDecoder() { - super(State.CHECK_PROTOCOL_VERSION); - } - - @Override - protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List out) - throws Exception { - switch (state()) { - case CHECK_PROTOCOL_VERSION: { - version = SocksSubnegotiationVersion.valueOf(byteBuf.readByte()); - if (version != SocksSubnegotiationVersion.AUTH_PASSWORD) { - break; - } - checkpoint(State.READ_AUTH_RESPONSE); - } - case READ_AUTH_RESPONSE: { - authStatus = SocksAuthStatus.valueOf(byteBuf.readByte()); - msg = new SocksAuthResponse(authStatus); - } - } - channelHandlerContext.pipeline().remove(this); - out.add(msg); - } - - enum State { - CHECK_PROTOCOL_VERSION, - READ_AUTH_RESPONSE - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksAuthScheme.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksAuthScheme.java deleted file mode 100755 index f00aea4311..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksAuthScheme.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.handler.codec.socks; - -public enum SocksAuthScheme { - NO_AUTH((byte) 0x00), - AUTH_GSSAPI((byte) 0x01), - AUTH_PASSWORD((byte) 0x02), - UNKNOWN((byte) 0xff); - - private final byte b; - - SocksAuthScheme(byte b) { - this.b = b; - } - - /** - * @deprecated Use {@link #valueOf(byte)} instead. - */ - @Deprecated - public static SocksAuthScheme fromByte(byte b) { - return valueOf(b); - } - - public static SocksAuthScheme valueOf(byte b) { - for (SocksAuthScheme code : values()) { - if (code.b == b) { - return code; - } - } - return UNKNOWN; - } - - public byte byteValue() { - return b; - } -} - diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksAuthStatus.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksAuthStatus.java deleted file mode 100755 index 6edfcc7788..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksAuthStatus.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.handler.codec.socks; - -public enum SocksAuthStatus { - SUCCESS((byte) 0x00), - FAILURE((byte) 0xff); - - private final byte b; - - SocksAuthStatus(byte b) { - this.b = b; - } - - /** - * @deprecated Use {@link #valueOf(byte)} instead. - */ - @Deprecated - public static SocksAuthStatus fromByte(byte b) { - return valueOf(b); - } - - public static SocksAuthStatus valueOf(byte b) { - for (SocksAuthStatus code : values()) { - if (code.b == b) { - return code; - } - } - return FAILURE; - } - - public byte byteValue() { - return b; - } -} - diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksCmdRequest.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksCmdRequest.java deleted file mode 100755 index 56ead07a07..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksCmdRequest.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.socks; - -import java.net.IDN; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.util.CharsetUtil; -import com.ai.cloud.io.netty.util.NetUtil; - -/** - * An socks cmd request. - * - * @see SocksCmdResponse - * @see SocksCmdRequestDecoder - */ -public final class SocksCmdRequest extends SocksRequest { - private final SocksCmdType cmdType; - private final SocksAddressType addressType; - private final String host; - private final int port; - - public SocksCmdRequest(SocksCmdType cmdType, SocksAddressType addressType, String host, int port) { - super(SocksRequestType.CMD); - if (cmdType == null) { - throw new NullPointerException("cmdType"); - } - if (addressType == null) { - throw new NullPointerException("addressType"); - } - if (host == null) { - throw new NullPointerException("host"); - } - switch (addressType) { - case IPv4: - if (!NetUtil.isValidIpV4Address(host)) { - throw new IllegalArgumentException(host + " is not a valid IPv4 address"); - } - break; - case DOMAIN: - if (IDN.toASCII(host).length() > 255) { - throw new IllegalArgumentException(host + " IDN: " + IDN.toASCII(host) + " exceeds 255 char limit"); - } - break; - case IPv6: - if (!NetUtil.isValidIpV6Address(host)) { - throw new IllegalArgumentException(host + " is not a valid IPv6 address"); - } - break; - case UNKNOWN: - break; - } - if (port <= 0 || port >= 65536) { - throw new IllegalArgumentException(port + " is not in bounds 0 < x < 65536"); - } - this.cmdType = cmdType; - this.addressType = addressType; - this.host = IDN.toASCII(host); - this.port = port; - } - - /** - * Returns the {@link SocksCmdType} of this {@link SocksCmdRequest} - * - * @return The {@link SocksCmdType} of this {@link SocksCmdRequest} - */ - public SocksCmdType cmdType() { - return cmdType; - } - - /** - * Returns the {@link SocksAddressType} of this {@link SocksCmdRequest} - * - * @return The {@link SocksAddressType} of this {@link SocksCmdRequest} - */ - public SocksAddressType addressType() { - return addressType; - } - - /** - * Returns host that is used as a parameter in {@link SocksCmdType} - * - * @return host that is used as a parameter in {@link SocksCmdType} - */ - public String host() { - return IDN.toUnicode(host); - } - - /** - * Returns port that is used as a parameter in {@link SocksCmdType} - * - * @return port that is used as a parameter in {@link SocksCmdType} - */ - public int port() { - return port; - } - - @Override - public void encodeAsByteBuf(ByteBuf byteBuf) { - byteBuf.writeByte(protocolVersion().byteValue()); - byteBuf.writeByte(cmdType.byteValue()); - byteBuf.writeByte(0x00); - byteBuf.writeByte(addressType.byteValue()); - switch (addressType) { - case IPv4: { - byteBuf.writeBytes(NetUtil.createByteArrayFromIpAddressString(host)); - byteBuf.writeShort(port); - break; - } - - case DOMAIN: { - byteBuf.writeByte(host.length()); - byteBuf.writeBytes(host.getBytes(CharsetUtil.US_ASCII)); - byteBuf.writeShort(port); - break; - } - - case IPv6: { - byteBuf.writeBytes(NetUtil.createByteArrayFromIpAddressString(host)); - byteBuf.writeShort(port); - break; - } - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksCmdRequestDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksCmdRequestDecoder.java deleted file mode 100755 index d90fa6216e..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksCmdRequestDecoder.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.socks; - -import java.util.List; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.handler.codec.ReplayingDecoder; -import com.ai.cloud.io.netty.handler.codec.socks.SocksCmdRequestDecoder.State; -import com.ai.cloud.io.netty.util.CharsetUtil; - -/** - * Decodes {@link ByteBuf}s into {@link SocksCmdRequest}. - * Before returning SocksRequest decoder removes itself from pipeline. - */ -public class SocksCmdRequestDecoder extends ReplayingDecoder { - private static final String name = "SOCKS_CMD_REQUEST_DECODER"; - - /** - * @deprecated Will be removed at the next minor version bump. - */ - @Deprecated - public static String getName() { - return name; - } - - private SocksProtocolVersion version; - private int fieldLength; - private SocksCmdType cmdType; - private SocksAddressType addressType; - @SuppressWarnings("UnusedDeclaration") - private byte reserved; - private String host; - private int port; - private SocksRequest msg = SocksCommonUtils.UNKNOWN_SOCKS_REQUEST; - - public SocksCmdRequestDecoder() { - super(State.CHECK_PROTOCOL_VERSION); - } - - @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuf, List out) throws Exception { - switch (state()) { - case CHECK_PROTOCOL_VERSION: { - version = SocksProtocolVersion.valueOf(byteBuf.readByte()); - if (version != SocksProtocolVersion.SOCKS5) { - break; - } - checkpoint(State.READ_CMD_HEADER); - } - case READ_CMD_HEADER: { - cmdType = SocksCmdType.valueOf(byteBuf.readByte()); - reserved = byteBuf.readByte(); - addressType = SocksAddressType.valueOf(byteBuf.readByte()); - checkpoint(State.READ_CMD_ADDRESS); - } - case READ_CMD_ADDRESS: { - switch (addressType) { - case IPv4: { - host = SocksCommonUtils.intToIp(byteBuf.readInt()); - port = byteBuf.readUnsignedShort(); - msg = new SocksCmdRequest(cmdType, addressType, host, port); - break; - } - case DOMAIN: { - fieldLength = byteBuf.readByte(); - host = byteBuf.readBytes(fieldLength).toString(CharsetUtil.US_ASCII); - port = byteBuf.readUnsignedShort(); - msg = new SocksCmdRequest(cmdType, addressType, host, port); - break; - } - case IPv6: { - host = SocksCommonUtils.ipv6toStr(byteBuf.readBytes(16).array()); - port = byteBuf.readUnsignedShort(); - msg = new SocksCmdRequest(cmdType, addressType, host, port); - break; - } - case UNKNOWN: - break; - } - } - } - ctx.pipeline().remove(this); - out.add(msg); - } - - enum State { - CHECK_PROTOCOL_VERSION, - READ_CMD_HEADER, - READ_CMD_ADDRESS - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksCmdResponse.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksCmdResponse.java deleted file mode 100755 index 3f8b1e6226..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksCmdResponse.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.socks; - -import java.net.IDN; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.util.CharsetUtil; -import com.ai.cloud.io.netty.util.NetUtil; - -/** - * A socks cmd response. - * - * @see SocksCmdRequest - * @see SocksCmdResponseDecoder - */ -public final class SocksCmdResponse extends SocksResponse { - private final SocksCmdStatus cmdStatus; - - private final SocksAddressType addressType; - private final String host; - private final int port; - - // All arrays are initialized on construction time to 0/false/null remove array Initialization - private static final byte[] DOMAIN_ZEROED = {0x00}; - private static final byte[] IPv4_HOSTNAME_ZEROED = {0x00, 0x00, 0x00, 0x00}; - private static final byte[] IPv6_HOSTNAME_ZEROED = {0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00}; - - public SocksCmdResponse(SocksCmdStatus cmdStatus, SocksAddressType addressType) { - this(cmdStatus, addressType, null, 0); - } - - /** - * Constructs new response and includes provided host and port as part of it. - * - * @param cmdStatus status of the response - * @param addressType type of host parameter - * @param host host (BND.ADDR field) is address that server used when connecting to the target host. - * When null a value of 4/8 0x00 octets will be used for IPv4/IPv6 and a single 0x00 byte will be - * used for domain addressType. Value is converted to ASCII using {@link IDN#toASCII(String)}. - * @param port port (BND.PORT field) that the server assigned to connect to the target host - * @throws NullPointerException in case cmdStatus or addressType are missing - * @throws IllegalArgumentException in case host or port cannot be validated - * @see IDN#toASCII(String) - */ - public SocksCmdResponse(SocksCmdStatus cmdStatus, SocksAddressType addressType, String host, int port) { - super(SocksResponseType.CMD); - if (cmdStatus == null) { - throw new NullPointerException("cmdStatus"); - } - if (addressType == null) { - throw new NullPointerException("addressType"); - } - if (host != null) { - switch (addressType) { - case IPv4: - if (!NetUtil.isValidIpV4Address(host)) { - throw new IllegalArgumentException(host + " is not a valid IPv4 address"); - } - break; - case DOMAIN: - if (IDN.toASCII(host).length() > 255) { - throw new IllegalArgumentException(host + " IDN: " + - IDN.toASCII(host) + " exceeds 255 char limit"); - } - break; - case IPv6: - if (!NetUtil.isValidIpV6Address(host)) { - throw new IllegalArgumentException(host + " is not a valid IPv6 address"); - } - break; - case UNKNOWN: - break; - } - host = IDN.toASCII(host); - } - if (port < 0 || port > 65535) { - throw new IllegalArgumentException(port + " is not in bounds 0 <= x <= 65535"); - } - this.cmdStatus = cmdStatus; - this.addressType = addressType; - this.host = host; - this.port = port; - } - - /** - * Returns the {@link SocksCmdStatus} of this {@link SocksCmdResponse} - * - * @return The {@link SocksCmdStatus} of this {@link SocksCmdResponse} - */ - public SocksCmdStatus cmdStatus() { - return cmdStatus; - } - - /** - * Returns the {@link SocksAddressType} of this {@link SocksCmdResponse} - * - * @return The {@link SocksAddressType} of this {@link SocksCmdResponse} - */ - public SocksAddressType addressType() { - return addressType; - } - - /** - * Returns host that is used as a parameter in {@link com.ai.cloud.io.netty.handler.codec.socks.SocksCmdType}. - * Host (BND.ADDR field in response) is address that server used when connecting to the target host. - * This is typically different from address which client uses to connect to the SOCKS server. - * - * @return host that is used as a parameter in {@link com.ai.cloud.io.netty.handler.codec.socks.SocksCmdType} - * or null when there was no host specified during response construction - */ - public String host() { - if (host != null) { - return IDN.toUnicode(host); - } else { - return null; - } - } - - /** - * Returns port that is used as a parameter in {@link com.ai.cloud.io.netty.handler.codec.socks.SocksCmdType}. - * Port (BND.PORT field in response) is port that the server assigned to connect to the target host. - * - * @return port that is used as a parameter in {@link com.ai.cloud.io.netty.handler.codec.socks.SocksCmdType} - */ - public int port() { - return port; - } - - @Override - public void encodeAsByteBuf(ByteBuf byteBuf) { - byteBuf.writeByte(protocolVersion().byteValue()); - byteBuf.writeByte(cmdStatus.byteValue()); - byteBuf.writeByte(0x00); - byteBuf.writeByte(addressType.byteValue()); - switch (addressType) { - case IPv4: { - byte[] hostContent = host == null ? - IPv4_HOSTNAME_ZEROED : NetUtil.createByteArrayFromIpAddressString(host); - byteBuf.writeBytes(hostContent); - byteBuf.writeShort(port); - break; - } - case DOMAIN: { - byte[] hostContent = host == null ? - DOMAIN_ZEROED : host.getBytes(CharsetUtil.US_ASCII); - byteBuf.writeByte(hostContent.length); // domain length - byteBuf.writeBytes(hostContent); // domain value - byteBuf.writeShort(port); // port value - break; - } - case IPv6: { - byte[] hostContent = host == null - ? IPv6_HOSTNAME_ZEROED : NetUtil.createByteArrayFromIpAddressString(host); - byteBuf.writeBytes(hostContent); - byteBuf.writeShort(port); - break; - } - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksCmdResponseDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksCmdResponseDecoder.java deleted file mode 100755 index ad90cb2631..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksCmdResponseDecoder.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.socks; - -import java.util.List; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.handler.codec.ReplayingDecoder; -import com.ai.cloud.io.netty.handler.codec.socks.SocksCmdResponseDecoder.State; -import com.ai.cloud.io.netty.util.CharsetUtil; - -/** - * Decodes {@link ByteBuf}s into {@link SocksCmdResponse}. - * Before returning SocksResponse decoder removes itself from pipeline. - */ -public class SocksCmdResponseDecoder extends ReplayingDecoder { - private static final String name = "SOCKS_CMD_RESPONSE_DECODER"; - - /** - * @deprecated Will be removed at the next minor version bump. - */ - @Deprecated - public static String getName() { - return name; - } - - private SocksProtocolVersion version; - private int fieldLength; - private SocksCmdStatus cmdStatus; - private SocksAddressType addressType; - private byte reserved; - private String host; - private int port; - private SocksResponse msg = SocksCommonUtils.UNKNOWN_SOCKS_RESPONSE; - - public SocksCmdResponseDecoder() { - super(State.CHECK_PROTOCOL_VERSION); - } - - @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuf, List out) throws Exception { - switch (state()) { - case CHECK_PROTOCOL_VERSION: { - version = SocksProtocolVersion.valueOf(byteBuf.readByte()); - if (version != SocksProtocolVersion.SOCKS5) { - break; - } - checkpoint(State.READ_CMD_HEADER); - } - case READ_CMD_HEADER: { - cmdStatus = SocksCmdStatus.valueOf(byteBuf.readByte()); - reserved = byteBuf.readByte(); - addressType = SocksAddressType.valueOf(byteBuf.readByte()); - checkpoint(State.READ_CMD_ADDRESS); - } - case READ_CMD_ADDRESS: { - switch (addressType) { - case IPv4: { - host = SocksCommonUtils.intToIp(byteBuf.readInt()); - port = byteBuf.readUnsignedShort(); - msg = new SocksCmdResponse(cmdStatus, addressType, host, port); - break; - } - case DOMAIN: { - fieldLength = byteBuf.readByte(); - host = byteBuf.readBytes(fieldLength).toString(CharsetUtil.US_ASCII); - port = byteBuf.readUnsignedShort(); - msg = new SocksCmdResponse(cmdStatus, addressType, host, port); - break; - } - case IPv6: { - host = SocksCommonUtils.ipv6toStr(byteBuf.readBytes(16).array()); - port = byteBuf.readUnsignedShort(); - msg = new SocksCmdResponse(cmdStatus, addressType, host, port); - break; - } - case UNKNOWN: - break; - } - } - } - ctx.pipeline().remove(this); - out.add(msg); - } - - enum State { - CHECK_PROTOCOL_VERSION, - READ_CMD_HEADER, - READ_CMD_ADDRESS - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksCmdStatus.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksCmdStatus.java deleted file mode 100755 index 185e464126..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksCmdStatus.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.handler.codec.socks; - -public enum SocksCmdStatus { - SUCCESS((byte) 0x00), - FAILURE((byte) 0x01), - FORBIDDEN((byte) 0x02), - NETWORK_UNREACHABLE((byte) 0x03), - HOST_UNREACHABLE((byte) 0x04), - REFUSED((byte) 0x05), - TTL_EXPIRED((byte) 0x06), - COMMAND_NOT_SUPPORTED((byte) 0x07), - ADDRESS_NOT_SUPPORTED((byte) 0x08), - UNASSIGNED((byte) 0xff); - - private final byte b; - - SocksCmdStatus(byte b) { - this.b = b; - } - - /** - * @deprecated Use {@link #valueOf(byte)} instead. - */ - @Deprecated - public static SocksCmdStatus fromByte(byte b) { - return valueOf(b); - } - - public static SocksCmdStatus valueOf(byte b) { - for (SocksCmdStatus code : values()) { - if (code.b == b) { - return code; - } - } - return UNASSIGNED; - } - - public byte byteValue() { - return b; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksCmdType.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksCmdType.java deleted file mode 100755 index cf3cad98f5..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksCmdType.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.handler.codec.socks; - -public enum SocksCmdType { - CONNECT((byte) 0x01), - BIND((byte) 0x02), - UDP((byte) 0x03), - UNKNOWN((byte) 0xff); - - private final byte b; - - SocksCmdType(byte b) { - this.b = b; - } - - /** - * @deprecated Use {@link #valueOf(byte)} instead. - */ - @Deprecated - public static SocksCmdType fromByte(byte b) { - return valueOf(b); - } - - public static SocksCmdType valueOf(byte b) { - for (SocksCmdType code : values()) { - if (code.b == b) { - return code; - } - } - return UNKNOWN; - } - - public byte byteValue() { - return b; - } -} - diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksCommonUtils.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksCommonUtils.java deleted file mode 100755 index da7803823d..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksCommonUtils.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.socks; - -import com.ai.cloud.io.netty.util.internal.StringUtil; - -final class SocksCommonUtils { - public static final SocksRequest UNKNOWN_SOCKS_REQUEST = new UnknownSocksRequest(); - public static final SocksResponse UNKNOWN_SOCKS_RESPONSE = new UnknownSocksResponse(); - - private static final int SECOND_ADDRESS_OCTET_SHIFT = 16; - private static final int FIRST_ADDRESS_OCTET_SHIFT = 24; - private static final int THIRD_ADDRESS_OCTET_SHIFT = 8; - private static final int XOR_DEFAULT_VALUE = 0xff; - - /** - * A constructor to stop this class being constructed. - */ - private SocksCommonUtils() { - // NOOP - } - - public static String intToIp(int i) { - return String.valueOf(i >> FIRST_ADDRESS_OCTET_SHIFT & XOR_DEFAULT_VALUE) + '.' + - (i >> SECOND_ADDRESS_OCTET_SHIFT & XOR_DEFAULT_VALUE) + '.' + - (i >> THIRD_ADDRESS_OCTET_SHIFT & XOR_DEFAULT_VALUE) + '.' + - (i & XOR_DEFAULT_VALUE); - } - - private static final char[] ipv6conseqZeroFiller = {':', ':'}; - private static final char ipv6hextetSeparator = ':'; - - /** - * Convert numeric IPv6 to compressed format, where - * the longest sequence of 0's (with 2 or more 0's) is replaced with "::" - */ - public static String ipv6toCompressedForm(byte[] src) { - assert src.length == 16; - //Find the longest sequence of 0's - //start of compressed region (hextet index) - int cmprHextet = -1; - //length of compressed region - int cmprSize = 0; - for (int hextet = 0; hextet < 8;) { - int curByte = hextet * 2; - int size = 0; - while (curByte < src.length && src[curByte] == 0 - && src[curByte + 1] == 0) { - curByte += 2; - size++; - } - if (size > cmprSize) { - cmprHextet = hextet; - cmprSize = size; - } - hextet = curByte / 2 + 1; - } - if (cmprHextet == -1 || cmprSize < 2) { - //No compression can be applied - return ipv6toStr(src); - } - StringBuilder sb = new StringBuilder(39); - ipv6toStr(sb, src, 0, cmprHextet); - sb.append(ipv6conseqZeroFiller); - ipv6toStr(sb, src, cmprHextet + cmprSize, 8); - return sb.toString(); - } - - /** - * Converts numeric IPv6 to standard (non-compressed) format. - */ - public static String ipv6toStr(byte[] src) { - assert src.length == 16; - StringBuilder sb = new StringBuilder(39); - ipv6toStr(sb, src, 0, 8); - return sb.toString(); - } - - private static void ipv6toStr(StringBuilder sb, byte[] src, int fromHextet, int toHextet) { - int i; - toHextet --; - for (i = fromHextet; i < toHextet; i++) { - appendHextet(sb, src, i); - sb.append(ipv6hextetSeparator); - } - - appendHextet(sb, src, i); - } - - private static void appendHextet(StringBuilder sb, byte[] src, int i) { - StringUtil.toHexString(sb, src, i << 1, 2); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksInitRequest.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksInitRequest.java deleted file mode 100755 index 7dd4897505..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksInitRequest.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.socks; - -import java.util.Collections; -import java.util.List; - -import com.ai.cloud.io.netty.buffer.ByteBuf; - -/** - * An socks init request. - * - * @see SocksInitResponse - * @see SocksInitRequestDecoder - */ -public final class SocksInitRequest extends SocksRequest { - private final List authSchemes; - - public SocksInitRequest(List authSchemes) { - super(SocksRequestType.INIT); - if (authSchemes == null) { - throw new NullPointerException("authSchemes"); - } - this.authSchemes = authSchemes; - } - - /** - * Returns the List<{@link SocksAuthScheme}> of this {@link SocksInitRequest} - * - * @return The List<{@link SocksAuthScheme}> of this {@link SocksInitRequest} - */ - public List authSchemes() { - return Collections.unmodifiableList(authSchemes); - } - - @Override - public void encodeAsByteBuf(ByteBuf byteBuf) { - byteBuf.writeByte(protocolVersion().byteValue()); - byteBuf.writeByte(authSchemes.size()); - for (SocksAuthScheme authScheme : authSchemes) { - byteBuf.writeByte(authScheme.byteValue()); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksInitRequestDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksInitRequestDecoder.java deleted file mode 100755 index 3af62ad435..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksInitRequestDecoder.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.socks; - -import java.util.ArrayList; -import java.util.List; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.handler.codec.ReplayingDecoder; -import com.ai.cloud.io.netty.handler.codec.socks.SocksInitRequestDecoder.State; - -/** - * Decodes {@link ByteBuf}s into {@link SocksInitRequest}. - * Before returning SocksRequest decoder removes itself from pipeline. - */ -public class SocksInitRequestDecoder extends ReplayingDecoder { - private static final String name = "SOCKS_INIT_REQUEST_DECODER"; - - /** - * @deprecated Will be removed at the next minor version bump. - */ - @Deprecated - public static String getName() { - return name; - } - - private final List authSchemes = new ArrayList(); - private SocksProtocolVersion version; - private byte authSchemeNum; - private SocksRequest msg = SocksCommonUtils.UNKNOWN_SOCKS_REQUEST; - - public SocksInitRequestDecoder() { - super(State.CHECK_PROTOCOL_VERSION); - } - - @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuf, List out) throws Exception { - switch (state()) { - case CHECK_PROTOCOL_VERSION: { - version = SocksProtocolVersion.valueOf(byteBuf.readByte()); - if (version != SocksProtocolVersion.SOCKS5) { - break; - } - checkpoint(State.READ_AUTH_SCHEMES); - } - case READ_AUTH_SCHEMES: { - authSchemes.clear(); - authSchemeNum = byteBuf.readByte(); - for (int i = 0; i < authSchemeNum; i++) { - authSchemes.add(SocksAuthScheme.valueOf(byteBuf.readByte())); - } - msg = new SocksInitRequest(authSchemes); - break; - } - } - ctx.pipeline().remove(this); - out.add(msg); - } - - enum State { - CHECK_PROTOCOL_VERSION, - READ_AUTH_SCHEMES - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksInitResponse.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksInitResponse.java deleted file mode 100755 index e236064106..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksInitResponse.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.socks; - -import com.ai.cloud.io.netty.buffer.ByteBuf; - -/** - * An socks init response. - * - * @see SocksInitRequest - * @see SocksInitResponseDecoder - */ -public final class SocksInitResponse extends SocksResponse { - private final SocksAuthScheme authScheme; - - public SocksInitResponse(SocksAuthScheme authScheme) { - super(SocksResponseType.INIT); - if (authScheme == null) { - throw new NullPointerException("authScheme"); - } - this.authScheme = authScheme; - } - - /** - * Returns the {@link SocksAuthScheme} of this {@link SocksInitResponse} - * - * @return The {@link SocksAuthScheme} of this {@link SocksInitResponse} - */ - public SocksAuthScheme authScheme() { - return authScheme; - } - - @Override - public void encodeAsByteBuf(ByteBuf byteBuf) { - byteBuf.writeByte(protocolVersion().byteValue()); - byteBuf.writeByte(authScheme.byteValue()); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksInitResponseDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksInitResponseDecoder.java deleted file mode 100755 index f5f272a22d..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksInitResponseDecoder.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.socks; - -import java.util.List; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.handler.codec.ReplayingDecoder; -import com.ai.cloud.io.netty.handler.codec.socks.SocksInitResponseDecoder.State; - -/** - * Decodes {@link ByteBuf}s into {@link SocksInitResponse}. - * Before returning SocksResponse decoder removes itself from pipeline. - */ -public class SocksInitResponseDecoder extends ReplayingDecoder { - private static final String name = "SOCKS_INIT_RESPONSE_DECODER"; - - /** - * @deprecated Will be removed at the next minor version bump. - */ - @Deprecated - public static String getName() { - return name; - } - - private SocksProtocolVersion version; - private SocksAuthScheme authScheme; - - private SocksResponse msg = SocksCommonUtils.UNKNOWN_SOCKS_RESPONSE; - - public SocksInitResponseDecoder() { - super(State.CHECK_PROTOCOL_VERSION); - } - - @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuf, List out) throws Exception { - switch (state()) { - case CHECK_PROTOCOL_VERSION: { - version = SocksProtocolVersion.valueOf(byteBuf.readByte()); - if (version != SocksProtocolVersion.SOCKS5) { - break; - } - checkpoint(State.READ_PREFFERED_AUTH_TYPE); - } - case READ_PREFFERED_AUTH_TYPE: { - authScheme = SocksAuthScheme.valueOf(byteBuf.readByte()); - msg = new SocksInitResponse(authScheme); - break; - } - } - ctx.pipeline().remove(this); - out.add(msg); - } - - enum State { - CHECK_PROTOCOL_VERSION, - READ_PREFFERED_AUTH_TYPE - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksMessage.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksMessage.java deleted file mode 100755 index bdb95eb970..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksMessage.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.socks; - -import com.ai.cloud.io.netty.buffer.ByteBuf; - -/** - * An abstract class that defines a SocksMessage, providing common properties for - * {@link SocksRequest} and {@link SocksResponse}. - * - * @see SocksRequest - * @see SocksResponse - */ - -public abstract class SocksMessage { - private final SocksMessageType type; - private final SocksProtocolVersion protocolVersion = SocksProtocolVersion.SOCKS5; - - protected SocksMessage(SocksMessageType type) { - if (type == null) { - throw new NullPointerException("type"); - } - this.type = type; - } - - /** - * Returns the {@link SocksMessageType} of this {@link SocksMessage} - * - * @return The {@link SocksMessageType} of this {@link SocksMessage} - */ - public SocksMessageType type() { - return type; - } - - /** - * Returns the {@link SocksProtocolVersion} of this {@link SocksMessage} - * - * @return The {@link SocksProtocolVersion} of this {@link SocksMessage} - */ - public SocksProtocolVersion protocolVersion() { - return protocolVersion; - } - - /** - * @deprecated Do not use; this method was intended for an internal use only. - */ - @Deprecated - public abstract void encodeAsByteBuf(ByteBuf byteBuf); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksMessageEncoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksMessageEncoder.java deleted file mode 100755 index 9b97facff1..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksMessageEncoder.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.socks; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelHandler; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.handler.codec.MessageToByteEncoder; - -/** - * Encodes an {@link SocksMessage} into a {@link ByteBuf}. - * {@link MessageToByteEncoder} implementation. - * Use this with {@link SocksInitRequest}, {@link SocksInitResponse}, {@link SocksAuthRequest}, - * {@link SocksAuthResponse}, {@link SocksCmdRequest} and {@link SocksCmdResponse} - */ -@ChannelHandler.Sharable -public class SocksMessageEncoder extends MessageToByteEncoder { - private static final String name = "SOCKS_MESSAGE_ENCODER"; - - /** - * @deprecated Will be removed at the next minor version bump. - */ - @Deprecated - public static String getName() { - return name; - } - - @Override - @SuppressWarnings("deprecation") - protected void encode(ChannelHandlerContext ctx, SocksMessage msg, ByteBuf out) throws Exception { - msg.encodeAsByteBuf(out); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksMessageType.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksMessageType.java deleted file mode 100755 index 81e284d4d5..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksMessageType.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.handler.codec.socks; - -public enum SocksMessageType { - REQUEST, - RESPONSE, - UNKNOWN -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksProtocolVersion.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksProtocolVersion.java deleted file mode 100755 index c49932633b..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksProtocolVersion.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.handler.codec.socks; - -public enum SocksProtocolVersion { - SOCKS4a((byte) 0x04), - SOCKS5((byte) 0x05), - UNKNOWN((byte) 0xff); - - private final byte b; - - SocksProtocolVersion(byte b) { - this.b = b; - } - - /** - * @deprecated Use {@link #valueOf(byte)} instead. - */ - @Deprecated - public static SocksProtocolVersion fromByte(byte b) { - return valueOf(b); - } - - public static SocksProtocolVersion valueOf(byte b) { - for (SocksProtocolVersion code : values()) { - if (code.b == b) { - return code; - } - } - return UNKNOWN; - } - - public byte byteValue() { - return b; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksRequest.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksRequest.java deleted file mode 100755 index 317e48e3c9..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksRequest.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.socks; - -/** - * An abstract class that defines a SocksRequest, providing common properties for - * {@link SocksInitRequest}, {@link SocksAuthRequest}, {@link SocksCmdRequest} and {@link UnknownSocksRequest}. - * - * @see SocksInitRequest - * @see SocksAuthRequest - * @see SocksCmdRequest - * @see UnknownSocksRequest - */ -public abstract class SocksRequest extends SocksMessage { - private final SocksRequestType requestType; - - protected SocksRequest(SocksRequestType requestType) { - super(SocksMessageType.REQUEST); - if (requestType == null) { - throw new NullPointerException("requestType"); - } - this.requestType = requestType; - } - - /** - * Returns socks request type - * - * @return socks request type - */ - public SocksRequestType requestType() { - return requestType; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksRequestType.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksRequestType.java deleted file mode 100755 index ecb558c67f..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksRequestType.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.handler.codec.socks; - -/** - * Type of socks request - */ -public enum SocksRequestType { - INIT, - AUTH, - CMD, - UNKNOWN -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksResponse.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksResponse.java deleted file mode 100755 index 6c140f65a7..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksResponse.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.socks; - -/** - * An abstract class that defines a SocksResponse, providing common properties for - * {@link SocksInitResponse}, {@link SocksAuthResponse}, {@link SocksCmdResponse} and {@link UnknownSocksResponse}. - * - * @see SocksInitResponse - * @see SocksAuthResponse - * @see SocksCmdResponse - * @see UnknownSocksResponse - */ -public abstract class SocksResponse extends SocksMessage { - private final SocksResponseType responseType; - - protected SocksResponse(SocksResponseType responseType) { - super(SocksMessageType.RESPONSE); - if (responseType == null) { - throw new NullPointerException("responseType"); - } - this.responseType = responseType; - } - - /** - * Returns socks response type - * - * @return socks response type - */ - public SocksResponseType responseType() { - return responseType; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksResponseType.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksResponseType.java deleted file mode 100755 index 50ee389b5b..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksResponseType.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.handler.codec.socks; - -/** - * Type of socks response - */ -public enum SocksResponseType { - INIT, - AUTH, - CMD, - UNKNOWN -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksSubnegotiationVersion.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksSubnegotiationVersion.java deleted file mode 100755 index ee73537909..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/SocksSubnegotiationVersion.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.handler.codec.socks; - -public enum SocksSubnegotiationVersion { - AUTH_PASSWORD((byte) 0x01), - UNKNOWN((byte) 0xff); - - private final byte b; - - SocksSubnegotiationVersion(byte b) { - this.b = b; - } - - /** - * @deprecated Use {@link #valueOf(byte)} instead. - */ - @Deprecated - public static SocksSubnegotiationVersion fromByte(byte b) { - return valueOf(b); - } - - public static SocksSubnegotiationVersion valueOf(byte b) { - for (SocksSubnegotiationVersion code : values()) { - if (code.b == b) { - return code; - } - } - return UNKNOWN; - } - - public byte byteValue() { - return b; - } -} - diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/UnknownSocksRequest.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/UnknownSocksRequest.java deleted file mode 100755 index 155935f544..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/UnknownSocksRequest.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.socks; - -import com.ai.cloud.io.netty.buffer.ByteBuf; - -/** - * An unknown socks request. - * - * @see SocksInitRequestDecoder - * @see SocksAuthRequestDecoder - * @see SocksCmdRequestDecoder - */ -public final class UnknownSocksRequest extends SocksRequest { - - public UnknownSocksRequest() { - super(SocksRequestType.UNKNOWN); - } - - @Override - public void encodeAsByteBuf(ByteBuf byteBuf) { - // NOOP - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/UnknownSocksResponse.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/UnknownSocksResponse.java deleted file mode 100755 index 245c80befb..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/UnknownSocksResponse.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.socks; - -import com.ai.cloud.io.netty.buffer.ByteBuf; - -/** - * An unknown socks response. - * - * @see SocksInitResponseDecoder - * @see SocksAuthResponseDecoder - * @see SocksCmdResponseDecoder - */ -public final class UnknownSocksResponse extends SocksResponse { - - public UnknownSocksResponse() { - super(SocksResponseType.UNKNOWN); - } - - @Override - public void encodeAsByteBuf(ByteBuf byteBuf) { - // NOOP - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/package-info.java deleted file mode 100755 index 6522ec9fde..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/socks/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * Encoder, decoder and their related message types for Socks. - */ -package com.ai.cloud.io.netty.handler.codec.socks; -// TODO: Combine decoders into one. diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/string/StringDecoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/string/StringDecoder.java deleted file mode 100755 index f9e60fade8..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/string/StringDecoder.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.string; - -import java.nio.charset.Charset; -import java.util.List; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelPipeline; -import com.ai.cloud.io.netty.channel.ChannelHandler.Sharable; -import com.ai.cloud.io.netty.handler.codec.ByteToMessageDecoder; -import com.ai.cloud.io.netty.handler.codec.DelimiterBasedFrameDecoder; -import com.ai.cloud.io.netty.handler.codec.LineBasedFrameDecoder; -import com.ai.cloud.io.netty.handler.codec.MessageToMessageDecoder; - -/** - * Decodes a received {@link ByteBuf} into a {@link String}. Please - * note that this decoder must be used with a proper {@link ByteToMessageDecoder} - * such as {@link DelimiterBasedFrameDecoder} or {@link LineBasedFrameDecoder} - * if you are using a stream-based transport such as TCP/IP. A typical setup for a - * text-based line protocol in a TCP/IP socket would be: - *
- * {@link ChannelPipeline} pipeline = ...;
- *
- * // Decoders
- * pipeline.addLast("frameDecoder", new {@link LineBasedFrameDecoder}(80));
- * pipeline.addLast("stringDecoder", new {@link StringDecoder}(CharsetUtil.UTF_8));
- *
- * // Encoder
- * pipeline.addLast("stringEncoder", new {@link StringEncoder}(CharsetUtil.UTF_8));
- * 
- * and then you can use a {@link String} instead of a {@link ByteBuf} - * as a message: - *
- * void channelRead({@link ChannelHandlerContext} ctx, {@link String} msg) {
- *     ch.write("Did you say '" + msg + "'?\n");
- * }
- * 
- */ -@Sharable -public class StringDecoder extends MessageToMessageDecoder { - - // TODO Use CharsetDecoder instead. - private final Charset charset; - - /** - * Creates a new instance with the current system character set. - */ - public StringDecoder() { - this(Charset.defaultCharset()); - } - - /** - * Creates a new instance with the specified character set. - */ - public StringDecoder(Charset charset) { - if (charset == null) { - throw new NullPointerException("charset"); - } - this.charset = charset; - } - - @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) throws Exception { - out.add(msg.toString(charset)); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/string/StringEncoder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/string/StringEncoder.java deleted file mode 100755 index 24e905add6..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/string/StringEncoder.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.codec.string; - -import java.nio.CharBuffer; -import java.nio.charset.Charset; -import java.util.List; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.ByteBufUtil; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelPipeline; -import com.ai.cloud.io.netty.channel.ChannelHandler.Sharable; -import com.ai.cloud.io.netty.handler.codec.LineBasedFrameDecoder; -import com.ai.cloud.io.netty.handler.codec.MessageToMessageEncoder; - -/** - * Encodes the requested {@link String} into a {@link ByteBuf}. - * A typical setup for a text-based line protocol in a TCP/IP socket would be: - *
- * {@link ChannelPipeline} pipeline = ...;
- *
- * // Decoders
- * pipeline.addLast("frameDecoder", new {@link LineBasedFrameDecoder}(80));
- * pipeline.addLast("stringDecoder", new {@link StringDecoder}(CharsetUtil.UTF_8));
- *
- * // Encoder
- * pipeline.addLast("stringEncoder", new {@link StringEncoder}(CharsetUtil.UTF_8));
- * 
- * and then you can use a {@link String} instead of a {@link ByteBuf} - * as a message: - *
- * void channelRead({@link ChannelHandlerContext} ctx, {@link String} msg) {
- *     ch.write("Did you say '" + msg + "'?\n");
- * }
- * 
- */ -@Sharable -public class StringEncoder extends MessageToMessageEncoder { - - // TODO Use CharsetEncoder instead. - private final Charset charset; - - /** - * Creates a new instance with the current system character set. - */ - public StringEncoder() { - this(Charset.defaultCharset()); - } - - /** - * Creates a new instance with the specified character set. - */ - public StringEncoder(Charset charset) { - if (charset == null) { - throw new NullPointerException("charset"); - } - this.charset = charset; - } - - @Override - protected void encode(ChannelHandlerContext ctx, CharSequence msg, List out) throws Exception { - if (msg.length() == 0) { - return; - } - - out.add(ByteBufUtil.encodeString(ctx.alloc(), CharBuffer.wrap(msg), charset)); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/string/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/string/package-info.java deleted file mode 100755 index 0450a53c56..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/codec/string/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * Encoder and decoder which transform a {@link java.lang.String} into a - * {@link com.ai.cloud.io.netty.buffer.ByteBuf} and vice versa. - */ -package com.ai.cloud.io.netty.handler.codec.string; diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/ipfilter/AbstractRemoteAddressFilter.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/ipfilter/AbstractRemoteAddressFilter.java deleted file mode 100755 index 9a0063efde..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/ipfilter/AbstractRemoteAddressFilter.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.ipfilter; - -import java.net.SocketAddress; - -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelFuture; -import com.ai.cloud.io.netty.channel.ChannelFutureListener; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelInboundHandlerAdapter; - -/** - * This class provides the functionality to either accept or reject new {@link Channel}s - * based on their IP address. - *

- * You should inherit from this class if you would like to implement your own IP-based filter. Basically you have to - * implement {@link #accept(ChannelHandlerContext, SocketAddress)} to decided whether you want to accept or reject - * a connection from the remote address. - *

- * Furthermore overriding {@link #channelRejected(ChannelHandlerContext, SocketAddress)} gives you the - * flexibility to respond to rejected (denied) connections. If you do not want to send a response, just have it return - * null. Take a look at {@link RuleBasedIpFilter} for details. - */ -public abstract class AbstractRemoteAddressFilter extends ChannelInboundHandlerAdapter { - - @Override - public void channelRegistered(ChannelHandlerContext ctx) throws Exception { - handleNewChannel(ctx); - ctx.fireChannelRegistered(); - } - - @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { - if (!handleNewChannel(ctx)) { - throw new IllegalStateException("cannot determine to accept or reject a channel: " + ctx.channel()); - } else { - ctx.fireChannelActive(); - } - } - - private boolean handleNewChannel(ChannelHandlerContext ctx) throws Exception { - @SuppressWarnings("unchecked") - T remoteAddress = (T) ctx.channel().remoteAddress(); - - // If the remote address is not available yet, defer the decision. - if (remoteAddress == null) { - return false; - } - - // No need to keep this handler in the pipeline anymore because the decision is going to be made now. - // Also, this will prevent the subsequent events from being handled by this handler. - ctx.pipeline().remove(this); - - if (accept(ctx, remoteAddress)) { - channelAccepted(ctx, remoteAddress); - } else { - ChannelFuture rejectedFuture = channelRejected(ctx, remoteAddress); - if (rejectedFuture != null) { - rejectedFuture.addListener(ChannelFutureListener.CLOSE); - } else { - ctx.close(); - } - } - - return true; - } - - /** - * This method is called immediately after a {@link com.ai.cloud.io.netty.channel.Channel} gets registered. - * - * @return Return true if connections from this IP address and port should be accepted. False otherwise. - */ - protected abstract boolean accept(ChannelHandlerContext ctx, T remoteAddress) throws Exception; - - /** - * This method is called if {@code remoteAddress} gets accepted by - * {@link #accept(ChannelHandlerContext, SocketAddress)}. You should override it if you would like to handle - * (e.g. respond to) accepted addresses. - */ - @SuppressWarnings("UnusedParameters") - protected void channelAccepted(ChannelHandlerContext ctx, T remoteAddress) { } - - /** - * This method is called if {@code remoteAddress} gets rejected by - * {@link #accept(ChannelHandlerContext, SocketAddress)}. You should override it if you would like to handle - * (e.g. respond to) rejected addresses. - * - * @return A {@link ChannelFuture} if you perform I/O operations, so that - * the {@link Channel} can be closed once it completes. Null otherwise. - */ - @SuppressWarnings("UnusedParameters") - protected ChannelFuture channelRejected(ChannelHandlerContext ctx, T remoteAddress) { - return null; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/ipfilter/IpFilterRule.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/ipfilter/IpFilterRule.java deleted file mode 100755 index 4696960d7c..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/ipfilter/IpFilterRule.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.ipfilter; - -import java.net.InetSocketAddress; - -/** - * Implement this interface to create new rules. - */ -public interface IpFilterRule { - /** - * @return This method should return true if remoteAddress is valid according to your criteria. False otherwise. - */ - boolean matches(InetSocketAddress remoteAddress); - - /** - * @return This method should return {@link IpFilterRuleType#ACCEPT} if all - * {@link IpFilterRule#matches(InetSocketAddress)} for which {@link #matches(InetSocketAddress)} - * returns true should the accepted. If you want to exclude all of those IP addresses then - * {@link IpFilterRuleType#REJECT} should be returned. - */ - IpFilterRuleType ruleType(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/ipfilter/IpFilterRuleType.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/ipfilter/IpFilterRuleType.java deleted file mode 100755 index 09ebd644af..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/ipfilter/IpFilterRuleType.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.ipfilter; - -/** - * Used in {@link IpFilterRule} to decide if a matching IP Address should be allowed or denied to connect. - */ -public enum IpFilterRuleType { - ACCEPT, - REJECT -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/ipfilter/IpSubnetFilterRule.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/ipfilter/IpSubnetFilterRule.java deleted file mode 100755 index 610d220370..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/ipfilter/IpSubnetFilterRule.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.ipfilter; - -import java.math.BigInteger; -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.UnknownHostException; - -/** - * Use this class to create rules for {@link RuleBasedIpFilter} that group IP addresses into subnets. - * Supports both, IPv4 and IPv6. - */ -public final class IpSubnetFilterRule implements IpFilterRule { - - private final IpFilterRule filterRule; - - public IpSubnetFilterRule(String ipAddress, int cidrPrefix, IpFilterRuleType ruleType) { - try { - filterRule = selectFilterRule(InetAddress.getByName(ipAddress), cidrPrefix, ruleType); - } catch (UnknownHostException e) { - throw new IllegalArgumentException("ipAddress", e); - } - } - - public IpSubnetFilterRule(InetAddress ipAddress, int cidrPrefix, IpFilterRuleType ruleType) { - filterRule = selectFilterRule(ipAddress, cidrPrefix, ruleType); - } - - private static IpFilterRule selectFilterRule(InetAddress ipAddress, int cidrPrefix, IpFilterRuleType ruleType) { - if (ipAddress == null) { - throw new NullPointerException("ipAddress"); - } - - if (ruleType == null) { - throw new NullPointerException("ruleType"); - } - - if (ipAddress instanceof Inet4Address) { - return new Ip4SubnetFilterRule((Inet4Address) ipAddress, cidrPrefix, ruleType); - } else if (ipAddress instanceof Inet6Address) { - return new Ip6SubnetFilterRule((Inet6Address) ipAddress, cidrPrefix, ruleType); - } else { - throw new IllegalArgumentException("Only IPv4 and IPv6 addresses are supported"); - } - } - - @Override - public boolean matches(InetSocketAddress remoteAddress) { - return filterRule.matches(remoteAddress); - } - - @Override - public IpFilterRuleType ruleType() { - return filterRule.ruleType(); - } - - private static final class Ip4SubnetFilterRule implements IpFilterRule { - - private final int networkAddress; - private final int subnetMask; - private final IpFilterRuleType ruleType; - - private Ip4SubnetFilterRule(Inet4Address ipAddress, int cidrPrefix, IpFilterRuleType ruleType) { - if (cidrPrefix < 0 || cidrPrefix > 32) { - throw new IllegalArgumentException(String.format("IPv4 requires the subnet prefix to be in range of " + - "[0,32]. The prefix was: %d", cidrPrefix)); - } - - subnetMask = prefixToSubnetMask(cidrPrefix); - networkAddress = ipToInt(ipAddress) & subnetMask; - this.ruleType = ruleType; - } - - @Override - public boolean matches(InetSocketAddress remoteAddress) { - int ipAddress = ipToInt((Inet4Address) remoteAddress.getAddress()); - - return (ipAddress & subnetMask) == networkAddress; - } - - @Override - public IpFilterRuleType ruleType() { - return ruleType; - } - - private static int ipToInt(Inet4Address ipAddress) { - byte[] octets = ipAddress.getAddress(); - assert octets.length == 4; - - return (octets[0] & 0xff) << 24 | - (octets[1] & 0xff) << 16 | - (octets[2] & 0xff) << 8 | - octets[3] & 0xff; - } - - private static int prefixToSubnetMask(int cidrPrefix) { - /** - * Perform the shift on a long and downcast it to int afterwards. - * This is necessary to handle a cidrPrefix of zero correctly. - * The left shift operator on an int only uses the five least - * significant bits of the right-hand operand. Thus -1 << 32 evaluates - * to -1 instead of 0. The left shift operator applied on a long - * uses the six least significant bits. - * - * Also see https://github.com/netty/netty/issues/2767 - */ - return (int) ((-1L << 32 - cidrPrefix) & 0xffffffff); - } - } - - private static final class Ip6SubnetFilterRule implements IpFilterRule { - - private static final BigInteger MINUS_ONE = BigInteger.valueOf(-1); - - private final BigInteger networkAddress; - private final BigInteger subnetMask; - private final IpFilterRuleType ruleType; - - private Ip6SubnetFilterRule(Inet6Address ipAddress, int cidrPrefix, IpFilterRuleType ruleType) { - if (cidrPrefix < 0 || cidrPrefix > 128) { - throw new IllegalArgumentException(String.format("IPv6 requires the subnet prefix to be in range of " + - "[0,128]. The prefix was: %d", cidrPrefix)); - } - - subnetMask = prefixToSubnetMask(cidrPrefix); - networkAddress = ipToInt(ipAddress).and(subnetMask); - this.ruleType = ruleType; - } - - @Override - public boolean matches(InetSocketAddress remoteAddress) { - BigInteger ipAddress = ipToInt((Inet6Address) remoteAddress.getAddress()); - - return ipAddress.and(subnetMask).equals(networkAddress); - } - - @Override - public IpFilterRuleType ruleType() { - return ruleType; - } - - private static BigInteger ipToInt(Inet6Address ipAddress) { - byte[] octets = ipAddress.getAddress(); - assert octets.length == 16; - - return new BigInteger(octets); - } - - private static BigInteger prefixToSubnetMask(int cidrPrefix) { - return MINUS_ONE.shiftLeft(128 - cidrPrefix); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/ipfilter/RuleBasedIpFilter.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/ipfilter/RuleBasedIpFilter.java deleted file mode 100755 index 6f6b6276af..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/ipfilter/RuleBasedIpFilter.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.ipfilter; - -import java.net.InetSocketAddress; -import java.net.SocketAddress; - -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelHandler.Sharable; - -/** - * This class allows one to filter new {@link Channel}s based on the - * {@link IpFilterRule}s passed to its constructor. If no rules are provided, all connections - * will be accepted. - * - * If you would like to explicitly take action on rejected {@link Channel}s, you should override - * {@link #channelRejected(ChannelHandlerContext, SocketAddress)}. - */ -@Sharable -public class RuleBasedIpFilter extends AbstractRemoteAddressFilter { - - private final IpFilterRule[] rules; - - public RuleBasedIpFilter(IpFilterRule... rules) { - if (rules == null) { - throw new NullPointerException("rules"); - } - - this.rules = rules; - } - - @Override - protected boolean accept(ChannelHandlerContext ctx, InetSocketAddress remoteAddress) throws Exception { - for (IpFilterRule rule : rules) { - if (rule == null) { - break; - } - - if (rule.matches(remoteAddress)) { - return rule.ruleType() == IpFilterRuleType.ACCEPT; - } - } - - return true; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/ipfilter/UniqueIpFilter.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/ipfilter/UniqueIpFilter.java deleted file mode 100755 index 5cb23da212..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/ipfilter/UniqueIpFilter.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.ipfilter; - -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.util.Set; - -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelFuture; -import com.ai.cloud.io.netty.channel.ChannelFutureListener; -import com.ai.cloud.io.netty.channel.ChannelHandler; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.util.internal.ConcurrentSet; - -/** - * This class allows one to ensure that at all times for every IP address there is at most one - * {@link Channel} connected to the server. - */ -@ChannelHandler.Sharable -public class UniqueIpFilter extends AbstractRemoteAddressFilter { - - private final Set connected = new ConcurrentSet(); - - @Override - protected boolean accept(ChannelHandlerContext ctx, InetSocketAddress remoteAddress) throws Exception { - final InetAddress remoteIp = remoteAddress.getAddress(); - if (connected.contains(remoteIp)) { - return false; - } else { - connected.add(remoteIp); - ctx.channel().closeFuture().addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - connected.remove(remoteIp); - } - }); - return true; - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/ipfilter/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/ipfilter/package-info.java deleted file mode 100755 index 963772107e..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/ipfilter/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * Package to filter IP addresses (allow/deny). - */ -package com.ai.cloud.io.netty.handler.ipfilter; diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/logging/LogLevel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/logging/LogLevel.java deleted file mode 100755 index 8b6c36a6d3..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/logging/LogLevel.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.logging; - -import com.ai.cloud.io.netty.util.internal.logging.InternalLogLevel; - -public enum LogLevel { - TRACE(InternalLogLevel.TRACE), - DEBUG(InternalLogLevel.DEBUG), - INFO(InternalLogLevel.INFO), - WARN(InternalLogLevel.WARN), - ERROR(InternalLogLevel.ERROR); - - private final InternalLogLevel internalLevel; - - LogLevel(InternalLogLevel internalLevel) { - this.internalLevel = internalLevel; - } - - InternalLogLevel toInternalLevel() { - return internalLevel; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/logging/LoggingHandler.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/logging/LoggingHandler.java deleted file mode 100755 index fde59f0839..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/logging/LoggingHandler.java +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.logging; - -import java.net.SocketAddress; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.ByteBufHolder; -import com.ai.cloud.io.netty.channel.ChannelDuplexHandler; -import com.ai.cloud.io.netty.channel.ChannelHandler; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelPromise; -import com.ai.cloud.io.netty.channel.ChannelHandler.Sharable; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogLevel; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -import static com.ai.cloud.io.netty.buffer.ByteBufUtil.appendPrettyHexDump; -import static com.ai.cloud.io.netty.util.internal.StringUtil.NEWLINE; - -/** - * A {@link ChannelHandler} that logs all events using a logging framework. - * By default, all events are logged at DEBUG level. - */ -@Sharable -public class LoggingHandler extends ChannelDuplexHandler { - - private static final LogLevel DEFAULT_LEVEL = LogLevel.DEBUG; - - protected final InternalLogger logger; - protected final InternalLogLevel internalLevel; - - private final LogLevel level; - - /** - * Creates a new instance whose logger name is the fully qualified class - * name of the instance with hex dump enabled. - */ - public LoggingHandler() { - this(DEFAULT_LEVEL); - } - - /** - * Creates a new instance whose logger name is the fully qualified class - * name of the instance. - * - * @param level the log level - */ - public LoggingHandler(LogLevel level) { - if (level == null) { - throw new NullPointerException("level"); - } - - logger = InternalLoggerFactory.getInstance(getClass()); - this.level = level; - internalLevel = level.toInternalLevel(); - } - - /** - * Creates a new instance with the specified logger name and with hex dump - * enabled. - */ - public LoggingHandler(Class clazz) { - this(clazz, DEFAULT_LEVEL); - } - - /** - * Creates a new instance with the specified logger name. - * - * @param level the log level - */ - public LoggingHandler(Class clazz, LogLevel level) { - if (clazz == null) { - throw new NullPointerException("clazz"); - } - if (level == null) { - throw new NullPointerException("level"); - } - logger = InternalLoggerFactory.getInstance(clazz); - this.level = level; - internalLevel = level.toInternalLevel(); - } - - /** - * Creates a new instance with the specified logger name. - */ - public LoggingHandler(String name) { - this(name, DEFAULT_LEVEL); - } - - /** - * Creates a new instance with the specified logger name. - * - * @param level the log level - */ - public LoggingHandler(String name, LogLevel level) { - if (name == null) { - throw new NullPointerException("name"); - } - if (level == null) { - throw new NullPointerException("level"); - } - logger = InternalLoggerFactory.getInstance(name); - this.level = level; - internalLevel = level.toInternalLevel(); - } - - /** - * Returns the {@link LogLevel} that this handler uses to log - */ - public LogLevel level() { - return level; - } - - protected String format(ChannelHandlerContext ctx, String message) { - String chStr = ctx.channel().toString(); - return new StringBuilder(chStr.length() + message.length() + 1) - .append(chStr) - .append(' ') - .append(message) - .toString(); - } - - @Override - public void channelRegistered(ChannelHandlerContext ctx) - throws Exception { - if (logger.isEnabled(internalLevel)) { - logger.log(internalLevel, format(ctx, "REGISTERED")); - } - super.channelRegistered(ctx); - } - - @Override - public void channelUnregistered(ChannelHandlerContext ctx) - throws Exception { - if (logger.isEnabled(internalLevel)) { - logger.log(internalLevel, format(ctx, "UNREGISTERED")); - } - super.channelUnregistered(ctx); - } - - @Override - public void channelActive(ChannelHandlerContext ctx) - throws Exception { - if (logger.isEnabled(internalLevel)) { - logger.log(internalLevel, format(ctx, "ACTIVE")); - } - super.channelActive(ctx); - } - - @Override - public void channelInactive(ChannelHandlerContext ctx) - throws Exception { - if (logger.isEnabled(internalLevel)) { - logger.log(internalLevel, format(ctx, "INACTIVE")); - } - super.channelInactive(ctx); - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, - Throwable cause) throws Exception { - if (logger.isEnabled(internalLevel)) { - logger.log(internalLevel, format(ctx, "EXCEPTION: " + cause), cause); - } - super.exceptionCaught(ctx, cause); - } - - @Override - public void userEventTriggered(ChannelHandlerContext ctx, - Object evt) throws Exception { - if (logger.isEnabled(internalLevel)) { - logger.log(internalLevel, format(ctx, "USER_EVENT: " + evt)); - } - super.userEventTriggered(ctx, evt); - } - - @Override - public void bind(ChannelHandlerContext ctx, - SocketAddress localAddress, ChannelPromise promise) throws Exception { - if (logger.isEnabled(internalLevel)) { - logger.log(internalLevel, format(ctx, "BIND(" + localAddress + ')')); - } - super.bind(ctx, localAddress, promise); - } - - @Override - public void connect(ChannelHandlerContext ctx, - SocketAddress remoteAddress, SocketAddress localAddress, - ChannelPromise promise) throws Exception { - if (logger.isEnabled(internalLevel)) { - logger.log(internalLevel, format(ctx, "CONNECT(" + remoteAddress + ", " + localAddress + ')')); - } - super.connect(ctx, remoteAddress, localAddress, promise); - } - - @Override - public void disconnect(ChannelHandlerContext ctx, - ChannelPromise promise) throws Exception { - if (logger.isEnabled(internalLevel)) { - logger.log(internalLevel, format(ctx, "DISCONNECT()")); - } - super.disconnect(ctx, promise); - } - - @Override - public void close(ChannelHandlerContext ctx, - ChannelPromise promise) throws Exception { - if (logger.isEnabled(internalLevel)) { - logger.log(internalLevel, format(ctx, "CLOSE()")); - } - super.close(ctx, promise); - } - - @Override - public void deregister(ChannelHandlerContext ctx, - ChannelPromise promise) throws Exception { - if (logger.isEnabled(internalLevel)) { - logger.log(internalLevel, format(ctx, "DEREGISTER()")); - } - super.deregister(ctx, promise); - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - logMessage(ctx, "RECEIVED", msg); - ctx.fireChannelRead(msg); - } - - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - logMessage(ctx, "WRITE", msg); - ctx.write(msg, promise); - } - - @Override - public void flush(ChannelHandlerContext ctx) throws Exception { - if (logger.isEnabled(internalLevel)) { - logger.log(internalLevel, format(ctx, "FLUSH")); - } - ctx.flush(); - } - - private void logMessage(ChannelHandlerContext ctx, String eventName, Object msg) { - if (logger.isEnabled(internalLevel)) { - logger.log(internalLevel, format(ctx, formatMessage(eventName, msg))); - } - } - - protected String formatMessage(String eventName, Object msg) { - if (msg instanceof ByteBuf) { - return formatByteBuf(eventName, (ByteBuf) msg); - } else if (msg instanceof ByteBufHolder) { - return formatByteBufHolder(eventName, (ByteBufHolder) msg); - } else { - return formatNonByteBuf(eventName, msg); - } - } - - /** - * Returns a String which contains all details to log the {@link ByteBuf} - */ - protected String formatByteBuf(String eventName, ByteBuf msg) { - int length = msg.readableBytes(); - if (length == 0) { - StringBuilder buf = new StringBuilder(eventName.length() + 4); - buf.append(eventName).append(": 0B"); - return buf.toString(); - } else { - int rows = length / 16 + (length % 15 == 0? 0 : 1) + 4; - StringBuilder buf = new StringBuilder(eventName.length() + 2 + 10 + 1 + 2 + rows * 80); - - buf.append(eventName).append(": ").append(length).append('B').append(NEWLINE); - appendPrettyHexDump(buf, msg); - - return buf.toString(); - } - } - - /** - * Returns a String which contains all details to log the {@link Object} - */ - protected String formatNonByteBuf(String eventName, Object msg) { - return eventName + ": " + msg; - } - - /** - * Returns a String which contains all details to log the {@link ByteBufHolder}. - * - * By default this method just delegates to {@link #formatByteBuf(String, ByteBuf)}, - * using the content of the {@link ByteBufHolder}. Sub-classes may override this. - */ - protected String formatByteBufHolder(String eventName, ByteBufHolder msg) { - String msgStr = msg.toString(); - ByteBuf content = msg.content(); - int length = content.readableBytes(); - if (length == 0) { - StringBuilder buf = new StringBuilder(eventName.length() + 2 + msgStr.length() + 4); - buf.append(eventName).append(", ").append(msgStr).append(", 0B"); - return buf.toString(); - } else { - int rows = length / 16 + (length % 15 == 0? 0 : 1) + 4; - StringBuilder buf = new StringBuilder( - eventName.length() + 2 + msgStr.length() + 2 + 10 + 1 + 2 + rows * 80); - - buf.append(eventName).append(": ") - .append(msgStr).append(", ").append(length).append('B').append(NEWLINE); - appendPrettyHexDump(buf, content); - - return buf.toString(); - } - } -} - diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/logging/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/logging/package-info.java deleted file mode 100755 index a2bb97b7c1..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/logging/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * Logs a {@link io.netty.channel.ChannelEvent} for debugging purpose. - */ -package com.ai.cloud.io.netty.handler.logging; diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/stream/ChunkedFile.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/stream/ChunkedFile.java deleted file mode 100755 index 3b11be1123..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/stream/ChunkedFile.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.stream; - -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.FileRegion; - -/** - * A {@link ChunkedInput} that fetches data from a file chunk by chunk. - *

- * If your operating system supports - * zero-copy file transfer - * such as {@code sendfile()}, you might want to use {@link FileRegion} instead. - */ -public class ChunkedFile implements ChunkedInput { - - private final RandomAccessFile file; - private final long startOffset; - private final long endOffset; - private final int chunkSize; - private long offset; - - /** - * Creates a new instance that fetches data from the specified file. - */ - public ChunkedFile(File file) throws IOException { - this(file, ChunkedStream.DEFAULT_CHUNK_SIZE); - } - - /** - * Creates a new instance that fetches data from the specified file. - * - * @param chunkSize the number of bytes to fetch on each - * {@link #readChunk(ChannelHandlerContext)} call - */ - public ChunkedFile(File file, int chunkSize) throws IOException { - this(new RandomAccessFile(file, "r"), chunkSize); - } - - /** - * Creates a new instance that fetches data from the specified file. - */ - public ChunkedFile(RandomAccessFile file) throws IOException { - this(file, ChunkedStream.DEFAULT_CHUNK_SIZE); - } - - /** - * Creates a new instance that fetches data from the specified file. - * - * @param chunkSize the number of bytes to fetch on each - * {@link #readChunk(ChannelHandlerContext)} call - */ - public ChunkedFile(RandomAccessFile file, int chunkSize) throws IOException { - this(file, 0, file.length(), chunkSize); - } - - /** - * Creates a new instance that fetches data from the specified file. - * - * @param offset the offset of the file where the transfer begins - * @param length the number of bytes to transfer - * @param chunkSize the number of bytes to fetch on each - * {@link #readChunk(ChannelHandlerContext)} call - */ - public ChunkedFile(RandomAccessFile file, long offset, long length, int chunkSize) throws IOException { - if (file == null) { - throw new NullPointerException("file"); - } - if (offset < 0) { - throw new IllegalArgumentException( - "offset: " + offset + " (expected: 0 or greater)"); - } - if (length < 0) { - throw new IllegalArgumentException( - "length: " + length + " (expected: 0 or greater)"); - } - if (chunkSize <= 0) { - throw new IllegalArgumentException( - "chunkSize: " + chunkSize + - " (expected: a positive integer)"); - } - - this.file = file; - this.offset = startOffset = offset; - endOffset = offset + length; - this.chunkSize = chunkSize; - - file.seek(offset); - } - - /** - * Returns the offset in the file where the transfer began. - */ - public long startOffset() { - return startOffset; - } - - /** - * Returns the offset in the file where the transfer will end. - */ - public long endOffset() { - return endOffset; - } - - /** - * Returns the offset in the file where the transfer is happening currently. - */ - public long currentOffset() { - return offset; - } - - @Override - public boolean isEndOfInput() throws Exception { - return !(offset < endOffset && file.getChannel().isOpen()); - } - - @Override - public void close() throws Exception { - file.close(); - } - - @Override - public ByteBuf readChunk(ChannelHandlerContext ctx) throws Exception { - long offset = this.offset; - if (offset >= endOffset) { - return null; - } - - int chunkSize = (int) Math.min(this.chunkSize, endOffset - offset); - // Check if the buffer is backed by an byte array. If so we can optimize it a bit an safe a copy - - ByteBuf buf = ctx.alloc().heapBuffer(chunkSize); - boolean release = true; - try { - file.readFully(buf.array(), buf.arrayOffset(), chunkSize); - buf.writerIndex(chunkSize); - this.offset = offset + chunkSize; - release = false; - return buf; - } finally { - if (release) { - buf.release(); - } - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/stream/ChunkedInput.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/stream/ChunkedInput.java deleted file mode 100755 index b4c5697d06..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/stream/ChunkedInput.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.stream; - - -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; - -/** - * A data stream of indefinite length which is consumed by {@link ChunkedWriteHandler}. - */ -public interface ChunkedInput { - - /** - * Return {@code true} if and only if there is no data left in the stream - * and the stream has reached at its end. - */ - boolean isEndOfInput() throws Exception; - - /** - * Releases the resources associated with the input. - */ - void close() throws Exception; - - /** - * Fetches a chunked data from the stream. Once this method returns the last chunk - * and thus the stream has reached at its end, any subsequent {@link #isEndOfInput()} - * call must return {@code true}. - * - * @return the fetched chunk. - * {@code null} if there is no data left in the stream. - * Please note that {@code null} does not necessarily mean that the - * stream has reached at its end. In a slow stream, the next chunk - * might be unavailable just momentarily. - */ - B readChunk(ChannelHandlerContext ctx) throws Exception; - -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/stream/ChunkedNioFile.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/stream/ChunkedNioFile.java deleted file mode 100755 index 768e777f51..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/stream/ChunkedNioFile.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.stream; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.nio.channels.FileChannel; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.FileRegion; - -/** - * A {@link ChunkedInput} that fetches data from a file chunk by chunk using - * NIO {@link FileChannel}. - *

- * If your operating system supports - * zero-copy file transfer - * such as {@code sendfile()}, you might want to use {@link FileRegion} instead. - */ -public class ChunkedNioFile implements ChunkedInput { - - private final FileChannel in; - private final long startOffset; - private final long endOffset; - private final int chunkSize; - private long offset; - - /** - * Creates a new instance that fetches data from the specified file. - */ - public ChunkedNioFile(File in) throws IOException { - this(new FileInputStream(in).getChannel()); - } - - /** - * Creates a new instance that fetches data from the specified file. - * - * @param chunkSize the number of bytes to fetch on each - * {@link #readChunk(ChannelHandlerContext)} call - */ - public ChunkedNioFile(File in, int chunkSize) throws IOException { - this(new FileInputStream(in).getChannel(), chunkSize); - } - - /** - * Creates a new instance that fetches data from the specified file. - */ - public ChunkedNioFile(FileChannel in) throws IOException { - this(in, ChunkedStream.DEFAULT_CHUNK_SIZE); - } - - /** - * Creates a new instance that fetches data from the specified file. - * - * @param chunkSize the number of bytes to fetch on each - * {@link #readChunk(ChannelHandlerContext)} call - */ - public ChunkedNioFile(FileChannel in, int chunkSize) throws IOException { - this(in, 0, in.size(), chunkSize); - } - - /** - * Creates a new instance that fetches data from the specified file. - * - * @param offset the offset of the file where the transfer begins - * @param length the number of bytes to transfer - * @param chunkSize the number of bytes to fetch on each - * {@link #readChunk(ChannelHandlerContext)} call - */ - public ChunkedNioFile(FileChannel in, long offset, long length, int chunkSize) - throws IOException { - if (in == null) { - throw new NullPointerException("in"); - } - if (offset < 0) { - throw new IllegalArgumentException( - "offset: " + offset + " (expected: 0 or greater)"); - } - if (length < 0) { - throw new IllegalArgumentException( - "length: " + length + " (expected: 0 or greater)"); - } - if (chunkSize <= 0) { - throw new IllegalArgumentException( - "chunkSize: " + chunkSize + - " (expected: a positive integer)"); - } - - if (offset != 0) { - in.position(offset); - } - this.in = in; - this.chunkSize = chunkSize; - this.offset = startOffset = offset; - endOffset = offset + length; - } - - /** - * Returns the offset in the file where the transfer began. - */ - public long startOffset() { - return startOffset; - } - - /** - * Returns the offset in the file where the transfer will end. - */ - public long endOffset() { - return endOffset; - } - - /** - * Returns the offset in the file where the transfer is happening currently. - */ - public long currentOffset() { - return offset; - } - - @Override - public boolean isEndOfInput() throws Exception { - return !(offset < endOffset && in.isOpen()); - } - - @Override - public void close() throws Exception { - in.close(); - } - - @Override - public ByteBuf readChunk(ChannelHandlerContext ctx) throws Exception { - long offset = this.offset; - if (offset >= endOffset) { - return null; - } - - int chunkSize = (int) Math.min(this.chunkSize, endOffset - offset); - ByteBuf buffer = ctx.alloc().buffer(chunkSize); - boolean release = true; - try { - int readBytes = 0; - for (;;) { - int localReadBytes = buffer.writeBytes(in, chunkSize - readBytes); - if (localReadBytes < 0) { - break; - } - readBytes += localReadBytes; - if (readBytes == chunkSize) { - break; - } - } - this.offset += readBytes; - release = false; - return buffer; - } finally { - if (release) { - buffer.release(); - } - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/stream/ChunkedNioStream.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/stream/ChunkedNioStream.java deleted file mode 100755 index 3ac1e9b8f6..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/stream/ChunkedNioStream.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.stream; - -import java.nio.ByteBuffer; -import java.nio.channels.ReadableByteChannel; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; - -/** - * A {@link ChunkedInput} that fetches data from a {@link ReadableByteChannel} - * chunk by chunk. Please note that the {@link ReadableByteChannel} must - * operate in blocking mode. Non-blocking mode channels are not supported. - */ -public class ChunkedNioStream implements ChunkedInput { - - private final ReadableByteChannel in; - - private final int chunkSize; - private long offset; - - /** - * Associated ByteBuffer - */ - private final ByteBuffer byteBuffer; - - /** - * Creates a new instance that fetches data from the specified channel. - */ - public ChunkedNioStream(ReadableByteChannel in) { - this(in, ChunkedStream.DEFAULT_CHUNK_SIZE); - } - - /** - * Creates a new instance that fetches data from the specified channel. - * - * @param chunkSize the number of bytes to fetch on each - * {@link #readChunk(ChannelHandlerContext)} call - */ - public ChunkedNioStream(ReadableByteChannel in, int chunkSize) { - if (in == null) { - throw new NullPointerException("in"); - } - if (chunkSize <= 0) { - throw new IllegalArgumentException("chunkSize: " + chunkSize + - " (expected: a positive integer)"); - } - this.in = in; - offset = 0; - this.chunkSize = chunkSize; - byteBuffer = ByteBuffer.allocate(chunkSize); - } - - /** - * Returns the number of transferred bytes. - */ - public long transferredBytes() { - return offset; - } - - @Override - public boolean isEndOfInput() throws Exception { - if (byteBuffer.position() > 0) { - // A previous read was not over, so there is a next chunk in the buffer at least - return false; - } - if (in.isOpen()) { - // Try to read a new part, and keep this part (no rewind) - int b = in.read(byteBuffer); - if (b < 0) { - return true; - } else { - offset += b; - return false; - } - } - return true; - } - - @Override - public void close() throws Exception { - in.close(); - } - - @Override - public ByteBuf readChunk(ChannelHandlerContext ctx) throws Exception { - if (isEndOfInput()) { - return null; - } - // buffer cannot be not be empty from there - int readBytes = byteBuffer.position(); - for (;;) { - int localReadBytes = in.read(byteBuffer); - if (localReadBytes < 0) { - break; - } - readBytes += localReadBytes; - offset += localReadBytes; - if (readBytes == chunkSize) { - break; - } - } - byteBuffer.flip(); - boolean release = true; - ByteBuf buffer = ctx.alloc().buffer(byteBuffer.remaining()); - try { - buffer.writeBytes(byteBuffer); - byteBuffer.clear(); - release = false; - return buffer; - } finally { - if (release) { - buffer.release(); - } - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/stream/ChunkedStream.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/stream/ChunkedStream.java deleted file mode 100755 index a778c74192..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/stream/ChunkedStream.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.stream; - -import java.io.InputStream; -import java.io.PushbackInputStream; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; - -/** - * A {@link ChunkedInput} that fetches data from an {@link InputStream} chunk by - * chunk. - *

- * Please note that the {@link InputStream} instance that feeds data into - * {@link ChunkedStream} must implement {@link InputStream#available()} as - * accurately as possible, rather than using the default implementation. - * Otherwise, {@link ChunkedStream} will generate many too small chunks or - * block unnecessarily often. - */ -public class ChunkedStream implements ChunkedInput { - - static final int DEFAULT_CHUNK_SIZE = 8192; - - private final PushbackInputStream in; - private final int chunkSize; - private long offset; - private boolean closed; - - /** - * Creates a new instance that fetches data from the specified stream. - */ - public ChunkedStream(InputStream in) { - this(in, DEFAULT_CHUNK_SIZE); - } - - /** - * Creates a new instance that fetches data from the specified stream. - * - * @param chunkSize the number of bytes to fetch on each - * {@link #readChunk(ChannelHandlerContext)} call - */ - public ChunkedStream(InputStream in, int chunkSize) { - if (in == null) { - throw new NullPointerException("in"); - } - if (chunkSize <= 0) { - throw new IllegalArgumentException( - "chunkSize: " + chunkSize + - " (expected: a positive integer)"); - } - - if (in instanceof PushbackInputStream) { - this.in = (PushbackInputStream) in; - } else { - this.in = new PushbackInputStream(in); - } - this.chunkSize = chunkSize; - } - - /** - * Returns the number of transferred bytes. - */ - public long transferredBytes() { - return offset; - } - - @Override - public boolean isEndOfInput() throws Exception { - if (closed) { - return true; - } - - int b = in.read(); - if (b < 0) { - return true; - } else { - in.unread(b); - return false; - } - } - - @Override - public void close() throws Exception { - closed = true; - in.close(); - } - - @Override - public ByteBuf readChunk(ChannelHandlerContext ctx) throws Exception { - if (isEndOfInput()) { - return null; - } - - final int availableBytes = in.available(); - final int chunkSize; - if (availableBytes <= 0) { - chunkSize = this.chunkSize; - } else { - chunkSize = Math.min(this.chunkSize, in.available()); - } - - boolean release = true; - ByteBuf buffer = ctx.alloc().buffer(chunkSize); - try { - // transfer to buffer - offset += buffer.writeBytes(in, chunkSize); - release = false; - return buffer; - } finally { - if (release) { - buffer.release(); - } - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/stream/ChunkedWriteHandler.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/stream/ChunkedWriteHandler.java deleted file mode 100755 index d4a9a538e0..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/stream/ChunkedWriteHandler.java +++ /dev/null @@ -1,379 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.stream; - -import java.nio.channels.ClosedChannelException; -import java.util.ArrayDeque; -import java.util.Queue; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.ByteBufHolder; -import com.ai.cloud.io.netty.buffer.Unpooled; -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelDuplexHandler; -import com.ai.cloud.io.netty.channel.ChannelFuture; -import com.ai.cloud.io.netty.channel.ChannelFutureListener; -import com.ai.cloud.io.netty.channel.ChannelHandler; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelPipeline; -import com.ai.cloud.io.netty.channel.ChannelProgressivePromise; -import com.ai.cloud.io.netty.channel.ChannelPromise; -import com.ai.cloud.io.netty.util.ReferenceCountUtil; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * A {@link ChannelHandler} that adds support for writing a large data stream - * asynchronously neither spending a lot of memory nor getting - * {@link OutOfMemoryError}. Large data streaming such as file - * transfer requires complicated state management in a {@link ChannelHandler} - * implementation. {@link ChunkedWriteHandler} manages such complicated states - * so that you can send a large data stream without difficulties. - *

- * To use {@link ChunkedWriteHandler} in your application, you have to insert - * a new {@link ChunkedWriteHandler} instance: - *

- * {@link ChannelPipeline} p = ...;
- * p.addLast("streamer", new {@link ChunkedWriteHandler}());
- * p.addLast("handler", new MyHandler());
- * 
- * Once inserted, you can write a {@link ChunkedInput} so that the - * {@link ChunkedWriteHandler} can pick it up and fetch the content of the - * stream chunk by chunk and write the fetched chunk downstream: - *
- * {@link Channel} ch = ...;
- * ch.write(new {@link ChunkedFile}(new File("video.mkv"));
- * 
- * - *

Sending a stream which generates a chunk intermittently

- * - * Some {@link ChunkedInput} generates a chunk on a certain event or timing. - * Such {@link ChunkedInput} implementation often returns {@code null} on - * {@link ChunkedInput#readChunk(ChannelHandlerContext)}, resulting in the indefinitely suspended - * transfer. To resume the transfer when a new chunk is available, you have to - * call {@link #resumeTransfer()}. - */ -public class ChunkedWriteHandler - extends ChannelDuplexHandler { - - private static final InternalLogger logger = - InternalLoggerFactory.getInstance(ChunkedWriteHandler.class); - - private final Queue queue = new ArrayDeque(); - private volatile ChannelHandlerContext ctx; - private PendingWrite currentWrite; - - public ChunkedWriteHandler() { - } - - /** - * @deprecated use {@link #ChunkedWriteHandler()} - */ - @Deprecated - public ChunkedWriteHandler(int maxPendingWrites) { - if (maxPendingWrites <= 0) { - throw new IllegalArgumentException( - "maxPendingWrites: " + maxPendingWrites + " (expected: > 0)"); - } - } - - @Override - public void handlerAdded(ChannelHandlerContext ctx) throws Exception { - this.ctx = ctx; - } - - /** - * Continues to fetch the chunks from the input. - */ - public void resumeTransfer() { - final ChannelHandlerContext ctx = this.ctx; - if (ctx == null) { - return; - } - if (ctx.executor().inEventLoop()) { - try { - doFlush(ctx); - } catch (Exception e) { - if (logger.isWarnEnabled()) { - logger.warn("Unexpected exception while sending chunks.", e); - } - } - } else { - // let the transfer resume on the next event loop round - ctx.executor().execute(new Runnable() { - - @Override - public void run() { - try { - doFlush(ctx); - } catch (Exception e) { - if (logger.isWarnEnabled()) { - logger.warn("Unexpected exception while sending chunks.", e); - } - } - } - }); - } - } - - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - queue.add(new PendingWrite(msg, promise)); - } - - @Override - public void flush(ChannelHandlerContext ctx) throws Exception { - if (!doFlush(ctx)) { - // Make sure to flush at least once. - ctx.flush(); - } - } - - @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { - doFlush(ctx); - ctx.fireChannelInactive(); - } - - @Override - public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception { - if (ctx.channel().isWritable()) { - // channel is writable again try to continue flushing - doFlush(ctx); - } - ctx.fireChannelWritabilityChanged(); - } - - private void discard(Throwable cause) { - for (;;) { - PendingWrite currentWrite = this.currentWrite; - - if (this.currentWrite == null) { - currentWrite = queue.poll(); - } else { - this.currentWrite = null; - } - - if (currentWrite == null) { - break; - } - Object message = currentWrite.msg; - if (message instanceof ChunkedInput) { - ChunkedInput in = (ChunkedInput) message; - try { - if (!in.isEndOfInput()) { - if (cause == null) { - cause = new ClosedChannelException(); - } - currentWrite.fail(cause); - } else { - currentWrite.success(); - } - closeInput(in); - } catch (Exception e) { - currentWrite.fail(e); - logger.warn(ChunkedInput.class.getSimpleName() + ".isEndOfInput() failed", e); - closeInput(in); - } - } else { - if (cause == null) { - cause = new ClosedChannelException(); - } - currentWrite.fail(cause); - } - } - } - - private boolean doFlush(final ChannelHandlerContext ctx) throws Exception { - final Channel channel = ctx.channel(); - if (!channel.isActive()) { - discard(null); - return false; - } - - boolean flushed = false; - while (channel.isWritable()) { - if (currentWrite == null) { - currentWrite = queue.poll(); - } - - if (currentWrite == null) { - break; - } - final PendingWrite currentWrite = this.currentWrite; - final Object pendingMessage = currentWrite.msg; - - if (pendingMessage instanceof ChunkedInput) { - final ChunkedInput chunks = (ChunkedInput) pendingMessage; - boolean endOfInput; - boolean suspend; - Object message = null; - try { - message = chunks.readChunk(ctx); - endOfInput = chunks.isEndOfInput(); - - if (message == null) { - // No need to suspend when reached at the end. - suspend = !endOfInput; - } else { - suspend = false; - } - } catch (final Throwable t) { - this.currentWrite = null; - - if (message != null) { - ReferenceCountUtil.release(message); - } - - currentWrite.fail(t); - closeInput(chunks); - break; - } - - if (suspend) { - // ChunkedInput.nextChunk() returned null and it has - // not reached at the end of input. Let's wait until - // more chunks arrive. Nothing to write or notify. - break; - } - - if (message == null) { - // If message is null write an empty ByteBuf. - // See https://github.com/netty/netty/issues/1671 - message = Unpooled.EMPTY_BUFFER; - } - - final int amount = amount(message); - ChannelFuture f = ctx.write(message); - if (endOfInput) { - this.currentWrite = null; - - // Register a listener which will close the input once the write is complete. - // This is needed because the Chunk may have some resource bound that can not - // be closed before its not written. - // - // See https://github.com/netty/netty/issues/303 - f.addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - currentWrite.progress(amount); - currentWrite.success(); - closeInput(chunks); - } - }); - } else if (channel.isWritable()) { - f.addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - if (!future.isSuccess()) { - closeInput((ChunkedInput) pendingMessage); - currentWrite.fail(future.cause()); - } else { - currentWrite.progress(amount); - } - } - }); - } else { - f.addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - if (!future.isSuccess()) { - closeInput((ChunkedInput) pendingMessage); - currentWrite.fail(future.cause()); - } else { - currentWrite.progress(amount); - if (channel.isWritable()) { - resumeTransfer(); - } - } - } - }); - } - } else { - ctx.write(pendingMessage, currentWrite.promise); - this.currentWrite = null; - } - - // Always need to flush - ctx.flush(); - flushed = true; - - if (!channel.isActive()) { - discard(new ClosedChannelException()); - break; - } - } - - return flushed; - } - - static void closeInput(ChunkedInput chunks) { - try { - chunks.close(); - } catch (Throwable t) { - if (logger.isWarnEnabled()) { - logger.warn("Failed to close a chunked input.", t); - } - } - } - - private static final class PendingWrite { - final Object msg; - final ChannelPromise promise; - private long progress; - - PendingWrite(Object msg, ChannelPromise promise) { - this.msg = msg; - this.promise = promise; - } - - void fail(Throwable cause) { - ReferenceCountUtil.release(msg); - promise.tryFailure(cause); - } - - void success() { - if (promise.isDone()) { - // No need to notify the progress or fulfill the promise because it's done already. - return; - } - - if (promise instanceof ChannelProgressivePromise) { - // Now we know what the total is. - ((ChannelProgressivePromise) promise).tryProgress(progress, progress); - } - - promise.trySuccess(); - } - - void progress(int amount) { - progress += amount; - if (promise instanceof ChannelProgressivePromise) { - ((ChannelProgressivePromise) promise).tryProgress(progress, -1); - } - } - } - - private static int amount(Object msg) { - if (msg instanceof ByteBuf) { - return ((ByteBuf) msg).readableBytes(); - } - if (msg instanceof ByteBufHolder) { - return ((ByteBufHolder) msg).content().readableBytes(); - } - return 1; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/stream/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/stream/package-info.java deleted file mode 100755 index ec8e4af697..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/stream/package-info.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * Writes very large data stream asynchronously neither spending a lot of - * memory nor getting {@link java.lang.OutOfMemoryError}. For a detailed - * example, please refer to {@code io.netty.example.http.file}. - */ -package com.ai.cloud.io.netty.handler.stream; diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/IdleState.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/IdleState.java deleted file mode 100755 index 26317fde21..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/IdleState.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.timeout; - -import com.ai.cloud.io.netty.channel.Channel; - - -/** - * An {@link Enum} that represents the idle state of a {@link Channel}. - */ -public enum IdleState { - /** - * No data was received for a while. - */ - READER_IDLE, - /** - * No data was sent for a while. - */ - WRITER_IDLE, - /** - * No data was either received or sent for a while. - */ - ALL_IDLE -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/IdleStateEvent.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/IdleStateEvent.java deleted file mode 100755 index d0d99b7ce6..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/IdleStateEvent.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.timeout; - -import com.ai.cloud.io.netty.channel.Channel; - -/** - * A user event triggered by {@link IdleStateHandler} when a {@link Channel} is idle. - */ -public final class IdleStateEvent { - public static final IdleStateEvent FIRST_READER_IDLE_STATE_EVENT = new IdleStateEvent(IdleState.READER_IDLE, true); - public static final IdleStateEvent READER_IDLE_STATE_EVENT = new IdleStateEvent(IdleState.READER_IDLE, false); - public static final IdleStateEvent FIRST_WRITER_IDLE_STATE_EVENT = new IdleStateEvent(IdleState.WRITER_IDLE, true); - public static final IdleStateEvent WRITER_IDLE_STATE_EVENT = new IdleStateEvent(IdleState.WRITER_IDLE, false); - public static final IdleStateEvent FIRST_ALL_IDLE_STATE_EVENT = new IdleStateEvent(IdleState.ALL_IDLE, true); - public static final IdleStateEvent ALL_IDLE_STATE_EVENT = new IdleStateEvent(IdleState.ALL_IDLE, false); - - private final IdleState state; - private final boolean first; - - private IdleStateEvent(IdleState state, boolean first) { - this.state = state; - this.first = first; - } - - /** - * Returns the idle state. - */ - public IdleState state() { - return state; - } - - /** - * Returns {@code true} if this was the first event for the {@link IdleState} - */ - public boolean isFirst() { - return first; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/IdleStateHandler.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/IdleStateHandler.java deleted file mode 100755 index b6e904568c..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/IdleStateHandler.java +++ /dev/null @@ -1,466 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.timeout; - -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; - -import com.ai.cloud.io.netty.bootstrap.ServerBootstrap; -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelDuplexHandler; -import com.ai.cloud.io.netty.channel.ChannelFuture; -import com.ai.cloud.io.netty.channel.ChannelFutureListener; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelInitializer; -import com.ai.cloud.io.netty.channel.ChannelPromise; -import com.ai.cloud.io.netty.util.concurrent.EventExecutor; - -/** - * Triggers an {@link IdleStateEvent} when a {@link Channel} has not performed - * read, write, or both operation for a while. - * - *

Supported idle states

- * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
PropertyMeaning
{@code readerIdleTime}an {@link IdleStateEvent} whose state is {@link IdleState#READER_IDLE} - * will be triggered when no read was performed for the specified period of - * time. Specify {@code 0} to disable.
{@code writerIdleTime}an {@link IdleStateEvent} whose state is {@link IdleState#WRITER_IDLE} - * will be triggered when no write was performed for the specified period of - * time. Specify {@code 0} to disable.
{@code allIdleTime}an {@link IdleStateEvent} whose state is {@link IdleState#ALL_IDLE} - * will be triggered when neither read nor write was performed for the - * specified period of time. Specify {@code 0} to disable.
- * - *
- * // An example that sends a ping message when there is no outbound traffic
- * // for 30 seconds.  The connection is closed when there is no inbound traffic
- * // for 60 seconds.
- *
- * public class MyChannelInitializer extends {@link ChannelInitializer}<{@link Channel}> {
- *     {@code @Override}
- *     public void initChannel({@link Channel} channel) {
- *         channel.pipeline().addLast("idleStateHandler", new {@link IdleStateHandler}(60, 30, 0));
- *         channel.pipeline().addLast("myHandler", new MyHandler());
- *     }
- * }
- *
- * // Handler should handle the {@link IdleStateEvent} triggered by {@link IdleStateHandler}.
- * public class MyHandler extends {@link ChannelDuplexHandler} {
- *     {@code @Override}
- *     public void userEventTriggered({@link ChannelHandlerContext} ctx, {@link Object} evt) throws {@link Exception} {
- *         if (evt instanceof {@link IdleStateEvent}) {
- *             {@link IdleStateEvent} e = ({@link IdleStateEvent}) evt;
- *             if (e.state() == {@link IdleState}.READER_IDLE) {
- *                 ctx.close();
- *             } else if (e.state() == {@link IdleState}.WRITER_IDLE) {
- *                 ctx.writeAndFlush(new PingMessage());
- *             }
- *         }
- *     }
- * }
- *
- * {@link ServerBootstrap} bootstrap = ...;
- * ...
- * bootstrap.childHandler(new MyChannelInitializer());
- * ...
- * 
- * - * @see ReadTimeoutHandler - * @see WriteTimeoutHandler - */ -public class IdleStateHandler extends ChannelDuplexHandler { - private static final long MIN_TIMEOUT_NANOS = TimeUnit.MILLISECONDS.toNanos(1); - - // Not create a new ChannelFutureListener per write operation to reduce GC pressure. - private final ChannelFutureListener writeListener = new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - lastWriteTime = System.nanoTime(); - firstWriterIdleEvent = firstAllIdleEvent = true; - } - }; - - private final long readerIdleTimeNanos; - private final long writerIdleTimeNanos; - private final long allIdleTimeNanos; - - volatile ScheduledFuture readerIdleTimeout; - volatile long lastReadTime; - private boolean firstReaderIdleEvent = true; - - volatile ScheduledFuture writerIdleTimeout; - volatile long lastWriteTime; - private boolean firstWriterIdleEvent = true; - - volatile ScheduledFuture allIdleTimeout; - private boolean firstAllIdleEvent = true; - - private volatile int state; // 0 - none, 1 - initialized, 2 - destroyed - private volatile boolean reading; - - /** - * Creates a new instance firing {@link IdleStateEvent}s. - * - * @param readerIdleTimeSeconds - * an {@link IdleStateEvent} whose state is {@link IdleState#READER_IDLE} - * will be triggered when no read was performed for the specified - * period of time. Specify {@code 0} to disable. - * @param writerIdleTimeSeconds - * an {@link IdleStateEvent} whose state is {@link IdleState#WRITER_IDLE} - * will be triggered when no write was performed for the specified - * period of time. Specify {@code 0} to disable. - * @param allIdleTimeSeconds - * an {@link IdleStateEvent} whose state is {@link IdleState#ALL_IDLE} - * will be triggered when neither read nor write was performed for - * the specified period of time. Specify {@code 0} to disable. - */ - public IdleStateHandler( - int readerIdleTimeSeconds, - int writerIdleTimeSeconds, - int allIdleTimeSeconds) { - - this(readerIdleTimeSeconds, writerIdleTimeSeconds, allIdleTimeSeconds, - TimeUnit.SECONDS); - } - - /** - * Creates a new instance firing {@link IdleStateEvent}s. - * - * @param readerIdleTime - * an {@link IdleStateEvent} whose state is {@link IdleState#READER_IDLE} - * will be triggered when no read was performed for the specified - * period of time. Specify {@code 0} to disable. - * @param writerIdleTime - * an {@link IdleStateEvent} whose state is {@link IdleState#WRITER_IDLE} - * will be triggered when no write was performed for the specified - * period of time. Specify {@code 0} to disable. - * @param allIdleTime - * an {@link IdleStateEvent} whose state is {@link IdleState#ALL_IDLE} - * will be triggered when neither read nor write was performed for - * the specified period of time. Specify {@code 0} to disable. - * @param unit - * the {@link TimeUnit} of {@code readerIdleTime}, - * {@code writeIdleTime}, and {@code allIdleTime} - */ - public IdleStateHandler( - long readerIdleTime, long writerIdleTime, long allIdleTime, - TimeUnit unit) { - if (unit == null) { - throw new NullPointerException("unit"); - } - - if (readerIdleTime <= 0) { - readerIdleTimeNanos = 0; - } else { - readerIdleTimeNanos = Math.max(unit.toNanos(readerIdleTime), MIN_TIMEOUT_NANOS); - } - if (writerIdleTime <= 0) { - writerIdleTimeNanos = 0; - } else { - writerIdleTimeNanos = Math.max(unit.toNanos(writerIdleTime), MIN_TIMEOUT_NANOS); - } - if (allIdleTime <= 0) { - allIdleTimeNanos = 0; - } else { - allIdleTimeNanos = Math.max(unit.toNanos(allIdleTime), MIN_TIMEOUT_NANOS); - } - } - - /** - * Return the readerIdleTime that was given when instance this class in milliseconds. - * - */ - public long getReaderIdleTimeInMillis() { - return TimeUnit.NANOSECONDS.toMillis(readerIdleTimeNanos); - } - - /** - * Return the writerIdleTime that was given when instance this class in milliseconds. - * - */ - public long getWriterIdleTimeInMillis() { - return TimeUnit.NANOSECONDS.toMillis(writerIdleTimeNanos); - } - - /** - * Return the allIdleTime that was given when instance this class in milliseconds. - * - */ - public long getAllIdleTimeInMillis() { - return TimeUnit.NANOSECONDS.toMillis(allIdleTimeNanos); - } - - @Override - public void handlerAdded(ChannelHandlerContext ctx) throws Exception { - if (ctx.channel().isActive() && ctx.channel().isRegistered()) { - // channelActvie() event has been fired already, which means this.channelActive() will - // not be invoked. We have to initialize here instead. - initialize(ctx); - } else { - // channelActive() event has not been fired yet. this.channelActive() will be invoked - // and initialization will occur there. - } - } - - @Override - public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { - destroy(); - } - - @Override - public void channelRegistered(ChannelHandlerContext ctx) throws Exception { - // Initialize early if channel is active already. - if (ctx.channel().isActive()) { - initialize(ctx); - } - super.channelRegistered(ctx); - } - - @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { - // This method will be invoked only if this handler was added - // before channelActive() event is fired. If a user adds this handler - // after the channelActive() event, initialize() will be called by beforeAdd(). - initialize(ctx); - super.channelActive(ctx); - } - - @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { - destroy(); - super.channelInactive(ctx); - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - if (readerIdleTimeNanos > 0 || allIdleTimeNanos > 0) { - reading = true; - firstReaderIdleEvent = firstAllIdleEvent = true; - } - ctx.fireChannelRead(msg); - } - - @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { - if (readerIdleTimeNanos > 0 || allIdleTimeNanos > 0) { - lastReadTime = System.nanoTime(); - reading = false; - } - ctx.fireChannelReadComplete(); - } - - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - // Allow writing with void promise if handler is only configured for read timeout events. - if (writerIdleTimeNanos > 0 || allIdleTimeNanos > 0) { - promise.addListener(writeListener); - } - ctx.write(msg, promise); - } - - private void initialize(ChannelHandlerContext ctx) { - // Avoid the case where destroy() is called before scheduling timeouts. - // See: https://github.com/netty/netty/issues/143 - switch (state) { - case 1: - case 2: - return; - } - - state = 1; - - EventExecutor loop = ctx.executor(); - - lastReadTime = lastWriteTime = System.nanoTime(); - if (readerIdleTimeNanos > 0) { - readerIdleTimeout = loop.schedule( - new ReaderIdleTimeoutTask(ctx), - readerIdleTimeNanos, TimeUnit.NANOSECONDS); - } - if (writerIdleTimeNanos > 0) { - writerIdleTimeout = loop.schedule( - new WriterIdleTimeoutTask(ctx), - writerIdleTimeNanos, TimeUnit.NANOSECONDS); - } - if (allIdleTimeNanos > 0) { - allIdleTimeout = loop.schedule( - new AllIdleTimeoutTask(ctx), - allIdleTimeNanos, TimeUnit.NANOSECONDS); - } - } - - private void destroy() { - state = 2; - - if (readerIdleTimeout != null) { - readerIdleTimeout.cancel(false); - readerIdleTimeout = null; - } - if (writerIdleTimeout != null) { - writerIdleTimeout.cancel(false); - writerIdleTimeout = null; - } - if (allIdleTimeout != null) { - allIdleTimeout.cancel(false); - allIdleTimeout = null; - } - } - - /** - * Is called when an {@link IdleStateEvent} should be fired. This implementation calls - * {@link ChannelHandlerContext#fireUserEventTriggered(Object)}. - */ - protected void channelIdle(ChannelHandlerContext ctx, IdleStateEvent evt) throws Exception { - ctx.fireUserEventTriggered(evt); - } - - private final class ReaderIdleTimeoutTask implements Runnable { - - private final ChannelHandlerContext ctx; - - ReaderIdleTimeoutTask(ChannelHandlerContext ctx) { - this.ctx = ctx; - } - - @Override - public void run() { - if (!ctx.channel().isOpen()) { - return; - } - - long nextDelay = readerIdleTimeNanos; - if (!reading) { - nextDelay -= System.nanoTime() - lastReadTime; - } - - if (nextDelay <= 0) { - // Reader is idle - set a new timeout and notify the callback. - readerIdleTimeout = - ctx.executor().schedule(this, readerIdleTimeNanos, TimeUnit.NANOSECONDS); - try { - IdleStateEvent event; - if (firstReaderIdleEvent) { - firstReaderIdleEvent = false; - event = IdleStateEvent.FIRST_READER_IDLE_STATE_EVENT; - } else { - event = IdleStateEvent.READER_IDLE_STATE_EVENT; - } - channelIdle(ctx, event); - } catch (Throwable t) { - ctx.fireExceptionCaught(t); - } - } else { - // Read occurred before the timeout - set a new timeout with shorter delay. - readerIdleTimeout = ctx.executor().schedule(this, nextDelay, TimeUnit.NANOSECONDS); - } - } - } - - private final class WriterIdleTimeoutTask implements Runnable { - - private final ChannelHandlerContext ctx; - - WriterIdleTimeoutTask(ChannelHandlerContext ctx) { - this.ctx = ctx; - } - - @Override - public void run() { - if (!ctx.channel().isOpen()) { - return; - } - - long lastWriteTime = IdleStateHandler.this.lastWriteTime; - long nextDelay = writerIdleTimeNanos - (System.nanoTime() - lastWriteTime); - if (nextDelay <= 0) { - // Writer is idle - set a new timeout and notify the callback. - writerIdleTimeout = ctx.executor().schedule( - this, writerIdleTimeNanos, TimeUnit.NANOSECONDS); - try { - IdleStateEvent event; - if (firstWriterIdleEvent) { - firstWriterIdleEvent = false; - event = IdleStateEvent.FIRST_WRITER_IDLE_STATE_EVENT; - } else { - event = IdleStateEvent.WRITER_IDLE_STATE_EVENT; - } - channelIdle(ctx, event); - } catch (Throwable t) { - ctx.fireExceptionCaught(t); - } - } else { - // Write occurred before the timeout - set a new timeout with shorter delay. - writerIdleTimeout = ctx.executor().schedule(this, nextDelay, TimeUnit.NANOSECONDS); - } - } - } - - private final class AllIdleTimeoutTask implements Runnable { - - private final ChannelHandlerContext ctx; - - AllIdleTimeoutTask(ChannelHandlerContext ctx) { - this.ctx = ctx; - } - - @Override - public void run() { - if (!ctx.channel().isOpen()) { - return; - } - - long nextDelay = allIdleTimeNanos; - if (!reading) { - nextDelay -= System.nanoTime() - Math.max(lastReadTime, lastWriteTime); - } - if (nextDelay <= 0) { - // Both reader and writer are idle - set a new timeout and - // notify the callback. - allIdleTimeout = ctx.executor().schedule( - this, allIdleTimeNanos, TimeUnit.NANOSECONDS); - try { - IdleStateEvent event; - if (firstAllIdleEvent) { - firstAllIdleEvent = false; - event = IdleStateEvent.FIRST_ALL_IDLE_STATE_EVENT; - } else { - event = IdleStateEvent.ALL_IDLE_STATE_EVENT; - } - channelIdle(ctx, event); - } catch (Throwable t) { - ctx.fireExceptionCaught(t); - } - } else { - // Either read or write occurred before the timeout - set a new - // timeout with shorter delay. - allIdleTimeout = ctx.executor().schedule(this, nextDelay, TimeUnit.NANOSECONDS); - } - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/ReadTimeoutException.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/ReadTimeoutException.java deleted file mode 100755 index 99030a6f6a..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/ReadTimeoutException.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.timeout; - -/** - * A {@link TimeoutException} raised by {@link ReadTimeoutHandler} when no data - * was read within a certain period of time. - */ -public final class ReadTimeoutException extends TimeoutException { - - private static final long serialVersionUID = 169287984113283421L; - - public static final ReadTimeoutException INSTANCE = new ReadTimeoutException(); - - private ReadTimeoutException() { } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/ReadTimeoutHandler.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/ReadTimeoutHandler.java deleted file mode 100755 index 83c4d0539a..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/ReadTimeoutHandler.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.timeout; - -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; - -import com.ai.cloud.io.netty.bootstrap.ServerBootstrap; -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelDuplexHandler; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelInboundHandlerAdapter; -import com.ai.cloud.io.netty.channel.ChannelInitializer; - -/** - * Raises a {@link ReadTimeoutException} when no data was read within a certain - * period of time. - * - *
- * // The connection is closed when there is no inbound traffic
- * // for 30 seconds.
- *
- * public class MyChannelInitializer extends {@link ChannelInitializer}<{@link Channel}> {
- *     public void initChannel({@link Channel} channel) {
- *         channel.pipeline().addLast("readTimeoutHandler", new {@link ReadTimeoutHandler}(30);
- *         channel.pipeline().addLast("myHandler", new MyHandler());
- *     }
- * }
- *
- * // Handler should handle the {@link ReadTimeoutException}.
- * public class MyHandler extends {@link ChannelDuplexHandler} {
- *     {@code @Override}
- *     public void exceptionCaught({@link ChannelHandlerContext} ctx, {@link Throwable} cause)
- *             throws {@link Exception} {
- *         if (cause instanceof {@link ReadTimeoutException}) {
- *             // do something
- *         } else {
- *             super.exceptionCaught(ctx, cause);
- *         }
- *     }
- * }
- *
- * {@link ServerBootstrap} bootstrap = ...;
- * ...
- * bootstrap.childHandler(new MyChannelInitializer());
- * ...
- * 
- * @see WriteTimeoutHandler - * @see IdleStateHandler - */ -public class ReadTimeoutHandler extends ChannelInboundHandlerAdapter { - private static final long MIN_TIMEOUT_NANOS = TimeUnit.MILLISECONDS.toNanos(1); - - private final long timeoutNanos; - - private long lastReadTime; - - private volatile ScheduledFuture timeout; - - private volatile int state; // 0 - none, 1 - Initialized, 2 - Destroyed; - - private volatile boolean reading; - private boolean closed; - - /** - * Creates a new instance. - * - * @param timeoutSeconds - * read timeout in seconds - */ - public ReadTimeoutHandler(int timeoutSeconds) { - this(timeoutSeconds, TimeUnit.SECONDS); - } - - /** - * Creates a new instance. - * - * @param timeout - * read timeout - * @param unit - * the {@link TimeUnit} of {@code timeout} - */ - public ReadTimeoutHandler(long timeout, TimeUnit unit) { - if (unit == null) { - throw new NullPointerException("unit"); - } - - if (timeout <= 0) { - timeoutNanos = 0; - } else { - timeoutNanos = Math.max(unit.toNanos(timeout), MIN_TIMEOUT_NANOS); - } - } - - @Override - public void handlerAdded(ChannelHandlerContext ctx) throws Exception { - if (ctx.channel().isActive() && ctx.channel().isRegistered()) { - // channelActvie() event has been fired already, which means this.channelActive() will - // not be invoked. We have to initialize here instead. - initialize(ctx); - } else { - // channelActive() event has not been fired yet. this.channelActive() will be invoked - // and initialization will occur there. - } - } - - @Override - public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { - destroy(); - } - - @Override - public void channelRegistered(ChannelHandlerContext ctx) throws Exception { - // Initialize early if channel is active already. - if (ctx.channel().isActive()) { - initialize(ctx); - } - super.channelRegistered(ctx); - } - - @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { - // This method will be invoked only if this handler was added - // before channelActive() event is fired. If a user adds this handler - // after the channelActive() event, initialize() will be called by beforeAdd(). - initialize(ctx); - super.channelActive(ctx); - } - - @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { - destroy(); - super.channelInactive(ctx); - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - reading = true; - ctx.fireChannelRead(msg); - } - - @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { - lastReadTime = System.nanoTime(); - reading = false; - ctx.fireChannelReadComplete(); - } - - private void initialize(ChannelHandlerContext ctx) { - // Avoid the case where destroy() is called before scheduling timeouts. - // See: https://github.com/netty/netty/issues/143 - switch (state) { - case 1: - case 2: - return; - } - - state = 1; - - lastReadTime = System.nanoTime(); - if (timeoutNanos > 0) { - timeout = ctx.executor().schedule( - new ReadTimeoutTask(ctx), - timeoutNanos, TimeUnit.NANOSECONDS); - } - } - - private void destroy() { - state = 2; - - if (timeout != null) { - timeout.cancel(false); - timeout = null; - } - } - - /** - * Is called when a read timeout was detected. - */ - protected void readTimedOut(ChannelHandlerContext ctx) throws Exception { - if (!closed) { - ctx.fireExceptionCaught(ReadTimeoutException.INSTANCE); - ctx.close(); - closed = true; - } - } - - private final class ReadTimeoutTask implements Runnable { - - private final ChannelHandlerContext ctx; - - ReadTimeoutTask(ChannelHandlerContext ctx) { - this.ctx = ctx; - } - - @Override - public void run() { - if (!ctx.channel().isOpen()) { - return; - } - - long nextDelay = timeoutNanos; - if (!reading) { - nextDelay -= System.nanoTime() - lastReadTime; - } - - if (nextDelay <= 0) { - // Read timed out - set a new timeout and notify the callback. - timeout = ctx.executor().schedule(this, timeoutNanos, TimeUnit.NANOSECONDS); - try { - readTimedOut(ctx); - } catch (Throwable t) { - ctx.fireExceptionCaught(t); - } - } else { - // Read occurred before the timeout - set a new timeout with shorter delay. - timeout = ctx.executor().schedule(this, nextDelay, TimeUnit.NANOSECONDS); - } - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/TimeoutException.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/TimeoutException.java deleted file mode 100755 index 4328756b86..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/TimeoutException.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.timeout; - -import com.ai.cloud.io.netty.channel.ChannelException; - -/** - * A {@link TimeoutException} when no data was either read or written within a - * certain period of time. - */ -public class TimeoutException extends ChannelException { - - private static final long serialVersionUID = 4673641882869672533L; - - TimeoutException() { } - - @Override - public Throwable fillInStackTrace() { - return this; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/WriteTimeoutException.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/WriteTimeoutException.java deleted file mode 100755 index 8eaf872e6d..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/WriteTimeoutException.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.timeout; - -/** - * A {@link TimeoutException} raised by {@link WriteTimeoutHandler} when no data - * was written within a certain period of time. - */ -public final class WriteTimeoutException extends TimeoutException { - - private static final long serialVersionUID = -144786655770296065L; - - public static final WriteTimeoutException INSTANCE = new WriteTimeoutException(); - - private WriteTimeoutException() { } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/WriteTimeoutHandler.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/WriteTimeoutHandler.java deleted file mode 100755 index e78057dccd..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/WriteTimeoutHandler.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.timeout; - -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; - -import com.ai.cloud.io.netty.bootstrap.ServerBootstrap; -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelDuplexHandler; -import com.ai.cloud.io.netty.channel.ChannelFuture; -import com.ai.cloud.io.netty.channel.ChannelFutureListener; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelInitializer; -import com.ai.cloud.io.netty.channel.ChannelOutboundHandlerAdapter; -import com.ai.cloud.io.netty.channel.ChannelPromise; - -/** - * Raises a {@link WriteTimeoutException} when no data was written within a - * certain period of time. - * - *
- * // The connection is closed when there is no outbound traffic
- * // for 30 seconds.
- *
- * public class MyChannelInitializer extends {@link ChannelInitializer}<{@link Channel}> {
- *     public void initChannel({@link Channel} channel) {
- *         channel.pipeline().addLast("writeTimeoutHandler", new {@link WriteTimeoutHandler}(30);
- *         channel.pipeline().addLast("myHandler", new MyHandler());
- *     }
- * }
- *
- * // Handler should handle the {@link WriteTimeoutException}.
- * public class MyHandler extends {@link ChannelDuplexHandler} {
- *     {@code @Override}
- *     public void exceptionCaught({@link ChannelHandlerContext} ctx, {@link Throwable} cause)
- *             throws {@link Exception} {
- *         if (cause instanceof {@link WriteTimeoutException}) {
- *             // do something
- *         } else {
- *             super.exceptionCaught(ctx, cause);
- *         }
- *     }
- * }
- *
- * {@link ServerBootstrap} bootstrap = ...;
- * ...
- * bootstrap.childHandler(new MyChannelInitializer());
- * ...
- * 
- * @see ReadTimeoutHandler - * @see IdleStateHandler - */ -public class WriteTimeoutHandler extends ChannelOutboundHandlerAdapter { - private static final long MIN_TIMEOUT_NANOS = TimeUnit.MILLISECONDS.toNanos(1); - - private final long timeoutNanos; - - private boolean closed; - - /** - * Creates a new instance. - * - * @param timeoutSeconds - * write timeout in seconds - */ - public WriteTimeoutHandler(int timeoutSeconds) { - this(timeoutSeconds, TimeUnit.SECONDS); - } - - /** - * Creates a new instance. - * - * @param timeout - * write timeout - * @param unit - * the {@link TimeUnit} of {@code timeout} - */ - public WriteTimeoutHandler(long timeout, TimeUnit unit) { - if (unit == null) { - throw new NullPointerException("unit"); - } - - if (timeout <= 0) { - timeoutNanos = 0; - } else { - timeoutNanos = Math.max(unit.toNanos(timeout), MIN_TIMEOUT_NANOS); - } - } - - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - scheduleTimeout(ctx, promise); - ctx.write(msg, promise); - } - - private void scheduleTimeout(final ChannelHandlerContext ctx, final ChannelPromise future) { - if (timeoutNanos > 0) { - // Schedule a timeout. - final ScheduledFuture sf = ctx.executor().schedule(new Runnable() { - @Override - public void run() { - // Was not written yet so issue a write timeout - // The future itself will be failed with a ClosedChannelException once the close() was issued - // See https://github.com/netty/netty/issues/2159 - if (!future.isDone()) { - try { - writeTimedOut(ctx); - } catch (Throwable t) { - ctx.fireExceptionCaught(t); - } - } - } - }, timeoutNanos, TimeUnit.NANOSECONDS); - - // Cancel the scheduled timeout if the flush future is complete. - future.addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - sf.cancel(false); - } - }); - } - } - - /** - * Is called when a write timeout was detected - */ - protected void writeTimedOut(ChannelHandlerContext ctx) throws Exception { - if (!closed) { - ctx.fireExceptionCaught(WriteTimeoutException.INSTANCE); - ctx.close(); - closed = true; - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/package-info.java deleted file mode 100755 index 5d94c03f32..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/timeout/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * Adds support for read and write timeout and idle connection notification - * using a {@link com.ai.cloud.io.netty.util.Timer}. - */ -package com.ai.cloud.io.netty.handler.timeout; diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/traffic/AbstractTrafficShapingHandler.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/traffic/AbstractTrafficShapingHandler.java deleted file mode 100755 index 8a2aa550b4..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/traffic/AbstractTrafficShapingHandler.java +++ /dev/null @@ -1,653 +0,0 @@ -/* - * Copyright 2011 The Netty Project - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.traffic; - -import java.util.concurrent.TimeUnit; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.buffer.ByteBufHolder; -import com.ai.cloud.io.netty.channel.ChannelConfig; -import com.ai.cloud.io.netty.channel.ChannelDuplexHandler; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelOutboundBuffer; -import com.ai.cloud.io.netty.channel.ChannelPromise; -import com.ai.cloud.io.netty.util.Attribute; -import com.ai.cloud.io.netty.util.AttributeKey; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - *

AbstractTrafficShapingHandler allows to limit the global bandwidth - * (see {@link GlobalTrafficShapingHandler}) or per session - * bandwidth (see {@link ChannelTrafficShapingHandler}), as traffic shaping. - * It allows you to implement an almost real time monitoring of the bandwidth using - * the monitors from {@link TrafficCounter} that will call back every checkInterval - * the method doAccounting of this handler.

- * - *

If you want for any particular reasons to stop the monitoring (accounting) or to change - * the read/write limit or the check interval, several methods allow that for you:

- *
    - *
  • configure allows you to change read or write limits, or the checkInterval
  • - *
  • getTrafficCounter allows you to have access to the TrafficCounter and so to stop or start the - * monitoring, to change the checkInterval directly, or to have access to its values.
  • - *
- */ -public abstract class AbstractTrafficShapingHandler extends ChannelDuplexHandler { - private static final InternalLogger logger = InternalLoggerFactory.getInstance(AbstractTrafficShapingHandler.class); - - /** - * Default delay between two checks: 1s - */ - public static final long DEFAULT_CHECK_INTERVAL = 1000; - - /** - * Default max delay in case of traffic shaping - * (during which no communication will occur). - * Shall be less than TIMEOUT. Here half of "standard" 30s - */ - public static final long DEFAULT_MAX_TIME = 15000; - - /** - * Default max size to not exceed in buffer (write only). - */ - static final long DEFAULT_MAX_SIZE = 4 * 1024 * 1024L; - - /** - * Default minimal time to wait - */ - static final long MINIMAL_WAIT = 10; - - /** - * Traffic Counter - */ - protected TrafficCounter trafficCounter; - - /** - * Limit in B/s to apply to write - */ - private volatile long writeLimit; - - /** - * Limit in B/s to apply to read - */ - private volatile long readLimit; - - /** - * Max delay in wait - */ - protected volatile long maxTime = DEFAULT_MAX_TIME; // default 15 s - - /** - * Delay between two performance snapshots - */ - protected volatile long checkInterval = DEFAULT_CHECK_INTERVAL; // default 1 s - - static final AttributeKey READ_SUSPENDED = AttributeKey - .valueOf(AbstractTrafficShapingHandler.class.getName() + ".READ_SUSPENDED"); - static final AttributeKey REOPEN_TASK = AttributeKey.valueOf(AbstractTrafficShapingHandler.class - .getName() + ".REOPEN_TASK"); - - /** - * Max time to delay before proposing to stop writing new objects from next handlers - */ - volatile long maxWriteDelay = 4 * DEFAULT_CHECK_INTERVAL; // default 4 s - /** - * Max size in the list before proposing to stop writing new objects from next handlers - */ - volatile long maxWriteSize = DEFAULT_MAX_SIZE; // default 4MB - - /** - * Rank in UserDefinedWritability (1 for Channel, 2 for Global TrafficShapingHandler). - * Set in final constructor. Must be between 1 and 31 - */ - final int userDefinedWritabilityIndex; - - /** - * Default value for Channel UserDefinedWritability index - */ - static final int CHANNEL_DEFAULT_USER_DEFINED_WRITABILITY_INDEX = 1; - - /** - * Default value for Global UserDefinedWritability index - */ - static final int GLOBAL_DEFAULT_USER_DEFINED_WRITABILITY_INDEX = 2; - - /** - * Default value for GlobalChannel UserDefinedWritability index - */ - static final int GLOBALCHANNEL_DEFAULT_USER_DEFINED_WRITABILITY_INDEX = 3; - - /** - * @param newTrafficCounter - * the TrafficCounter to set - */ - void setTrafficCounter(TrafficCounter newTrafficCounter) { - trafficCounter = newTrafficCounter; - } - - /** - * @return the index to be used by the TrafficShapingHandler to manage the user defined writability. - * For Channel TSH it is defined as {@value #CHANNEL_DEFAULT_USER_DEFINED_WRITABILITY_INDEX}, - * for Global TSH it is defined as {@value #GLOBAL_DEFAULT_USER_DEFINED_WRITABILITY_INDEX}, - * for GlobalChannel TSH it is defined as - * {@value #GLOBALCHANNEL_DEFAULT_USER_DEFINED_WRITABILITY_INDEX}. - */ - int userDefinedWritabilityIndex() { - if (this instanceof GlobalChannelTrafficShapingHandler) { - return GLOBALCHANNEL_DEFAULT_USER_DEFINED_WRITABILITY_INDEX; - } else if (this instanceof GlobalTrafficShapingHandler) { - return GLOBAL_DEFAULT_USER_DEFINED_WRITABILITY_INDEX; - } else { - return CHANNEL_DEFAULT_USER_DEFINED_WRITABILITY_INDEX; - } - } - - /** - * @param writeLimit - * 0 or a limit in bytes/s - * @param readLimit - * 0 or a limit in bytes/s - * @param checkInterval - * The delay between two computations of performances for - * channels or 0 if no stats are to be computed. - * @param maxTime - * The maximum delay to wait in case of traffic excess. - * Must be positive. - */ - protected AbstractTrafficShapingHandler(long writeLimit, long readLimit, long checkInterval, long maxTime) { - if (maxTime <= 0) { - throw new IllegalArgumentException("maxTime must be positive"); - } - - userDefinedWritabilityIndex = userDefinedWritabilityIndex(); - this.writeLimit = writeLimit; - this.readLimit = readLimit; - this.checkInterval = checkInterval; - this.maxTime = maxTime; - } - - /** - * Constructor using default max time as delay allowed value of {@value #DEFAULT_MAX_TIME} ms. - * @param writeLimit - * 0 or a limit in bytes/s - * @param readLimit - * 0 or a limit in bytes/s - * @param checkInterval - * The delay between two computations of performances for - * channels or 0 if no stats are to be computed. - */ - protected AbstractTrafficShapingHandler(long writeLimit, long readLimit, long checkInterval) { - this(writeLimit, readLimit, checkInterval, DEFAULT_MAX_TIME); - } - - /** - * Constructor using default Check Interval value of {@value #DEFAULT_CHECK_INTERVAL} ms and - * default max time as delay allowed value of {@value #DEFAULT_MAX_TIME} ms. - * - * @param writeLimit - * 0 or a limit in bytes/s - * @param readLimit - * 0 or a limit in bytes/s - */ - protected AbstractTrafficShapingHandler(long writeLimit, long readLimit) { - this(writeLimit, readLimit, DEFAULT_CHECK_INTERVAL, DEFAULT_MAX_TIME); - } - - /** - * Constructor using NO LIMIT, default Check Interval value of {@value #DEFAULT_CHECK_INTERVAL} ms and - * default max time as delay allowed value of {@value #DEFAULT_MAX_TIME} ms. - */ - protected AbstractTrafficShapingHandler() { - this(0, 0, DEFAULT_CHECK_INTERVAL, DEFAULT_MAX_TIME); - } - - /** - * Constructor using NO LIMIT and - * default max time as delay allowed value of {@value #DEFAULT_MAX_TIME} ms. - * - * @param checkInterval - * The delay between two computations of performances for - * channels or 0 if no stats are to be computed. - */ - protected AbstractTrafficShapingHandler(long checkInterval) { - this(0, 0, checkInterval, DEFAULT_MAX_TIME); - } - - /** - * Change the underlying limitations and check interval. - *

Note the change will be taken as best effort, meaning - * that all already scheduled traffics will not be - * changed, but only applied to new traffics.

- *

So the expected usage of this method is to be used not too often, - * accordingly to the traffic shaping configuration.

- * - * @param newWriteLimit - * The new write limit (in bytes) - * @param newReadLimit - * The new read limit (in bytes) - * @param newCheckInterval - * The new check interval (in milliseconds) - */ - public void configure(long newWriteLimit, long newReadLimit, long newCheckInterval) { - configure(newWriteLimit, newReadLimit); - configure(newCheckInterval); - } - - /** - * Change the underlying limitations. - *

Note the change will be taken as best effort, meaning - * that all already scheduled traffics will not be - * changed, but only applied to new traffics.

- *

So the expected usage of this method is to be used not too often, - * accordingly to the traffic shaping configuration.

- * - * @param newWriteLimit - * The new write limit (in bytes) - * @param newReadLimit - * The new read limit (in bytes) - */ - public void configure(long newWriteLimit, long newReadLimit) { - writeLimit = newWriteLimit; - readLimit = newReadLimit; - if (trafficCounter != null) { - trafficCounter.resetAccounting(TrafficCounter.milliSecondFromNano()); - } - } - - /** - * Change the check interval. - * - * @param newCheckInterval - * The new check interval (in milliseconds) - */ - public void configure(long newCheckInterval) { - checkInterval = newCheckInterval; - if (trafficCounter != null) { - trafficCounter.configure(checkInterval); - } - } - - /** - * @return the writeLimit - */ - public long getWriteLimit() { - return writeLimit; - } - - /** - *

Note the change will be taken as best effort, meaning - * that all already scheduled traffics will not be - * changed, but only applied to new traffics.

- *

So the expected usage of this method is to be used not too often, - * accordingly to the traffic shaping configuration.

- * - * @param writeLimit the writeLimit to set - */ - public void setWriteLimit(long writeLimit) { - this.writeLimit = writeLimit; - if (trafficCounter != null) { - trafficCounter.resetAccounting(TrafficCounter.milliSecondFromNano()); - } - } - - /** - * @return the readLimit - */ - public long getReadLimit() { - return readLimit; - } - - /** - *

Note the change will be taken as best effort, meaning - * that all already scheduled traffics will not be - * changed, but only applied to new traffics.

- *

So the expected usage of this method is to be used not too often, - * accordingly to the traffic shaping configuration.

- * - * @param readLimit the readLimit to set - */ - public void setReadLimit(long readLimit) { - this.readLimit = readLimit; - if (trafficCounter != null) { - trafficCounter.resetAccounting(TrafficCounter.milliSecondFromNano()); - } - } - - /** - * @return the checkInterval - */ - public long getCheckInterval() { - return checkInterval; - } - - /** - * @param checkInterval the interval in ms between each step check to set, default value beeing 1000 ms. - */ - public void setCheckInterval(long checkInterval) { - this.checkInterval = checkInterval; - if (trafficCounter != null) { - trafficCounter.configure(checkInterval); - } - } - - /** - *

Note the change will be taken as best effort, meaning - * that all already scheduled traffics will not be - * changed, but only applied to new traffics.

- *

So the expected usage of this method is to be used not too often, - * accordingly to the traffic shaping configuration.

- * - * @param maxTime - * Max delay in wait, shall be less than TIME OUT in related protocol. - * Must be positive. - */ - public void setMaxTimeWait(long maxTime) { - if (maxTime <= 0) { - throw new IllegalArgumentException("maxTime must be positive"); - } - this.maxTime = maxTime; - } - - /** - * @return the max delay in wait to prevent TIME OUT - */ - public long getMaxTimeWait() { - return maxTime; - } - - /** - * @return the maxWriteDelay - */ - public long getMaxWriteDelay() { - return maxWriteDelay; - } - - /** - *

Note the change will be taken as best effort, meaning - * that all already scheduled traffics will not be - * changed, but only applied to new traffics.

- *

So the expected usage of this method is to be used not too often, - * accordingly to the traffic shaping configuration.

- * - * @param maxWriteDelay the maximum Write Delay in ms in the buffer allowed before write suspension is set. - * Must be positive. - */ - public void setMaxWriteDelay(long maxWriteDelay) { - if (maxWriteDelay <= 0) { - throw new IllegalArgumentException("maxWriteDelay must be positive"); - } - this.maxWriteDelay = maxWriteDelay; - } - - /** - * @return the maxWriteSize default being {@value #DEFAULT_MAX_SIZE} bytes. - */ - public long getMaxWriteSize() { - return maxWriteSize; - } - - /** - *

Note that this limit is a best effort on memory limitation to prevent Out Of - * Memory Exception. To ensure it works, the handler generating the write should - * use one of the way provided by Netty to handle the capacity:

- *

- the {@code Channel.isWritable()} property and the corresponding - * {@code channelWritabilityChanged()}

- *

- the {@code ChannelFuture.addListener(new GenericFutureListener())}

- * - * @param maxWriteSize the maximum Write Size allowed in the buffer - * per channel before write suspended is set, - * default being {@value #DEFAULT_MAX_SIZE} bytes. - */ - public void setMaxWriteSize(long maxWriteSize) { - this.maxWriteSize = maxWriteSize; - } - - /** - * Called each time the accounting is computed from the TrafficCounters. - * This method could be used for instance to implement almost real time accounting. - * - * @param counter - * the TrafficCounter that computes its performance - */ - protected void doAccounting(TrafficCounter counter) { - // NOOP by default - } - - /** - * Class to implement setReadable at fix time - */ - static final class ReopenReadTimerTask implements Runnable { - final ChannelHandlerContext ctx; - - ReopenReadTimerTask(ChannelHandlerContext ctx) { - this.ctx = ctx; - } - - @Override - public void run() { - ChannelConfig config = ctx.channel().config(); - if (!config.isAutoRead() && isHandlerActive(ctx)) { - // If AutoRead is False and Active is True, user make a direct setAutoRead(false) - // Then Just reset the status - if (logger.isDebugEnabled()) { - logger.debug("Not unsuspend: " + config.isAutoRead() + ':' + - isHandlerActive(ctx)); - } - ctx.attr(READ_SUSPENDED).set(false); - } else { - // Anything else allows the handler to reset the AutoRead - if (logger.isDebugEnabled()) { - if (config.isAutoRead() && !isHandlerActive(ctx)) { - logger.debug("Unsuspend: " + config.isAutoRead() + ':' + - isHandlerActive(ctx)); - } else { - logger.debug("Normal unsuspend: " + config.isAutoRead() + ':' - + isHandlerActive(ctx)); - } - } - ctx.attr(READ_SUSPENDED).set(false); - config.setAutoRead(true); - ctx.channel().read(); - } - if (logger.isDebugEnabled()) { - logger.debug("Unsupsend final status => " + config.isAutoRead() + ':' - + isHandlerActive(ctx)); - } - } - } - - /** - * Release the Read suspension - */ - void releaseReadSuspended(ChannelHandlerContext ctx) { - ctx.attr(READ_SUSPENDED).set(false); - ctx.channel().config().setAutoRead(true); - } - - @Override - public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception { - long size = calculateSize(msg); - long now = TrafficCounter.milliSecondFromNano(); - if (size > 0) { - // compute the number of ms to wait before reopening the channel - long wait = trafficCounter.readTimeToWait(size, readLimit, maxTime, now); - wait = checkWaitReadTime(ctx, wait, now); - if (wait >= MINIMAL_WAIT) { // At least 10ms seems a minimal - // time in order to try to limit the traffic - // Only AutoRead AND HandlerActive True means Context Active - ChannelConfig config = ctx.channel().config(); - if (logger.isDebugEnabled()) { - logger.debug("Read suspend: " + wait + ':' + config.isAutoRead() + ':' - + isHandlerActive(ctx)); - } - if (config.isAutoRead() && isHandlerActive(ctx)) { - config.setAutoRead(false); - ctx.attr(READ_SUSPENDED).set(true); - // Create a Runnable to reactive the read if needed. If one was create before it will just be - // reused to limit object creation - Attribute attr = ctx.attr(REOPEN_TASK); - Runnable reopenTask = attr.get(); - if (reopenTask == null) { - reopenTask = new ReopenReadTimerTask(ctx); - attr.set(reopenTask); - } - ctx.executor().schedule(reopenTask, wait, TimeUnit.MILLISECONDS); - if (logger.isDebugEnabled()) { - logger.debug("Suspend final status => " + config.isAutoRead() + ':' - + isHandlerActive(ctx) + " will reopened at: " + wait); - } - } - } - } - informReadOperation(ctx, now); - ctx.fireChannelRead(msg); - } - - /** - * Method overridden in GTSH to take into account specific timer for the channel. - * @param wait the wait delay computed in ms - * @param now the relative now time in ms - * @return the wait to use according to the context - */ - long checkWaitReadTime(final ChannelHandlerContext ctx, long wait, final long now) { - // no change by default - return wait; - } - - /** - * Method overridden in GTSH to take into account specific timer for the channel. - * @param now the relative now time in ms - */ - void informReadOperation(final ChannelHandlerContext ctx, final long now) { - // default noop - } - - protected static boolean isHandlerActive(ChannelHandlerContext ctx) { - Boolean suspended = ctx.attr(READ_SUSPENDED).get(); - return suspended == null || Boolean.FALSE.equals(suspended); - } - - @Override - public void read(ChannelHandlerContext ctx) { - if (isHandlerActive(ctx)) { - // For Global Traffic (and Read when using EventLoop in pipeline) : check if READ_SUSPENDED is False - ctx.read(); - } - } - - @Override - public void write(final ChannelHandlerContext ctx, final Object msg, final ChannelPromise promise) - throws Exception { - long size = calculateSize(msg); - long now = TrafficCounter.milliSecondFromNano(); - if (size > 0) { - // compute the number of ms to wait before continue with the channel - long wait = trafficCounter.writeTimeToWait(size, writeLimit, maxTime, now); - if (wait >= MINIMAL_WAIT) { - if (logger.isDebugEnabled()) { - logger.debug("Write suspend: " + wait + ':' + ctx.channel().config().isAutoRead() + ':' - + isHandlerActive(ctx)); - } - submitWrite(ctx, msg, size, wait, now, promise); - return; - } - } - // to maintain order of write - submitWrite(ctx, msg, size, 0, now, promise); - } - - @Deprecated - protected void submitWrite(final ChannelHandlerContext ctx, final Object msg, - final long delay, final ChannelPromise promise) { - submitWrite(ctx, msg, calculateSize(msg), - delay, TrafficCounter.milliSecondFromNano(), promise); - } - - abstract void submitWrite( - ChannelHandlerContext ctx, Object msg, long size, long delay, long now, ChannelPromise promise); - - @Override - public void channelRegistered(ChannelHandlerContext ctx) throws Exception { - setUserDefinedWritability(ctx, true); - super.channelRegistered(ctx); - } - - void setUserDefinedWritability(ChannelHandlerContext ctx, boolean writable) { - ChannelOutboundBuffer cob = ctx.channel().unsafe().outboundBuffer(); - if (cob != null) { - cob.setUserDefinedWritability(userDefinedWritabilityIndex, writable); - } - } - - /** - * Check the writability according to delay and size for the channel. - * Set if necessary setUserDefinedWritability status. - * @param delay the computed delay - * @param queueSize the current queueSize - */ - void checkWriteSuspend(ChannelHandlerContext ctx, long delay, long queueSize) { - if (queueSize > maxWriteSize || delay > maxWriteDelay) { - setUserDefinedWritability(ctx, false); - } - } - /** - * Explicitly release the Write suspended status. - */ - void releaseWriteSuspended(ChannelHandlerContext ctx) { - setUserDefinedWritability(ctx, true); - } - - /** - * @return the current TrafficCounter (if - * channel is still connected) - */ - public TrafficCounter trafficCounter() { - return trafficCounter; - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(290) - .append("TrafficShaping with Write Limit: ").append(writeLimit) - .append(" Read Limit: ").append(readLimit) - .append(" CheckInterval: ").append(checkInterval) - .append(" maxDelay: ").append(maxWriteDelay) - .append(" maxSize: ").append(maxWriteSize) - .append(" and Counter: "); - if (trafficCounter != null) { - builder.append(trafficCounter); - } else { - builder.append("none"); - } - return builder.toString(); - } - - /** - * Calculate the size of the given {@link Object}. - * - * This implementation supports {@link ByteBuf} and {@link ByteBufHolder}. Sub-classes may override this. - * - * @param msg - * the msg for which the size should be calculated. - * @return size the size of the msg or {@code -1} if unknown. - */ - protected long calculateSize(Object msg) { - if (msg instanceof ByteBuf) { - return ((ByteBuf) msg).readableBytes(); - } - if (msg instanceof ByteBufHolder) { - return ((ByteBufHolder) msg).content().readableBytes(); - } - return -1; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/traffic/ChannelTrafficShapingHandler.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/traffic/ChannelTrafficShapingHandler.java deleted file mode 100755 index 3c25ecab3c..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/traffic/ChannelTrafficShapingHandler.java +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.traffic; - -import java.util.ArrayDeque; -import java.util.concurrent.TimeUnit; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelPromise; - -/** - *

This implementation of the {@link AbstractTrafficShapingHandler} is for channel - * traffic shaping, that is to say a per channel limitation of the bandwidth.

- *

Note the index used in {@code OutboundBuffer.setUserDefinedWritability(index, boolean)} is 1.

- * - *

The general use should be as follow:

- *
    - *
  • Add in your pipeline a new ChannelTrafficShapingHandler.

    - *

    ChannelTrafficShapingHandler myHandler = new ChannelTrafficShapingHandler();

    - *

    pipeline.addLast(myHandler);

    - * - *

    Note that this handler has a Pipeline Coverage of "one" which means a new handler must be created - * for each new channel as the counter cannot be shared among all channels..

    - * - *

    Other arguments can be passed like write or read limitation (in bytes/s where 0 means no limitation) - * or the check interval (in millisecond) that represents the delay between two computations of the - * bandwidth and so the call back of the doAccounting method (0 means no accounting at all).

    - * - *

    A value of 0 means no accounting for checkInterval. If you need traffic shaping but no such accounting, - * it is recommended to set a positive value, even if it is high since the precision of the - * Traffic Shaping depends on the period where the traffic is computed. The highest the interval, - * the less precise the traffic shaping will be. It is suggested as higher value something close - * to 5 or 10 minutes.

    - * - *

    maxTimeToWait, by default set to 15s, allows to specify an upper bound of time shaping.

    - *
  • - *
  • In your handler, you should consider to use the {@code channel.isWritable()} and - * {@code channelWritabilityChanged(ctx)} to handle writability, or through - * {@code future.addListener(new GenericFutureListener())} on the future returned by - * {@code ctx.write()}.
  • - *
  • You shall also consider to have object size in read or write operations relatively adapted to - * the bandwidth you required: for instance having 10 MB objects for 10KB/s will lead to burst effect, - * while having 100 KB objects for 1 MB/s should be smoothly handle by this TrafficShaping handler.

  • - *
  • Some configuration methods will be taken as best effort, meaning - * that all already scheduled traffics will not be - * changed, but only applied to new traffics.

    - *

    So the expected usage of those methods are to be used not too often, - * accordingly to the traffic shaping configuration.

  • - *
- */ -public class ChannelTrafficShapingHandler extends AbstractTrafficShapingHandler { - private final ArrayDeque messagesQueue = new ArrayDeque(); - private long queueSize; - - /** - * Create a new instance. - * - * @param writeLimit - * 0 or a limit in bytes/s - * @param readLimit - * 0 or a limit in bytes/s - * @param checkInterval - * The delay between two computations of performances for - * channels or 0 if no stats are to be computed. - * @param maxTime - * The maximum delay to wait in case of traffic excess. - */ - public ChannelTrafficShapingHandler(long writeLimit, long readLimit, - long checkInterval, long maxTime) { - super(writeLimit, readLimit, checkInterval, maxTime); - } - - /** - * Create a new instance using default - * max time as delay allowed value of 15000 ms. - * - * @param writeLimit - * 0 or a limit in bytes/s - * @param readLimit - * 0 or a limit in bytes/s - * @param checkInterval - * The delay between two computations of performances for - * channels or 0 if no stats are to be computed. - */ - public ChannelTrafficShapingHandler(long writeLimit, - long readLimit, long checkInterval) { - super(writeLimit, readLimit, checkInterval); - } - - /** - * Create a new instance using default Check Interval value of 1000 ms and - * max time as delay allowed value of 15000 ms. - * - * @param writeLimit - * 0 or a limit in bytes/s - * @param readLimit - * 0 or a limit in bytes/s - */ - public ChannelTrafficShapingHandler(long writeLimit, - long readLimit) { - super(writeLimit, readLimit); - } - - /** - * Create a new instance using - * default max time as delay allowed value of 15000 ms and no limit. - * - * @param checkInterval - * The delay between two computations of performances for - * channels or 0 if no stats are to be computed. - */ - public ChannelTrafficShapingHandler(long checkInterval) { - super(checkInterval); - } - - @Override - public void handlerAdded(ChannelHandlerContext ctx) throws Exception { - TrafficCounter trafficCounter = new TrafficCounter(this, ctx.executor(), "ChannelTC" + - ctx.channel().hashCode(), checkInterval); - setTrafficCounter(trafficCounter); - trafficCounter.start(); - super.handlerAdded(ctx); - } - - @Override - public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { - trafficCounter.stop(); - // write order control - synchronized (this) { - if (ctx.channel().isActive()) { - for (ToSend toSend : messagesQueue) { - long size = calculateSize(toSend.toSend); - trafficCounter.bytesRealWriteFlowControl(size); - queueSize -= size; - ctx.write(toSend.toSend, toSend.promise); - } - } else { - for (ToSend toSend : messagesQueue) { - if (toSend.toSend instanceof ByteBuf) { - ((ByteBuf) toSend.toSend).release(); - } - } - } - messagesQueue.clear(); - } - releaseWriteSuspended(ctx); - releaseReadSuspended(ctx); - super.handlerRemoved(ctx); - } - - private static final class ToSend { - final long relativeTimeAction; - final Object toSend; - final ChannelPromise promise; - - private ToSend(final long delay, final Object toSend, final ChannelPromise promise) { - relativeTimeAction = delay; - this.toSend = toSend; - this.promise = promise; - } - } - - @Override - void submitWrite(final ChannelHandlerContext ctx, final Object msg, - final long size, final long delay, final long now, - final ChannelPromise promise) { - final ToSend newToSend; - // write order control - synchronized (this) { - if (delay == 0 && messagesQueue.isEmpty()) { - trafficCounter.bytesRealWriteFlowControl(size); - ctx.write(msg, promise); - return; - } - newToSend = new ToSend(delay + now, msg, promise); - messagesQueue.addLast(newToSend); - queueSize += size; - checkWriteSuspend(ctx, delay, queueSize); - } - final long futureNow = newToSend.relativeTimeAction; - ctx.executor().schedule(new Runnable() { - @Override - public void run() { - sendAllValid(ctx, futureNow); - } - }, delay, TimeUnit.MILLISECONDS); - } - - private void sendAllValid(final ChannelHandlerContext ctx, final long now) { - // write order control - synchronized (this) { - ToSend newToSend = messagesQueue.pollFirst(); - for (; newToSend != null; newToSend = messagesQueue.pollFirst()) { - if (newToSend.relativeTimeAction <= now) { - long size = calculateSize(newToSend.toSend); - trafficCounter.bytesRealWriteFlowControl(size); - queueSize -= size; - ctx.write(newToSend.toSend, newToSend.promise); - } else { - messagesQueue.addFirst(newToSend); - break; - } - } - if (messagesQueue.isEmpty()) { - releaseWriteSuspended(ctx); - } - } - ctx.flush(); - } - - /** - * @return current size in bytes of the write buffer. - */ - public long queueSize() { - return queueSize; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/traffic/GlobalChannelTrafficCounter.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/traffic/GlobalChannelTrafficCounter.java deleted file mode 100755 index 2f9842d401..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/traffic/GlobalChannelTrafficCounter.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.traffic; - -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -import com.ai.cloud.io.netty.handler.traffic.GlobalChannelTrafficShapingHandler.PerChannel; - -/** - * Version for {@link GlobalChannelTrafficShapingHandler}. - * This TrafficCounter is the Global one, and its special property is to directly handle - * other channel's TrafficCounters. In particular, there are no scheduler for those - * channel's TrafficCounters because it is managed by this one. - */ -public class GlobalChannelTrafficCounter extends TrafficCounter { - /** - * @param trafficShapingHandler the associated {@link GlobalChannelTrafficShapingHandler}. - * @param executor the underlying executor service for scheduling checks (both Global and per Channel). - * @param name the name given to this monitor. - * @param checkInterval the checkInterval in millisecond between two computations. - */ - public GlobalChannelTrafficCounter(GlobalChannelTrafficShapingHandler trafficShapingHandler, - ScheduledExecutorService executor, String name, long checkInterval) { - super(trafficShapingHandler, executor, name, checkInterval); - if (executor == null) { - throw new IllegalArgumentException("Executor must not be null"); - } - } - - /** - * Class to implement monitoring at fix delay. - * This version is Mixed in the way it mixes Global and Channel counters. - */ - private static class MixedTrafficMonitoringTask implements Runnable { - /** - * The associated TrafficShapingHandler - */ - private final GlobalChannelTrafficShapingHandler trafficShapingHandler1; - - /** - * The associated TrafficCounter - */ - private final TrafficCounter counter; - - /** - * @param trafficShapingHandler The parent handler to which this task needs to callback to for accounting. - * @param counter The parent TrafficCounter that we need to reset the statistics for. - */ - MixedTrafficMonitoringTask( - GlobalChannelTrafficShapingHandler trafficShapingHandler, - TrafficCounter counter) { - trafficShapingHandler1 = trafficShapingHandler; - this.counter = counter; - } - - @Override - public void run() { - if (!counter.monitorActive) { - return; - } - long newLastTime = milliSecondFromNano(); - counter.resetAccounting(newLastTime); - for (PerChannel perChannel : trafficShapingHandler1.channelQueues.values()) { - perChannel.channelTrafficCounter.resetAccounting(newLastTime); - } - trafficShapingHandler1.doAccounting(counter); - counter.scheduledFuture = counter.executor.schedule(this, counter.checkInterval.get(), - TimeUnit.MILLISECONDS); - } - } - - /** - * Start the monitoring process. - */ - @Override - public synchronized void start() { - if (monitorActive) { - return; - } - lastTime.set(milliSecondFromNano()); - long localCheckInterval = checkInterval.get(); - if (localCheckInterval > 0) { - monitorActive = true; - monitor = new MixedTrafficMonitoringTask((GlobalChannelTrafficShapingHandler) trafficShapingHandler, this); - scheduledFuture = - executor.schedule(monitor, localCheckInterval, TimeUnit.MILLISECONDS); - } - } - - /** - * Stop the monitoring process. - */ - @Override - public synchronized void stop() { - if (!monitorActive) { - return; - } - monitorActive = false; - resetAccounting(milliSecondFromNano()); - trafficShapingHandler.doAccounting(this); - if (scheduledFuture != null) { - scheduledFuture.cancel(true); - } - } - - @Override - public void resetCumulativeTime() { - for (PerChannel perChannel : - ((GlobalChannelTrafficShapingHandler) trafficShapingHandler).channelQueues.values()) { - perChannel.channelTrafficCounter.resetCumulativeTime(); - } - super.resetCumulativeTime(); - } - -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/traffic/GlobalChannelTrafficShapingHandler.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/traffic/GlobalChannelTrafficShapingHandler.java deleted file mode 100755 index 5d5b83cdb4..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/traffic/GlobalChannelTrafficShapingHandler.java +++ /dev/null @@ -1,775 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.traffic; - -import java.util.AbstractCollection; -import java.util.ArrayDeque; -import java.util.Collection; -import java.util.Iterator; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelConfig; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelPromise; -import com.ai.cloud.io.netty.channel.ChannelHandler.Sharable; -import com.ai.cloud.io.netty.util.Attribute; -import com.ai.cloud.io.netty.util.concurrent.EventExecutor; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * This implementation of the {@link AbstractTrafficShapingHandler} is for global - * and per channel traffic shaping, that is to say a global limitation of the bandwidth, whatever - * the number of opened channels and a per channel limitation of the bandwidth.

- * This version shall not be in the same pipeline than other TrafficShapingHandler.

- * - * The general use should be as follow:
- *
    - *
  • Create your unique GlobalChannelTrafficShapingHandler like:

    - * GlobalChannelTrafficShapingHandler myHandler = new GlobalChannelTrafficShapingHandler(executor);

    - * The executor could be the underlying IO worker pool
    - * pipeline.addLast(myHandler);

    - * - * Note that this handler has a Pipeline Coverage of "all" which means only one such handler must be created - * and shared among all channels as the counter must be shared among all channels.

    - * - * Other arguments can be passed like write or read limitation (in bytes/s where 0 means no limitation) - * or the check interval (in millisecond) that represents the delay between two computations of the - * bandwidth and so the call back of the doAccounting method (0 means no accounting at all).
    - * Note that as this is a fusion of both Global and Channel Traffic Shaping, limits are in 2 sets, - * respectively Global and Channel.

    - * - * A value of 0 means no accounting for checkInterval. If you need traffic shaping but no such accounting, - * it is recommended to set a positive value, even if it is high since the precision of the - * Traffic Shaping depends on the period where the traffic is computed. The highest the interval, - * the less precise the traffic shaping will be. It is suggested as higher value something close - * to 5 or 10 minutes.

    - * - * maxTimeToWait, by default set to 15s, allows to specify an upper bound of time shaping.

    - *
  • - *
  • In your handler, you should consider to use the {@code channel.isWritable()} and - * {@code channelWritabilityChanged(ctx)} to handle writability, or through - * {@code future.addListener(new GenericFutureListener())} on the future returned by - * {@code ctx.write()}.
  • - *
  • You shall also consider to have object size in read or write operations relatively adapted to - * the bandwidth you required: for instance having 10 MB objects for 10KB/s will lead to burst effect, - * while having 100 KB objects for 1 MB/s should be smoothly handle by this TrafficShaping handler.

  • - *
  • Some configuration methods will be taken as best effort, meaning - * that all already scheduled traffics will not be - * changed, but only applied to new traffics.
    - * So the expected usage of those methods are to be used not too often, - * accordingly to the traffic shaping configuration.
  • - *

- * - * Be sure to call {@link #release()} once this handler is not needed anymore to release all internal resources. - * This will not shutdown the {@link EventExecutor} as it may be shared, so you need to do this by your own. - */ -@Sharable -public class GlobalChannelTrafficShapingHandler extends AbstractTrafficShapingHandler { - private static final InternalLogger logger = - InternalLoggerFactory.getInstance(GlobalChannelTrafficShapingHandler.class); - /** - * All queues per channel - */ - final ConcurrentMap channelQueues = PlatformDependent.newConcurrentHashMap(); - - /** - * Global queues size - */ - private final AtomicLong queuesSize = new AtomicLong(); - - /** - * Maximum cumulative writing bytes for one channel among all (as long as channels stay the same) - */ - private final AtomicLong cumulativeWrittenBytes = new AtomicLong(); - - /** - * Maximum cumulative read bytes for one channel among all (as long as channels stay the same) - */ - private final AtomicLong cumulativeReadBytes = new AtomicLong(); - - /** - * Max size in the list before proposing to stop writing new objects from next handlers - * for all channel (global) - */ - volatile long maxGlobalWriteSize = DEFAULT_MAX_SIZE * 100; // default 400MB - - /** - * Limit in B/s to apply to write - */ - private volatile long writeChannelLimit; - - /** - * Limit in B/s to apply to read - */ - private volatile long readChannelLimit; - - private static final float DEFAULT_DEVIATION = 0.1F; - private static final float MAX_DEVIATION = 0.4F; - private static final float DEFAULT_SLOWDOWN = 0.4F; - private static final float DEFAULT_ACCELERATION = -0.1F; - private volatile float maxDeviation; - private volatile float accelerationFactor; - private volatile float slowDownFactor; - private volatile boolean readDeviationActive; - private volatile boolean writeDeviationActive; - - static final class PerChannel { - ArrayDeque messagesQueue; - TrafficCounter channelTrafficCounter; - long queueSize; - long lastWriteTimestamp; - long lastReadTimestamp; - } - - /** - * Create the global TrafficCounter - */ - void createGlobalTrafficCounter(ScheduledExecutorService executor) { - // Default - setMaxDeviation(DEFAULT_DEVIATION, DEFAULT_SLOWDOWN, DEFAULT_ACCELERATION); - if (executor == null) { - throw new IllegalArgumentException("Executor must not be null"); - } - TrafficCounter tc = new GlobalChannelTrafficCounter(this, executor, "GlobalChannelTC", checkInterval); - setTrafficCounter(tc); - tc.start(); - } - - @Override - int userDefinedWritabilityIndex() { - return AbstractTrafficShapingHandler.GLOBALCHANNEL_DEFAULT_USER_DEFINED_WRITABILITY_INDEX; - } - - /** - * Create a new instance. - * - * @param executor - * the {@link ScheduledExecutorService} to use for the {@link TrafficCounter}. - * @param writeGlobalLimit - * 0 or a limit in bytes/s - * @param readGlobalLimit - * 0 or a limit in bytes/s - * @param writeChannelLimit - * 0 or a limit in bytes/s - * @param readChannelLimit - * 0 or a limit in bytes/s - * @param checkInterval - * The delay between two computations of performances for - * channels or 0 if no stats are to be computed. - * @param maxTime - * The maximum delay to wait in case of traffic excess. - */ - public GlobalChannelTrafficShapingHandler(ScheduledExecutorService executor, - long writeGlobalLimit, long readGlobalLimit, - long writeChannelLimit, long readChannelLimit, - long checkInterval, long maxTime) { - super(writeGlobalLimit, readGlobalLimit, checkInterval, maxTime); - createGlobalTrafficCounter(executor); - this.writeChannelLimit = writeChannelLimit; - this.readChannelLimit = readChannelLimit; - } - - /** - * Create a new instance. - * - * @param executor - * the {@link ScheduledExecutorService} to use for the {@link TrafficCounter}. - * @param writeGlobalLimit - * 0 or a limit in bytes/s - * @param readGlobalLimit - * 0 or a limit in bytes/s - * @param writeChannelLimit - * 0 or a limit in bytes/s - * @param readChannelLimit - * 0 or a limit in bytes/s - * @param checkInterval - * The delay between two computations of performances for - * channels or 0 if no stats are to be computed. - */ - public GlobalChannelTrafficShapingHandler(ScheduledExecutorService executor, - long writeGlobalLimit, long readGlobalLimit, - long writeChannelLimit, long readChannelLimit, - long checkInterval) { - super(writeGlobalLimit, readGlobalLimit, checkInterval); - this.writeChannelLimit = writeChannelLimit; - this.readChannelLimit = readChannelLimit; - createGlobalTrafficCounter(executor); - } - - /** - * Create a new instance. - * - * @param executor - * the {@link ScheduledExecutorService} to use for the {@link TrafficCounter}. - * @param writeGlobalLimit - * 0 or a limit in bytes/s - * @param readGlobalLimit - * 0 or a limit in bytes/s - * @param writeChannelLimit - * 0 or a limit in bytes/s - * @param readChannelLimit - * 0 or a limit in bytes/s - */ - public GlobalChannelTrafficShapingHandler(ScheduledExecutorService executor, - long writeGlobalLimit, long readGlobalLimit, - long writeChannelLimit, long readChannelLimit) { - super(writeGlobalLimit, readGlobalLimit); - this.writeChannelLimit = writeChannelLimit; - this.readChannelLimit = readChannelLimit; - createGlobalTrafficCounter(executor); - } - - /** - * Create a new instance. - * - * @param executor - * the {@link ScheduledExecutorService} to use for the {@link TrafficCounter}. - * @param checkInterval - * The delay between two computations of performances for - * channels or 0 if no stats are to be computed. - */ - public GlobalChannelTrafficShapingHandler(ScheduledExecutorService executor, long checkInterval) { - super(checkInterval); - createGlobalTrafficCounter(executor); - } - - /** - * Create a new instance. - * - * @param executor - * the {@link ScheduledExecutorService} to use for the {@link TrafficCounter}. - */ - public GlobalChannelTrafficShapingHandler(ScheduledExecutorService executor) { - createGlobalTrafficCounter(executor); - } - - /** - * @return the current max deviation - */ - public float maxDeviation() { - return maxDeviation; - } - - /** - * @return the current acceleration factor - */ - public float accelerationFactor() { - return accelerationFactor; - } - - /** - * @return the current slow down factor - */ - public float slowDownFactor() { - return slowDownFactor; - } - - /** - * @param maxDeviation - * the maximum deviation to allow during computation of average, default deviation - * being 0.1, so +/-10% of the desired bandwidth. Maximum being 0.4. - * @param slowDownFactor - * the factor set as +x% to the too fast client (minimal value being 0, meaning no - * slow down factor), default being 40% (0.4). - * @param accelerationFactor - * the factor set as -x% to the too slow client (maximal value being 0, meaning no - * acceleration factor), default being -10% (-0.1). - */ - public void setMaxDeviation(float maxDeviation, float slowDownFactor, float accelerationFactor) { - if (maxDeviation > MAX_DEVIATION) { - throw new IllegalArgumentException("maxDeviation must be <= " + MAX_DEVIATION); - } - if (slowDownFactor < 0) { - throw new IllegalArgumentException("slowDownFactor must be >= 0"); - } - if (accelerationFactor > 0) { - throw new IllegalArgumentException("accelerationFactor must be <= 0"); - } - this.maxDeviation = maxDeviation; - this.accelerationFactor = 1 + accelerationFactor; - this.slowDownFactor = 1 + slowDownFactor; - } - - private void computeDeviationCumulativeBytes() { - // compute the maximum cumulativeXxxxBytes among still connected Channels - long maxWrittenBytes = 0; - long maxReadBytes = 0; - long minWrittenBytes = Long.MAX_VALUE; - long minReadBytes = Long.MAX_VALUE; - for (PerChannel perChannel : channelQueues.values()) { - long value = perChannel.channelTrafficCounter.cumulativeWrittenBytes(); - if (maxWrittenBytes < value) { - maxWrittenBytes = value; - } - if (minWrittenBytes > value) { - minWrittenBytes = value; - } - value = perChannel.channelTrafficCounter.cumulativeReadBytes(); - if (maxReadBytes < value) { - maxReadBytes = value; - } - if (minReadBytes > value) { - minReadBytes = value; - } - } - boolean multiple = channelQueues.size() > 1; - readDeviationActive = multiple && minReadBytes < maxReadBytes / 2; - writeDeviationActive = multiple && minWrittenBytes < maxWrittenBytes / 2; - cumulativeWrittenBytes.set(maxWrittenBytes); - cumulativeReadBytes.set(maxReadBytes); - } - - @Override - protected void doAccounting(TrafficCounter counter) { - computeDeviationCumulativeBytes(); - super.doAccounting(counter); - } - - private long computeBalancedWait(float maxLocal, float maxGlobal, long wait) { - if (maxGlobal == 0) { - // no change - return wait; - } - float ratio = maxLocal / maxGlobal; - // if in the boundaries, same value - if (ratio > maxDeviation) { - if (ratio < 1 - maxDeviation) { - return wait; - } else { - ratio = slowDownFactor; - if (wait < MINIMAL_WAIT) { - wait = MINIMAL_WAIT; - } - } - } else { - ratio = accelerationFactor; - } - return (long) (wait * ratio); - } - - /** - * @return the maxGlobalWriteSize - */ - public long getMaxGlobalWriteSize() { - return maxGlobalWriteSize; - } - - /** - * Note the change will be taken as best effort, meaning - * that all already scheduled traffics will not be - * changed, but only applied to new traffics.
- * So the expected usage of this method is to be used not too often, - * accordingly to the traffic shaping configuration. - * - * @param maxGlobalWriteSize the maximum Global Write Size allowed in the buffer - * globally for all channels before write suspended is set. - */ - public void setMaxGlobalWriteSize(long maxGlobalWriteSize) { - if (maxGlobalWriteSize <= 0) { - throw new IllegalArgumentException("maxGlobalWriteSize must be positive"); - } - this.maxGlobalWriteSize = maxGlobalWriteSize; - } - - /** - * @return the global size of the buffers for all queues. - */ - public long queuesSize() { - return queuesSize.get(); - } - - /** - * @param newWriteLimit Channel write limit - * @param newReadLimit Channel read limit - */ - public void configureChannel(long newWriteLimit, long newReadLimit) { - writeChannelLimit = newWriteLimit; - readChannelLimit = newReadLimit; - long now = TrafficCounter.milliSecondFromNano(); - for (PerChannel perChannel : channelQueues.values()) { - perChannel.channelTrafficCounter.resetAccounting(now); - } - } - - /** - * @return Channel write limit - */ - public long getWriteChannelLimit() { - return writeChannelLimit; - } - - /** - * @param writeLimit Channel write limit - */ - public void setWriteChannelLimit(long writeLimit) { - writeChannelLimit = writeLimit; - long now = TrafficCounter.milliSecondFromNano(); - for (PerChannel perChannel : channelQueues.values()) { - perChannel.channelTrafficCounter.resetAccounting(now); - } - } - - /** - * @return Channel read limit - */ - public long getReadChannelLimit() { - return readChannelLimit; - } - - /** - * @param readLimit Channel read limit - */ - public void setReadChannelLimit(long readLimit) { - readChannelLimit = readLimit; - long now = TrafficCounter.milliSecondFromNano(); - for (PerChannel perChannel : channelQueues.values()) { - perChannel.channelTrafficCounter.resetAccounting(now); - } - } - - /** - * Release all internal resources of this instance. - */ - public final void release() { - trafficCounter.stop(); - } - - private PerChannel getOrSetPerChannel(ChannelHandlerContext ctx) { - // ensure creation is limited to one thread per channel - Channel channel = ctx.channel(); - Integer key = channel.hashCode(); - PerChannel perChannel = channelQueues.get(key); - if (perChannel == null) { - perChannel = new PerChannel(); - perChannel.messagesQueue = new ArrayDeque(); - // Don't start it since managed through the Global one - perChannel.channelTrafficCounter = new TrafficCounter(this, null, "ChannelTC" + - ctx.channel().hashCode(), checkInterval); - perChannel.queueSize = 0L; - perChannel.lastReadTimestamp = TrafficCounter.milliSecondFromNano(); - perChannel.lastWriteTimestamp = perChannel.lastReadTimestamp; - channelQueues.put(key, perChannel); - } - return perChannel; - } - - @Override - public void handlerAdded(ChannelHandlerContext ctx) throws Exception { - getOrSetPerChannel(ctx); - trafficCounter.resetCumulativeTime(); - super.handlerAdded(ctx); - } - - @Override - public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { - trafficCounter.resetCumulativeTime(); - Channel channel = ctx.channel(); - Integer key = channel.hashCode(); - PerChannel perChannel = channelQueues.remove(key); - if (perChannel != null) { - // write operations need synchronization - synchronized (perChannel) { - if (channel.isActive()) { - for (ToSend toSend : perChannel.messagesQueue) { - long size = calculateSize(toSend.toSend); - trafficCounter.bytesRealWriteFlowControl(size); - perChannel.channelTrafficCounter.bytesRealWriteFlowControl(size); - perChannel.queueSize -= size; - queuesSize.addAndGet(-size); - ctx.write(toSend.toSend, toSend.promise); - } - } else { - queuesSize.addAndGet(-perChannel.queueSize); - for (ToSend toSend : perChannel.messagesQueue) { - if (toSend.toSend instanceof ByteBuf) { - ((ByteBuf) toSend.toSend).release(); - } - } - } - perChannel.messagesQueue.clear(); - } - } - releaseWriteSuspended(ctx); - releaseReadSuspended(ctx); - super.handlerRemoved(ctx); - } - - @Override - public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception { - long size = calculateSize(msg); - long now = TrafficCounter.milliSecondFromNano(); - if (size > 0) { - // compute the number of ms to wait before reopening the channel - long waitGlobal = trafficCounter.readTimeToWait(size, getReadLimit(), maxTime, now); - Integer key = ctx.channel().hashCode(); - PerChannel perChannel = channelQueues.get(key); - long wait = 0; - if (perChannel != null) { - wait = perChannel.channelTrafficCounter.readTimeToWait(size, readChannelLimit, maxTime, now); - if (readDeviationActive) { - // now try to balance between the channels - long maxLocalRead; - maxLocalRead = perChannel.channelTrafficCounter.cumulativeReadBytes(); - long maxGlobalRead = cumulativeReadBytes.get(); - if (maxLocalRead <= 0) { - maxLocalRead = 0; - } - if (maxGlobalRead < maxLocalRead) { - maxGlobalRead = maxLocalRead; - } - wait = computeBalancedWait(maxLocalRead, maxGlobalRead, wait); - } - } - if (wait < waitGlobal) { - wait = waitGlobal; - } - wait = checkWaitReadTime(ctx, wait, now); - if (wait >= MINIMAL_WAIT) { // At least 10ms seems a minimal - // time in order to try to limit the traffic - // Only AutoRead AND HandlerActive True means Context Active - ChannelConfig config = ctx.channel().config(); - if (logger.isDebugEnabled()) { - logger.debug("Read Suspend: " + wait + ':' + config.isAutoRead() + ':' - + isHandlerActive(ctx)); - } - if (config.isAutoRead() && isHandlerActive(ctx)) { - config.setAutoRead(false); - ctx.attr(READ_SUSPENDED).set(true); - // Create a Runnable to reactive the read if needed. If one was create before it will just be - // reused to limit object creation - Attribute attr = ctx.attr(REOPEN_TASK); - Runnable reopenTask = attr.get(); - if (reopenTask == null) { - reopenTask = new ReopenReadTimerTask(ctx); - attr.set(reopenTask); - } - ctx.executor().schedule(reopenTask, wait, TimeUnit.MILLISECONDS); - if (logger.isDebugEnabled()) { - logger.debug("Suspend final status => " + config.isAutoRead() + ':' - + isHandlerActive(ctx) + " will reopened at: " + wait); - } - } - } - } - informReadOperation(ctx, now); - ctx.fireChannelRead(msg); - } - - @Override - protected long checkWaitReadTime(final ChannelHandlerContext ctx, long wait, final long now) { - Integer key = ctx.channel().hashCode(); - PerChannel perChannel = channelQueues.get(key); - if (perChannel != null) { - if (wait > maxTime && now + wait - perChannel.lastReadTimestamp > maxTime) { - wait = maxTime; - } - } - return wait; - } - - @Override - protected void informReadOperation(final ChannelHandlerContext ctx, final long now) { - Integer key = ctx.channel().hashCode(); - PerChannel perChannel = channelQueues.get(key); - if (perChannel != null) { - perChannel.lastReadTimestamp = now; - } - } - - private static final class ToSend { - final long relativeTimeAction; - final Object toSend; - final ChannelPromise promise; - final long size; - - private ToSend(final long delay, final Object toSend, final long size, final ChannelPromise promise) { - relativeTimeAction = delay; - this.toSend = toSend; - this.size = size; - this.promise = promise; - } - } - - protected long maximumCumulativeWrittenBytes() { - return cumulativeWrittenBytes.get(); - } - - protected long maximumCumulativeReadBytes() { - return cumulativeReadBytes.get(); - } - - /** - * To allow for instance doAccounting to use the TrafficCounter per channel. - * @return the list of TrafficCounters that exists at the time of the call. - */ - public Collection channelTrafficCounters() { - return new AbstractCollection() { - @Override - public Iterator iterator() { - return new Iterator() { - final Iterator iter = channelQueues.values().iterator(); - @Override - public boolean hasNext() { - return iter.hasNext(); - } - @Override - public TrafficCounter next() { - return iter.next().channelTrafficCounter; - } - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - @Override - public int size() { - return channelQueues.size(); - } - }; - } - - @Override - public void write(final ChannelHandlerContext ctx, final Object msg, final ChannelPromise promise) - throws Exception { - long size = calculateSize(msg); - long now = TrafficCounter.milliSecondFromNano(); - if (size > 0) { - // compute the number of ms to wait before continue with the channel - long waitGlobal = trafficCounter.writeTimeToWait(size, getWriteLimit(), maxTime, now); - Integer key = ctx.channel().hashCode(); - PerChannel perChannel = channelQueues.get(key); - long wait = 0; - if (perChannel != null) { - wait = perChannel.channelTrafficCounter.writeTimeToWait(size, writeChannelLimit, maxTime, now); - if (writeDeviationActive) { - // now try to balance between the channels - long maxLocalWrite; - maxLocalWrite = perChannel.channelTrafficCounter.cumulativeWrittenBytes(); - long maxGlobalWrite = cumulativeWrittenBytes.get(); - if (maxLocalWrite <= 0) { - maxLocalWrite = 0; - } - if (maxGlobalWrite < maxLocalWrite) { - maxGlobalWrite = maxLocalWrite; - } - wait = computeBalancedWait(maxLocalWrite, maxGlobalWrite, wait); - } - } - if (wait < waitGlobal) { - wait = waitGlobal; - } - if (wait >= MINIMAL_WAIT) { - if (logger.isDebugEnabled()) { - logger.debug("Write suspend: " + wait + ':' + ctx.channel().config().isAutoRead() + ':' - + isHandlerActive(ctx)); - } - submitWrite(ctx, msg, size, wait, now, promise); - return; - } - } - // to maintain order of write - submitWrite(ctx, msg, size, 0, now, promise); - } - - @Override - protected void submitWrite(final ChannelHandlerContext ctx, final Object msg, - final long size, final long writedelay, final long now, - final ChannelPromise promise) { - Channel channel = ctx.channel(); - Integer key = channel.hashCode(); - PerChannel perChannel = channelQueues.get(key); - if (perChannel == null) { - // in case write occurs before handlerAdded is raized for this handler - // imply a synchronized only if needed - perChannel = getOrSetPerChannel(ctx); - } - final ToSend newToSend; - long delay = writedelay; - boolean globalSizeExceeded = false; - // write operations need synchronization - synchronized (perChannel) { - if (writedelay == 0 && perChannel.messagesQueue.isEmpty()) { - trafficCounter.bytesRealWriteFlowControl(size); - perChannel.channelTrafficCounter.bytesRealWriteFlowControl(size); - ctx.write(msg, promise); - perChannel.lastWriteTimestamp = now; - return; - } - if (delay > maxTime && now + delay - perChannel.lastWriteTimestamp > maxTime) { - delay = maxTime; - } - newToSend = new ToSend(delay + now, msg, size, promise); - perChannel.messagesQueue.addLast(newToSend); - perChannel.queueSize += size; - queuesSize.addAndGet(size); - checkWriteSuspend(ctx, delay, perChannel.queueSize); - if (queuesSize.get() > maxGlobalWriteSize) { - globalSizeExceeded = true; - } - } - if (globalSizeExceeded) { - setUserDefinedWritability(ctx, false); - } - final long futureNow = newToSend.relativeTimeAction; - final PerChannel forSchedule = perChannel; - ctx.executor().schedule(new Runnable() { - @Override - public void run() { - sendAllValid(ctx, forSchedule, futureNow); - } - }, delay, TimeUnit.MILLISECONDS); - } - - private void sendAllValid(final ChannelHandlerContext ctx, final PerChannel perChannel, final long now) { - // write operations need synchronization - synchronized (perChannel) { - ToSend newToSend = perChannel.messagesQueue.pollFirst(); - for (; newToSend != null; newToSend = perChannel.messagesQueue.pollFirst()) { - if (newToSend.relativeTimeAction <= now) { - long size = newToSend.size; - trafficCounter.bytesRealWriteFlowControl(size); - perChannel.channelTrafficCounter.bytesRealWriteFlowControl(size); - perChannel.queueSize -= size; - queuesSize.addAndGet(-size); - ctx.write(newToSend.toSend, newToSend.promise); - perChannel.lastWriteTimestamp = now; - } else { - perChannel.messagesQueue.addFirst(newToSend); - break; - } - } - if (perChannel.messagesQueue.isEmpty()) { - releaseWriteSuspended(ctx); - } - } - ctx.flush(); - } - - @Override - public String toString() { - return new StringBuilder(340).append(super.toString()) - .append(" Write Channel Limit: ").append(writeChannelLimit) - .append(" Read Channel Limit: ").append(readChannelLimit).toString(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/traffic/GlobalTrafficShapingHandler.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/traffic/GlobalTrafficShapingHandler.java deleted file mode 100755 index c59d887594..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/traffic/GlobalTrafficShapingHandler.java +++ /dev/null @@ -1,394 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.traffic; - -import java.util.ArrayDeque; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; - -import com.ai.cloud.io.netty.buffer.ByteBuf; -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelPromise; -import com.ai.cloud.io.netty.channel.ChannelHandler.Sharable; -import com.ai.cloud.io.netty.util.concurrent.EventExecutor; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - -/** - *

This implementation of the {@link AbstractTrafficShapingHandler} is for global - * traffic shaping, that is to say a global limitation of the bandwidth, whatever - * the number of opened channels.

- *

Note the index used in {@code OutboundBuffer.setUserDefinedWritability(index, boolean)} is 2.

- * - *

The general use should be as follow:

- *
    - *
  • Create your unique GlobalTrafficShapingHandler like:

    - *

    GlobalTrafficShapingHandler myHandler = new GlobalTrafficShapingHandler(executor);

    - *

    The executor could be the underlying IO worker pool

    - *

    pipeline.addLast(myHandler);

    - * - *

    Note that this handler has a Pipeline Coverage of "all" which means only one such handler must be created - * and shared among all channels as the counter must be shared among all channels.

    - * - *

    Other arguments can be passed like write or read limitation (in bytes/s where 0 means no limitation) - * or the check interval (in millisecond) that represents the delay between two computations of the - * bandwidth and so the call back of the doAccounting method (0 means no accounting at all).

    - * - *

    A value of 0 means no accounting for checkInterval. If you need traffic shaping but no such accounting, - * it is recommended to set a positive value, even if it is high since the precision of the - * Traffic Shaping depends on the period where the traffic is computed. The highest the interval, - * the less precise the traffic shaping will be. It is suggested as higher value something close - * to 5 or 10 minutes.

    - * - *

    maxTimeToWait, by default set to 15s, allows to specify an upper bound of time shaping.

    - *
  • - *
  • In your handler, you should consider to use the {@code channel.isWritable()} and - * {@code channelWritabilityChanged(ctx)} to handle writability, or through - * {@code future.addListener(new GenericFutureListener())} on the future returned by - * {@code ctx.write()}.
  • - *
  • You shall also consider to have object size in read or write operations relatively adapted to - * the bandwidth you required: for instance having 10 MB objects for 10KB/s will lead to burst effect, - * while having 100 KB objects for 1 MB/s should be smoothly handle by this TrafficShaping handler.

  • - *
  • Some configuration methods will be taken as best effort, meaning - * that all already scheduled traffics will not be - * changed, but only applied to new traffics.

    - * So the expected usage of those methods are to be used not too often, - * accordingly to the traffic shaping configuration.
  • - *
- * - * Be sure to call {@link #release()} once this handler is not needed anymore to release all internal resources. - * This will not shutdown the {@link EventExecutor} as it may be shared, so you need to do this by your own. - */ -@Sharable -public class GlobalTrafficShapingHandler extends AbstractTrafficShapingHandler { - /** - * All queues per channel - */ - private final ConcurrentMap channelQueues = PlatformDependent.newConcurrentHashMap(); - - /** - * Global queues size - */ - private final AtomicLong queuesSize = new AtomicLong(); - - /** - * Max size in the list before proposing to stop writing new objects from next handlers - * for all channel (global) - */ - long maxGlobalWriteSize = DEFAULT_MAX_SIZE * 100; // default 400MB - - private static final class PerChannel { - ArrayDeque messagesQueue; - long queueSize; - long lastWriteTimestamp; - long lastReadTimestamp; - } - - /** - * Create the global TrafficCounter. - */ - void createGlobalTrafficCounter(ScheduledExecutorService executor) { - if (executor == null) { - throw new NullPointerException("executor"); - } - TrafficCounter tc = new TrafficCounter(this, executor, "GlobalTC", checkInterval); - setTrafficCounter(tc); - tc.start(); - } - - /** - * Create a new instance. - * - * @param executor - * the {@link ScheduledExecutorService} to use for the {@link TrafficCounter}. - * @param writeLimit - * 0 or a limit in bytes/s - * @param readLimit - * 0 or a limit in bytes/s - * @param checkInterval - * The delay between two computations of performances for - * channels or 0 if no stats are to be computed. - * @param maxTime - * The maximum delay to wait in case of traffic excess. - */ - public GlobalTrafficShapingHandler(ScheduledExecutorService executor, long writeLimit, long readLimit, - long checkInterval, long maxTime) { - super(writeLimit, readLimit, checkInterval, maxTime); - createGlobalTrafficCounter(executor); - } - - /** - * Create a new instance using - * default max time as delay allowed value of 15000 ms. - * - * @param executor - * the {@link ScheduledExecutorService} to use for the {@link TrafficCounter}. - * @param writeLimit - * 0 or a limit in bytes/s - * @param readLimit - * 0 or a limit in bytes/s - * @param checkInterval - * The delay between two computations of performances for - * channels or 0 if no stats are to be computed. - */ - public GlobalTrafficShapingHandler(ScheduledExecutorService executor, long writeLimit, - long readLimit, long checkInterval) { - super(writeLimit, readLimit, checkInterval); - createGlobalTrafficCounter(executor); - } - - /** - * Create a new instance using default Check Interval value of 1000 ms and - * default max time as delay allowed value of 15000 ms. - * - * @param executor - * the {@link ScheduledExecutorService} to use for the {@link TrafficCounter}. - * @param writeLimit - * 0 or a limit in bytes/s - * @param readLimit - * 0 or a limit in bytes/s - */ - public GlobalTrafficShapingHandler(ScheduledExecutorService executor, long writeLimit, - long readLimit) { - super(writeLimit, readLimit); - createGlobalTrafficCounter(executor); - } - - /** - * Create a new instance using - * default max time as delay allowed value of 15000 ms and no limit. - * - * @param executor - * the {@link ScheduledExecutorService} to use for the {@link TrafficCounter}. - * @param checkInterval - * The delay between two computations of performances for - * channels or 0 if no stats are to be computed. - */ - public GlobalTrafficShapingHandler(ScheduledExecutorService executor, long checkInterval) { - super(checkInterval); - createGlobalTrafficCounter(executor); - } - - /** - * Create a new instance using default Check Interval value of 1000 ms and - * default max time as delay allowed value of 15000 ms and no limit. - * - * @param executor - * the {@link ScheduledExecutorService} to use for the {@link TrafficCounter}. - */ - public GlobalTrafficShapingHandler(EventExecutor executor) { - createGlobalTrafficCounter(executor); - } - - /** - * @return the maxGlobalWriteSize default value being 400 MB. - */ - public long getMaxGlobalWriteSize() { - return maxGlobalWriteSize; - } - - /** - * Note the change will be taken as best effort, meaning - * that all already scheduled traffics will not be - * changed, but only applied to new traffics.
- * So the expected usage of this method is to be used not too often, - * accordingly to the traffic shaping configuration. - * - * @param maxGlobalWriteSize the maximum Global Write Size allowed in the buffer - * globally for all channels before write suspended is set, - * default value being 400 MB. - */ - public void setMaxGlobalWriteSize(long maxGlobalWriteSize) { - this.maxGlobalWriteSize = maxGlobalWriteSize; - } - - /** - * @return the global size of the buffers for all queues. - */ - public long queuesSize() { - return queuesSize.get(); - } - - /** - * Release all internal resources of this instance. - */ - public final void release() { - trafficCounter.stop(); - } - - private PerChannel getOrSetPerChannel(ChannelHandlerContext ctx) { - // ensure creation is limited to one thread per channel - Channel channel = ctx.channel(); - Integer key = channel.hashCode(); - PerChannel perChannel = channelQueues.get(key); - if (perChannel == null) { - perChannel = new PerChannel(); - perChannel.messagesQueue = new ArrayDeque(); - perChannel.queueSize = 0L; - perChannel.lastReadTimestamp = TrafficCounter.milliSecondFromNano(); - perChannel.lastWriteTimestamp = perChannel.lastReadTimestamp; - channelQueues.put(key, perChannel); - } - return perChannel; - } - - @Override - public void handlerAdded(ChannelHandlerContext ctx) throws Exception { - getOrSetPerChannel(ctx); - super.handlerAdded(ctx); - } - - @Override - public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { - Channel channel = ctx.channel(); - Integer key = channel.hashCode(); - PerChannel perChannel = channelQueues.remove(key); - if (perChannel != null) { - // write operations need synchronization - synchronized (perChannel) { - if (channel.isActive()) { - for (ToSend toSend : perChannel.messagesQueue) { - long size = calculateSize(toSend.toSend); - trafficCounter.bytesRealWriteFlowControl(size); - perChannel.queueSize -= size; - queuesSize.addAndGet(-size); - ctx.write(toSend.toSend, toSend.promise); - } - } else { - queuesSize.addAndGet(-perChannel.queueSize); - for (ToSend toSend : perChannel.messagesQueue) { - if (toSend.toSend instanceof ByteBuf) { - ((ByteBuf) toSend.toSend).release(); - } - } - } - perChannel.messagesQueue.clear(); - } - } - releaseWriteSuspended(ctx); - releaseReadSuspended(ctx); - super.handlerRemoved(ctx); - } - - @Override - long checkWaitReadTime(final ChannelHandlerContext ctx, long wait, final long now) { - Integer key = ctx.channel().hashCode(); - PerChannel perChannel = channelQueues.get(key); - if (perChannel != null) { - if (wait > maxTime && now + wait - perChannel.lastReadTimestamp > maxTime) { - wait = maxTime; - } - } - return wait; - } - - @Override - void informReadOperation(final ChannelHandlerContext ctx, final long now) { - Integer key = ctx.channel().hashCode(); - PerChannel perChannel = channelQueues.get(key); - if (perChannel != null) { - perChannel.lastReadTimestamp = now; - } - } - - private static final class ToSend { - final long relativeTimeAction; - final Object toSend; - final long size; - final ChannelPromise promise; - - private ToSend(final long delay, final Object toSend, final long size, final ChannelPromise promise) { - relativeTimeAction = delay; - this.toSend = toSend; - this.size = size; - this.promise = promise; - } - } - - @Override - void submitWrite(final ChannelHandlerContext ctx, final Object msg, - final long size, final long writedelay, final long now, - final ChannelPromise promise) { - Channel channel = ctx.channel(); - Integer key = channel.hashCode(); - PerChannel perChannel = channelQueues.get(key); - if (perChannel == null) { - // in case write occurs before handlerAdded is raized for this handler - // imply a synchronized only if needed - perChannel = getOrSetPerChannel(ctx); - } - final ToSend newToSend; - long delay = writedelay; - boolean globalSizeExceeded = false; - // write operations need synchronization - synchronized (perChannel) { - if (writedelay == 0 && perChannel.messagesQueue.isEmpty()) { - trafficCounter.bytesRealWriteFlowControl(size); - ctx.write(msg, promise); - perChannel.lastWriteTimestamp = now; - return; - } - if (delay > maxTime && now + delay - perChannel.lastWriteTimestamp > maxTime) { - delay = maxTime; - } - newToSend = new ToSend(delay + now, msg, size, promise); - perChannel.messagesQueue.addLast(newToSend); - perChannel.queueSize += size; - queuesSize.addAndGet(size); - checkWriteSuspend(ctx, delay, perChannel.queueSize); - if (queuesSize.get() > maxGlobalWriteSize) { - globalSizeExceeded = true; - } - } - if (globalSizeExceeded) { - setUserDefinedWritability(ctx, false); - } - final long futureNow = newToSend.relativeTimeAction; - final PerChannel forSchedule = perChannel; - ctx.executor().schedule(new Runnable() { - @Override - public void run() { - sendAllValid(ctx, forSchedule, futureNow); - } - }, delay, TimeUnit.MILLISECONDS); - } - - private void sendAllValid(final ChannelHandlerContext ctx, final PerChannel perChannel, final long now) { - // write operations need synchronization - synchronized (perChannel) { - ToSend newToSend = perChannel.messagesQueue.pollFirst(); - for (; newToSend != null; newToSend = perChannel.messagesQueue.pollFirst()) { - if (newToSend.relativeTimeAction <= now) { - long size = newToSend.size; - trafficCounter.bytesRealWriteFlowControl(size); - perChannel.queueSize -= size; - queuesSize.addAndGet(-size); - ctx.write(newToSend.toSend, newToSend.promise); - perChannel.lastWriteTimestamp = now; - } else { - perChannel.messagesQueue.addFirst(newToSend); - break; - } - } - if (perChannel.messagesQueue.isEmpty()) { - releaseWriteSuspended(ctx); - } - } - ctx.flush(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/traffic/TrafficCounter.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/traffic/TrafficCounter.java deleted file mode 100755 index f096d6b32f..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/traffic/TrafficCounter.java +++ /dev/null @@ -1,624 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.handler.traffic; - -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; - -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * Counts the number of read and written bytes for rate-limiting traffic. - *

- * It computes the statistics for both inbound and outbound traffic periodically at the given - * {@code checkInterval}, and calls the {@link AbstractTrafficShapingHandler#doAccounting(TrafficCounter)} method back. - * If the {@code checkInterval} is {@code 0}, no accounting will be done and statistics will only be computed at each - * receive or write operation. - *

- */ -public class TrafficCounter { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(TrafficCounter.class); - - /** - * @return the time in ms using nanoTime, so not real EPOCH time but elapsed time in ms. - */ - public static long milliSecondFromNano() { - return System.nanoTime() / 1000000; - } - - /** - * Current written bytes - */ - private final AtomicLong currentWrittenBytes = new AtomicLong(); - - /** - * Current read bytes - */ - private final AtomicLong currentReadBytes = new AtomicLong(); - - /** - * Last writing time during current check interval - */ - private long writingTime; - - /** - * Last reading delay during current check interval - */ - private long readingTime; - - /** - * Long life written bytes - */ - private final AtomicLong cumulativeWrittenBytes = new AtomicLong(); - - /** - * Long life read bytes - */ - private final AtomicLong cumulativeReadBytes = new AtomicLong(); - - /** - * Last Time where cumulative bytes where reset to zero: this time is a real EPOC time (informative only) - */ - private long lastCumulativeTime; - - /** - * Last writing bandwidth - */ - private long lastWriteThroughput; - - /** - * Last reading bandwidth - */ - private long lastReadThroughput; - - /** - * Last Time Check taken - */ - final AtomicLong lastTime = new AtomicLong(); - - /** - * Last written bytes number during last check interval - */ - private volatile long lastWrittenBytes; - - /** - * Last read bytes number during last check interval - */ - private volatile long lastReadBytes; - - /** - * Last future writing time during last check interval - */ - private volatile long lastWritingTime; - - /** - * Last reading time during last check interval - */ - private volatile long lastReadingTime; - - /** - * Real written bytes - */ - private final AtomicLong realWrittenBytes = new AtomicLong(); - - /** - * Real writing bandwidth - */ - private long realWriteThroughput; - - /** - * Delay between two captures - */ - final AtomicLong checkInterval = new AtomicLong(AbstractTrafficShapingHandler.DEFAULT_CHECK_INTERVAL); - - // default 1 s - - /** - * Name of this Monitor - */ - final String name; - - /** - * The associated TrafficShapingHandler - */ - final AbstractTrafficShapingHandler trafficShapingHandler; - - /** - * Executor that will run the monitor - */ - final ScheduledExecutorService executor; - /** - * Monitor created once in start() - */ - Runnable monitor; - /** - * used in stop() to cancel the timer - */ - volatile ScheduledFuture scheduledFuture; - - /** - * Is Monitor active - */ - volatile boolean monitorActive; - - /** - * Class to implement monitoring at fix delay - * - */ - private final class TrafficMonitoringTask implements Runnable { - @Override - public void run() { - if (!monitorActive) { - return; - } - resetAccounting(milliSecondFromNano()); - if (trafficShapingHandler != null) { - trafficShapingHandler.doAccounting(TrafficCounter.this); - } - scheduledFuture = executor.schedule(this, checkInterval.get(), TimeUnit.MILLISECONDS); - } - } - - /** - * Start the monitoring process. - */ - public synchronized void start() { - if (monitorActive) { - return; - } - lastTime.set(milliSecondFromNano()); - long localCheckInterval = checkInterval.get(); - // if executor is null, it means it is piloted by a GlobalChannelTrafficCounter, so no executor - if (localCheckInterval > 0 && executor != null) { - monitorActive = true; - monitor = new TrafficMonitoringTask(); - scheduledFuture = - executor.schedule(monitor, localCheckInterval, TimeUnit.MILLISECONDS); - } - } - - /** - * Stop the monitoring process. - */ - public synchronized void stop() { - if (!monitorActive) { - return; - } - monitorActive = false; - resetAccounting(milliSecondFromNano()); - if (trafficShapingHandler != null) { - trafficShapingHandler.doAccounting(this); - } - if (scheduledFuture != null) { - scheduledFuture.cancel(true); - } - } - - /** - * Reset the accounting on Read and Write. - * - * @param newLastTime the milliseconds unix timestamp that we should be considered up-to-date for. - */ - synchronized void resetAccounting(long newLastTime) { - long interval = newLastTime - lastTime.getAndSet(newLastTime); - if (interval == 0) { - // nothing to do - return; - } - if (logger.isDebugEnabled() && interval > checkInterval() << 1) { - logger.debug("Acct schedule not ok: " + interval + " > 2*" + checkInterval() + " from " + name); - } - lastReadBytes = currentReadBytes.getAndSet(0); - lastWrittenBytes = currentWrittenBytes.getAndSet(0); - lastReadThroughput = lastReadBytes * 1000 / interval; - // nb byte / checkInterval in ms * 1000 (1s) - lastWriteThroughput = lastWrittenBytes * 1000 / interval; - // nb byte / checkInterval in ms * 1000 (1s) - realWriteThroughput = realWrittenBytes.getAndSet(0) * 1000 / interval; - lastWritingTime = Math.max(lastWritingTime, writingTime); - lastReadingTime = Math.max(lastReadingTime, readingTime); - } - - /** - * Constructor with the {@link AbstractTrafficShapingHandler} that hosts it, the {@link ScheduledExecutorService} - * to use, its name, the checkInterval between two computations in milliseconds. - * - * @param executor - * the underlying executor service for scheduling checks, might be null when used - * from {@link GlobalChannelTrafficCounter}. - * @param name - * the name given to this monitor. - * @param checkInterval - * the checkInterval in millisecond between two computations. - */ - public TrafficCounter(ScheduledExecutorService executor, String name, long checkInterval) { - if (name == null) { - throw new NullPointerException("name"); - } - - trafficShapingHandler = null; - this.executor = executor; - this.name = name; - - init(checkInterval); - } - - /** - * Constructor with the {@link AbstractTrafficShapingHandler} that hosts it, the Timer to use, its - * name, the checkInterval between two computations in millisecond. - * - * @param trafficShapingHandler - * the associated AbstractTrafficShapingHandler. - * @param executor - * the underlying executor service for scheduling checks, might be null when used - * from {@link GlobalChannelTrafficCounter}. - * @param name - * the name given to this monitor. - * @param checkInterval - * the checkInterval in millisecond between two computations. - */ - public TrafficCounter( - AbstractTrafficShapingHandler trafficShapingHandler, ScheduledExecutorService executor, - String name, long checkInterval) { - - if (trafficShapingHandler == null) { - throw new IllegalArgumentException("trafficShapingHandler"); - } - if (name == null) { - throw new NullPointerException("name"); - } - - this.trafficShapingHandler = trafficShapingHandler; - this.executor = executor; - this.name = name; - - init(checkInterval); - } - - private void init(long checkInterval) { - // absolute time: informative only - lastCumulativeTime = System.currentTimeMillis(); - writingTime = milliSecondFromNano(); - readingTime = writingTime; - lastWritingTime = writingTime; - lastReadingTime = writingTime; - configure(checkInterval); - } - - /** - * Change checkInterval between two computations in millisecond. - * - * @param newcheckInterval - * The new check interval (in milliseconds) - */ - public void configure(long newcheckInterval) { - long newInterval = newcheckInterval / 10 * 10; - if (checkInterval.getAndSet(newInterval) != newInterval) { - if (newInterval <= 0) { - stop(); - // No more active monitoring - lastTime.set(milliSecondFromNano()); - } else { - // Start if necessary - start(); - } - } - } - - /** - * Computes counters for Read. - * - * @param recv - * the size in bytes to read - */ - void bytesRecvFlowControl(long recv) { - currentReadBytes.addAndGet(recv); - cumulativeReadBytes.addAndGet(recv); - } - - /** - * Computes counters for Write. - * - * @param write - * the size in bytes to write - */ - void bytesWriteFlowControl(long write) { - currentWrittenBytes.addAndGet(write); - cumulativeWrittenBytes.addAndGet(write); - } - - /** - * Computes counters for Real Write. - * - * @param write - * the size in bytes to write - */ - void bytesRealWriteFlowControl(long write) { - realWrittenBytes.addAndGet(write); - } - - /** - * @return the current checkInterval between two computations of traffic counter - * in millisecond. - */ - public long checkInterval() { - return checkInterval.get(); - } - - /** - * @return the Read Throughput in bytes/s computes in the last check interval. - */ - public long lastReadThroughput() { - return lastReadThroughput; - } - - /** - * @return the Write Throughput in bytes/s computes in the last check interval. - */ - public long lastWriteThroughput() { - return lastWriteThroughput; - } - - /** - * @return the number of bytes read during the last check Interval. - */ - public long lastReadBytes() { - return lastReadBytes; - } - - /** - * @return the number of bytes written during the last check Interval. - */ - public long lastWrittenBytes() { - return lastWrittenBytes; - } - - /** - * @return the current number of bytes read since the last checkInterval. - */ - public long currentReadBytes() { - return currentReadBytes.get(); - } - - /** - * @return the current number of bytes written since the last check Interval. - */ - public long currentWrittenBytes() { - return currentWrittenBytes.get(); - } - - /** - * @return the Time in millisecond of the last check as of System.currentTimeMillis(). - */ - public long lastTime() { - return lastTime.get(); - } - - /** - * @return the cumulativeWrittenBytes - */ - public long cumulativeWrittenBytes() { - return cumulativeWrittenBytes.get(); - } - - /** - * @return the cumulativeReadBytes - */ - public long cumulativeReadBytes() { - return cumulativeReadBytes.get(); - } - - /** - * @return the lastCumulativeTime in millisecond as of System.currentTimeMillis() - * when the cumulative counters were reset to 0. - */ - public long lastCumulativeTime() { - return lastCumulativeTime; - } - - /** - * @return the realWrittenBytes - */ - public AtomicLong getRealWrittenBytes() { - return realWrittenBytes; - } - - /** - * @return the realWriteThroughput - */ - public long getRealWriteThroughput() { - return realWriteThroughput; - } - - /** - * Reset both read and written cumulative bytes counters and the associated absolute time - * from System.currentTimeMillis(). - */ - public void resetCumulativeTime() { - lastCumulativeTime = System.currentTimeMillis(); - cumulativeReadBytes.set(0); - cumulativeWrittenBytes.set(0); - } - - /** - * @return the name of this TrafficCounter. - */ - public String name() { - return name; - } - - /** - * Returns the time to wait (if any) for the given length message, using the given limitTraffic and the max wait - * time. - * - * @param size - * the recv size - * @param limitTraffic - * the traffic limit in bytes per second. - * @param maxTime - * the max time in ms to wait in case of excess of traffic. - * @return the current time to wait (in ms) if needed for Read operation. - */ - @Deprecated - public long readTimeToWait(final long size, final long limitTraffic, final long maxTime) { - return readTimeToWait(size, limitTraffic, maxTime, milliSecondFromNano()); - } - - /** - * Returns the time to wait (if any) for the given length message, using the given limitTraffic and the max wait - * time. - * - * @param size - * the recv size - * @param limitTraffic - * the traffic limit in bytes per second - * @param maxTime - * the max time in ms to wait in case of excess of traffic. - * @param now the current time - * @return the current time to wait (in ms) if needed for Read operation. - */ - public long readTimeToWait(final long size, final long limitTraffic, final long maxTime, final long now) { - bytesRecvFlowControl(size); - if (size == 0 || limitTraffic == 0) { - return 0; - } - final long lastTimeCheck = lastTime.get(); - long sum = currentReadBytes.get(); - long localReadingTime = readingTime; - long lastRB = lastReadBytes; - final long interval = now - lastTimeCheck; - long pastDelay = Math.max(lastReadingTime - lastTimeCheck, 0); - if (interval > AbstractTrafficShapingHandler.MINIMAL_WAIT) { - // Enough interval time to compute shaping - long time = sum * 1000 / limitTraffic - interval + pastDelay; - if (time > AbstractTrafficShapingHandler.MINIMAL_WAIT) { - if (logger.isDebugEnabled()) { - logger.debug("Time: " + time + ':' + sum + ':' + interval + ':' + pastDelay); - } - if (time > maxTime && now + time - localReadingTime > maxTime) { - time = maxTime; - } - readingTime = Math.max(localReadingTime, now + time); - return time; - } - readingTime = Math.max(localReadingTime, now); - return 0; - } - // take the last read interval check to get enough interval time - long lastsum = sum + lastRB; - long lastinterval = interval + checkInterval.get(); - long time = lastsum * 1000 / limitTraffic - lastinterval + pastDelay; - if (time > AbstractTrafficShapingHandler.MINIMAL_WAIT) { - if (logger.isDebugEnabled()) { - logger.debug("Time: " + time + ':' + lastsum + ':' + lastinterval + ':' + pastDelay); - } - if (time > maxTime && now + time - localReadingTime > maxTime) { - time = maxTime; - } - readingTime = Math.max(localReadingTime, now + time); - return time; - } - readingTime = Math.max(localReadingTime, now); - return 0; - } - - /** - * Returns the time to wait (if any) for the given length message, using the given limitTraffic and - * the max wait time. - * - * @param size - * the write size - * @param limitTraffic - * the traffic limit in bytes per second. - * @param maxTime - * the max time in ms to wait in case of excess of traffic. - * @return the current time to wait (in ms) if needed for Write operation. - */ - @Deprecated - public long writeTimeToWait(final long size, final long limitTraffic, final long maxTime) { - return writeTimeToWait(size, limitTraffic, maxTime, milliSecondFromNano()); - } - - /** - * Returns the time to wait (if any) for the given length message, using the given limitTraffic and - * the max wait time. - * - * @param size - * the write size - * @param limitTraffic - * the traffic limit in bytes per second. - * @param maxTime - * the max time in ms to wait in case of excess of traffic. - * @param now the current time - * @return the current time to wait (in ms) if needed for Write operation. - */ - public long writeTimeToWait(final long size, final long limitTraffic, final long maxTime, final long now) { - bytesWriteFlowControl(size); - if (size == 0 || limitTraffic == 0) { - return 0; - } - final long lastTimeCheck = lastTime.get(); - long sum = currentWrittenBytes.get(); - long lastWB = lastWrittenBytes; - long localWritingTime = writingTime; - long pastDelay = Math.max(lastWritingTime - lastTimeCheck, 0); - final long interval = now - lastTimeCheck; - if (interval > AbstractTrafficShapingHandler.MINIMAL_WAIT) { - // Enough interval time to compute shaping - long time = sum * 1000 / limitTraffic - interval + pastDelay; - if (time > AbstractTrafficShapingHandler.MINIMAL_WAIT) { - if (logger.isDebugEnabled()) { - logger.debug("Time: " + time + ':' + sum + ':' + interval + ':' + pastDelay); - } - if (time > maxTime && now + time - localWritingTime > maxTime) { - time = maxTime; - } - writingTime = Math.max(localWritingTime, now + time); - return time; - } - writingTime = Math.max(localWritingTime, now); - return 0; - } - // take the last write interval check to get enough interval time - long lastsum = sum + lastWB; - long lastinterval = interval + checkInterval.get(); - long time = lastsum * 1000 / limitTraffic - lastinterval + pastDelay; - if (time > AbstractTrafficShapingHandler.MINIMAL_WAIT) { - if (logger.isDebugEnabled()) { - logger.debug("Time: " + time + ':' + lastsum + ':' + lastinterval + ':' + pastDelay); - } - if (time > maxTime && now + time - localWritingTime > maxTime) { - time = maxTime; - } - writingTime = Math.max(localWritingTime, now + time); - return time; - } - writingTime = Math.max(localWritingTime, now); - return 0; - } - - @Override - public String toString() { - return new StringBuilder(165).append("Monitor ").append(name) - .append(" Current Speed Read: ").append(lastReadThroughput >> 10).append(" KB/s, ") - .append("Asked Write: ").append(lastWriteThroughput >> 10).append(" KB/s, ") - .append("Real Write: ").append(realWriteThroughput >> 10).append(" KB/s, ") - .append("Current Read: ").append(currentReadBytes.get() >> 10).append(" KB, ") - .append("Current asked Write: ").append(currentWrittenBytes.get() >> 10).append(" KB, ") - .append("Current real Write: ").append(realWrittenBytes.get() >> 10).append(" KB").toString(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/traffic/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/traffic/package-info.java deleted file mode 100755 index 4074657c89..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/handler/traffic/package-info.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * Implementation of a Traffic Shaping Handler and Dynamic Statistics. - * - *

The main goal of this package is to allow you to shape the traffic (bandwidth limitation), - * but also to get statistics on how many bytes are read or written. Both functions can - * be active or inactive (traffic or statistics).

- * - *

Two classes implement this behavior: - *

    - *
  • {@link TrafficCounter}: this class implements the counters needed by the handlers. - * It can be accessed to get some extra information like the read or write bytes since last check, the read and write - * bandwidth from last check...
  • - * - *
  • {@link AbstractTrafficShapingHandler}: this abstract class implements the kernel - * of traffic shaping. It could be extended to fit your needs. Two classes are proposed as default - * implementations: see {@link ChannelTrafficShapingHandler} and see {@link GlobalTrafficShapingHandler} - * respectively for Channel traffic shaping and Global traffic shaping.
  • - *

- * - *

Both inbound and outbound traffic can be shaped independently. This is done by either passing in - * the desired limiting values to the constructors of both the Channel and Global traffic shaping handlers, - * or by calling the configure method on the {@link AbstractTrafficShapingHandler}. A value of - * 0 for either parameter indicates that there should be no limitation. This allows you to monitor the - * incoming and outgoing traffic without shaping.

- * - *

To activate or deactivate the statistics, you can adjust the delay to a low (suggested not less than 200ms - * for efficiency reasons) or a high value (let say 24H in millisecond is huge enough to not get the problem) - * or even using 0 which means no computation will be done.

- * - *

If you want to do anything with these statistics, just override the doAccounting method.
- * This interval can be changed either from the method configure in {@link AbstractTrafficShapingHandler} - * or directly using the method configure of {@link TrafficCounter}.

- * - *

Note that a new {@link ChannelTrafficShapingHandler} must be created for each new channel, - * but only one {@link GlobalTrafficShapingHandler} must be created for all channels.

- * - *

Note also that you can create different GlobalTrafficShapingHandler if you want to separate classes of - * channels (for instance either from business point of view or from bind address point of view).

- */ -package com.ai.cloud.io.netty.handler.traffic; - diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/AbstractReferenceCounted.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/AbstractReferenceCounted.java deleted file mode 100755 index 2277e79fd2..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/AbstractReferenceCounted.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util; - -import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; - -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - -/** - * Abstract base class for classes wants to implement {@link ReferenceCounted}. - */ -public abstract class AbstractReferenceCounted implements ReferenceCounted { - - private static final AtomicIntegerFieldUpdater refCntUpdater; - - static { - AtomicIntegerFieldUpdater updater = - PlatformDependent.newAtomicIntegerFieldUpdater(AbstractReferenceCounted.class, "refCnt"); - if (updater == null) { - updater = AtomicIntegerFieldUpdater.newUpdater(AbstractReferenceCounted.class, "refCnt"); - } - refCntUpdater = updater; - } - - private volatile int refCnt = 1; - - @Override - public final int refCnt() { - return refCnt; - } - - /** - * An unsafe operation intended for use by a subclass that sets the reference count of the buffer directly - */ - protected final void setRefCnt(int refCnt) { - this.refCnt = refCnt; - } - - @Override - public ReferenceCounted retain() { - for (;;) { - int refCnt = this.refCnt; - if (refCnt == 0) { - throw new IllegalReferenceCountException(0, 1); - } - if (refCnt == Integer.MAX_VALUE) { - throw new IllegalReferenceCountException(Integer.MAX_VALUE, 1); - } - if (refCntUpdater.compareAndSet(this, refCnt, refCnt + 1)) { - break; - } - } - return this; - } - - @Override - public ReferenceCounted retain(int increment) { - if (increment <= 0) { - throw new IllegalArgumentException("increment: " + increment + " (expected: > 0)"); - } - - for (;;) { - int refCnt = this.refCnt; - if (refCnt == 0) { - throw new IllegalReferenceCountException(0, 1); - } - if (refCnt > Integer.MAX_VALUE - increment) { - throw new IllegalReferenceCountException(refCnt, increment); - } - if (refCntUpdater.compareAndSet(this, refCnt, refCnt + increment)) { - break; - } - } - return this; - } - - @Override - public final boolean release() { - for (;;) { - int refCnt = this.refCnt; - if (refCnt == 0) { - throw new IllegalReferenceCountException(0, -1); - } - - if (refCntUpdater.compareAndSet(this, refCnt, refCnt - 1)) { - if (refCnt == 1) { - deallocate(); - return true; - } - return false; - } - } - } - - @Override - public final boolean release(int decrement) { - if (decrement <= 0) { - throw new IllegalArgumentException("decrement: " + decrement + " (expected: > 0)"); - } - - for (;;) { - int refCnt = this.refCnt; - if (refCnt < decrement) { - throw new IllegalReferenceCountException(refCnt, -decrement); - } - - if (refCntUpdater.compareAndSet(this, refCnt, refCnt - decrement)) { - if (refCnt == decrement) { - deallocate(); - return true; - } - return false; - } - } - } - - /** - * Called once {@link #refCnt()} is equals 0. - */ - protected abstract void deallocate(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/Attribute.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/Attribute.java deleted file mode 100755 index b01b12b79b..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/Attribute.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util; - -/** - * An attribute which allows to store a value reference. It may be updated atomically and so is thread-safe. - * - * @param the type of the value it holds. - */ -public interface Attribute { - - /** - * Returns the key of this attribute. - */ - AttributeKey key(); - - /** - * Returns the current value, which may be {@code null} - */ - T get(); - - /** - * Sets the value - */ - void set(T value); - - /** - * Atomically sets to the given value and returns the old value which may be {@code null} if non was set before. - */ - T getAndSet(T value); - - /** - * Atomically sets to the given value if this {@link Attribute}'s value is {@code null}. - * If it was not possible to set the value as it contains a value it will just return the current value. - */ - T setIfAbsent(T value); - - /** - * Removes this attribute from the {@link AttributeMap} and returns the old value. Subsequent {@link #get()} - * calls will return {@code null}. - * - * If you only want to return the old value and clear the {@link Attribute} while still keep it in - * {@link AttributeMap} use {@link #getAndSet(Object)} with a value of {@code null}. - */ - T getAndRemove(); - - /** - * Atomically sets the value to the given updated value if the current value == the expected value. - * If it the set was successful it returns {@code true} otherwise {@code false}. - */ - boolean compareAndSet(T oldValue, T newValue); - - /** - * Removes this attribute from the {@link AttributeMap}. Subsequent {@link #get()} calls will return @{code null}. - * - * If you only want to remove the value and clear the {@link Attribute} while still keep it in - * {@link AttributeMap} use {@link #set(Object)} with a value of {@code null}. - */ - void remove(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/AttributeKey.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/AttributeKey.java deleted file mode 100755 index e6d87b311b..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/AttributeKey.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util; - -import java.util.concurrent.ConcurrentMap; - -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - -import static com.ai.cloud.io.netty.util.internal.ObjectUtil.checkNotNull; - -/** - * Key which can be used to access {@link Attribute} out of the {@link AttributeMap}. Be aware that it is not be - * possible to have multiple keys with the same name. - * - * - * @param the type of the {@link Attribute} which can be accessed via this {@link AttributeKey}. - */ -@SuppressWarnings({ "UnusedDeclaration", "deprecation" }) // 'T' is used only at compile time -public final class AttributeKey extends UniqueName { - - @SuppressWarnings("rawtypes") - private static final ConcurrentMap names = PlatformDependent.newConcurrentHashMap(); - - /** - * Creates a new {@link AttributeKey} with the specified {@param name} or return the already existing - * {@link AttributeKey} for the given name. - */ - @SuppressWarnings("unchecked") - public static AttributeKey valueOf(String name) { - checkNotNull(name, "name"); - AttributeKey option = names.get(name); - if (option == null) { - option = new AttributeKey(name); - AttributeKey old = names.putIfAbsent(name, option); - if (old != null) { - option = old; - } - } - return option; - } - - /** - * Returns {@code true} if a {@link AttributeKey} exists for the given {@code name}. - */ - public static boolean exists(String name) { - checkNotNull(name, "name"); - return names.containsKey(name); - } - - /** - * Creates a new {@link AttributeKey} for the given {@param name} or fail with an - * {@link IllegalArgumentException} if a {@link AttributeKey} for the given {@param name} exists. - */ - @SuppressWarnings("unchecked") - public static AttributeKey newInstance(String name) { - checkNotNull(name, "name"); - AttributeKey option = new AttributeKey(name); - AttributeKey old = names.putIfAbsent(name, option); - if (old != null) { - throw new IllegalArgumentException(String.format("'%s' is already in use", name)); - } - return option; - } - - /** - * @deprecated Use {@link #valueOf(String)} instead. - */ - @Deprecated - public AttributeKey(String name) { - super(name); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/AttributeMap.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/AttributeMap.java deleted file mode 100755 index 072daa4cd0..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/AttributeMap.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util; - -/** - * Holds {@link Attribute}s which can be accessed via {@link AttributeKey}. - * - * Implementations must be Thread-safe. - */ -public interface AttributeMap { - /** - * Get the {@link Attribute} for the given {@link AttributeKey}. This method will never return null, but may return - * an {@link Attribute} which does not have a value set yet. - */ - Attribute attr(AttributeKey key); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/CharsetUtil.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/CharsetUtil.java deleted file mode 100755 index 9a8e3999ac..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/CharsetUtil.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util; - -import java.nio.charset.Charset; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CharsetEncoder; -import java.nio.charset.CodingErrorAction; -import java.util.Map; - -import com.ai.cloud.io.netty.util.internal.InternalThreadLocalMap; - -/** - * A utility class that provides various common operations and constants - * related with {@link Charset} and its relevant classes. - */ -public final class CharsetUtil { - - /** - * 16-bit UTF (UCS Transformation Format) whose byte order is identified by - * an optional byte-order mark - */ - public static final Charset UTF_16 = Charset.forName("UTF-16"); - - /** - * 16-bit UTF (UCS Transformation Format) whose byte order is big-endian - */ - public static final Charset UTF_16BE = Charset.forName("UTF-16BE"); - - /** - * 16-bit UTF (UCS Transformation Format) whose byte order is little-endian - */ - public static final Charset UTF_16LE = Charset.forName("UTF-16LE"); - - /** - * 8-bit UTF (UCS Transformation Format) - */ - public static final Charset UTF_8 = Charset.forName("UTF-8"); - - /** - * ISO Latin Alphabet No. 1, as known as ISO-LATIN-1 - */ - public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1"); - - /** - * 7-bit ASCII, as known as ISO646-US or the Basic Latin block of the - * Unicode character set - */ - public static final Charset US_ASCII = Charset.forName("US-ASCII"); - - /** - * Returns a cached thread-local {@link CharsetEncoder} for the specified - * charset. - */ - public static CharsetEncoder getEncoder(Charset charset) { - if (charset == null) { - throw new NullPointerException("charset"); - } - - Map map = InternalThreadLocalMap.get().charsetEncoderCache(); - CharsetEncoder e = map.get(charset); - if (e != null) { - e.reset(); - e.onMalformedInput(CodingErrorAction.REPLACE); - e.onUnmappableCharacter(CodingErrorAction.REPLACE); - return e; - } - - e = charset.newEncoder(); - e.onMalformedInput(CodingErrorAction.REPLACE); - e.onUnmappableCharacter(CodingErrorAction.REPLACE); - map.put(charset, e); - return e; - } - - /** - * Returns a cached thread-local {@link CharsetDecoder} for the specified - * charset. - */ - public static CharsetDecoder getDecoder(Charset charset) { - if (charset == null) { - throw new NullPointerException("charset"); - } - - Map map = InternalThreadLocalMap.get().charsetDecoderCache(); - CharsetDecoder d = map.get(charset); - if (d != null) { - d.reset(); - d.onMalformedInput(CodingErrorAction.REPLACE); - d.onUnmappableCharacter(CodingErrorAction.REPLACE); - return d; - } - - d = charset.newDecoder(); - d.onMalformedInput(CodingErrorAction.REPLACE); - d.onUnmappableCharacter(CodingErrorAction.REPLACE); - map.put(charset, d); - return d; - } - - private CharsetUtil() { - // Unused - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/DefaultAttributeMap.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/DefaultAttributeMap.java deleted file mode 100755 index 8084a4d991..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/DefaultAttributeMap.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util; - -import java.util.concurrent.atomic.AtomicReference; -import java.util.concurrent.atomic.AtomicReferenceArray; -import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; - -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - -/** - * Default {@link AttributeMap} implementation which use simple synchronization per bucket to keep the memory overhead - * as low as possible. - */ -public class DefaultAttributeMap implements AttributeMap { - - @SuppressWarnings("rawtypes") - private static final AtomicReferenceFieldUpdater updater; - - static { - @SuppressWarnings("rawtypes") - AtomicReferenceFieldUpdater referenceFieldUpdater = - PlatformDependent.newAtomicReferenceFieldUpdater(DefaultAttributeMap.class, "attributes"); - if (referenceFieldUpdater == null) { - referenceFieldUpdater = AtomicReferenceFieldUpdater - .newUpdater(DefaultAttributeMap.class, AtomicReferenceArray.class, "attributes"); - } - updater = referenceFieldUpdater; - } - - private static final int BUCKET_SIZE = 4; - private static final int MASK = BUCKET_SIZE - 1; - - // Initialize lazily to reduce memory consumption; updated by AtomicReferenceFieldUpdater above. - @SuppressWarnings("UnusedDeclaration") - private volatile AtomicReferenceArray> attributes; - - @SuppressWarnings("unchecked") - @Override - public Attribute attr(AttributeKey key) { - if (key == null) { - throw new NullPointerException("key"); - } - AtomicReferenceArray> attributes = this.attributes; - if (attributes == null) { - // Not using ConcurrentHashMap due to high memory consumption. - attributes = new AtomicReferenceArray>(BUCKET_SIZE); - - if (!updater.compareAndSet(this, null, attributes)) { - attributes = this.attributes; - } - } - - int i = index(key); - DefaultAttribute head = attributes.get(i); - if (head == null) { - // No head exists yet which means we may be able to add the attribute without synchronization and just - // use compare and set. At worst we need to fallback to synchronization - head = new DefaultAttribute(key); - if (attributes.compareAndSet(i, null, head)) { - // we were able to add it so return the head right away - return (Attribute) head; - } else { - head = attributes.get(i); - } - } - - synchronized (head) { - DefaultAttribute curr = head; - for (;;) { - if (!curr.removed && curr.key == key) { - return (Attribute) curr; - } - - DefaultAttribute next = curr.next; - if (next == null) { - DefaultAttribute attr = new DefaultAttribute(head, key); - curr.next = attr; - attr.prev = curr; - return attr; - } else { - curr = next; - } - } - } - } - - private static int index(AttributeKey key) { - return key.id() & MASK; - } - - @SuppressWarnings("serial") - private static final class DefaultAttribute extends AtomicReference implements Attribute { - - private static final long serialVersionUID = -2661411462200283011L; - - // The head of the linked-list this attribute belongs to, which may be itself - private final DefaultAttribute head; - private final AttributeKey key; - - // Double-linked list to prev and next node to allow fast removal - private DefaultAttribute prev; - private DefaultAttribute next; - - // Will be set to true one the attribute is removed via getAndRemove() or remove() - private volatile boolean removed; - - DefaultAttribute(DefaultAttribute head, AttributeKey key) { - this.head = head; - this.key = key; - } - - DefaultAttribute(AttributeKey key) { - head = this; - this.key = key; - } - - @Override - public AttributeKey key() { - return key; - } - - @Override - public T setIfAbsent(T value) { - while (!compareAndSet(null, value)) { - T old = get(); - if (old != null) { - return old; - } - } - return null; - } - - @Override - public T getAndRemove() { - removed = true; - T oldValue = getAndSet(null); - remove0(); - return oldValue; - } - - @Override - public void remove() { - removed = true; - set(null); - remove0(); - } - - private void remove0() { - synchronized (head) { - // We only update the linked-list structure if prev != null because if it is null this - // DefaultAttribute acts also as head. The head must never be removed completely and just be - // marked as removed as all synchronization is done on the head itself for each bucket. - // The head itself will be GC'ed once the DefaultAttributeMap is GC'ed. So at most 5 heads will - // be removed lazy as the array size is 5. - if (prev != null) { - prev.next = next; - - if (next != null) { - next.prev = prev; - } - - // Null out prev and next - this will guard against multiple remove0() calls which may corrupt - // the linked list for the bucket. - prev = null; - next = null; - } - } - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/DomainNameMapping.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/DomainNameMapping.java deleted file mode 100755 index 8b34b5d4cd..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/DomainNameMapping.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.util; - -import java.net.IDN; -import java.util.LinkedHashMap; -import java.util.Locale; -import java.util.Map; -import java.util.regex.Pattern; - -import com.ai.cloud.io.netty.util.internal.StringUtil; - -/** - * Maps a domain name to its associated value object. - *

- * DNS wildcard is supported as hostname, so you can use {@code *.netty.io} to match both {@code netty.io} - * and {@code downloads.netty.io}. - *

- */ -public class DomainNameMapping implements Mapping { - - private static final Pattern DNS_WILDCARD_PATTERN = Pattern.compile("^\\*\\..*"); - - private final Map map; - - private final V defaultValue; - - /** - * Creates a default, order-sensitive mapping. If your hostnames are in conflict, the mapping - * will choose the one you add first. - * - * @param defaultValue the default value for {@link #map(String)} to return when nothing matches the input - */ - public DomainNameMapping(V defaultValue) { - this(4, defaultValue); - } - - /** - * Creates a default, order-sensitive mapping. If your hostnames are in conflict, the mapping - * will choose the one you add first. - * - * @param initialCapacity initial capacity for the internal map - * @param defaultValue the default value for {@link #map(String)} to return when nothing matches the input - */ - public DomainNameMapping(int initialCapacity, V defaultValue) { - if (defaultValue == null) { - throw new NullPointerException("defaultValue"); - } - map = new LinkedHashMap(initialCapacity); - this.defaultValue = defaultValue; - } - - /** - * Adds a mapping that maps the specified (optionally wildcard) host name to the specified output value. - *

- * DNS wildcard is supported as hostname. - * For example, you can use {@code *.netty.io} to match {@code netty.io} and {@code downloads.netty.io}. - *

- * - * @param hostname the host name (optionally wildcard) - * @param output the output value that will be returned by {@link #map(String)} when the specified host name - * matches the specified input host name - */ - public DomainNameMapping add(String hostname, V output) { - if (hostname == null) { - throw new NullPointerException("input"); - } - - if (output == null) { - throw new NullPointerException("output"); - } - - map.put(normalizeHostname(hostname), output); - return this; - } - - /** - * Simple function to match DNS wildcard. - */ - private static boolean matches(String hostNameTemplate, String hostName) { - // note that inputs are converted and lowercased already - if (DNS_WILDCARD_PATTERN.matcher(hostNameTemplate).matches()) { - return hostNameTemplate.substring(2).equals(hostName) || - hostName.endsWith(hostNameTemplate.substring(1)); - } else { - return hostNameTemplate.equals(hostName); - } - } - - /** - * IDNA ASCII conversion and case normalization - */ - private static String normalizeHostname(String hostname) { - if (needsNormalization(hostname)) { - hostname = IDN.toASCII(hostname, IDN.ALLOW_UNASSIGNED); - } - return hostname.toLowerCase(Locale.US); - } - - private static boolean needsNormalization(String hostname) { - final int length = hostname.length(); - for (int i = 0; i < length; i ++) { - int c = hostname.charAt(i); - if (c > 0x7F) { - return true; - } - } - return false; - } - - @Override - public V map(String input) { - if (input != null) { - input = normalizeHostname(input); - - for (Map.Entry entry : map.entrySet()) { - if (matches(entry.getKey(), input)) { - return entry.getValue(); - } - } - } - - return defaultValue; - } - - @Override - public String toString() { - return StringUtil.simpleClassName(this) + "(default: " + defaultValue + ", map: " + map + ')'; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/HashedWheelTimer.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/HashedWheelTimer.java deleted file mode 100755 index f1ed073a0e..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/HashedWheelTimer.java +++ /dev/null @@ -1,740 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Queue; -import java.util.Set; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Executors; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; - -import com.ai.cloud.io.netty.util.internal.MpscLinkedQueueNode; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; -import com.ai.cloud.io.netty.util.internal.StringUtil; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * A {@link Timer} optimized for approximated I/O timeout scheduling. - * - *

Tick Duration

- * - * As described with 'approximated', this timer does not execute the scheduled - * {@link TimerTask} on time. {@link HashedWheelTimer}, on every tick, will - * check if there are any {@link TimerTask}s behind the schedule and execute - * them. - *

- * You can increase or decrease the accuracy of the execution timing by - * specifying smaller or larger tick duration in the constructor. In most - * network applications, I/O timeout does not need to be accurate. Therefore, - * the default tick duration is 100 milliseconds and you will not need to try - * different configurations in most cases. - * - *

Ticks per Wheel (Wheel Size)

- * - * {@link HashedWheelTimer} maintains a data structure called 'wheel'. - * To put simply, a wheel is a hash table of {@link TimerTask}s whose hash - * function is 'dead line of the task'. The default number of ticks per wheel - * (i.e. the size of the wheel) is 512. You could specify a larger value - * if you are going to schedule a lot of timeouts. - * - *

Do not create many instances.

- * - * {@link HashedWheelTimer} creates a new thread whenever it is instantiated and - * started. Therefore, you should make sure to create only one instance and - * share it across your application. One of the common mistakes, that makes - * your application unresponsive, is to create a new instance for every connection. - * - *

Implementation Details

- * - * {@link HashedWheelTimer} is based on - * George Varghese and - * Tony Lauck's paper, - * 'Hashed - * and Hierarchical Timing Wheels: data structures to efficiently implement a - * timer facility'. More comprehensive slides are located - * here. - */ -public class HashedWheelTimer implements Timer { - - static final InternalLogger logger = - InternalLoggerFactory.getInstance(HashedWheelTimer.class); - - private static final ResourceLeakDetector leakDetector = - new ResourceLeakDetector( - HashedWheelTimer.class, 1, Runtime.getRuntime().availableProcessors() * 4); - - private static final AtomicIntegerFieldUpdater WORKER_STATE_UPDATER; - static { - AtomicIntegerFieldUpdater workerStateUpdater = - PlatformDependent.newAtomicIntegerFieldUpdater(HashedWheelTimer.class, "workerState"); - if (workerStateUpdater == null) { - workerStateUpdater = AtomicIntegerFieldUpdater.newUpdater(HashedWheelTimer.class, "workerState"); - } - WORKER_STATE_UPDATER = workerStateUpdater; - } - - private final ResourceLeak leak; - private final Worker worker = new Worker(); - private final Thread workerThread; - - public static final int WORKER_STATE_INIT = 0; - public static final int WORKER_STATE_STARTED = 1; - public static final int WORKER_STATE_SHUTDOWN = 2; - @SuppressWarnings({ "unused", "FieldMayBeFinal", "RedundantFieldInitialization" }) - private volatile int workerState = WORKER_STATE_INIT; // 0 - init, 1 - started, 2 - shut down - - private final long tickDuration; - private final HashedWheelBucket[] wheel; - private final int mask; - private final CountDownLatch startTimeInitialized = new CountDownLatch(1); - private final Queue timeouts = PlatformDependent.newMpscQueue(); - private final Queue cancelledTimeouts = PlatformDependent.newMpscQueue(); - - private volatile long startTime; - - /** - * Creates a new timer with the default thread factory - * ({@link Executors#defaultThreadFactory()}), default tick duration, and - * default number of ticks per wheel. - */ - public HashedWheelTimer() { - this(Executors.defaultThreadFactory()); - } - - /** - * Creates a new timer with the default thread factory - * ({@link Executors#defaultThreadFactory()}) and default number of ticks - * per wheel. - * - * @param tickDuration the duration between tick - * @param unit the time unit of the {@code tickDuration} - * @throws NullPointerException if {@code unit} is {@code null} - * @throws IllegalArgumentException if {@code tickDuration} is <= 0 - */ - public HashedWheelTimer(long tickDuration, TimeUnit unit) { - this(Executors.defaultThreadFactory(), tickDuration, unit); - } - - /** - * Creates a new timer with the default thread factory - * ({@link Executors#defaultThreadFactory()}). - * - * @param tickDuration the duration between tick - * @param unit the time unit of the {@code tickDuration} - * @param ticksPerWheel the size of the wheel - * @throws NullPointerException if {@code unit} is {@code null} - * @throws IllegalArgumentException if either of {@code tickDuration} and {@code ticksPerWheel} is <= 0 - */ - public HashedWheelTimer(long tickDuration, TimeUnit unit, int ticksPerWheel) { - this(Executors.defaultThreadFactory(), tickDuration, unit, ticksPerWheel); - } - - /** - * Creates a new timer with the default tick duration and default number of - * ticks per wheel. - * - * @param threadFactory a {@link ThreadFactory} that creates a - * background {@link Thread} which is dedicated to - * {@link TimerTask} execution. - * @throws NullPointerException if {@code threadFactory} is {@code null} - */ - public HashedWheelTimer(ThreadFactory threadFactory) { - this(threadFactory, 100, TimeUnit.MILLISECONDS); - } - - /** - * Creates a new timer with the default number of ticks per wheel. - * - * @param threadFactory a {@link ThreadFactory} that creates a - * background {@link Thread} which is dedicated to - * {@link TimerTask} execution. - * @param tickDuration the duration between tick - * @param unit the time unit of the {@code tickDuration} - * @throws NullPointerException if either of {@code threadFactory} and {@code unit} is {@code null} - * @throws IllegalArgumentException if {@code tickDuration} is <= 0 - */ - public HashedWheelTimer( - ThreadFactory threadFactory, long tickDuration, TimeUnit unit) { - this(threadFactory, tickDuration, unit, 512); - } - - /** - * Creates a new timer. - * - * @param threadFactory a {@link ThreadFactory} that creates a - * background {@link Thread} which is dedicated to - * {@link TimerTask} execution. - * @param tickDuration the duration between tick - * @param unit the time unit of the {@code tickDuration} - * @param ticksPerWheel the size of the wheel - * @throws NullPointerException if either of {@code threadFactory} and {@code unit} is {@code null} - * @throws IllegalArgumentException if either of {@code tickDuration} and {@code ticksPerWheel} is <= 0 - */ - public HashedWheelTimer( - ThreadFactory threadFactory, - long tickDuration, TimeUnit unit, int ticksPerWheel) { - - if (threadFactory == null) { - throw new NullPointerException("threadFactory"); - } - if (unit == null) { - throw new NullPointerException("unit"); - } - if (tickDuration <= 0) { - throw new IllegalArgumentException("tickDuration must be greater than 0: " + tickDuration); - } - if (ticksPerWheel <= 0) { - throw new IllegalArgumentException("ticksPerWheel must be greater than 0: " + ticksPerWheel); - } - - // Normalize ticksPerWheel to power of two and initialize the wheel. - wheel = createWheel(ticksPerWheel); - mask = wheel.length - 1; - - // Convert tickDuration to nanos. - this.tickDuration = unit.toNanos(tickDuration); - - // Prevent overflow. - if (this.tickDuration >= Long.MAX_VALUE / wheel.length) { - throw new IllegalArgumentException(String.format( - "tickDuration: %d (expected: 0 < tickDuration in nanos < %d", - tickDuration, Long.MAX_VALUE / wheel.length)); - } - workerThread = threadFactory.newThread(worker); - - leak = leakDetector.open(this); - } - - private static HashedWheelBucket[] createWheel(int ticksPerWheel) { - if (ticksPerWheel <= 0) { - throw new IllegalArgumentException( - "ticksPerWheel must be greater than 0: " + ticksPerWheel); - } - if (ticksPerWheel > 1073741824) { - throw new IllegalArgumentException( - "ticksPerWheel may not be greater than 2^30: " + ticksPerWheel); - } - - ticksPerWheel = normalizeTicksPerWheel(ticksPerWheel); - HashedWheelBucket[] wheel = new HashedWheelBucket[ticksPerWheel]; - for (int i = 0; i < wheel.length; i ++) { - wheel[i] = new HashedWheelBucket(); - } - return wheel; - } - - private static int normalizeTicksPerWheel(int ticksPerWheel) { - int normalizedTicksPerWheel = 1; - while (normalizedTicksPerWheel < ticksPerWheel) { - normalizedTicksPerWheel <<= 1; - } - return normalizedTicksPerWheel; - } - - /** - * Starts the background thread explicitly. The background thread will - * start automatically on demand even if you did not call this method. - * - * @throws IllegalStateException if this timer has been - * {@linkplain #stop() stopped} already - */ - public void start() { - switch (WORKER_STATE_UPDATER.get(this)) { - case WORKER_STATE_INIT: - if (WORKER_STATE_UPDATER.compareAndSet(this, WORKER_STATE_INIT, WORKER_STATE_STARTED)) { - workerThread.start(); - } - break; - case WORKER_STATE_STARTED: - break; - case WORKER_STATE_SHUTDOWN: - throw new IllegalStateException("cannot be started once stopped"); - default: - throw new Error("Invalid WorkerState"); - } - - // Wait until the startTime is initialized by the worker. - while (startTime == 0) { - try { - startTimeInitialized.await(); - } catch (InterruptedException ignore) { - // Ignore - it will be ready very soon. - } - } - } - - @Override - public Set stop() { - if (Thread.currentThread() == workerThread) { - throw new IllegalStateException( - HashedWheelTimer.class.getSimpleName() + - ".stop() cannot be called from " + - TimerTask.class.getSimpleName()); - } - - if (!WORKER_STATE_UPDATER.compareAndSet(this, WORKER_STATE_STARTED, WORKER_STATE_SHUTDOWN)) { - // workerState can be 0 or 2 at this moment - let it always be 2. - WORKER_STATE_UPDATER.set(this, WORKER_STATE_SHUTDOWN); - - if (leak != null) { - leak.close(); - } - - return Collections.emptySet(); - } - - boolean interrupted = false; - while (workerThread.isAlive()) { - workerThread.interrupt(); - try { - workerThread.join(100); - } catch (InterruptedException ignored) { - interrupted = true; - } - } - - if (interrupted) { - Thread.currentThread().interrupt(); - } - - if (leak != null) { - leak.close(); - } - return worker.unprocessedTimeouts(); - } - - @Override - public Timeout newTimeout(TimerTask task, long delay, TimeUnit unit) { - if (task == null) { - throw new NullPointerException("task"); - } - if (unit == null) { - throw new NullPointerException("unit"); - } - start(); - - // Add the timeout to the timeout queue which will be processed on the next tick. - // During processing all the queued HashedWheelTimeouts will be added to the correct HashedWheelBucket. - long deadline = System.nanoTime() + unit.toNanos(delay) - startTime; - HashedWheelTimeout timeout = new HashedWheelTimeout(this, task, deadline); - timeouts.add(timeout); - return timeout; - } - - private final class Worker implements Runnable { - private final Set unprocessedTimeouts = new HashSet(); - - private long tick; - - @Override - public void run() { - // Initialize the startTime. - startTime = System.nanoTime(); - if (startTime == 0) { - // We use 0 as an indicator for the uninitialized value here, so make sure it's not 0 when initialized. - startTime = 1; - } - - // Notify the other threads waiting for the initialization at start(). - startTimeInitialized.countDown(); - - do { - final long deadline = waitForNextTick(); - if (deadline > 0) { - int idx = (int) (tick & mask); - processCancelledTasks(); - HashedWheelBucket bucket = - wheel[idx]; - transferTimeoutsToBuckets(); - bucket.expireTimeouts(deadline); - tick++; - } - } while (WORKER_STATE_UPDATER.get(HashedWheelTimer.this) == WORKER_STATE_STARTED); - - // Fill the unprocessedTimeouts so we can return them from stop() method. - for (HashedWheelBucket bucket: wheel) { - bucket.clearTimeouts(unprocessedTimeouts); - } - for (;;) { - HashedWheelTimeout timeout = timeouts.poll(); - if (timeout == null) { - break; - } - if (!timeout.isCancelled()) { - unprocessedTimeouts.add(timeout); - } - } - processCancelledTasks(); - } - - private void transferTimeoutsToBuckets() { - // transfer only max. 100000 timeouts per tick to prevent a thread to stale the workerThread when it just - // adds new timeouts in a loop. - for (int i = 0; i < 100000; i++) { - HashedWheelTimeout timeout = timeouts.poll(); - if (timeout == null) { - // all processed - break; - } - if (timeout.state() == HashedWheelTimeout.ST_CANCELLED) { - // Was cancelled in the meantime. - continue; - } - - long calculated = timeout.deadline / tickDuration; - timeout.remainingRounds = (calculated - tick) / wheel.length; - - final long ticks = Math.max(calculated, tick); // Ensure we don't schedule for past. - int stopIndex = (int) (ticks & mask); - - HashedWheelBucket bucket = wheel[stopIndex]; - bucket.addTimeout(timeout); - } - } - - private void processCancelledTasks() { - for (;;) { - Runnable task = cancelledTimeouts.poll(); - if (task == null) { - // all processed - break; - } - try { - task.run(); - } catch (Throwable t) { - if (logger.isWarnEnabled()) { - logger.warn("An exception was thrown while process a cancellation task", t); - } - } - } - } - - /** - * calculate goal nanoTime from startTime and current tick number, - * then wait until that goal has been reached. - * @return Long.MIN_VALUE if received a shutdown request, - * current time otherwise (with Long.MIN_VALUE changed by +1) - */ - private long waitForNextTick() { - long deadline = tickDuration * (tick + 1); - - for (;;) { - final long currentTime = System.nanoTime() - startTime; - long sleepTimeMs = (deadline - currentTime + 999999) / 1000000; - - if (sleepTimeMs <= 0) { - if (currentTime == Long.MIN_VALUE) { - return -Long.MAX_VALUE; - } else { - return currentTime; - } - } - - // Check if we run on windows, as if thats the case we will need - // to round the sleepTime as workaround for a bug that only affect - // the JVM if it runs on windows. - // - // See https://github.com/netty/netty/issues/356 - if (PlatformDependent.isWindows()) { - sleepTimeMs = sleepTimeMs / 10 * 10; - } - - try { - Thread.sleep(sleepTimeMs); - } catch (InterruptedException ignored) { - if (WORKER_STATE_UPDATER.get(HashedWheelTimer.this) == WORKER_STATE_SHUTDOWN) { - return Long.MIN_VALUE; - } - } - } - } - - public Set unprocessedTimeouts() { - return Collections.unmodifiableSet(unprocessedTimeouts); - } - } - - private static final class HashedWheelTimeout extends MpscLinkedQueueNode - implements Timeout { - - private static final int ST_INIT = 0; - private static final int ST_CANCELLED = 1; - private static final int ST_EXPIRED = 2; - private static final AtomicIntegerFieldUpdater STATE_UPDATER; - - static { - AtomicIntegerFieldUpdater updater = - PlatformDependent.newAtomicIntegerFieldUpdater(HashedWheelTimeout.class, "state"); - if (updater == null) { - updater = AtomicIntegerFieldUpdater.newUpdater(HashedWheelTimeout.class, "state"); - } - STATE_UPDATER = updater; - } - - private final HashedWheelTimer timer; - private final TimerTask task; - private final long deadline; - - @SuppressWarnings({"unused", "FieldMayBeFinal", "RedundantFieldInitialization" }) - private volatile int state = ST_INIT; - - // remainingRounds will be calculated and set by Worker.transferTimeoutsToBuckets() before the - // HashedWheelTimeout will be added to the correct HashedWheelBucket. - long remainingRounds; - - // This will be used to chain timeouts in HashedWheelTimerBucket via a double-linked-list. - // As only the workerThread will act on it there is no need for synchronization / volatile. - HashedWheelTimeout next; - HashedWheelTimeout prev; - - // The bucket to which the timeout was added - HashedWheelBucket bucket; - - HashedWheelTimeout(HashedWheelTimer timer, TimerTask task, long deadline) { - this.timer = timer; - this.task = task; - this.deadline = deadline; - } - - @Override - public Timer timer() { - return timer; - } - - @Override - public TimerTask task() { - return task; - } - - @Override - public boolean cancel() { - // only update the state it will be removed from HashedWheelBucket on next tick. - if (!compareAndSetState(ST_INIT, ST_CANCELLED)) { - return false; - } - // If a task should be canceled we create a new Runnable for this to another queue which will - // be processed on each tick. So this means that we will have a GC latency of max. 1 tick duration - // which is good enough. This way we can make again use of our MpscLinkedQueue and so minimize the - // locking / overhead as much as possible. - // - // It is important that we not just add the HashedWheelTimeout itself again as it extends - // MpscLinkedQueueNode and so may still be used as tombstone. - timer.cancelledTimeouts.add(new Runnable() { - @Override - public void run() { - HashedWheelBucket bucket = HashedWheelTimeout.this.bucket; - if (bucket != null) { - bucket.remove(HashedWheelTimeout.this); - } - } - }); - return true; - } - - public boolean compareAndSetState(int expected, int state) { - return STATE_UPDATER.compareAndSet(this, expected, state); - } - - public int state() { - return state; - } - - @Override - public boolean isCancelled() { - return state() == ST_CANCELLED; - } - - @Override - public boolean isExpired() { - return state() == ST_EXPIRED; - } - - @Override - public HashedWheelTimeout value() { - return this; - } - - public void expire() { - if (!compareAndSetState(ST_INIT, ST_EXPIRED)) { - return; - } - - try { - task.run(this); - } catch (Throwable t) { - if (logger.isWarnEnabled()) { - logger.warn("An exception was thrown by " + TimerTask.class.getSimpleName() + '.', t); - } - } - } - - @Override - public String toString() { - final long currentTime = System.nanoTime(); - long remaining = deadline - currentTime + timer.startTime; - - StringBuilder buf = new StringBuilder(192) - .append(StringUtil.simpleClassName(this)) - .append('(') - .append("deadline: "); - if (remaining > 0) { - buf.append(remaining) - .append(" ns later"); - } else if (remaining < 0) { - buf.append(-remaining) - .append(" ns ago"); - } else { - buf.append("now"); - } - - if (isCancelled()) { - buf.append(", cancelled"); - } - - return buf.append(", task: ") - .append(task()) - .append(')') - .toString(); - } - } - - /** - * Bucket that stores HashedWheelTimeouts. These are stored in a linked-list like datastructure to allow easy - * removal of HashedWheelTimeouts in the middle. Also the HashedWheelTimeout act as nodes themself and so no - * extra object creation is needed. - */ - private static final class HashedWheelBucket { - // Used for the linked-list datastructure - private HashedWheelTimeout head; - private HashedWheelTimeout tail; - - /** - * Add {@link HashedWheelTimeout} to this bucket. - */ - public void addTimeout(HashedWheelTimeout timeout) { - assert timeout.bucket == null; - timeout.bucket = this; - if (head == null) { - head = tail = timeout; - } else { - tail.next = timeout; - timeout.prev = tail; - tail = timeout; - } - } - - /** - * Expire all {@link HashedWheelTimeout}s for the given {@code deadline}. - */ - public void expireTimeouts(long deadline) { - HashedWheelTimeout timeout = head; - - // process all timeouts - while (timeout != null) { - boolean remove = false; - if (timeout.remainingRounds <= 0) { - if (timeout.deadline <= deadline) { - timeout.expire(); - } else { - // The timeout was placed into a wrong slot. This should never happen. - throw new IllegalStateException(String.format( - "timeout.deadline (%d) > deadline (%d)", timeout.deadline, deadline)); - } - remove = true; - } else if (timeout.isCancelled()) { - remove = true; - } else { - timeout.remainingRounds --; - } - // store reference to next as we may null out timeout.next in the remove block. - HashedWheelTimeout next = timeout.next; - if (remove) { - remove(timeout); - } - timeout = next; - } - } - - public void remove(HashedWheelTimeout timeout) { - HashedWheelTimeout next = timeout.next; - // remove timeout that was either processed or cancelled by updating the linked-list - if (timeout.prev != null) { - timeout.prev.next = next; - } - if (timeout.next != null) { - timeout.next.prev = timeout.prev; - } - - if (timeout == head) { - // if timeout is also the tail we need to adjust the entry too - if (timeout == tail) { - tail = null; - head = null; - } else { - head = next; - } - } else if (timeout == tail) { - // if the timeout is the tail modify the tail to be the prev node. - tail = timeout.prev; - } - // null out prev, next and bucket to allow for GC. - timeout.prev = null; - timeout.next = null; - timeout.bucket = null; - } - - /** - * Clear this bucket and return all not expired / cancelled {@link Timeout}s. - */ - public void clearTimeouts(Set set) { - for (;;) { - HashedWheelTimeout timeout = pollTimeout(); - if (timeout == null) { - return; - } - if (timeout.isExpired() || timeout.isCancelled()) { - continue; - } - set.add(timeout); - } - } - - private HashedWheelTimeout pollTimeout() { - HashedWheelTimeout head = this.head; - if (head == null) { - return null; - } - HashedWheelTimeout next = head.next; - if (next == null) { - tail = this.head = null; - } else { - this.head = next; - next.prev = null; - } - - // null out prev and next to allow for GC. - head.next = null; - head.prev = null; - head.bucket = null; - return head; - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/IllegalReferenceCountException.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/IllegalReferenceCountException.java deleted file mode 100755 index 08f1e7bd70..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/IllegalReferenceCountException.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.util; - -/** - * An {@link IllegalStateException} which is raised when a user attempts to access a {@link ReferenceCounted} whose - * reference count has been decreased to 0 (and consequently freed). - */ -public class IllegalReferenceCountException extends IllegalStateException { - - private static final long serialVersionUID = -2507492394288153468L; - - public IllegalReferenceCountException() { } - - public IllegalReferenceCountException(int refCnt) { - this("refCnt: " + refCnt); - } - - public IllegalReferenceCountException(int refCnt, int increment) { - this("refCnt: " + refCnt + ", " + (increment > 0? "increment: " + increment : "decrement: " + -increment)); - } - - public IllegalReferenceCountException(String message) { - super(message); - } - - public IllegalReferenceCountException(String message, Throwable cause) { - super(message, cause); - } - - public IllegalReferenceCountException(Throwable cause) { - super(cause); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/Mapping.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/Mapping.java deleted file mode 100755 index 37c1ffc7c0..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/Mapping.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util; - -/** - * Maintains the mapping from the objects of one type to the objects of the other type. - */ -public interface Mapping { - - /** - * Returns mapped value of the specified input. - */ - OUT map(IN input); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/NetUtil.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/NetUtil.java deleted file mode 100755 index 54a983b36e..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/NetUtil.java +++ /dev/null @@ -1,1020 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.net.SocketException; -import java.net.UnknownHostException; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.List; -import java.util.StringTokenizer; - -import com.ai.cloud.io.netty.util.internal.PlatformDependent; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * A class that holds a number of network-related constants. - *

- * This class borrowed some of its methods from a modified fork of the - * Inet6Util class which was part of Apache Harmony. - */ -public final class NetUtil { - - /** - * The {@link Inet4Address} that represents the IPv4 loopback address '127.0.0.1' - */ - public static final Inet4Address LOCALHOST4; - - /** - * The {@link Inet6Address} that represents the IPv6 loopback address '::1' - */ - public static final Inet6Address LOCALHOST6; - - /** - * The {@link InetAddress} that represents the loopback address. If IPv6 stack is available, it will refer to - * {@link #LOCALHOST6}. Otherwise, {@link #LOCALHOST4}. - */ - public static final InetAddress LOCALHOST; - - /** - * The loopback {@link NetworkInterface} of the current machine - */ - public static final NetworkInterface LOOPBACK_IF; - - /** - * The SOMAXCONN value of the current machine. If failed to get the value, {@code 200} is used as a - * default value for Windows or {@code 128} for others. - */ - public static final int SOMAXCONN; - - /** - * This defines how many words (represented as ints) are needed to represent an IPv6 address - */ - private static final int IPV6_WORD_COUNT = 8; - - /** - * The maximum number of characters for an IPV6 string with no scope - */ - private static final int IPV6_MAX_CHAR_COUNT = 39; - - /** - * Number of bytes needed to represent and IPV6 value - */ - private static final int IPV6_BYTE_COUNT = 16; - - /** - * Maximum amount of value adding characters in between IPV6 separators - */ - private static final int IPV6_MAX_CHAR_BETWEEN_SEPARATOR = 4; - - /** - * Minimum number of separators that must be present in an IPv6 string - */ - private static final int IPV6_MIN_SEPARATORS = 2; - - /** - * Maximum number of separators that must be present in an IPv6 string - */ - private static final int IPV6_MAX_SEPARATORS = 8; - - /** - * Number of bytes needed to represent and IPV4 value - */ - private static final int IPV4_BYTE_COUNT = 4; - - /** - * Maximum amount of value adding characters in between IPV4 separators - */ - private static final int IPV4_MAX_CHAR_BETWEEN_SEPARATOR = 3; - - /** - * Number of separators that must be present in an IPv4 string - */ - private static final int IPV4_SEPARATORS = 3; - - /** - * {@code true} if ipv4 should be used on a system that supports ipv4 and ipv6. - */ - private static final boolean IPV4_PREFERRED = Boolean.getBoolean("java.net.preferIPv4Stack"); - - /** - * The logger being used by this class - */ - private static final InternalLogger logger = InternalLoggerFactory.getInstance(NetUtil.class); - - static { - byte[] LOCALHOST4_BYTES = {127, 0, 0, 1}; - byte[] LOCALHOST6_BYTES = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; - - // Create IPv4 loopback address. - Inet4Address localhost4 = null; - try { - localhost4 = (Inet4Address) InetAddress.getByAddress(LOCALHOST4_BYTES); - } catch (Exception e) { - // We should not get here as long as the length of the address is correct. - PlatformDependent.throwException(e); - } - LOCALHOST4 = localhost4; - - // Create IPv6 loopback address. - Inet6Address localhost6 = null; - try { - localhost6 = (Inet6Address) InetAddress.getByAddress(LOCALHOST6_BYTES); - } catch (Exception e) { - // We should not get here as long as the length of the address is correct. - PlatformDependent.throwException(e); - } - LOCALHOST6 = localhost6; - - // Retrieve the list of available network interfaces. - List ifaces = new ArrayList(); - try { - for (Enumeration i = NetworkInterface.getNetworkInterfaces(); i.hasMoreElements();) { - NetworkInterface iface = i.nextElement(); - // Use the interface with proper INET addresses only. - if (iface.getInetAddresses().hasMoreElements()) { - ifaces.add(iface); - } - } - } catch (SocketException e) { - logger.warn("Failed to retrieve the list of available network interfaces", e); - } - - // Find the first loopback interface available from its INET address (127.0.0.1 or ::1) - // Note that we do not use NetworkInterface.isLoopback() in the first place because it takes long time - // on a certain environment. (e.g. Windows with -Djava.net.preferIPv4Stack=true) - NetworkInterface loopbackIface = null; - InetAddress loopbackAddr = null; - loop: for (NetworkInterface iface: ifaces) { - for (Enumeration i = iface.getInetAddresses(); i.hasMoreElements();) { - InetAddress addr = i.nextElement(); - if (addr.isLoopbackAddress()) { - // Found - loopbackIface = iface; - loopbackAddr = addr; - break loop; - } - } - } - - // If failed to find the loopback interface from its INET address, fall back to isLoopback(). - if (loopbackIface == null) { - try { - for (NetworkInterface iface: ifaces) { - if (iface.isLoopback()) { - Enumeration i = iface.getInetAddresses(); - if (i.hasMoreElements()) { - // Found the one with INET address. - loopbackIface = iface; - loopbackAddr = i.nextElement(); - break; - } - } - } - - if (loopbackIface == null) { - logger.warn("Failed to find the loopback interface"); - } - } catch (SocketException e) { - logger.warn("Failed to find the loopback interface", e); - } - } - - if (loopbackIface != null) { - // Found the loopback interface with an INET address. - logger.debug( - "Loopback interface: {} ({}, {})", - loopbackIface.getName(), loopbackIface.getDisplayName(), loopbackAddr.getHostAddress()); - } else { - // Could not find the loopback interface, but we can't leave LOCALHOST as null. - // Use LOCALHOST6 or LOCALHOST4, preferably the IPv6 one. - if (loopbackAddr == null) { - try { - if (NetworkInterface.getByInetAddress(LOCALHOST6) != null) { - logger.debug("Using hard-coded IPv6 localhost address: {}", localhost6); - loopbackAddr = localhost6; - } - } catch (Exception e) { - // Ignore - } finally { - if (loopbackAddr == null) { - logger.debug("Using hard-coded IPv4 localhost address: {}", localhost4); - loopbackAddr = localhost4; - } - } - } - } - - LOOPBACK_IF = loopbackIface; - LOCALHOST = loopbackAddr; - - // As a SecurityManager may prevent reading the somaxconn file we wrap this in a privileged block. - // - // See https://github.com/netty/netty/issues/3680 - SOMAXCONN = AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Integer run() { - // Determine the default somaxconn (server socket backlog) value of the platform. - // The known defaults: - // - Windows NT Server 4.0+: 200 - // - Linux and Mac OS X: 128 - int somaxconn = PlatformDependent.isWindows() ? 200 : 128; - File file = new File("/proc/sys/net/core/somaxconn"); - if (file.exists()) { - BufferedReader in = null; - try { - in = new BufferedReader(new FileReader(file)); - somaxconn = Integer.parseInt(in.readLine()); - if (logger.isDebugEnabled()) { - logger.debug("{}: {}", file, somaxconn); - } - } catch (Exception e) { - logger.debug("Failed to get SOMAXCONN from: {}", file, e); - } finally { - if (in != null) { - try { - in.close(); - } catch (Exception e) { - // Ignored. - } - } - } - } else { - if (logger.isDebugEnabled()) { - logger.debug("{}: {} (non-existent)", file, somaxconn); - } - } - return somaxconn; - } - }); - } - - /** - * Returns {@code true} if ipv4 should be prefered on a system that supports ipv4 and ipv6. - */ - public static boolean isIpV4StackPreferred() { - return IPV4_PREFERRED; - } - - /** - * Creates an byte[] based on an ipAddressString. No error handling is - * performed here. - */ - public static byte[] createByteArrayFromIpAddressString(String ipAddressString) { - - if (isValidIpV4Address(ipAddressString)) { - StringTokenizer tokenizer = new StringTokenizer(ipAddressString, "."); - String token; - int tempInt; - byte[] byteAddress = new byte[IPV4_BYTE_COUNT]; - for (int i = 0; i < IPV4_BYTE_COUNT; i ++) { - token = tokenizer.nextToken(); - tempInt = Integer.parseInt(token); - byteAddress[i] = (byte) tempInt; - } - - return byteAddress; - } - - if (isValidIpV6Address(ipAddressString)) { - if (ipAddressString.charAt(0) == '[') { - ipAddressString = ipAddressString.substring(1, ipAddressString.length() - 1); - } - - int percentPos = ipAddressString.indexOf('%'); - if (percentPos >= 0) { - ipAddressString = ipAddressString.substring(0, percentPos); - } - - StringTokenizer tokenizer = new StringTokenizer(ipAddressString, ":.", true); - ArrayList hexStrings = new ArrayList(); - ArrayList decStrings = new ArrayList(); - String token = ""; - String prevToken = ""; - int doubleColonIndex = -1; // If a double colon exists, we need to - // insert 0s. - - // Go through the tokens, including the seperators ':' and '.' - // When we hit a : or . the previous token will be added to either - // the hex list or decimal list. In the case where we hit a :: - // we will save the index of the hexStrings so we can add zeros - // in to fill out the string - while (tokenizer.hasMoreTokens()) { - prevToken = token; - token = tokenizer.nextToken(); - - if (":".equals(token)) { - if (":".equals(prevToken)) { - doubleColonIndex = hexStrings.size(); - } else if (!prevToken.isEmpty()) { - hexStrings.add(prevToken); - } - } else if (".".equals(token)) { - decStrings.add(prevToken); - } - } - - if (":".equals(prevToken)) { - if (":".equals(token)) { - doubleColonIndex = hexStrings.size(); - } else { - hexStrings.add(token); - } - } else if (".".equals(prevToken)) { - decStrings.add(token); - } - - // figure out how many hexStrings we should have - // also check if it is a IPv4 address - int hexStringsLength = 8; - - // If we have an IPv4 address tagged on at the end, subtract - // 4 bytes, or 2 hex words from the total - if (!decStrings.isEmpty()) { - hexStringsLength -= 2; - } - - // if we hit a double Colon add the appropriate hex strings - if (doubleColonIndex != -1) { - int numberToInsert = hexStringsLength - hexStrings.size(); - for (int i = 0; i < numberToInsert; i ++) { - hexStrings.add(doubleColonIndex, "0"); - } - } - - byte[] ipByteArray = new byte[IPV6_BYTE_COUNT]; - - // Finally convert these strings to bytes... - for (int i = 0; i < hexStrings.size(); i ++) { - convertToBytes(hexStrings.get(i), ipByteArray, i << 1); - } - - // Now if there are any decimal values, we know where they go... - for (int i = 0; i < decStrings.size(); i ++) { - ipByteArray[i + 12] = (byte) (Integer.parseInt(decStrings.get(i)) & 255); - } - return ipByteArray; - } - return null; - } - - /** - * Converts a 4 character hex word into a 2 byte word equivalent - */ - private static void convertToBytes(String hexWord, byte[] ipByteArray, int byteIndex) { - - int hexWordLength = hexWord.length(); - int hexWordIndex = 0; - ipByteArray[byteIndex] = 0; - ipByteArray[byteIndex + 1] = 0; - int charValue; - - // high order 4 bits of first byte - if (hexWordLength > 3) { - charValue = getIntValue(hexWord.charAt(hexWordIndex ++)); - ipByteArray[byteIndex] |= charValue << 4; - } - - // low order 4 bits of the first byte - if (hexWordLength > 2) { - charValue = getIntValue(hexWord.charAt(hexWordIndex ++)); - ipByteArray[byteIndex] |= charValue; - } - - // high order 4 bits of second byte - if (hexWordLength > 1) { - charValue = getIntValue(hexWord.charAt(hexWordIndex ++)); - ipByteArray[byteIndex + 1] |= charValue << 4; - } - - // low order 4 bits of the first byte - charValue = getIntValue(hexWord.charAt(hexWordIndex)); - ipByteArray[byteIndex + 1] |= charValue & 15; - } - - static int getIntValue(char c) { - - switch (c) { - case '0': - return 0; - case '1': - return 1; - case '2': - return 2; - case '3': - return 3; - case '4': - return 4; - case '5': - return 5; - case '6': - return 6; - case '7': - return 7; - case '8': - return 8; - case '9': - return 9; - } - - c = Character.toLowerCase(c); - switch (c) { - case 'a': - return 10; - case 'b': - return 11; - case 'c': - return 12; - case 'd': - return 13; - case 'e': - return 14; - case 'f': - return 15; - } - return 0; - } - - public static boolean isValidIpV6Address(String ipAddress) { - int length = ipAddress.length(); - boolean doubleColon = false; - int numberOfColons = 0; - int numberOfPeriods = 0; - StringBuilder word = new StringBuilder(); - char c = 0; - char prevChar; - int startOffset = 0; // offset for [] ip addresses - int endOffset = ipAddress.length(); - - if (endOffset < 2) { - return false; - } - - // Strip [] - if (ipAddress.charAt(0) == '[') { - if (ipAddress.charAt(endOffset - 1) != ']') { - return false; // must have a close ] - } - - startOffset = 1; - endOffset --; - } - - // Strip the interface name/index after the percent sign. - int percentIdx = ipAddress.indexOf('%', startOffset); - if (percentIdx >= 0) { - endOffset = percentIdx; - } - - for (int i = startOffset; i < endOffset; i ++) { - prevChar = c; - c = ipAddress.charAt(i); - switch (c) { - // case for the last 32-bits represented as IPv4 x:x:x:x:x:x:d.d.d.d - case '.': - numberOfPeriods ++; - if (numberOfPeriods > 3) { - return false; - } - if (!isValidIp4Word(word.toString())) { - return false; - } - if (numberOfColons != 6 && !doubleColon) { - return false; - } - // a special case ::1:2:3:4:5:d.d.d.d allows 7 colons with an - // IPv4 ending, otherwise 7 :'s is bad - if (numberOfColons == 7 && ipAddress.charAt(startOffset) != ':' && - ipAddress.charAt(1 + startOffset) != ':') { - return false; - } - word.delete(0, word.length()); - break; - - case ':': - // FIX "IP6 mechanism syntax #ip6-bad1" - // An IPV6 address cannot start with a single ":". - // Either it can starti with "::" or with a number. - if (i == startOffset && (ipAddress.length() <= i || ipAddress.charAt(i + 1) != ':')) { - return false; - } - // END FIX "IP6 mechanism syntax #ip6-bad1" - numberOfColons ++; - if (numberOfColons > 7) { - return false; - } - if (numberOfPeriods > 0) { - return false; - } - if (prevChar == ':') { - if (doubleColon) { - return false; - } - doubleColon = true; - } - word.delete(0, word.length()); - break; - - default: - if (word != null && word.length() > 3) { - return false; - } - if (!isValidHexChar(c)) { - return false; - } - word.append(c); - } - } - - // Check if we have an IPv4 ending - if (numberOfPeriods > 0) { - // There is a test case with 7 colons and valid ipv4 this should resolve it - if (numberOfPeriods != 3 || !(isValidIp4Word(word.toString()) && numberOfColons < 7)) { - return false; - } - } else { - // If we're at then end and we haven't had 7 colons then there is a - // problem unless we encountered a doubleColon - if (numberOfColons != 7 && !doubleColon) { - return false; - } - - // If we have an empty word at the end, it means we ended in either - // a : or a . - // If we did not end in :: then this is invalid - if (word.length() == 0 && ipAddress.charAt(length - 1 - startOffset) == ':' && - ipAddress.charAt(length - 2 - startOffset) != ':') { - return false; - } - } - - return true; - } - - /** - * @deprecated Do not use; published by mistake. - */ - @Deprecated - public static boolean isValidIp4Word(String word) { - char c; - if (word.length() < 1 || word.length() > 3) { - return false; - } - for (int i = 0; i < word.length(); i ++) { - c = word.charAt(i); - if (!(c >= '0' && c <= '9')) { - return false; - } - } - return Integer.parseInt(word) <= 255; - } - - private static boolean isValidHexChar(char c) { - return c >= '0' && c <= '9' || c >= 'A' && c <= 'F' || c >= 'a' && c <= 'f'; - } - - private static boolean isValidNumericChar(char c) { - return c >= '0' && c <= '9'; - } - - /** - * Takes a string and parses it to see if it is a valid IPV4 address. - * - * @return true, if the string represents an IPV4 address in dotted - * notation, false otherwise - */ - public static boolean isValidIpV4Address(String value) { - - int periods = 0; - int i; - int length = value.length(); - - if (length > 15) { - return false; - } - char c; - StringBuilder word = new StringBuilder(); - for (i = 0; i < length; i ++) { - c = value.charAt(i); - if (c == '.') { - periods ++; - if (periods > 3) { - return false; - } - if (word.length() == 0) { - return false; - } - if (Integer.parseInt(word.toString()) > 255) { - return false; - } - word.delete(0, word.length()); - } else if (!Character.isDigit(c)) { - return false; - } else { - if (word.length() > 2) { - return false; - } - word.append(c); - } - } - - if (word.length() == 0 || Integer.parseInt(word.toString()) > 255) { - return false; - } - - return periods == 3; - } - - /** - * Returns the {@link Inet6Address} representation of a {@link CharSequence} IP address. - *

- * This method will treat all IPv4 type addresses as "IPv4 mapped" (see {@link #getByName(CharSequence, boolean)}) - * @param ip {@link CharSequence} IP address to be converted to a {@link Inet6Address} - * @return {@link Inet6Address} representation of the {@code ip} or {@code null} if not a valid IP address. - */ - public static Inet6Address getByName(CharSequence ip) { - return getByName(ip, true); - } - - /** - * Returns the {@link Inet6Address} representation of a {@link CharSequence} IP address. - *

- * The {@code ipv4Mapped} parameter specifies how IPv4 addresses should be treated. - * "IPv4 mapped" format as - * defined in rfc 4291 section 2 is supported. - * @param ip {@link CharSequence} IP address to be converted to a {@link Inet6Address} - * @param ipv4Mapped - *

    - *
  • {@code true} To allow IPv4 mapped inputs to be translated into {@link Inet6Address}
  • - *
  • {@code false} Don't turn IPv4 addressed to mapped addresses
  • - *
- * @return {@link Inet6Address} representation of the {@code ip} or {@code null} if not a valid IP address. - */ - public static Inet6Address getByName(CharSequence ip, boolean ipv4Mapped) { - final byte[] bytes = new byte[IPV6_BYTE_COUNT]; - final int ipLength = ip.length(); - int compressBegin = 0; - int compressLength = 0; - int currentIndex = 0; - int value = 0; - int begin = -1; - int i = 0; - int ipv6Seperators = 0; - int ipv4Seperators = 0; - int tmp; - boolean needsShift = false; - for (; i < ipLength; ++i) { - final char c = ip.charAt(i); - switch (c) { - case ':': - ++ipv6Seperators; - if (i - begin > IPV6_MAX_CHAR_BETWEEN_SEPARATOR || - ipv4Seperators > 0 || ipv6Seperators > IPV6_MAX_SEPARATORS || - currentIndex + 1 >= bytes.length) { - return null; - } - value <<= (IPV6_MAX_CHAR_BETWEEN_SEPARATOR - (i - begin)) << 2; - - if (compressLength > 0) { - compressLength -= 2; - } - - // The value integer holds at most 4 bytes from right (most significant) to left (least significant). - // The following bit shifting is used to extract and re-order the individual bytes to achieve a - // left (most significant) to right (least significant) ordering. - bytes[currentIndex++] = (byte) (((value & 0xf) << 4) | ((value >> 4) & 0xf)); - bytes[currentIndex++] = (byte) ((((value >> 8) & 0xf) << 4) | ((value >> 12) & 0xf)); - tmp = i + 1; - if (tmp < ipLength && ip.charAt(tmp) == ':') { - ++tmp; - if (compressBegin != 0 || (tmp < ipLength && ip.charAt(tmp) == ':')) { - return null; - } - ++ipv6Seperators; - needsShift = ipv6Seperators == 2 && value == 0; - compressBegin = currentIndex; - compressLength = bytes.length - compressBegin - 2; - ++i; - } - value = 0; - begin = -1; - break; - case '.': - ++ipv4Seperators; - if (i - begin > IPV4_MAX_CHAR_BETWEEN_SEPARATOR - || ipv4Seperators > IPV4_SEPARATORS - || (ipv6Seperators > 0 && (currentIndex + compressLength < 12)) - || i + 1 >= ipLength - || currentIndex >= bytes.length - || begin < 0 - || (begin == 0 && (i == 3 && (!isValidNumericChar(ip.charAt(2)) || - !isValidNumericChar(ip.charAt(1)) || - !isValidNumericChar(ip.charAt(0))) || - i == 2 && (!isValidNumericChar(ip.charAt(1)) || - !isValidNumericChar(ip.charAt(0))) || - i == 1 && !isValidNumericChar(ip.charAt(0))))) { - return null; - } - value <<= (IPV4_MAX_CHAR_BETWEEN_SEPARATOR - (i - begin)) << 2; - - // The value integer holds at most 3 bytes from right (most significant) to left (least significant). - // The following bit shifting is to restructure the bytes to be left (most significant) to - // right (least significant) while also accounting for each IPv4 digit is base 10. - begin = (value & 0xf) * 100 + ((value >> 4) & 0xf) * 10 + ((value >> 8) & 0xf); - if (begin < 0 || begin > 255) { - return null; - } - bytes[currentIndex++] = (byte) begin; - value = 0; - begin = -1; - break; - default: - if (!isValidHexChar(c) || (ipv4Seperators > 0 && !isValidNumericChar(c))) { - return null; - } - if (begin < 0) { - begin = i; - } else if (i - begin > IPV6_MAX_CHAR_BETWEEN_SEPARATOR) { - return null; - } - // The value is treated as a sort of array of numbers because we are dealing with - // at most 4 consecutive bytes we can use bit shifting to accomplish this. - // The most significant byte will be encountered first, and reside in the right most - // position of the following integer - value += getIntValue(c) << ((i - begin) << 2); - break; - } - } - - final boolean isCompressed = compressBegin > 0; - // Finish up last set of data that was accumulated in the loop (or before the loop) - if (ipv4Seperators > 0) { - if (begin > 0 && i - begin > IPV4_MAX_CHAR_BETWEEN_SEPARATOR || - ipv4Seperators != IPV4_SEPARATORS || - currentIndex >= bytes.length) { - return null; - } - if (ipv6Seperators == 0) { - compressLength = 12; - } else if (ipv6Seperators >= IPV6_MIN_SEPARATORS && - ip.charAt(ipLength - 1) != ':' && - (!isCompressed && (ipv6Seperators == 6 && ip.charAt(0) != ':') || - isCompressed && (ipv6Seperators + 1 < IPV6_MAX_SEPARATORS && - (ip.charAt(0) != ':' || compressBegin <= 2)))) { - compressLength -= 2; - } else { - return null; - } - value <<= (IPV4_MAX_CHAR_BETWEEN_SEPARATOR - (i - begin)) << 2; - - // The value integer holds at most 3 bytes from right (most significant) to left (least significant). - // The following bit shifting is to restructure the bytes to be left (most significant) to - // right (least significant) while also accounting for each IPv4 digit is base 10. - begin = (value & 0xf) * 100 + ((value >> 4) & 0xf) * 10 + ((value >> 8) & 0xf); - if (begin < 0 || begin > 255) { - return null; - } - bytes[currentIndex++] = (byte) begin; - } else { - tmp = ipLength - 1; - if (begin > 0 && i - begin > IPV6_MAX_CHAR_BETWEEN_SEPARATOR || - ipv6Seperators < IPV6_MIN_SEPARATORS || - !isCompressed && (ipv6Seperators + 1 != IPV6_MAX_SEPARATORS || - ip.charAt(0) == ':' || ip.charAt(tmp) == ':') || - isCompressed && (ipv6Seperators > IPV6_MAX_SEPARATORS || - (ipv6Seperators == IPV6_MAX_SEPARATORS && - (compressBegin <= 2 && ip.charAt(0) != ':' || - compressBegin >= 14 && ip.charAt(tmp) != ':'))) || - currentIndex + 1 >= bytes.length) { - return null; - } - if (begin >= 0 && i - begin <= IPV6_MAX_CHAR_BETWEEN_SEPARATOR) { - value <<= (IPV6_MAX_CHAR_BETWEEN_SEPARATOR - (i - begin)) << 2; - } - // The value integer holds at most 4 bytes from right (most significant) to left (least significant). - // The following bit shifting is used to extract and re-order the individual bytes to achieve a - // left (most significant) to right (least significant) ordering. - bytes[currentIndex++] = (byte) (((value & 0xf) << 4) | ((value >> 4) & 0xf)); - bytes[currentIndex++] = (byte) ((((value >> 8) & 0xf) << 4) | ((value >> 12) & 0xf)); - } - - i = currentIndex + compressLength; - if (needsShift || i >= bytes.length) { - // Right shift array - if (i >= bytes.length) { - ++compressBegin; - } - for (i = currentIndex; i < bytes.length; ++i) { - for (begin = bytes.length - 1; begin >= compressBegin; --begin) { - bytes[begin] = bytes[begin - 1]; - } - bytes[begin] = 0; - ++compressBegin; - } - } else { - // Selectively move elements - for (i = 0; i < compressLength; ++i) { - begin = i + compressBegin; - currentIndex = begin + compressLength; - if (currentIndex < bytes.length) { - bytes[currentIndex] = bytes[begin]; - bytes[begin] = 0; - } else { - break; - } - } - } - - if (ipv4Mapped && ipv4Seperators > 0 && - bytes[0] == 0 && bytes[1] == 0 && bytes[2] == 0 && bytes[3] == 0 && bytes[4] == 0 && - bytes[5] == 0 && bytes[6] == 0 && bytes[7] == 0 && bytes[8] == 0 && bytes[9] == 0) { - bytes[10] = bytes[11] = (byte) 0xff; - } - - try { - return Inet6Address.getByAddress(null, bytes, -1); - } catch (UnknownHostException e) { - throw new RuntimeException(e); // Should never happen - } - } - - /** - * Returns the {@link String} representation of an {@link InetAddress}. - *
    - *
  • Inet4Address results are identical to {@link InetAddress#getHostAddress()}
  • - *
  • Inet6Address results adhere to - * rfc 5952 section 4
  • - *
- *

- * The output does not include Scope ID. - * @param ip {@link InetAddress} to be converted to an address string - * @return {@code String} containing the text-formatted IP address - */ - public static String toAddressString(InetAddress ip) { - return toAddressString(ip, false); - } - - /** - * Returns the {@link String} representation of an {@link InetAddress}. - *

    - *
  • Inet4Address results are identical to {@link InetAddress#getHostAddress()}
  • - *
  • Inet6Address results adhere to - * rfc 5952 section 4 if - * {@code ipv4Mapped} is false. If {@code ipv4Mapped} is true then "IPv4 mapped" format - * from rfc 4291 section 2 will be supported. - * The compressed result will always obey the compression rules defined in - * rfc 5952 section 4
  • - *
- *

- * The output does not include Scope ID. - * @param ip {@link InetAddress} to be converted to an address string - * @param ipv4Mapped - *

    - *
  • {@code true} to stray from strict rfc 5952 and support the "IPv4 mapped" format - * defined in rfc 4291 section 2 while still - * following the updated guidelines in - * rfc 5952 section 4
  • - *
  • {@code false} to strictly follow rfc 5952
  • - *
- * @return {@code String} containing the text-formatted IP address - */ - public static String toAddressString(InetAddress ip, boolean ipv4Mapped) { - if (ip instanceof Inet4Address) { - return ip.getHostAddress(); - } - if (!(ip instanceof Inet6Address)) { - throw new IllegalArgumentException("Unhandled type: " + ip.getClass()); - } - - final byte[] bytes = ip.getAddress(); - final int[] words = new int[IPV6_WORD_COUNT]; - int i; - for (i = 0; i < words.length; ++i) { - words[i] = ((bytes[i << 1] & 0xff) << 8) | (bytes[(i << 1) + 1] & 0xff); - } - - // Find longest run of 0s, tie goes to first found instance - int currentStart = -1; - int currentLength = 0; - int shortestStart = -1; - int shortestLength = 0; - for (i = 0; i < words.length; ++i) { - if (words[i] == 0) { - if (currentStart < 0) { - currentStart = i; - } - } else if (currentStart >= 0) { - currentLength = i - currentStart; - if (currentLength > shortestLength) { - shortestStart = currentStart; - shortestLength = currentLength; - } - currentStart = -1; - } - } - // If the array ends on a streak of zeros, make sure we account for it - if (currentStart >= 0) { - currentLength = i - currentStart; - if (currentLength > shortestLength) { - shortestStart = currentStart; - shortestLength = currentLength; - } - } - // Ignore the longest streak if it is only 1 long - if (shortestLength == 1) { - shortestLength = 0; - shortestStart = -1; - } - - // Translate to string taking into account longest consecutive 0s - final int shortestEnd = shortestStart + shortestLength; - final StringBuilder b = new StringBuilder(IPV6_MAX_CHAR_COUNT); - if (shortestEnd < 0) { // Optimization when there is no compressing needed - b.append(Integer.toHexString(words[0])); - for (i = 1; i < words.length; ++i) { - b.append(':'); - b.append(Integer.toHexString(words[i])); - } - } else { // General case that can handle compressing (and not compressing) - // Loop unroll the first index (so we don't constantly check i==0 cases in loop) - final boolean isIpv4Mapped; - if (inRangeEndExclusive(0, shortestStart, shortestEnd)) { - b.append("::"); - isIpv4Mapped = ipv4Mapped && (shortestEnd == 5 && words[5] == 0xffff); - } else { - b.append(Integer.toHexString(words[0])); - isIpv4Mapped = false; - } - for (i = 1; i < words.length; ++i) { - if (!inRangeEndExclusive(i, shortestStart, shortestEnd)) { - if (!inRangeEndExclusive(i - 1, shortestStart, shortestEnd)) { - // If the last index was not part of the shortened sequence - if (!isIpv4Mapped || i == 6) { - b.append(':'); - } else { - b.append('.'); - } - } - if (isIpv4Mapped && i > 5) { - b.append(words[i] >> 8); - b.append('.'); - b.append(words[i] & 0xff); - } else { - b.append(Integer.toHexString(words[i])); - } - } else if (!inRangeEndExclusive(i - 1, shortestStart, shortestEnd)) { - // If we are in the shortened sequence and the last index was not - b.append("::"); - } - } - } - - return b.toString(); - } - - /** - * Does a range check on {@code value} if is within {@code start} (inclusive) and {@code end} (exclusive). - * @param value The value to checked if is within {@code start} (inclusive) and {@code end} (exclusive) - * @param start The start of the range (inclusive) - * @param end The end of the range (exclusive) - * @return - *
    - *
  • {@code true} if {@code value} if is within {@code start} (inclusive) and {@code end} (exclusive)
  • - *
  • {@code false} otherwise
  • - *
- */ - private static boolean inRangeEndExclusive(int value, int start, int end) { - return value >= start && value < end; - } - - /** - * A constructor to stop this class being constructed. - */ - private NetUtil() { - // Unused - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/Recycler.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/Recycler.java deleted file mode 100755 index 4d606bd338..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/Recycler.java +++ /dev/null @@ -1,413 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.util; - -import java.lang.ref.WeakReference; -import java.util.Arrays; -import java.util.Map; -import java.util.WeakHashMap; -import java.util.concurrent.atomic.AtomicInteger; - -import com.ai.cloud.io.netty.util.concurrent.FastThreadLocal; -import com.ai.cloud.io.netty.util.internal.SystemPropertyUtil; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * Light-weight object pool based on a thread-local stack. - * - * @param the type of the pooled object - */ -public abstract class Recycler { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(Recycler.class); - - private static final Handle NOOP_HANDLE = new Handle() { }; - private static final AtomicInteger ID_GENERATOR = new AtomicInteger(Integer.MIN_VALUE); - private static final int OWN_THREAD_ID = ID_GENERATOR.getAndIncrement(); - // TODO: Some arbitrary large number - should adjust as we get more production experience. - private static final int DEFAULT_INITIAL_MAX_CAPACITY = 262144; - private static final int DEFAULT_MAX_CAPACITY; - private static final int INITIAL_CAPACITY; - - static { - // In the future, we might have different maxCapacity for different object types. - // e.g. io.netty.recycler.maxCapacity.writeTask - // io.netty.recycler.maxCapacity.outboundBuffer - int maxCapacity = SystemPropertyUtil.getInt("io.netty.recycler.maxCapacity.default", - DEFAULT_INITIAL_MAX_CAPACITY); - if (maxCapacity < 0) { - maxCapacity = DEFAULT_INITIAL_MAX_CAPACITY; - } - - DEFAULT_MAX_CAPACITY = maxCapacity; - if (logger.isDebugEnabled()) { - if (DEFAULT_MAX_CAPACITY == 0) { - logger.debug("-Dio.netty.recycler.maxCapacity.default: disabled"); - } else { - logger.debug("-Dio.netty.recycler.maxCapacity.default: {}", DEFAULT_MAX_CAPACITY); - } - } - - INITIAL_CAPACITY = Math.min(DEFAULT_MAX_CAPACITY, 256); - } - - private final int maxCapacity; - private final FastThreadLocal> threadLocal = new FastThreadLocal>() { - @Override - protected Stack initialValue() { - return new Stack(Recycler.this, Thread.currentThread(), maxCapacity); - } - }; - - protected Recycler() { - this(DEFAULT_MAX_CAPACITY); - } - - protected Recycler(int maxCapacity) { - this.maxCapacity = Math.max(0, maxCapacity); - } - - @SuppressWarnings("unchecked") - public final T get() { - if (maxCapacity == 0) { - return newObject(NOOP_HANDLE); - } - Stack stack = threadLocal.get(); - DefaultHandle handle = stack.pop(); - if (handle == null) { - handle = stack.newHandle(); - handle.value = newObject(handle); - } - return (T) handle.value; - } - - public final boolean recycle(T o, Handle handle) { - if (handle == NOOP_HANDLE) { - return false; - } - - DefaultHandle h = (DefaultHandle) handle; - if (h.stack.parent != this) { - return false; - } - if (o != h.value) { - throw new IllegalArgumentException("o does not belong to handle"); - } - h.recycle(); - return true; - } - - protected abstract T newObject(Handle handle); - - final int threadLocalCapacity() { - return threadLocal.get().elements.length; - } - - final int threadLocalSize() { - return threadLocal.get().size; - } - - public interface Handle { } - - static final class DefaultHandle implements Handle { - private int lastRecycledId; - private int recycleId; - - private Stack stack; - private Object value; - - DefaultHandle(Stack stack) { - this.stack = stack; - } - - public void recycle() { - Thread thread = Thread.currentThread(); - if (thread == stack.thread) { - stack.push(this); - return; - } - // we don't want to have a ref to the queue as the value in our weak map - // so we null it out; to ensure there are no races with restoring it later - // we impose a memory ordering here (no-op on x86) - Map, WeakOrderQueue> delayedRecycled = DELAYED_RECYCLED.get(); - WeakOrderQueue queue = delayedRecycled.get(stack); - if (queue == null) { - delayedRecycled.put(stack, queue = new WeakOrderQueue(stack, thread)); - } - queue.add(this); - } - } - - private static final FastThreadLocal, WeakOrderQueue>> DELAYED_RECYCLED = - new FastThreadLocal, WeakOrderQueue>>() { - @Override - protected Map, WeakOrderQueue> initialValue() { - return new WeakHashMap, WeakOrderQueue>(); - } - }; - - // a queue that makes only moderate guarantees about visibility: items are seen in the correct order, - // but we aren't absolutely guaranteed to ever see anything at all, thereby keeping the queue cheap to maintain - private static final class WeakOrderQueue { - private static final int LINK_CAPACITY = 16; - - // Let Link extend AtomicInteger for intrinsics. The Link itself will be used as writerIndex. - @SuppressWarnings("serial") - private static final class Link extends AtomicInteger { - private final DefaultHandle[] elements = new DefaultHandle[LINK_CAPACITY]; - - private int readIndex; - private Link next; - } - - // chain of data items - private Link head, tail; - // pointer to another queue of delayed items for the same stack - private WeakOrderQueue next; - private final WeakReference owner; - private final int id = ID_GENERATOR.getAndIncrement(); - - WeakOrderQueue(Stack stack, Thread thread) { - head = tail = new Link(); - owner = new WeakReference(thread); - synchronized (stack) { - next = stack.head; - stack.head = this; - } - } - - void add(DefaultHandle handle) { - handle.lastRecycledId = id; - - Link tail = this.tail; - int writeIndex; - if ((writeIndex = tail.get()) == LINK_CAPACITY) { - this.tail = tail = tail.next = new Link(); - writeIndex = tail.get(); - } - tail.elements[writeIndex] = handle; - handle.stack = null; - // we lazy set to ensure that setting stack to null appears before we unnull it in the owning thread; - // this also means we guarantee visibility of an element in the queue if we see the index updated - tail.lazySet(writeIndex + 1); - } - - boolean hasFinalData() { - return tail.readIndex != tail.get(); - } - - // transfer as many items as we can from this queue to the stack, returning true if any were transferred - @SuppressWarnings("rawtypes") - boolean transfer(Stack dst) { - - Link head = this.head; - if (head == null) { - return false; - } - - if (head.readIndex == LINK_CAPACITY) { - if (head.next == null) { - return false; - } - this.head = head = head.next; - } - - final int srcStart = head.readIndex; - int srcEnd = head.get(); - final int srcSize = srcEnd - srcStart; - if (srcSize == 0) { - return false; - } - - final int dstSize = dst.size; - final int expectedCapacity = dstSize + srcSize; - - if (expectedCapacity > dst.elements.length) { - final int actualCapacity = dst.increaseCapacity(expectedCapacity); - srcEnd = Math.min(srcStart + actualCapacity - dstSize, srcEnd); - } - - if (srcStart != srcEnd) { - final DefaultHandle[] srcElems = head.elements; - final DefaultHandle[] dstElems = dst.elements; - int newDstSize = dstSize; - for (int i = srcStart; i < srcEnd; i++) { - DefaultHandle element = srcElems[i]; - if (element.recycleId == 0) { - element.recycleId = element.lastRecycledId; - } else if (element.recycleId != element.lastRecycledId) { - throw new IllegalStateException("recycled already"); - } - element.stack = dst; - dstElems[newDstSize ++] = element; - srcElems[i] = null; - } - dst.size = newDstSize; - - if (srcEnd == LINK_CAPACITY && head.next != null) { - this.head = head.next; - } - - head.readIndex = srcEnd; - return true; - } else { - // The destination stack is full already. - return false; - } - } - } - - static final class Stack { - - // we keep a queue of per-thread queues, which is appended to once only, each time a new thread other - // than the stack owner recycles: when we run out of items in our stack we iterate this collection - // to scavenge those that can be reused. this permits us to incur minimal thread synchronisation whilst - // still recycling all items. - final Recycler parent; - final Thread thread; - private DefaultHandle[] elements; - private final int maxCapacity; - private int size; - - private volatile WeakOrderQueue head; - private WeakOrderQueue cursor, prev; - - Stack(Recycler parent, Thread thread, int maxCapacity) { - this.parent = parent; - this.thread = thread; - this.maxCapacity = maxCapacity; - elements = new DefaultHandle[Math.min(INITIAL_CAPACITY, maxCapacity)]; - } - - int increaseCapacity(int expectedCapacity) { - int newCapacity = elements.length; - int maxCapacity = this.maxCapacity; - do { - newCapacity <<= 1; - } while (newCapacity < expectedCapacity && newCapacity < maxCapacity); - - newCapacity = Math.min(newCapacity, maxCapacity); - if (newCapacity != elements.length) { - elements = Arrays.copyOf(elements, newCapacity); - } - - return newCapacity; - } - - DefaultHandle pop() { - int size = this.size; - if (size == 0) { - if (!scavenge()) { - return null; - } - size = this.size; - } - size --; - DefaultHandle ret = elements[size]; - if (ret.lastRecycledId != ret.recycleId) { - throw new IllegalStateException("recycled multiple times"); - } - ret.recycleId = 0; - ret.lastRecycledId = 0; - this.size = size; - return ret; - } - - boolean scavenge() { - // continue an existing scavenge, if any - if (scavengeSome()) { - return true; - } - - // reset our scavenge cursor - prev = null; - cursor = head; - return false; - } - - boolean scavengeSome() { - WeakOrderQueue cursor = this.cursor; - if (cursor == null) { - cursor = head; - if (cursor == null) { - return false; - } - } - - boolean success = false; - WeakOrderQueue prev = this.prev; - do { - if (cursor.transfer(this)) { - success = true; - break; - } - - WeakOrderQueue next = cursor.next; - if (cursor.owner.get() == null) { - // If the thread associated with the queue is gone, unlink it, after - // performing a volatile read to confirm there is no data left to collect. - // We never unlink the first queue, as we don't want to synchronize on updating the head. - if (cursor.hasFinalData()) { - for (;;) { - if (cursor.transfer(this)) { - success = true; - } else { - break; - } - } - } - if (prev != null) { - prev.next = next; - } - } else { - prev = cursor; - } - - cursor = next; - - } while (cursor != null && !success); - - this.prev = prev; - this.cursor = cursor; - return success; - } - - void push(DefaultHandle item) { - if ((item.recycleId | item.lastRecycledId) != 0) { - throw new IllegalStateException("recycled already"); - } - item.recycleId = item.lastRecycledId = OWN_THREAD_ID; - - int size = this.size; - if (size >= maxCapacity) { - // Hit the maximum capacity - drop the possibly youngest object. - return; - } - if (size == elements.length) { - elements = Arrays.copyOf(elements, Math.min(size << 1, maxCapacity)); - } - - elements[size] = item; - this.size = size + 1; - } - - DefaultHandle newHandle() { - return new DefaultHandle(this); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/ReferenceCountUtil.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/ReferenceCountUtil.java deleted file mode 100755 index 6d3aaa4dbe..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/ReferenceCountUtil.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util; - -import com.ai.cloud.io.netty.util.internal.StringUtil; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * Collection of method to handle objects that may implement {@link ReferenceCounted}. - */ -public final class ReferenceCountUtil { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(ReferenceCountUtil.class); - - /** - * Try to call {@link ReferenceCounted#retain()} if the specified message implements {@link ReferenceCounted}. - * If the specified message doesn't implement {@link ReferenceCounted}, this method does nothing. - */ - @SuppressWarnings("unchecked") - public static T retain(T msg) { - if (msg instanceof ReferenceCounted) { - return (T) ((ReferenceCounted) msg).retain(); - } - return msg; - } - - /** - * Try to call {@link ReferenceCounted#retain()} if the specified message implements {@link ReferenceCounted}. - * If the specified message doesn't implement {@link ReferenceCounted}, this method does nothing. - */ - @SuppressWarnings("unchecked") - public static T retain(T msg, int increment) { - if (msg instanceof ReferenceCounted) { - return (T) ((ReferenceCounted) msg).retain(increment); - } - return msg; - } - - /** - * Try to call {@link ReferenceCounted#release()} if the specified message implements {@link ReferenceCounted}. - * If the specified message doesn't implement {@link ReferenceCounted}, this method does nothing. - */ - public static boolean release(Object msg) { - if (msg instanceof ReferenceCounted) { - return ((ReferenceCounted) msg).release(); - } - return false; - } - - /** - * Try to call {@link ReferenceCounted#release(int)} if the specified message implements {@link ReferenceCounted}. - * If the specified message doesn't implement {@link ReferenceCounted}, this method does nothing. - */ - public static boolean release(Object msg, int decrement) { - if (msg instanceof ReferenceCounted) { - return ((ReferenceCounted) msg).release(decrement); - } - return false; - } - - /** - * Try to call {@link ReferenceCounted#release()} if the specified message implements {@link ReferenceCounted}. - * If the specified message doesn't implement {@link ReferenceCounted}, this method does nothing. - * Unlike {@link #release(Object)} this method catches an exception raised by {@link ReferenceCounted#release()} - * and logs it, rather than rethrowing it to the caller. It is usually recommended to use {@link #release(Object)} - * instead, unless you absolutely need to swallow an exception. - */ - public static void safeRelease(Object msg) { - try { - release(msg); - } catch (Throwable t) { - logger.warn("Failed to release a message: {}", msg, t); - } - } - - /** - * Try to call {@link ReferenceCounted#release(int)} if the specified message implements {@link ReferenceCounted}. - * If the specified message doesn't implement {@link ReferenceCounted}, this method does nothing. - * Unlike {@link #release(Object)} this method catches an exception raised by {@link ReferenceCounted#release(int)} - * and logs it, rather than rethrowing it to the caller. It is usually recommended to use - * {@link #release(Object, int)} instead, unless you absolutely need to swallow an exception. - */ - public static void safeRelease(Object msg, int decrement) { - try { - release(msg, decrement); - } catch (Throwable t) { - if (logger.isWarnEnabled()) { - logger.warn("Failed to release a message: {} (decrement: {})", msg, decrement, t); - } - } - } - - /** - * Schedules the specified object to be released when the caller thread terminates. Note that this operation is - * intended to simplify reference counting of ephemeral objects during unit tests. Do not use it beyond the - * intended use case. - */ - public static T releaseLater(T msg) { - return releaseLater(msg, 1); - } - - /** - * Schedules the specified object to be released when the caller thread terminates. Note that this operation is - * intended to simplify reference counting of ephemeral objects during unit tests. Do not use it beyond the - * intended use case. - */ - public static T releaseLater(T msg, int decrement) { - if (msg instanceof ReferenceCounted) { - ThreadDeathWatcher.watch(Thread.currentThread(), new ReleasingTask((ReferenceCounted) msg, decrement)); - } - return msg; - } - - /** - * Releases the objects when the thread that called {@link #releaseLater(Object)} has been terminated. - */ - private static final class ReleasingTask implements Runnable { - - private final ReferenceCounted obj; - private final int decrement; - - ReleasingTask(ReferenceCounted obj, int decrement) { - this.obj = obj; - this.decrement = decrement; - } - - @Override - public void run() { - try { - if (!obj.release(decrement)) { - logger.warn("Non-zero refCnt: {}", this); - } else { - logger.debug("Released: {}", this); - } - } catch (Exception ex) { - logger.warn("Failed to release an object: {}", obj, ex); - } - } - - @Override - public String toString() { - return StringUtil.simpleClassName(obj) + ".release(" + decrement + ") refCnt: " + obj.refCnt(); - } - } - - private ReferenceCountUtil() { } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/ReferenceCounted.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/ReferenceCounted.java deleted file mode 100755 index 8464fd411c..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/ReferenceCounted.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util; - -/** - * A reference-counted object that requires explicit deallocation. - *

- * When a new {@link ReferenceCounted} is instantiated, it starts with the reference count of {@code 1}. - * {@link #retain()} increases the reference count, and {@link #release()} decreases the reference count. - * If the reference count is decreased to {@code 0}, the object will be deallocated explicitly, and accessing - * the deallocated object will usually result in an access violation. - *

- *

- * If an object that implements {@link ReferenceCounted} is a container of other objects that implement - * {@link ReferenceCounted}, the contained objects will also be released via {@link #release()} when the container's - * reference count becomes 0. - *

- */ -public interface ReferenceCounted { - /** - * Returns the reference count of this object. If {@code 0}, it means this object has been deallocated. - */ - int refCnt(); - - /** - * Increases the reference count by {@code 1}. - */ - ReferenceCounted retain(); - - /** - * Increases the reference count by the specified {@code increment}. - */ - ReferenceCounted retain(int increment); - - /** - * Decreases the reference count by {@code 1} and deallocates this object if the reference count reaches at - * {@code 0}. - * - * @return {@code true} if and only if the reference count became {@code 0} and this object has been deallocated - */ - boolean release(); - - /** - * Decreases the reference count by the specified {@code decrement} and deallocates this object if the reference - * count reaches at {@code 0}. - * - * @return {@code true} if and only if the reference count became {@code 0} and this object has been deallocated - */ - boolean release(int decrement); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/ResourceLeak.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/ResourceLeak.java deleted file mode 100755 index 9615be0314..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/ResourceLeak.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.util; - -public interface ResourceLeak { - /** - * Records the caller's current stack trace so that the {@link ResourceLeakDetector} can tell where the leaked - * resource was accessed lastly. - */ - void record(); - - /** - * Close the leak so that {@link ResourceLeakDetector} does not warn about leaked resources. - * - * @return {@code true} if called first time, {@code false} if called already - */ - boolean close(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/ResourceLeakDetector.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/ResourceLeakDetector.java deleted file mode 100755 index 8491f8bf07..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/ResourceLeakDetector.java +++ /dev/null @@ -1,407 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.util; - -import java.lang.ref.PhantomReference; -import java.lang.ref.ReferenceQueue; -import java.util.ArrayDeque; -import java.util.Deque; -import java.util.EnumSet; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.atomic.AtomicBoolean; - -import com.ai.cloud.io.netty.util.internal.MathUtil; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; -import com.ai.cloud.io.netty.util.internal.SystemPropertyUtil; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -import static com.ai.cloud.io.netty.util.internal.StringUtil.*; - -public final class ResourceLeakDetector { - - private static final String PROP_LEVEL_OLD = "io.netty.leakDetectionLevel"; - private static final String PROP_LEVEL = "io.netty.leakDetection.level"; - private static final Level DEFAULT_LEVEL = Level.SIMPLE; - - private static final String PROP_MAX_RECORDS = "io.netty.leakDetection.maxRecords"; - private static final int DEFAULT_MAX_RECORDS = 4; - private static final int MAX_RECORDS; - - /** - * Represents the level of resource leak detection. - */ - public enum Level { - /** - * Disables resource leak detection. - */ - DISABLED, - /** - * Enables simplistic sampling resource leak detection which reports there is a leak or not, - * at the cost of small overhead (default). - */ - SIMPLE, - /** - * Enables advanced sampling resource leak detection which reports where the leaked object was accessed - * recently at the cost of high overhead. - */ - ADVANCED, - /** - * Enables paranoid resource leak detection which reports where the leaked object was accessed recently, - * at the cost of the highest possible overhead (for testing purposes only). - */ - PARANOID - } - - private static Level level; - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(ResourceLeakDetector.class); - - static { - final boolean disabled; - if (SystemPropertyUtil.get("io.netty.noResourceLeakDetection") != null) { - disabled = SystemPropertyUtil.getBoolean("io.netty.noResourceLeakDetection", false); - logger.debug("-Dio.netty.noResourceLeakDetection: {}", disabled); - logger.warn( - "-Dio.netty.noResourceLeakDetection is deprecated. Use '-D{}={}' instead.", - PROP_LEVEL, DEFAULT_LEVEL.name().toLowerCase()); - } else { - disabled = false; - } - - Level defaultLevel = disabled? Level.DISABLED : DEFAULT_LEVEL; - - // First read old property name - String levelStr = SystemPropertyUtil.get(PROP_LEVEL_OLD, defaultLevel.name()).trim().toUpperCase(); - - // If new property name is present, use it - levelStr = SystemPropertyUtil.get(PROP_LEVEL, levelStr).trim().toUpperCase(); - Level level = DEFAULT_LEVEL; - for (Level l: EnumSet.allOf(Level.class)) { - if (levelStr.equals(l.name()) || levelStr.equals(String.valueOf(l.ordinal()))) { - level = l; - } - } - - MAX_RECORDS = SystemPropertyUtil.getInt(PROP_MAX_RECORDS, DEFAULT_MAX_RECORDS); - - ResourceLeakDetector.level = level; - if (logger.isDebugEnabled()) { - logger.debug("-D{}: {}", PROP_LEVEL, level.name().toLowerCase()); - logger.debug("-D{}: {}", PROP_MAX_RECORDS, MAX_RECORDS); - } - } - - // Should be power of two. - private static final int DEFAULT_SAMPLING_INTERVAL = 128; - - /** - * @deprecated Use {@link #setLevel(Level)} instead. - */ - @Deprecated - public static void setEnabled(boolean enabled) { - setLevel(enabled? Level.SIMPLE : Level.DISABLED); - } - - /** - * Returns {@code true} if resource leak detection is enabled. - */ - public static boolean isEnabled() { - return getLevel().ordinal() > Level.DISABLED.ordinal(); - } - - /** - * Sets the resource leak detection level. - */ - public static void setLevel(Level level) { - if (level == null) { - throw new NullPointerException("level"); - } - ResourceLeakDetector.level = level; - } - - /** - * Returns the current resource leak detection level. - */ - public static Level getLevel() { - return level; - } - - /** the linked list of active resources */ - private final DefaultResourceLeak head = new DefaultResourceLeak(null); - private final DefaultResourceLeak tail = new DefaultResourceLeak(null); - - private final ReferenceQueue refQueue = new ReferenceQueue(); - private final ConcurrentMap reportedLeaks = PlatformDependent.newConcurrentHashMap(); - - private final String resourceType; - private final int samplingInterval; - private final int mask; - private final long maxActive; - private long active; - private final AtomicBoolean loggedTooManyActive = new AtomicBoolean(); - - private long leakCheckCnt; - - public ResourceLeakDetector(Class resourceType) { - this(simpleClassName(resourceType)); - } - - public ResourceLeakDetector(String resourceType) { - this(resourceType, DEFAULT_SAMPLING_INTERVAL, Long.MAX_VALUE); - } - - public ResourceLeakDetector(Class resourceType, int samplingInterval, long maxActive) { - this(simpleClassName(resourceType), samplingInterval, maxActive); - } - - public ResourceLeakDetector(String resourceType, int samplingInterval, long maxActive) { - if (resourceType == null) { - throw new NullPointerException("resourceType"); - } - if (samplingInterval <= 0) { - throw new IllegalArgumentException("samplingInterval: " + samplingInterval + " (expected: 1+)"); - } - if (maxActive <= 0) { - throw new IllegalArgumentException("maxActive: " + maxActive + " (expected: 1+)"); - } - - this.resourceType = resourceType; - this.samplingInterval = MathUtil.findNextPositivePowerOfTwo(samplingInterval); - // samplingInterval is a power of two so we calculate a mask that we can use to - // check if we need to do any leak detection or not. - mask = this.samplingInterval - 1; - this.maxActive = maxActive; - - head.next = tail; - tail.prev = head; - } - - /** - * Creates a new {@link ResourceLeak} which is expected to be closed via {@link ResourceLeak#close()} when the - * related resource is deallocated. - * - * @return the {@link ResourceLeak} or {@code null} - */ - public ResourceLeak open(T obj) { - Level level = ResourceLeakDetector.level; - if (level == Level.DISABLED) { - return null; - } - - if (level.ordinal() < Level.PARANOID.ordinal()) { - if ((leakCheckCnt ++ & mask) == 0) { - reportLeak(level); - return new DefaultResourceLeak(obj); - } else { - return null; - } - } else { - reportLeak(level); - return new DefaultResourceLeak(obj); - } - } - - private void reportLeak(Level level) { - if (!logger.isErrorEnabled()) { - for (;;) { - @SuppressWarnings("unchecked") - DefaultResourceLeak ref = (DefaultResourceLeak) refQueue.poll(); - if (ref == null) { - break; - } - ref.close(); - } - return; - } - - // Report too many instances. - int samplingInterval = level == Level.PARANOID? 1 : this.samplingInterval; - if (active * samplingInterval > maxActive && loggedTooManyActive.compareAndSet(false, true)) { - logger.error("LEAK: You are creating too many " + resourceType + " instances. " + - resourceType + " is a shared resource that must be reused across the JVM," + - "so that only a few instances are created."); - } - - // Detect and report previous leaks. - for (;;) { - @SuppressWarnings("unchecked") - DefaultResourceLeak ref = (DefaultResourceLeak) refQueue.poll(); - if (ref == null) { - break; - } - - ref.clear(); - - if (!ref.close()) { - continue; - } - - String records = ref.toString(); - if (reportedLeaks.putIfAbsent(records, Boolean.TRUE) == null) { - if (records.isEmpty()) { - logger.error("LEAK: {}.release() was not called before it's garbage-collected. " + - "Enable advanced leak reporting to find out where the leak occurred. " + - "To enable advanced leak reporting, " + - "specify the JVM option '-D{}={}' or call {}.setLevel() " + - "See http://netty.io/wiki/reference-counted-objects.html for more information.", - resourceType, PROP_LEVEL, Level.ADVANCED.name().toLowerCase(), simpleClassName(this)); - } else { - logger.error( - "LEAK: {}.release() was not called before it's garbage-collected. " + - "See http://netty.io/wiki/reference-counted-objects.html for more information.{}", - resourceType, records); - } - } - } - } - - private final class DefaultResourceLeak extends PhantomReference implements ResourceLeak { - private final String creationRecord; - private final Deque lastRecords = new ArrayDeque(); - private final AtomicBoolean freed; - private DefaultResourceLeak prev; - private DefaultResourceLeak next; - - DefaultResourceLeak(Object referent) { - super(referent, referent != null? refQueue : null); - - if (referent != null) { - Level level = getLevel(); - if (level.ordinal() >= Level.ADVANCED.ordinal()) { - creationRecord = newRecord(3); - } else { - creationRecord = null; - } - - // TODO: Use CAS to update the list. - synchronized (head) { - prev = head; - next = head.next; - head.next.prev = this; - head.next = this; - active ++; - } - freed = new AtomicBoolean(); - } else { - creationRecord = null; - freed = new AtomicBoolean(true); - } - } - - @Override - public void record() { - if (creationRecord != null) { - String value = newRecord(2); - - synchronized (lastRecords) { - int size = lastRecords.size(); - if (size == 0 || !lastRecords.getLast().equals(value)) { - lastRecords.add(value); - } - if (size > MAX_RECORDS) { - lastRecords.removeFirst(); - } - } - } - } - - @Override - public boolean close() { - if (freed.compareAndSet(false, true)) { - synchronized (head) { - active --; - prev.next = next; - next.prev = prev; - prev = null; - next = null; - } - return true; - } - return false; - } - - @Override - public String toString() { - if (creationRecord == null) { - return ""; - } - - Object[] array; - synchronized (lastRecords) { - array = lastRecords.toArray(); - } - - StringBuilder buf = new StringBuilder(16384) - .append(NEWLINE) - .append("Recent access records: ") - .append(array.length) - .append(NEWLINE); - - if (array.length > 0) { - for (int i = array.length - 1; i >= 0; i --) { - buf.append('#') - .append(i + 1) - .append(':') - .append(NEWLINE) - .append(array[i]); - } - } - - buf.append("Created at:") - .append(NEWLINE) - .append(creationRecord); - - buf.setLength(buf.length() - NEWLINE.length()); - return buf.toString(); - } - } - - private static final String[] STACK_TRACE_ELEMENT_EXCLUSIONS = { - "io.netty.buffer.AbstractByteBufAllocator.toLeakAwareBuffer(", - "io.netty.buffer.AdvancedLeakAwareByteBuf.recordLeakNonRefCountingOperation(" - }; - - static String newRecord(int recordsToSkip) { - StringBuilder buf = new StringBuilder(4096); - StackTraceElement[] array = new Throwable().getStackTrace(); - for (StackTraceElement e: array) { - if (recordsToSkip > 0) { - recordsToSkip --; - } else { - String estr = e.toString(); - - // Strip the noisy stack trace elements. - boolean excluded = false; - for (String exclusion: STACK_TRACE_ELEMENT_EXCLUSIONS) { - if (estr.startsWith(exclusion)) { - excluded = true; - break; - } - } - - if (!excluded) { - buf.append('\t'); - buf.append(estr); - buf.append(NEWLINE); - } - } - } - - return buf.toString(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/ResourceLeakException.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/ResourceLeakException.java deleted file mode 100755 index d362f602c4..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/ResourceLeakException.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.util; - -import java.util.Arrays; - -/** - * @deprecated This class will be removed in the future version. - */ -@Deprecated -public class ResourceLeakException extends RuntimeException { - - private static final long serialVersionUID = 7186453858343358280L; - - private final StackTraceElement[] cachedStackTrace; - - public ResourceLeakException() { - cachedStackTrace = getStackTrace(); - } - - public ResourceLeakException(String message) { - super(message); - cachedStackTrace = getStackTrace(); - } - - public ResourceLeakException(String message, Throwable cause) { - super(message, cause); - cachedStackTrace = getStackTrace(); - } - - public ResourceLeakException(Throwable cause) { - super(cause); - cachedStackTrace = getStackTrace(); - } - - @Override - public int hashCode() { - StackTraceElement[] trace = cachedStackTrace; - int hashCode = 0; - for (StackTraceElement e: trace) { - hashCode = hashCode * 31 + e.hashCode(); - } - return hashCode; - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof ResourceLeakException)) { - return false; - } - if (o == this) { - return true; - } - - return Arrays.equals(cachedStackTrace, ((ResourceLeakException) o).cachedStackTrace); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/Signal.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/Signal.java deleted file mode 100755 index 80c4d6007f..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/Signal.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util; - - -import java.util.concurrent.ConcurrentMap; - -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - -/** - * A special {@link Error} which is used to signal some state or request by throwing it. - * {@link Signal} has an empty stack trace and has no cause to save the instantiation overhead. - */ -public final class Signal extends Error { - - private static final long serialVersionUID = -221145131122459977L; - - private static final ConcurrentMap map = PlatformDependent.newConcurrentHashMap(); - - @SuppressWarnings("deprecation") - private final UniqueName uname; - - /** - * Creates a new {@link Signal} with the specified {@code name}. - */ - @SuppressWarnings("deprecation") - public static Signal valueOf(String name) { - return new Signal(name); - } - - /** - * @deprecated Use {@link #valueOf(String)} instead. - */ - @Deprecated - public Signal(String name) { - super(name); - uname = new UniqueName(map, name); - } - - /** - * Check if the given {@link Signal} is the same as this instance. If not an {@link IllegalStateException} will - * be thrown. - */ - public void expect(Signal signal) { - if (this != signal) { - throw new IllegalStateException("unexpected signal: " + signal); - } - } - - @Override - public Throwable initCause(Throwable cause) { - return this; - } - - @Override - public Throwable fillInStackTrace() { - return this; - } - - @Override - public String toString() { - return uname.name(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/ThreadDeathWatcher.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/ThreadDeathWatcher.java deleted file mode 100755 index 7e3649b8a3..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/ThreadDeathWatcher.java +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.util; - -import java.util.ArrayList; -import java.util.List; -import java.util.Queue; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -import com.ai.cloud.io.netty.util.concurrent.DefaultThreadFactory; -import com.ai.cloud.io.netty.util.internal.MpscLinkedQueueNode; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * Checks if a thread is alive periodically and runs a task when a thread dies. - *

- * This thread starts a daemon thread to check the state of the threads being watched and to invoke their - * associated {@link Runnable}s. When there is no thread to watch (i.e. all threads are dead), the daemon thread - * will terminate itself, and a new daemon thread will be started again when a new watch is added. - *

- */ -public final class ThreadDeathWatcher { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(ThreadDeathWatcher.class); - private static final ThreadFactory threadFactory = - new DefaultThreadFactory(ThreadDeathWatcher.class, true, Thread.MIN_PRIORITY); - - private static final Queue pendingEntries = PlatformDependent.newMpscQueue(); - private static final Watcher watcher = new Watcher(); - private static final AtomicBoolean started = new AtomicBoolean(); - private static volatile Thread watcherThread; - - /** - * Schedules the specified {@code task} to run when the specified {@code thread} dies. - * - * @param thread the {@link Thread} to watch - * @param task the {@link Runnable} to run when the {@code thread} dies - * - * @throws IllegalArgumentException if the specified {@code thread} is not alive - */ - public static void watch(Thread thread, Runnable task) { - if (thread == null) { - throw new NullPointerException("thread"); - } - if (task == null) { - throw new NullPointerException("task"); - } - if (!thread.isAlive()) { - throw new IllegalArgumentException("thread must be alive."); - } - - schedule(thread, task, true); - } - - /** - * Cancels the task scheduled via {@link #watch(Thread, Runnable)}. - */ - public static void unwatch(Thread thread, Runnable task) { - if (thread == null) { - throw new NullPointerException("thread"); - } - if (task == null) { - throw new NullPointerException("task"); - } - - schedule(thread, task, false); - } - - private static void schedule(Thread thread, Runnable task, boolean isWatch) { - pendingEntries.add(new Entry(thread, task, isWatch)); - - if (started.compareAndSet(false, true)) { - Thread watcherThread = threadFactory.newThread(watcher); - watcherThread.start(); - ThreadDeathWatcher.watcherThread = watcherThread; - } - } - - /** - * Waits until the thread of this watcher has no threads to watch and terminates itself. - * Because a new watcher thread will be started again on {@link #watch(Thread, Runnable)}, - * this operation is only useful when you want to ensure that the watcher thread is terminated - * after your application is shut down and there's no chance of calling - * {@link #watch(Thread, Runnable)} afterwards. - * - * @return {@code true} if and only if the watcher thread has been terminated - */ - public static boolean awaitInactivity(long timeout, TimeUnit unit) throws InterruptedException { - if (unit == null) { - throw new NullPointerException("unit"); - } - - Thread watcherThread = ThreadDeathWatcher.watcherThread; - if (watcherThread != null) { - watcherThread.join(unit.toMillis(timeout)); - return !watcherThread.isAlive(); - } else { - return true; - } - } - - private ThreadDeathWatcher() { } - - private static final class Watcher implements Runnable { - - private final List watchees = new ArrayList(); - - @Override - public void run() { - for (;;) { - fetchWatchees(); - notifyWatchees(); - - // Try once again just in case notifyWatchees() triggered watch() or unwatch(). - fetchWatchees(); - notifyWatchees(); - - try { - Thread.sleep(1000); - } catch (InterruptedException ignore) { - // Ignore the interrupt; do not terminate until all tasks are run. - } - - if (watchees.isEmpty() && pendingEntries.isEmpty()) { - - // Mark the current worker thread as stopped. - // The following CAS must always success and must be uncontended, - // because only one watcher thread should be running at the same time. - boolean stopped = started.compareAndSet(true, false); - assert stopped; - - // Check if there are pending entries added by watch() while we do CAS above. - if (pendingEntries.isEmpty()) { - // A) watch() was not invoked and thus there's nothing to handle - // -> safe to terminate because there's nothing left to do - // B) a new watcher thread started and handled them all - // -> safe to terminate the new watcher thread will take care the rest - break; - } - - // There are pending entries again, added by watch() - if (!started.compareAndSet(false, true)) { - // watch() started a new watcher thread and set 'started' to true. - // -> terminate this thread so that the new watcher reads from pendingEntries exclusively. - break; - } - - // watch() added an entry, but this worker was faster to set 'started' to true. - // i.e. a new watcher thread was not started - // -> keep this thread alive to handle the newly added entries. - } - } - } - - private void fetchWatchees() { - for (;;) { - Entry e = pendingEntries.poll(); - if (e == null) { - break; - } - - if (e.isWatch) { - watchees.add(e); - } else { - watchees.remove(e); - } - } - } - - private void notifyWatchees() { - List watchees = this.watchees; - for (int i = 0; i < watchees.size();) { - Entry e = watchees.get(i); - if (!e.thread.isAlive()) { - watchees.remove(i); - try { - e.task.run(); - } catch (Throwable t) { - logger.warn("Thread death watcher task raised an exception:", t); - } - } else { - i ++; - } - } - } - } - - private static final class Entry extends MpscLinkedQueueNode { - final Thread thread; - final Runnable task; - final boolean isWatch; - - Entry(Thread thread, Runnable task, boolean isWatch) { - this.thread = thread; - this.task = task; - this.isWatch = isWatch; - } - - @Override - public Entry value() { - return this; - } - - @Override - public int hashCode() { - return thread.hashCode() ^ task.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - - if (!(obj instanceof Entry)) { - return false; - } - - Entry that = (Entry) obj; - return thread == that.thread && task == that.task; - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/Timeout.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/Timeout.java deleted file mode 100755 index 17ad244ff3..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/Timeout.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util; - -/** - * A handle associated with a {@link TimerTask} that is returned by a - * {@link Timer}. - */ -public interface Timeout { - - /** - * Returns the {@link Timer} that created this handle. - */ - Timer timer(); - - /** - * Returns the {@link TimerTask} which is associated with this handle. - */ - TimerTask task(); - - /** - * Returns {@code true} if and only if the {@link TimerTask} associated - * with this handle has been expired. - */ - boolean isExpired(); - - /** - * Returns {@code true} if and only if the {@link TimerTask} associated - * with this handle has been cancelled. - */ - boolean isCancelled(); - - /** - * Attempts to cancel the {@link TimerTask} associated with this handle. - * If the task has been executed or cancelled already, it will return with - * no side effect. - * - * @return True if the cancellation completed successfully, otherwise false - */ - boolean cancel(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/Timer.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/Timer.java deleted file mode 100755 index 3fabac51ce..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/Timer.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util; - -import java.util.Set; -import java.util.concurrent.TimeUnit; - -/** - * Schedules {@link TimerTask}s for one-time future execution in a background - * thread. - */ -public interface Timer { - - /** - * Schedules the specified {@link TimerTask} for one-time execution after - * the specified delay. - * - * @return a handle which is associated with the specified task - * - * @throws IllegalStateException if this timer has been - * {@linkplain #stop() stopped} already - */ - Timeout newTimeout(TimerTask task, long delay, TimeUnit unit); - - /** - * Releases all resources acquired by this {@link Timer} and cancels all - * tasks which were scheduled but not executed yet. - * - * @return the handles associated with the tasks which were canceled by - * this method - */ - Set stop(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/TimerTask.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/TimerTask.java deleted file mode 100755 index e42682e37f..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/TimerTask.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util; - -import java.util.concurrent.TimeUnit; - -/** - * A task which is executed after the delay specified with - * {@link Timer#newTimeout(TimerTask, long, TimeUnit)}. - */ -public interface TimerTask { - - /** - * Executed after the delay specified with - * {@link Timer#newTimeout(TimerTask, long, TimeUnit)}. - * - * @param timeout a handle which is associated with this task - */ - void run(Timeout timeout) throws Exception; -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/UniqueName.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/UniqueName.java deleted file mode 100755 index 2220bc0065..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/UniqueName.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util; - -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.atomic.AtomicInteger; - -import static com.ai.cloud.io.netty.util.internal.ObjectUtil.checkNotNull; - -/** - * @deprecated Known to have problems with class loaders. - * - * Defines a name that must be unique in the map that is provided during construction. - */ -@Deprecated -public class UniqueName implements Comparable { - - private static final AtomicInteger nextId = new AtomicInteger(); - - private final int id; - private final String name; - - /** - * Constructs a new {@link UniqueName} - * - * @param map the map of names to compare with - * @param name the name of this {@link UniqueName} - * @param args the arguments to process - */ - public UniqueName(ConcurrentMap map, String name, Object... args) { - checkNotNull(map, "map"); - - if (args != null && args.length > 0) { - validateArgs(args); - } - - if (map.putIfAbsent(name, Boolean.TRUE) != null) { - throw new IllegalArgumentException(String.format("'%s' is already in use", name)); - } - this.name = checkNotNull(name, "name"); - id = nextId.incrementAndGet(); - } - - protected UniqueName(String name) { - this.name = checkNotNull(name, "name"); - id = nextId.incrementAndGet(); - } - - /** - * Validates the given arguments. This method does not do anything on its own, but must be - * overridden by its subclasses. - * - * @param args arguments to validate - */ - @SuppressWarnings("unused") - protected void validateArgs(Object... args) { - // Subclasses will override. - } - - /** - * Returns this {@link UniqueName}'s name - * - * @return the name - */ - public final String name() { - return name; - } - - /** - * Returns this {@link UniqueName}'s ID - * - * @return the id - */ - public final int id() { - return id; - } - - @Override - public final int hashCode() { - return super.hashCode(); - } - - @Override - public final boolean equals(Object o) { - return super.equals(o); - } - - @Override - public int compareTo(UniqueName other) { - if (this == other) { - return 0; - } - - int returnCode = name.compareTo(other.name); - if (returnCode != 0) { - return returnCode; - } - - return ((Integer) id).compareTo(other.id); - } - - @Override - public String toString() { - return name(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/Version.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/Version.java deleted file mode 100755 index 3f102a572e..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/Version.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.util; - -import java.io.InputStream; -import java.net.URL; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.TreeMap; - -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - -/** - * Retrieves the version information of available Netty artifacts. - *

- * This class retrieves the version information from {@code META-INF/io.netty.versions.properties}, which is - * generated in build time. Note that it may not be possible to retrieve the information completely, depending on - * your environment, such as the specified {@link ClassLoader}, the current {@link SecurityManager}. - *

- */ -public final class Version { - - private static final String PROP_VERSION = ".version"; - private static final String PROP_BUILD_DATE = ".buildDate"; - private static final String PROP_COMMIT_DATE = ".commitDate"; - private static final String PROP_SHORT_COMMIT_HASH = ".shortCommitHash"; - private static final String PROP_LONG_COMMIT_HASH = ".longCommitHash"; - private static final String PROP_REPO_STATUS = ".repoStatus"; - - /** - * Retrieves the version information of Netty artifacts using the current - * {@linkplain Thread#getContextClassLoader() context class loader}. - * - * @return A {@link Map} whose keys are Maven artifact IDs and whose values are {@link Version}s - */ - public static Map identify() { - return identify(null); - } - - /** - * Retrieves the version information of Netty artifacts using the specified {@link ClassLoader}. - * - * @return A {@link Map} whose keys are Maven artifact IDs and whose values are {@link Version}s - */ - public static Map identify(ClassLoader classLoader) { - if (classLoader == null) { - classLoader = PlatformDependent.getContextClassLoader(); - } - - // Collect all properties. - Properties props = new Properties(); - try { - Enumeration resources = classLoader.getResources("META-INF/io.netty.versions.properties"); - while (resources.hasMoreElements()) { - URL url = resources.nextElement(); - InputStream in = url.openStream(); - try { - props.load(in); - } finally { - try { - in.close(); - } catch (Exception ignore) { - // Ignore. - } - } - } - } catch (Exception ignore) { - // Not critical. Just ignore. - } - - // Collect all artifactIds. - Set artifactIds = new HashSet(); - for (Object o: props.keySet()) { - String k = (String) o; - - int dotIndex = k.indexOf('.'); - if (dotIndex <= 0) { - continue; - } - - String artifactId = k.substring(0, dotIndex); - - // Skip the entries without required information. - if (!props.containsKey(artifactId + PROP_VERSION) || - !props.containsKey(artifactId + PROP_BUILD_DATE) || - !props.containsKey(artifactId + PROP_COMMIT_DATE) || - !props.containsKey(artifactId + PROP_SHORT_COMMIT_HASH) || - !props.containsKey(artifactId + PROP_LONG_COMMIT_HASH) || - !props.containsKey(artifactId + PROP_REPO_STATUS)) { - continue; - } - - artifactIds.add(artifactId); - } - - Map versions = new TreeMap(); - for (String artifactId: artifactIds) { - versions.put( - artifactId, - new Version( - artifactId, - props.getProperty(artifactId + PROP_VERSION), - parseIso8601(props.getProperty(artifactId + PROP_BUILD_DATE)), - parseIso8601(props.getProperty(artifactId + PROP_COMMIT_DATE)), - props.getProperty(artifactId + PROP_SHORT_COMMIT_HASH), - props.getProperty(artifactId + PROP_LONG_COMMIT_HASH), - props.getProperty(artifactId + PROP_REPO_STATUS))); - } - - return versions; - } - - private static long parseIso8601(String value) { - try { - return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z").parse(value).getTime(); - } catch (ParseException ignored) { - return 0; - } - } - - /** - * Prints the version information to {@link System#err}. - */ - public static void main(String[] args) { - for (Version v: identify().values()) { - System.err.println(v); - } - } - - private final String artifactId; - private final String artifactVersion; - private final long buildTimeMillis; - private final long commitTimeMillis; - private final String shortCommitHash; - private final String longCommitHash; - private final String repositoryStatus; - - private Version( - String artifactId, String artifactVersion, - long buildTimeMillis, long commitTimeMillis, - String shortCommitHash, String longCommitHash, String repositoryStatus) { - this.artifactId = artifactId; - this.artifactVersion = artifactVersion; - this.buildTimeMillis = buildTimeMillis; - this.commitTimeMillis = commitTimeMillis; - this.shortCommitHash = shortCommitHash; - this.longCommitHash = longCommitHash; - this.repositoryStatus = repositoryStatus; - } - - public String artifactId() { - return artifactId; - } - - public String artifactVersion() { - return artifactVersion; - } - - public long buildTimeMillis() { - return buildTimeMillis; - } - - public long commitTimeMillis() { - return commitTimeMillis; - } - - public String shortCommitHash() { - return shortCommitHash; - } - - public String longCommitHash() { - return longCommitHash; - } - - public String repositoryStatus() { - return repositoryStatus; - } - - @Override - public String toString() { - return artifactId + '-' + artifactVersion + '.' + shortCommitHash + - ("clean".equals(repositoryStatus)? "" : " (repository: " + repositoryStatus + ')'); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/collection/IntObjectHashMap.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/collection/IntObjectHashMap.java deleted file mode 100755 index 26437d66f8..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/collection/IntObjectHashMap.java +++ /dev/null @@ -1,552 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, version 2.0 (the - * "License"); you may not use this file except in compliance with the License. You may obtain a - * copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ - -package com.ai.cloud.io.netty.util.collection; - -import java.lang.reflect.Array; -import java.util.AbstractCollection; -import java.util.Arrays; -import java.util.Collection; -import java.util.Iterator; -import java.util.NoSuchElementException; - -/** - * A hash map implementation of {@link IntObjectMap} that uses open addressing for keys. - * To minimize the memory footprint, this class uses open addressing rather than chaining. - * Collisions are resolved using linear probing. Deletions implement compaction, so cost of - * remove can approach O(N) for full maps, which makes a small loadFactor recommended. - * - * @param The value type stored in the map. - */ -public class IntObjectHashMap implements IntObjectMap, Iterable> { - - /** Default initial capacity. Used if not specified in the constructor */ - private static final int DEFAULT_CAPACITY = 11; - - /** Default load factor. Used if not specified in the constructor */ - private static final float DEFAULT_LOAD_FACTOR = 0.5f; - - /** - * Placeholder for null values, so we can use the actual null to mean available. - * (Better than using a placeholder for available: less references for GC processing.) - */ - private static final Object NULL_VALUE = new Object(); - - /** The maximum number of elements allowed without allocating more space. */ - private int maxSize; - - /** The load factor for the map. Used to calculate {@link #maxSize}. */ - private final float loadFactor; - - private int[] keys; - private V[] values; - private Collection valueCollection; - private int size; - - public IntObjectHashMap() { - this(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR); - } - - public IntObjectHashMap(int initialCapacity) { - this(initialCapacity, DEFAULT_LOAD_FACTOR); - } - - public IntObjectHashMap(int initialCapacity, float loadFactor) { - if (initialCapacity < 1) { - throw new IllegalArgumentException("initialCapacity must be >= 1"); - } - if (loadFactor <= 0.0f || loadFactor > 1.0f) { - // Cannot exceed 1 because we can never store more than capacity elements; - // using a bigger loadFactor would trigger rehashing before the desired load is reached. - throw new IllegalArgumentException("loadFactor must be > 0 and <= 1"); - } - - this.loadFactor = loadFactor; - - // Adjust the initial capacity if necessary. - int capacity = adjustCapacity(initialCapacity); - - // Allocate the arrays. - keys = new int[capacity]; - @SuppressWarnings({ "unchecked", "SuspiciousArrayCast" }) - V[] temp = (V[]) new Object[capacity]; - values = temp; - - // Initialize the maximum size value. - maxSize = calcMaxSize(capacity); - } - - private static T toExternal(T value) { - return value == NULL_VALUE ? null : value; - } - - @SuppressWarnings("unchecked") - private static T toInternal(T value) { - return value == null ? (T) NULL_VALUE : value; - } - - @Override - public V get(int key) { - int index = indexOf(key); - return index == -1 ? null : toExternal(values[index]); - } - - @Override - public V put(int key, V value) { - int startIndex = hashIndex(key); - int index = startIndex; - - for (;;) { - if (values[index] == null) { - // Found empty slot, use it. - keys[index] = key; - values[index] = toInternal(value); - growSize(); - return null; - } - if (keys[index] == key) { - // Found existing entry with this key, just replace the value. - V previousValue = values[index]; - values[index] = toInternal(value); - return toExternal(previousValue); - } - - // Conflict, keep probing ... - if ((index = probeNext(index)) == startIndex) { - // Can only happen if the map was full at MAX_ARRAY_SIZE and couldn't grow. - throw new IllegalStateException("Unable to insert"); - } - } - } - - private int probeNext(int index) { - return index == values.length - 1 ? 0 : index + 1; - } - - @Override - public void putAll(IntObjectMap sourceMap) { - if (sourceMap instanceof IntObjectHashMap) { - // Optimization - iterate through the arrays. - IntObjectHashMap source = (IntObjectHashMap) sourceMap; - for (int i = 0; i < source.values.length; ++i) { - V sourceValue = source.values[i]; - if (sourceValue != null) { - put(source.keys[i], sourceValue); - } - } - return; - } - - // Otherwise, just add each entry. - for (Entry entry : sourceMap.entries()) { - put(entry.key(), entry.value()); - } - } - - @Override - public V remove(int key) { - int index = indexOf(key); - if (index == -1) { - return null; - } - - V prev = values[index]; - removeAt(index); - return toExternal(prev); - } - - @Override - public int size() { - return size; - } - - @Override - public boolean isEmpty() { - return size == 0; - } - - @Override - public void clear() { - Arrays.fill(keys, 0); - Arrays.fill(values, null); - size = 0; - } - - @Override - public boolean containsKey(int key) { - return indexOf(key) >= 0; - } - - @Override - public boolean containsValue(V value) { - V v1 = toInternal(value); - for (V v2 : values) { - // The map supports null values; this will be matched as NULL_VALUE.equals(NULL_VALUE). - if (v2 != null && v2.equals(v1)) { - return true; - } - } - return false; - } - - @Override - public Iterable> entries() { - return this; - } - - @Override - public Iterator> iterator() { - return new IteratorImpl(); - } - - @Override - public int[] keys() { - int[] outKeys = new int[size()]; - int targetIx = 0; - for (int i = 0; i < values.length; ++i) { - if (values[i] != null) { - outKeys[targetIx++] = keys[i]; - } - } - return outKeys; - } - - @Override - public V[] values(Class clazz) { - @SuppressWarnings("unchecked") - V[] outValues = (V[]) Array.newInstance(clazz, size()); - int targetIx = 0; - for (V value : values) { - if (value != null) { - outValues[targetIx++] = value; - } - } - return outValues; - } - - @Override - public Collection values() { - Collection valueCollection = this.valueCollection; - if (valueCollection == null) { - this.valueCollection = valueCollection = new AbstractCollection() { - @Override - public Iterator iterator() { - return new Iterator() { - final Iterator> iter = IntObjectHashMap.this.iterator(); - @Override - public boolean hasNext() { - return iter.hasNext(); - } - - @Override - public V next() { - return iter.next().value(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - - @Override - public int size() { - return size; - } - }; - } - - return valueCollection; - } - - @Override - public int hashCode() { - // Hashcode is based on all non-zero, valid keys. We have to scan the whole keys - // array, which may have different lengths for two maps of same size(), so the - // capacity cannot be used as input for hashing but the size can. - int hash = size; - for (int key : keys) { - // 0 can be a valid key or unused slot, but won't impact the hashcode in either case. - // This way we can use a cheap loop without conditionals, or hard-to-unroll operations, - // or the devastatingly bad memory locality of visiting value objects. - // Also, it's important to use a hash function that does not depend on the ordering - // of terms, only their values; since the map is an unordered collection and - // entries can end up in different positions in different maps that have the same - // elements, but with different history of puts/removes, due to conflicts. - hash ^= key; - } - return hash; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!(obj instanceof IntObjectMap)) { - return false; - } - @SuppressWarnings("rawtypes") - IntObjectMap other = (IntObjectMap) obj; - if (size != other.size()) { - return false; - } - for (int i = 0; i < values.length; ++i) { - V value = values[i]; - if (value != null) { - int key = keys[i]; - Object otherValue = other.get(key); - if (value == NULL_VALUE) { - if (otherValue != null) { - return false; - } - } else if (!value.equals(otherValue)) { - return false; - } - } - } - return true; - } - - /** - * Locates the index for the given key. This method probes using double hashing. - * - * @param key the key for an entry in the map. - * @return the index where the key was found, or {@code -1} if no entry is found for that key. - */ - private int indexOf(int key) { - int startIndex = hashIndex(key); - int index = startIndex; - - for (;;) { - if (values[index] == null) { - // It's available, so no chance that this value exists anywhere in the map. - return -1; - } - if (key == keys[index]) { - return index; - } - - // Conflict, keep probing ... - if ((index = probeNext(index)) == startIndex) { - return -1; - } - } - } - - /** - * Returns the hashed index for the given key. - */ - private int hashIndex(int key) { - // Allowing for negative keys by adding the length after the first mod operation. - return (key % keys.length + keys.length) % keys.length; - } - - /** - * Grows the map size after an insertion. If necessary, performs a rehash of the map. - */ - private void growSize() { - size++; - - if (size > maxSize) { - // Need to grow the arrays. We take care to detect integer overflow, - // also limit array size to ArrayList.MAX_ARRAY_SIZE. - rehash(adjustCapacity((int) Math.min(keys.length * 2.0, Integer.MAX_VALUE - 8))); - } else if (size == keys.length) { - // Open addressing requires that we have at least 1 slot available. Need to refresh - // the arrays to clear any removed elements. - rehash(keys.length); - } - } - - /** - * Adjusts the given capacity value to ensure that it's odd. Even capacities can break probing. - */ - private static int adjustCapacity(int capacity) { - return capacity | 1; - } - - /** - * Removes entry at the given index position. Also performs opportunistic, incremental rehashing - * if necessary to not break conflict chains. - * - * @param index the index position of the element to remove. - */ - private void removeAt(int index) { - --size; - // Clearing the key is not strictly necessary (for GC like in a regular collection), - // but recommended for security. The memory location is still fresh in the cache anyway. - keys[index] = 0; - values[index] = null; - - // In the interval from index to the next available entry, the arrays may have entries - // that are displaced from their base position due to prior conflicts. Iterate these - // entries and move them back if possible, optimizing future lookups. - // Knuth Section 6.4 Algorithm R, also used by the JDK's IdentityHashMap. - - int nextFree = index; - for (int i = probeNext(index); values[i] != null; i = probeNext(i)) { - int bucket = hashIndex(keys[i]); - if (i < bucket && (bucket <= nextFree || nextFree <= i) || - bucket <= nextFree && nextFree <= i) { - // Move the displaced entry "back" to the first available position. - keys[nextFree] = keys[i]; - values[nextFree] = values[i]; - // Put the first entry after the displaced entry - keys[i] = 0; - values[i] = null; - nextFree = i; - } - } - } - - /** - * Calculates the maximum size allowed before rehashing. - */ - private int calcMaxSize(int capacity) { - // Clip the upper bound so that there will always be at least one available slot. - int upperBound = capacity - 1; - return Math.min(upperBound, (int) (capacity * loadFactor)); - } - - /** - * Rehashes the map for the given capacity. - * - * @param newCapacity the new capacity for the map. - */ - private void rehash(int newCapacity) { - int[] oldKeys = keys; - V[] oldVals = values; - - keys = new int[newCapacity]; - @SuppressWarnings({ "unchecked", "SuspiciousArrayCast" }) - V[] temp = (V[]) new Object[newCapacity]; - values = temp; - - maxSize = calcMaxSize(newCapacity); - - // Insert to the new arrays. - for (int i = 0; i < oldVals.length; ++i) { - V oldVal = oldVals[i]; - if (oldVal != null) { - // Inlined put(), but much simpler: we don't need to worry about - // duplicated keys, growing/rehashing, or failing to insert. - int oldKey = oldKeys[i]; - int index = hashIndex(oldKey); - - for (;;) { - if (values[index] == null) { - keys[index] = oldKey; - values[index] = toInternal(oldVal); - break; - } - - // Conflict, keep probing. Can wrap around, but never reaches startIndex again. - index = probeNext(index); - } - } - } - } - - /** - * Iterator for traversing the entries in this map. - */ - private final class IteratorImpl implements Iterator>, Entry { - private int prevIndex = -1; - private int nextIndex = -1; - private int entryIndex = -1; - - private void scanNext() { - for (;;) { - if (++nextIndex == values.length || values[nextIndex] != null) { - break; - } - } - } - - @Override - public boolean hasNext() { - if (nextIndex == -1) { - scanNext(); - } - return nextIndex < keys.length; - } - - @Override - public Entry next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - - prevIndex = nextIndex; - scanNext(); - - // Always return the same Entry object, just change its index each time. - entryIndex = prevIndex; - return this; - } - - @Override - public void remove() { - if (prevIndex < 0) { - throw new IllegalStateException("next must be called before each remove."); - } - removeAt(prevIndex); - prevIndex = -1; - } - - // Entry implementation. Since this implementation uses a single Entry, we coalesce that - // into the Iterator object (potentially making loop optimization much easier). - - @Override - public int key() { - return keys[entryIndex]; - } - - @Override - public V value() { - return toExternal(values[entryIndex]); - } - - @Override - public void setValue(V value) { - values[entryIndex] = toInternal(value); - } - } - - @Override - public String toString() { - if (size == 0) { - return "{}"; - } - StringBuilder sb = new StringBuilder(4 * size); - for (int i = 0; i < values.length; ++i) { - V value = values[i]; - if (value != null) { - sb.append(sb.length() == 0 ? "{" : ", "); - sb.append(keyToString(keys[i])).append('=').append(value == this ? "(this Map)" : value); - } - } - return sb.append('}').toString(); - } - - /** - * Helper method called by {@link #toString()} in order to convert a single map key into a string. - */ - protected String keyToString(int key) { - return Integer.toString(key); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/collection/IntObjectMap.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/collection/IntObjectMap.java deleted file mode 100755 index e34a58172b..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/collection/IntObjectMap.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, version 2.0 (the - * "License"); you may not use this file except in compliance with the License. You may obtain a - * copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package com.ai.cloud.io.netty.util.collection; - -import java.util.Collection; - -/** - * Interface for a primitive map that uses {@code int}s as keys. - * - * @param the value type stored in the map. - */ -public interface IntObjectMap { - - /** - * An Entry in the map. - * - * @param the value type stored in the map. - */ - interface Entry { - /** - * Gets the key for this entry. - */ - int key(); - - /** - * Gets the value for this entry. - */ - V value(); - - /** - * Sets the value for this entry. - */ - void setValue(V value); - } - - /** - * Gets the value in the map with the specified key. - * - * @param key the key whose associated value is to be returned. - * @return the value or {@code null} if the key was not found in the map. - */ - V get(int key); - - /** - * Puts the given entry into the map. - * - * @param key the key of the entry. - * @param value the value of the entry. - * @return the previous value for this key or {@code null} if there was no previous mapping. - */ - V put(int key, V value); - - /** - * Puts all of the entries from the given map into this map. - */ - void putAll(IntObjectMap sourceMap); - - /** - * Removes the entry with the specified key. - * - * @param key the key for the entry to be removed from this map. - * @return the previous value for the key, or {@code null} if there was no mapping. - */ - V remove(int key); - - /** - * Returns the number of entries contained in this map. - */ - int size(); - - /** - * Indicates whether or not this map is empty (i.e {@link #size()} == {@code 0]). - - */ - boolean isEmpty(); - - /** - * Clears all entries from this map. - */ - void clear(); - - /** - * Indicates whether or not this map contains a value for the specified key. - */ - boolean containsKey(int key); - - /** - * Indicates whether or not the map contains the specified value. - */ - boolean containsValue(V value); - - /** - * Gets an iterable collection of the entries contained in this map. - */ - Iterable> entries(); - - /** - * Gets the keys contained in this map. - */ - int[] keys(); - - /** - * Gets the values contained in this map. - */ - V[] values(Class clazz); - - /** - * Gets the values contatins in this map as a {@link Collection}. - */ - Collection values(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/collection/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/collection/package-info.java deleted file mode 100755 index fef725f56b..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/collection/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * Utility classes for commonly used collections. - */ -package com.ai.cloud.io.netty.util.collection; diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/AbstractEventExecutor.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/AbstractEventExecutor.java deleted file mode 100755 index 627f2d49b9..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/AbstractEventExecutor.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.concurrent; - -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.concurrent.AbstractExecutorService; -import java.util.concurrent.Callable; -import java.util.concurrent.RunnableFuture; -import java.util.concurrent.TimeUnit; - -/** - * Abstract base class for {@link EventExecutor} implementations. - */ -public abstract class AbstractEventExecutor extends AbstractExecutorService implements EventExecutor { - - @Override - public EventExecutor next() { - return this; - } - - @Override - public boolean inEventLoop() { - return inEventLoop(Thread.currentThread()); - } - - @Override - public Iterator iterator() { - return new EventExecutorIterator(); - } - - @Override - public Future shutdownGracefully() { - return shutdownGracefully(2, 15, TimeUnit.SECONDS); - } - - /** - * @deprecated {@link #shutdownGracefully(long, long, TimeUnit)} or {@link #shutdownGracefully()} instead. - */ - @Override - @Deprecated - public abstract void shutdown(); - - /** - * @deprecated {@link #shutdownGracefully(long, long, TimeUnit)} or {@link #shutdownGracefully()} instead. - */ - @Override - @Deprecated - public List shutdownNow() { - shutdown(); - return Collections.emptyList(); - } - - @Override - public Promise newPromise() { - return new DefaultPromise(this); - } - - @Override - public ProgressivePromise newProgressivePromise() { - return new DefaultProgressivePromise(this); - } - - @Override - public Future newSucceededFuture(V result) { - return new SucceededFuture(this, result); - } - - @Override - public Future newFailedFuture(Throwable cause) { - return new FailedFuture(this, cause); - } - - @Override - public Future submit(Runnable task) { - return (Future) super.submit(task); - } - - @Override - public Future submit(Runnable task, T result) { - return (Future) super.submit(task, result); - } - - @Override - public Future submit(Callable task) { - return (Future) super.submit(task); - } - - @Override - protected final RunnableFuture newTaskFor(Runnable runnable, T value) { - return new PromiseTask(this, runnable, value); - } - - @Override - protected final RunnableFuture newTaskFor(Callable callable) { - return new PromiseTask(this, callable); - } - - @Override - public ScheduledFuture schedule(Runnable command, long delay, - TimeUnit unit) { - throw new UnsupportedOperationException(); - } - - @Override - public ScheduledFuture schedule(Callable callable, long delay, TimeUnit unit) { - throw new UnsupportedOperationException(); - } - - @Override - public ScheduledFuture scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) { - throw new UnsupportedOperationException(); - } - - @Override - public ScheduledFuture scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) { - throw new UnsupportedOperationException(); - } - - private final class EventExecutorIterator implements Iterator { - private boolean nextCalled; - - @Override - public boolean hasNext() { - return !nextCalled; - } - - @Override - public EventExecutor next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - nextCalled = true; - return AbstractEventExecutor.this; - } - - @Override - public void remove() { - throw new UnsupportedOperationException("read-only"); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/AbstractEventExecutorGroup.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/AbstractEventExecutorGroup.java deleted file mode 100755 index 213f61c0cb..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/AbstractEventExecutorGroup.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.concurrent; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - - -/** - * Abstract base class for {@link EventExecutorGroup} implementations. - */ -public abstract class AbstractEventExecutorGroup implements EventExecutorGroup { - - @Override - public Future submit(Runnable task) { - return next().submit(task); - } - - @Override - public Future submit(Runnable task, T result) { - return next().submit(task, result); - } - - @Override - public Future submit(Callable task) { - return next().submit(task); - } - - @Override - public ScheduledFuture schedule(Runnable command, long delay, TimeUnit unit) { - return next().schedule(command, delay, unit); - } - - @Override - public ScheduledFuture schedule(Callable callable, long delay, TimeUnit unit) { - return next().schedule(callable, delay, unit); - } - - @Override - public ScheduledFuture scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) { - return next().scheduleAtFixedRate(command, initialDelay, period, unit); - } - - @Override - public ScheduledFuture scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) { - return next().scheduleWithFixedDelay(command, initialDelay, delay, unit); - } - - @Override - public Future shutdownGracefully() { - return shutdownGracefully(2, 15, TimeUnit.SECONDS); - } - - /** - * @deprecated {@link #shutdownGracefully(long, long, TimeUnit)} or {@link #shutdownGracefully()} instead. - */ - @Override - @Deprecated - public abstract void shutdown(); - - /** - * @deprecated {@link #shutdownGracefully(long, long, TimeUnit)} or {@link #shutdownGracefully()} instead. - */ - @Override - @Deprecated - public List shutdownNow() { - shutdown(); - return Collections.emptyList(); - } - - @Override - public List> invokeAll(Collection> tasks) - throws InterruptedException { - return next().invokeAll(tasks); - } - - @Override - public List> invokeAll( - Collection> tasks, long timeout, TimeUnit unit) throws InterruptedException { - return next().invokeAll(tasks, timeout, unit); - } - - @Override - public T invokeAny(Collection> tasks) throws InterruptedException, ExecutionException { - return next().invokeAny(tasks); - } - - @Override - public T invokeAny(Collection> tasks, long timeout, TimeUnit unit) - throws InterruptedException, ExecutionException, TimeoutException { - return next().invokeAny(tasks, timeout, unit); - } - - @Override - public void execute(Runnable command) { - next().execute(command); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/AbstractFuture.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/AbstractFuture.java deleted file mode 100755 index f7ef4915e1..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/AbstractFuture.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.concurrent; - -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -/** - * Abstract {@link Future} implementation which does not allow for cancellation. - * - * @param - */ -public abstract class AbstractFuture implements Future { - - @Override - public V get() throws InterruptedException, ExecutionException { - await(); - - Throwable cause = cause(); - if (cause == null) { - return getNow(); - } - throw new ExecutionException(cause); - } - - @Override - public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { - if (await(timeout, unit)) { - Throwable cause = cause(); - if (cause == null) { - return getNow(); - } - throw new ExecutionException(cause); - } - throw new TimeoutException(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/AbstractScheduledEventExecutor.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/AbstractScheduledEventExecutor.java deleted file mode 100755 index d109128a53..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/AbstractScheduledEventExecutor.java +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.concurrent; - -import java.util.PriorityQueue; -import java.util.Queue; -import java.util.concurrent.Callable; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -import com.ai.cloud.io.netty.util.internal.ObjectUtil; -import com.ai.cloud.io.netty.util.internal.OneTimeTask; - -/** - * Abstract base class for {@link EventExecutor}s that want to support scheduling. - */ -public abstract class AbstractScheduledEventExecutor extends AbstractEventExecutor { - - Queue> scheduledTaskQueue; - - protected static long nanoTime() { - return ScheduledFutureTask.nanoTime(); - } - - Queue> scheduledTaskQueue() { - if (scheduledTaskQueue == null) { - scheduledTaskQueue = new PriorityQueue>(); - } - return scheduledTaskQueue; - } - - private static boolean isNullOrEmpty(Queue> queue) { - return queue == null || queue.isEmpty(); - } - - /** - * Cancel all scheduled tasks. - * - * This method MUST be called only when {@link #inEventLoop()} is {@code true}. - */ - protected void cancelScheduledTasks() { - assert inEventLoop(); - Queue> scheduledTaskQueue = this.scheduledTaskQueue; - if (isNullOrEmpty(scheduledTaskQueue)) { - return; - } - - final ScheduledFutureTask[] scheduledTasks = - scheduledTaskQueue.toArray(new ScheduledFutureTask[scheduledTaskQueue.size()]); - - for (ScheduledFutureTask task: scheduledTasks) { - task.cancelWithoutRemove(false); - } - - scheduledTaskQueue.clear(); - } - - /** - * @see {@link #pollScheduledTask(long)} - */ - protected final Runnable pollScheduledTask() { - return pollScheduledTask(nanoTime()); - } - - /** - * Return the {@link Runnable} which is ready to be executed with the given {@code nanoTime}. - * You should use {@link #nanoTime()} to retrieve the the correct {@code nanoTime}. - */ - protected final Runnable pollScheduledTask(long nanoTime) { - assert inEventLoop(); - - Queue> scheduledTaskQueue = this.scheduledTaskQueue; - ScheduledFutureTask scheduledTask = scheduledTaskQueue == null ? null : scheduledTaskQueue.peek(); - if (scheduledTask == null) { - return null; - } - - if (scheduledTask.deadlineNanos() <= nanoTime) { - scheduledTaskQueue.remove(); - return scheduledTask; - } - return null; - } - - /** - * Return the nanoseconds when the next scheduled task is ready to be run or {@code -1} if no task is scheduled. - */ - protected final long nextScheduledTaskNano() { - Queue> scheduledTaskQueue = this.scheduledTaskQueue; - ScheduledFutureTask scheduledTask = scheduledTaskQueue == null ? null : scheduledTaskQueue.peek(); - if (scheduledTask == null) { - return -1; - } - return Math.max(0, scheduledTask.deadlineNanos() - nanoTime()); - } - - final ScheduledFutureTask peekScheduledTask() { - Queue> scheduledTaskQueue = this.scheduledTaskQueue; - if (scheduledTaskQueue == null) { - return null; - } - return scheduledTaskQueue.peek(); - } - - /** - * Returns {@code true} if a scheduled task is ready for processing. - */ - protected final boolean hasScheduledTasks() { - Queue> scheduledTaskQueue = this.scheduledTaskQueue; - ScheduledFutureTask scheduledTask = scheduledTaskQueue == null ? null : scheduledTaskQueue.peek(); - return scheduledTask != null && scheduledTask.deadlineNanos() <= nanoTime(); - } - - @Override - public ScheduledFuture schedule(Runnable command, long delay, TimeUnit unit) { - ObjectUtil.checkNotNull(command, "command"); - ObjectUtil.checkNotNull(unit, "unit"); - if (delay < 0) { - throw new IllegalArgumentException( - String.format("delay: %d (expected: >= 0)", delay)); - } - return schedule(new ScheduledFutureTask( - this, command, null, ScheduledFutureTask.deadlineNanos(unit.toNanos(delay)))); - } - - @Override - public ScheduledFuture schedule(Callable callable, long delay, TimeUnit unit) { - ObjectUtil.checkNotNull(callable, "callable"); - ObjectUtil.checkNotNull(unit, "unit"); - if (delay < 0) { - throw new IllegalArgumentException( - String.format("delay: %d (expected: >= 0)", delay)); - } - return schedule(new ScheduledFutureTask( - this, callable, ScheduledFutureTask.deadlineNanos(unit.toNanos(delay)))); - } - - @Override - public ScheduledFuture scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) { - ObjectUtil.checkNotNull(command, "command"); - ObjectUtil.checkNotNull(unit, "unit"); - if (initialDelay < 0) { - throw new IllegalArgumentException( - String.format("initialDelay: %d (expected: >= 0)", initialDelay)); - } - if (period <= 0) { - throw new IllegalArgumentException( - String.format("period: %d (expected: > 0)", period)); - } - - return schedule(new ScheduledFutureTask( - this, Executors.callable(command, null), - ScheduledFutureTask.deadlineNanos(unit.toNanos(initialDelay)), unit.toNanos(period))); - } - - @Override - public ScheduledFuture scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) { - ObjectUtil.checkNotNull(command, "command"); - ObjectUtil.checkNotNull(unit, "unit"); - if (initialDelay < 0) { - throw new IllegalArgumentException( - String.format("initialDelay: %d (expected: >= 0)", initialDelay)); - } - if (delay <= 0) { - throw new IllegalArgumentException( - String.format("delay: %d (expected: > 0)", delay)); - } - - return schedule(new ScheduledFutureTask( - this, Executors.callable(command, null), - ScheduledFutureTask.deadlineNanos(unit.toNanos(initialDelay)), -unit.toNanos(delay))); - } - - ScheduledFuture schedule(final ScheduledFutureTask task) { - if (inEventLoop()) { - scheduledTaskQueue().add(task); - } else { - execute(new OneTimeTask() { - @Override - public void run() { - scheduledTaskQueue().add(task); - } - }); - } - - return task; - } - - final void removeScheduled(final ScheduledFutureTask task) { - if (inEventLoop()) { - scheduledTaskQueue().remove(task); - } else { - execute(new OneTimeTask() { - @Override - public void run() { - removeScheduled(task); - } - }); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/BlockingOperationException.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/BlockingOperationException.java deleted file mode 100755 index 34e42669cb..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/BlockingOperationException.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.concurrent; - -/** - * An {@link IllegalStateException} which is raised when a user performed a blocking operation - * when the user is in an event loop thread. If a blocking operation is performed in an event loop - * thread, the blocking operation will most likely enter a dead lock state, hence throwing this - * exception. - */ -public class BlockingOperationException extends IllegalStateException { - - private static final long serialVersionUID = 2462223247762460301L; - - public BlockingOperationException() { } - - public BlockingOperationException(String s) { - super(s); - } - - public BlockingOperationException(Throwable cause) { - super(cause); - } - - public BlockingOperationException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/CompleteFuture.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/CompleteFuture.java deleted file mode 100755 index f86f82ce83..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/CompleteFuture.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.util.concurrent; - -import java.util.concurrent.TimeUnit; - -/** - * A skeletal {@link Future} implementation which represents a {@link Future} which has been completed already. - */ -public abstract class CompleteFuture extends AbstractFuture { - - private final EventExecutor executor; - - /** - * Creates a new instance. - * - * @param executor the {@link EventExecutor} associated with this future - */ - protected CompleteFuture(EventExecutor executor) { - this.executor = executor; - } - - /** - * Return the {@link EventExecutor} which is used by this {@link CompleteFuture}. - */ - protected EventExecutor executor() { - return executor; - } - - @Override - public Future addListener(GenericFutureListener> listener) { - if (listener == null) { - throw new NullPointerException("listener"); - } - DefaultPromise.notifyListener(executor(), this, listener); - return this; - } - - @Override - public Future addListeners(GenericFutureListener>... listeners) { - if (listeners == null) { - throw new NullPointerException("listeners"); - } - for (GenericFutureListener> l: listeners) { - if (l == null) { - break; - } - DefaultPromise.notifyListener(executor(), this, l); - } - return this; - } - - @Override - public Future removeListener(GenericFutureListener> listener) { - // NOOP - return this; - } - - @Override - public Future removeListeners(GenericFutureListener>... listeners) { - // NOOP - return this; - } - - @Override - public Future await() throws InterruptedException { - if (Thread.interrupted()) { - throw new InterruptedException(); - } - return this; - } - - @Override - public boolean await(long timeout, TimeUnit unit) throws InterruptedException { - if (Thread.interrupted()) { - throw new InterruptedException(); - } - return true; - } - - @Override - public Future sync() throws InterruptedException { - return this; - } - - @Override - public Future syncUninterruptibly() { - return this; - } - - @Override - public boolean await(long timeoutMillis) throws InterruptedException { - if (Thread.interrupted()) { - throw new InterruptedException(); - } - return true; - } - - @Override - public Future awaitUninterruptibly() { - return this; - } - - @Override - public boolean awaitUninterruptibly(long timeout, TimeUnit unit) { - return true; - } - - @Override - public boolean awaitUninterruptibly(long timeoutMillis) { - return true; - } - - @Override - public boolean isDone() { - return true; - } - - @Override - public boolean isCancellable() { - return false; - } - - @Override - public boolean isCancelled() { - return false; - } - - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - return false; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/DefaultEventExecutor.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/DefaultEventExecutor.java deleted file mode 100755 index bdf7d796e3..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/DefaultEventExecutor.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.concurrent; - -import java.util.concurrent.ThreadFactory; - -/** - * Default {@link SingleThreadEventExecutor} implementation which just execute all submitted task in a - * serial fashion - * - */ -final class DefaultEventExecutor extends SingleThreadEventExecutor { - - DefaultEventExecutor(DefaultEventExecutorGroup parent, ThreadFactory threadFactory) { - super(parent, threadFactory, true); - } - - @Override - protected void run() { - for (;;) { - Runnable task = takeTask(); - if (task != null) { - task.run(); - updateLastExecutionTime(); - } - - if (confirmShutdown()) { - break; - } - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/DefaultEventExecutorGroup.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/DefaultEventExecutorGroup.java deleted file mode 100755 index dde66fdb74..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/DefaultEventExecutorGroup.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.concurrent; - -import java.util.concurrent.ThreadFactory; - -/** - * Default implementation of {@link MultithreadEventExecutorGroup} which will use {@link DefaultEventExecutor} instances - * to handle the tasks. - */ -public class DefaultEventExecutorGroup extends MultithreadEventExecutorGroup { - - /** - * @see {@link #DefaultEventExecutorGroup(int, ThreadFactory)} - */ - public DefaultEventExecutorGroup(int nThreads) { - this(nThreads, null); - } - - /** - * Create a new instance. - * - * @param nThreads the number of threads that will be used by this instance. - * @param threadFactory the ThreadFactory to use, or {@code null} if the default should be used. - */ - public DefaultEventExecutorGroup(int nThreads, ThreadFactory threadFactory) { - super(nThreads, threadFactory); - } - - @Override - protected EventExecutor newChild( - ThreadFactory threadFactory, Object... args) throws Exception { - return new DefaultEventExecutor(this, threadFactory); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/DefaultFutureListeners.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/DefaultFutureListeners.java deleted file mode 100755 index 3f94a78df4..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/DefaultFutureListeners.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.concurrent; - -import java.util.Arrays; - -final class DefaultFutureListeners { - - private GenericFutureListener>[] listeners; - private int size; - private int progressiveSize; // the number of progressive listeners - - @SuppressWarnings("unchecked") - DefaultFutureListeners( - GenericFutureListener> first, GenericFutureListener> second) { - listeners = new GenericFutureListener[2]; - listeners[0] = first; - listeners[1] = second; - size = 2; - if (first instanceof GenericProgressiveFutureListener) { - progressiveSize ++; - } - if (second instanceof GenericProgressiveFutureListener) { - progressiveSize ++; - } - } - - public void add(GenericFutureListener> l) { - GenericFutureListener>[] listeners = this.listeners; - final int size = this.size; - if (size == listeners.length) { - this.listeners = listeners = Arrays.copyOf(listeners, size << 1); - } - listeners[size] = l; - this.size = size + 1; - - if (l instanceof GenericProgressiveFutureListener) { - progressiveSize ++; - } - } - - public void remove(GenericFutureListener> l) { - final GenericFutureListener>[] listeners = this.listeners; - int size = this.size; - for (int i = 0; i < size; i ++) { - if (listeners[i] == l) { - int listenersToMove = size - i - 1; - if (listenersToMove > 0) { - System.arraycopy(listeners, i + 1, listeners, i, listenersToMove); - } - listeners[-- size] = null; - this.size = size; - - if (l instanceof GenericProgressiveFutureListener) { - progressiveSize --; - } - return; - } - } - } - - public GenericFutureListener>[] listeners() { - return listeners; - } - - public int size() { - return size; - } - - public int progressiveSize() { - return progressiveSize; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/DefaultProgressivePromise.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/DefaultProgressivePromise.java deleted file mode 100755 index d97e8c6c94..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/DefaultProgressivePromise.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.util.concurrent; - -public class DefaultProgressivePromise extends DefaultPromise implements ProgressivePromise { - - /** - * Creates a new instance. - * - * It is preferable to use {@link EventExecutor#newProgressivePromise()} to create a new progressive promise - * - * @param executor - * the {@link EventExecutor} which is used to notify the promise when it progresses or it is complete - */ - public DefaultProgressivePromise(EventExecutor executor) { - super(executor); - } - - protected DefaultProgressivePromise() { /* only for subclasses */ } - - @Override - public ProgressivePromise setProgress(long progress, long total) { - if (total < 0) { - // total unknown - total = -1; // normalize - if (progress < 0) { - throw new IllegalArgumentException("progress: " + progress + " (expected: >= 0)"); - } - } else if (progress < 0 || progress > total) { - throw new IllegalArgumentException( - "progress: " + progress + " (expected: 0 <= progress <= total (" + total + "))"); - } - - if (isDone()) { - throw new IllegalStateException("complete already"); - } - - notifyProgressiveListeners(progress, total); - return this; - } - - @Override - public boolean tryProgress(long progress, long total) { - if (total < 0) { - total = -1; - if (progress < 0 || isDone()) { - return false; - } - } else if (progress < 0 || progress > total || isDone()) { - return false; - } - - notifyProgressiveListeners(progress, total); - return true; - } - - @Override - public ProgressivePromise addListener(GenericFutureListener> listener) { - super.addListener(listener); - return this; - } - - @Override - public ProgressivePromise addListeners(GenericFutureListener>... listeners) { - super.addListeners(listeners); - return this; - } - - @Override - public ProgressivePromise removeListener(GenericFutureListener> listener) { - super.removeListener(listener); - return this; - } - - @Override - public ProgressivePromise removeListeners(GenericFutureListener>... listeners) { - super.removeListeners(listeners); - return this; - } - - @Override - public ProgressivePromise sync() throws InterruptedException { - super.sync(); - return this; - } - - @Override - public ProgressivePromise syncUninterruptibly() { - super.syncUninterruptibly(); - return this; - } - - @Override - public ProgressivePromise await() throws InterruptedException { - super.await(); - return this; - } - - @Override - public ProgressivePromise awaitUninterruptibly() { - super.awaitUninterruptibly(); - return this; - } - - @Override - public ProgressivePromise setSuccess(V result) { - super.setSuccess(result); - return this; - } - - @Override - public ProgressivePromise setFailure(Throwable cause) { - super.setFailure(cause); - return this; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/DefaultPromise.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/DefaultPromise.java deleted file mode 100755 index 3a4950c915..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/DefaultPromise.java +++ /dev/null @@ -1,882 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.concurrent; - -import java.util.ArrayDeque; -import java.util.concurrent.CancellationException; -import java.util.concurrent.TimeUnit; - -import com.ai.cloud.io.netty.util.Signal; -import com.ai.cloud.io.netty.util.internal.EmptyArrays; -import com.ai.cloud.io.netty.util.internal.InternalThreadLocalMap; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; -import com.ai.cloud.io.netty.util.internal.StringUtil; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -import static java.util.concurrent.TimeUnit.*; - -public class DefaultPromise extends AbstractFuture implements Promise { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(DefaultPromise.class); - private static final InternalLogger rejectedExecutionLogger = - InternalLoggerFactory.getInstance(DefaultPromise.class.getName() + ".rejectedExecution"); - - private static final int MAX_LISTENER_STACK_DEPTH = 8; - private static final Signal SUCCESS = Signal.valueOf(DefaultPromise.class.getName() + ".SUCCESS"); - private static final Signal UNCANCELLABLE = Signal.valueOf(DefaultPromise.class.getName() + ".UNCANCELLABLE"); - private static final CauseHolder CANCELLATION_CAUSE_HOLDER = new CauseHolder(new CancellationException()); - - static { - CANCELLATION_CAUSE_HOLDER.cause.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); - } - - private final EventExecutor executor; - - private volatile Object result; - - /** - * One or more listeners. Can be a {@link GenericFutureListener} or a {@link DefaultFutureListeners}. - * If {@code null}, it means either 1) no listeners were added yet or 2) all listeners were notified. - */ - private Object listeners; - - /** - * The list of the listeners that were added after the promise is done. Initially {@code null} and lazily - * instantiated when the late listener is scheduled to be notified later. Also used as a cached {@link Runnable} - * that performs the notification of the listeners it contains. - */ - private LateListeners lateListeners; - - private short waiters; - - /** - * Creates a new instance. - * - * It is preferable to use {@link EventExecutor#newPromise()} to create a new promise - * - * @param executor - * the {@link EventExecutor} which is used to notify the promise once it is complete - */ - public DefaultPromise(EventExecutor executor) { - if (executor == null) { - throw new NullPointerException("executor"); - } - this.executor = executor; - } - - protected DefaultPromise() { - // only for subclasses - executor = null; - } - - protected EventExecutor executor() { - return executor; - } - - @Override - public boolean isCancelled() { - return isCancelled0(result); - } - - private static boolean isCancelled0(Object result) { - return result instanceof CauseHolder && ((CauseHolder) result).cause instanceof CancellationException; - } - - @Override - public boolean isCancellable() { - return result == null; - } - - @Override - public boolean isDone() { - return isDone0(result); - } - - private static boolean isDone0(Object result) { - return result != null && result != UNCANCELLABLE; - } - - @Override - public boolean isSuccess() { - Object result = this.result; - if (result == null || result == UNCANCELLABLE) { - return false; - } - return !(result instanceof CauseHolder); - } - - @Override - public Throwable cause() { - Object result = this.result; - if (result instanceof CauseHolder) { - return ((CauseHolder) result).cause; - } - return null; - } - - @Override - public Promise addListener(GenericFutureListener> listener) { - if (listener == null) { - throw new NullPointerException("listener"); - } - - if (isDone()) { - notifyLateListener(listener); - return this; - } - - synchronized (this) { - if (!isDone()) { - if (listeners == null) { - listeners = listener; - } else { - if (listeners instanceof DefaultFutureListeners) { - ((DefaultFutureListeners) listeners).add(listener); - } else { - final GenericFutureListener> firstListener = - (GenericFutureListener>) listeners; - listeners = new DefaultFutureListeners(firstListener, listener); - } - } - return this; - } - } - - notifyLateListener(listener); - return this; - } - - @Override - public Promise addListeners(GenericFutureListener>... listeners) { - if (listeners == null) { - throw new NullPointerException("listeners"); - } - - for (GenericFutureListener> l: listeners) { - if (l == null) { - break; - } - addListener(l); - } - return this; - } - - @Override - public Promise removeListener(GenericFutureListener> listener) { - if (listener == null) { - throw new NullPointerException("listener"); - } - - if (isDone()) { - return this; - } - - synchronized (this) { - if (!isDone()) { - if (listeners instanceof DefaultFutureListeners) { - ((DefaultFutureListeners) listeners).remove(listener); - } else if (listeners == listener) { - listeners = null; - } - } - } - - return this; - } - - @Override - public Promise removeListeners(GenericFutureListener>... listeners) { - if (listeners == null) { - throw new NullPointerException("listeners"); - } - - for (GenericFutureListener> l: listeners) { - if (l == null) { - break; - } - removeListener(l); - } - return this; - } - - @Override - public Promise sync() throws InterruptedException { - await(); - rethrowIfFailed(); - return this; - } - - @Override - public Promise syncUninterruptibly() { - awaitUninterruptibly(); - rethrowIfFailed(); - return this; - } - - private void rethrowIfFailed() { - Throwable cause = cause(); - if (cause == null) { - return; - } - - PlatformDependent.throwException(cause); - } - - @Override - public Promise await() throws InterruptedException { - if (isDone()) { - return this; - } - - if (Thread.interrupted()) { - throw new InterruptedException(toString()); - } - - synchronized (this) { - while (!isDone()) { - checkDeadLock(); - incWaiters(); - try { - wait(); - } finally { - decWaiters(); - } - } - } - return this; - } - - @Override - public boolean await(long timeout, TimeUnit unit) - throws InterruptedException { - return await0(unit.toNanos(timeout), true); - } - - @Override - public boolean await(long timeoutMillis) throws InterruptedException { - return await0(MILLISECONDS.toNanos(timeoutMillis), true); - } - - @Override - public Promise awaitUninterruptibly() { - if (isDone()) { - return this; - } - - boolean interrupted = false; - synchronized (this) { - while (!isDone()) { - checkDeadLock(); - incWaiters(); - try { - wait(); - } catch (InterruptedException e) { - // Interrupted while waiting. - interrupted = true; - } finally { - decWaiters(); - } - } - } - - if (interrupted) { - Thread.currentThread().interrupt(); - } - - return this; - } - - @Override - public boolean awaitUninterruptibly(long timeout, TimeUnit unit) { - try { - return await0(unit.toNanos(timeout), false); - } catch (InterruptedException e) { - // Should not be raised at all. - throw new InternalError(); - } - } - - @Override - public boolean awaitUninterruptibly(long timeoutMillis) { - try { - return await0(MILLISECONDS.toNanos(timeoutMillis), false); - } catch (InterruptedException e) { - // Should not be raised at all. - throw new InternalError(); - } - } - - private boolean await0(long timeoutNanos, boolean interruptable) throws InterruptedException { - if (isDone()) { - return true; - } - - if (timeoutNanos <= 0) { - return isDone(); - } - - if (interruptable && Thread.interrupted()) { - throw new InterruptedException(toString()); - } - - long startTime = System.nanoTime(); - long waitTime = timeoutNanos; - boolean interrupted = false; - - try { - synchronized (this) { - if (isDone()) { - return true; - } - - if (waitTime <= 0) { - return isDone(); - } - - checkDeadLock(); - incWaiters(); - try { - for (;;) { - try { - wait(waitTime / 1000000, (int) (waitTime % 1000000)); - } catch (InterruptedException e) { - if (interruptable) { - throw e; - } else { - interrupted = true; - } - } - - if (isDone()) { - return true; - } else { - waitTime = timeoutNanos - (System.nanoTime() - startTime); - if (waitTime <= 0) { - return isDone(); - } - } - } - } finally { - decWaiters(); - } - } - } finally { - if (interrupted) { - Thread.currentThread().interrupt(); - } - } - } - - /** - * Do deadlock checks - */ - protected void checkDeadLock() { - EventExecutor e = executor(); - if (e != null && e.inEventLoop()) { - throw new BlockingOperationException(toString()); - } - } - - @Override - public Promise setSuccess(V result) { - if (setSuccess0(result)) { - notifyListeners(); - return this; - } - throw new IllegalStateException("complete already: " + this); - } - - @Override - public boolean trySuccess(V result) { - if (setSuccess0(result)) { - notifyListeners(); - return true; - } - return false; - } - - @Override - public Promise setFailure(Throwable cause) { - if (setFailure0(cause)) { - notifyListeners(); - return this; - } - throw new IllegalStateException("complete already: " + this, cause); - } - - @Override - public boolean tryFailure(Throwable cause) { - if (setFailure0(cause)) { - notifyListeners(); - return true; - } - return false; - } - - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - Object result = this.result; - if (isDone0(result) || result == UNCANCELLABLE) { - return false; - } - - synchronized (this) { - // Allow only once. - result = this.result; - if (isDone0(result) || result == UNCANCELLABLE) { - return false; - } - - this.result = CANCELLATION_CAUSE_HOLDER; - if (hasWaiters()) { - notifyAll(); - } - } - - notifyListeners(); - return true; - } - - @Override - public boolean setUncancellable() { - Object result = this.result; - if (isDone0(result)) { - return !isCancelled0(result); - } - - synchronized (this) { - // Allow only once. - result = this.result; - if (isDone0(result)) { - return !isCancelled0(result); - } - - this.result = UNCANCELLABLE; - } - return true; - } - - private boolean setFailure0(Throwable cause) { - if (cause == null) { - throw new NullPointerException("cause"); - } - - if (isDone()) { - return false; - } - - synchronized (this) { - // Allow only once. - if (isDone()) { - return false; - } - - result = new CauseHolder(cause); - if (hasWaiters()) { - notifyAll(); - } - } - return true; - } - - private boolean setSuccess0(V result) { - if (isDone()) { - return false; - } - - synchronized (this) { - // Allow only once. - if (isDone()) { - return false; - } - if (result == null) { - this.result = SUCCESS; - } else { - this.result = result; - } - if (hasWaiters()) { - notifyAll(); - } - } - return true; - } - - @Override - @SuppressWarnings("unchecked") - public V getNow() { - Object result = this.result; - if (result instanceof CauseHolder || result == SUCCESS) { - return null; - } - return (V) result; - } - - private boolean hasWaiters() { - return waiters > 0; - } - - private void incWaiters() { - if (waiters == Short.MAX_VALUE) { - throw new IllegalStateException("too many waiters: " + this); - } - waiters ++; - } - - private void decWaiters() { - waiters --; - } - - private void notifyListeners() { - // This method doesn't need synchronization because: - // 1) This method is always called after synchronized (this) block. - // Hence any listener list modification happens-before this method. - // 2) This method is called only when 'done' is true. Once 'done' - // becomes true, the listener list is never modified - see add/removeListener() - - Object listeners = this.listeners; - if (listeners == null) { - return; - } - - EventExecutor executor = executor(); - if (executor.inEventLoop()) { - final InternalThreadLocalMap threadLocals = InternalThreadLocalMap.get(); - final int stackDepth = threadLocals.futureListenerStackDepth(); - if (stackDepth < MAX_LISTENER_STACK_DEPTH) { - threadLocals.setFutureListenerStackDepth(stackDepth + 1); - try { - if (listeners instanceof DefaultFutureListeners) { - notifyListeners0(this, (DefaultFutureListeners) listeners); - } else { - final GenericFutureListener> l = - (GenericFutureListener>) listeners; - notifyListener0(this, l); - } - } finally { - this.listeners = null; - threadLocals.setFutureListenerStackDepth(stackDepth); - } - return; - } - } - - if (listeners instanceof DefaultFutureListeners) { - final DefaultFutureListeners dfl = (DefaultFutureListeners) listeners; - execute(executor, new Runnable() { - @Override - public void run() { - notifyListeners0(DefaultPromise.this, dfl); - DefaultPromise.this.listeners = null; - } - }); - } else { - final GenericFutureListener> l = - (GenericFutureListener>) listeners; - execute(executor, new Runnable() { - @Override - public void run() { - notifyListener0(DefaultPromise.this, l); - DefaultPromise.this.listeners = null; - } - }); - } - } - - private static void notifyListeners0(Future future, DefaultFutureListeners listeners) { - final GenericFutureListener[] a = listeners.listeners(); - final int size = listeners.size(); - for (int i = 0; i < size; i ++) { - notifyListener0(future, a[i]); - } - } - - /** - * Notifies the specified listener which were added after this promise is already done. - * This method ensures that the specified listener is not notified until {@link #listeners} becomes {@code null} - * to avoid the case where the late listeners are notified even before the early listeners are notified. - */ - private void notifyLateListener(final GenericFutureListener l) { - final EventExecutor executor = executor(); - if (executor.inEventLoop()) { - if (listeners == null && lateListeners == null) { - final InternalThreadLocalMap threadLocals = InternalThreadLocalMap.get(); - final int stackDepth = threadLocals.futureListenerStackDepth(); - if (stackDepth < MAX_LISTENER_STACK_DEPTH) { - threadLocals.setFutureListenerStackDepth(stackDepth + 1); - try { - notifyListener0(this, l); - } finally { - threadLocals.setFutureListenerStackDepth(stackDepth); - } - return; - } - } else { - LateListeners lateListeners = this.lateListeners; - if (lateListeners == null) { - this.lateListeners = lateListeners = new LateListeners(); - } - lateListeners.add(l); - execute(executor, lateListeners); - return; - } - } - - // Add the late listener to lateListeners in the executor thread for thread safety. - // We could just make LateListeners extend ConcurrentLinkedQueue, but it's an overkill considering - // that most asynchronous applications won't execute this code path. - execute(executor, new LateListenerNotifier(l)); - } - - protected static void notifyListener( - final EventExecutor eventExecutor, final Future future, final GenericFutureListener l) { - - if (eventExecutor.inEventLoop()) { - final InternalThreadLocalMap threadLocals = InternalThreadLocalMap.get(); - final int stackDepth = threadLocals.futureListenerStackDepth(); - if (stackDepth < MAX_LISTENER_STACK_DEPTH) { - threadLocals.setFutureListenerStackDepth(stackDepth + 1); - try { - notifyListener0(future, l); - } finally { - threadLocals.setFutureListenerStackDepth(stackDepth); - } - return; - } - } - - execute(eventExecutor, new Runnable() { - @Override - public void run() { - notifyListener0(future, l); - } - }); - } - - private static void execute(EventExecutor executor, Runnable task) { - try { - executor.execute(task); - } catch (Throwable t) { - rejectedExecutionLogger.error("Failed to submit a listener notification task. Event loop shut down?", t); - } - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - static void notifyListener0(Future future, GenericFutureListener l) { - try { - l.operationComplete(future); - } catch (Throwable t) { - if (logger.isWarnEnabled()) { - logger.warn("An exception was thrown by " + l.getClass().getName() + ".operationComplete()", t); - } - } - } - - /** - * Returns a {@link GenericProgressiveFutureListener}, an array of {@link GenericProgressiveFutureListener}, or - * {@code null}. - */ - private synchronized Object progressiveListeners() { - Object listeners = this.listeners; - if (listeners == null) { - // No listeners added - return null; - } - - if (listeners instanceof DefaultFutureListeners) { - // Copy DefaultFutureListeners into an array of listeners. - DefaultFutureListeners dfl = (DefaultFutureListeners) listeners; - int progressiveSize = dfl.progressiveSize(); - switch (progressiveSize) { - case 0: - return null; - case 1: - for (GenericFutureListener l: dfl.listeners()) { - if (l instanceof GenericProgressiveFutureListener) { - return l; - } - } - return null; - } - - GenericFutureListener[] array = dfl.listeners(); - GenericProgressiveFutureListener[] copy = new GenericProgressiveFutureListener[progressiveSize]; - for (int i = 0, j = 0; j < progressiveSize; i ++) { - GenericFutureListener l = array[i]; - if (l instanceof GenericProgressiveFutureListener) { - copy[j ++] = (GenericProgressiveFutureListener) l; - } - } - - return copy; - } else if (listeners instanceof GenericProgressiveFutureListener) { - return listeners; - } else { - // Only one listener was added and it's not a progressive listener. - return null; - } - } - - @SuppressWarnings("unchecked") - void notifyProgressiveListeners(final long progress, final long total) { - final Object listeners = progressiveListeners(); - if (listeners == null) { - return; - } - - final ProgressiveFuture self = (ProgressiveFuture) this; - - EventExecutor executor = executor(); - if (executor.inEventLoop()) { - if (listeners instanceof GenericProgressiveFutureListener[]) { - notifyProgressiveListeners0( - self, (GenericProgressiveFutureListener[]) listeners, progress, total); - } else { - notifyProgressiveListener0( - self, (GenericProgressiveFutureListener>) listeners, progress, total); - } - } else { - if (listeners instanceof GenericProgressiveFutureListener[]) { - final GenericProgressiveFutureListener[] array = - (GenericProgressiveFutureListener[]) listeners; - execute(executor, new Runnable() { - @Override - public void run() { - notifyProgressiveListeners0(self, array, progress, total); - } - }); - } else { - final GenericProgressiveFutureListener> l = - (GenericProgressiveFutureListener>) listeners; - execute(executor, new Runnable() { - @Override - public void run() { - notifyProgressiveListener0(self, l, progress, total); - } - }); - } - } - } - - private static void notifyProgressiveListeners0( - ProgressiveFuture future, GenericProgressiveFutureListener[] listeners, long progress, long total) { - for (GenericProgressiveFutureListener l: listeners) { - if (l == null) { - break; - } - notifyProgressiveListener0(future, l, progress, total); - } - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - private static void notifyProgressiveListener0( - ProgressiveFuture future, GenericProgressiveFutureListener l, long progress, long total) { - try { - l.operationProgressed(future, progress, total); - } catch (Throwable t) { - if (logger.isWarnEnabled()) { - logger.warn("An exception was thrown by " + l.getClass().getName() + ".operationProgressed()", t); - } - } - } - - private static final class CauseHolder { - final Throwable cause; - CauseHolder(Throwable cause) { - this.cause = cause; - } - } - - @Override - public String toString() { - return toStringBuilder().toString(); - } - - protected StringBuilder toStringBuilder() { - StringBuilder buf = new StringBuilder(64) - .append(StringUtil.simpleClassName(this)) - .append('@') - .append(Integer.toHexString(hashCode())); - - Object result = this.result; - if (result == SUCCESS) { - buf.append("(success)"); - } else if (result == UNCANCELLABLE) { - buf.append("(uncancellable)"); - } else if (result instanceof CauseHolder) { - buf.append("(failure: ") - .append(((CauseHolder) result).cause) - .append(')'); - } else if (result != null) { - buf.append("(success: ") - .append(result) - .append(')'); - } else { - buf.append("(incomplete)"); - } - - return buf; - } - - private final class LateListeners extends ArrayDeque> implements Runnable { - - private static final long serialVersionUID = -687137418080392244L; - - LateListeners() { - super(2); - } - - @Override - public void run() { - final EventExecutor executor = executor(); - if (listeners == null || executor == ImmediateEventExecutor.INSTANCE) { - for (;;) { - GenericFutureListener l = poll(); - if (l == null) { - break; - } - notifyListener0(DefaultPromise.this, l); - } - } else { - // Reschedule until the initial notification is done to avoid the race condition - // where the notification is made in an incorrect order. - execute(executor, this); - } - } - } - - private final class LateListenerNotifier implements Runnable { - private GenericFutureListener l; - - LateListenerNotifier(GenericFutureListener l) { - this.l = l; - } - - @Override - public void run() { - LateListeners lateListeners = DefaultPromise.this.lateListeners; - if (l != null) { - if (lateListeners == null) { - DefaultPromise.this.lateListeners = lateListeners = new LateListeners(); - } - lateListeners.add(l); - l = null; - } - - lateListeners.run(); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/DefaultThreadFactory.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/DefaultThreadFactory.java deleted file mode 100755 index 3c0ed0ec11..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/DefaultThreadFactory.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.util.concurrent; - -import java.util.Locale; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.atomic.AtomicInteger; - -import com.ai.cloud.io.netty.util.internal.StringUtil; - -/** - * A {@link ThreadFactory} implementation with a simple naming rule. - */ -public class DefaultThreadFactory implements ThreadFactory { - - private static final AtomicInteger poolId = new AtomicInteger(); - - private final AtomicInteger nextId = new AtomicInteger(); - private final String prefix; - private final boolean daemon; - private final int priority; - - public DefaultThreadFactory(Class poolType) { - this(poolType, false, Thread.NORM_PRIORITY); - } - - public DefaultThreadFactory(String poolName) { - this(poolName, false, Thread.NORM_PRIORITY); - } - - public DefaultThreadFactory(Class poolType, boolean daemon) { - this(poolType, daemon, Thread.NORM_PRIORITY); - } - - public DefaultThreadFactory(String poolName, boolean daemon) { - this(poolName, daemon, Thread.NORM_PRIORITY); - } - - public DefaultThreadFactory(Class poolType, int priority) { - this(poolType, false, priority); - } - - public DefaultThreadFactory(String poolName, int priority) { - this(poolName, false, priority); - } - - public DefaultThreadFactory(Class poolType, boolean daemon, int priority) { - this(toPoolName(poolType), daemon, priority); - } - - private static String toPoolName(Class poolType) { - if (poolType == null) { - throw new NullPointerException("poolType"); - } - - String poolName = StringUtil.simpleClassName(poolType); - switch (poolName.length()) { - case 0: - return "unknown"; - case 1: - return poolName.toLowerCase(Locale.US); - default: - if (Character.isUpperCase(poolName.charAt(0)) && Character.isLowerCase(poolName.charAt(1))) { - return Character.toLowerCase(poolName.charAt(0)) + poolName.substring(1); - } else { - return poolName; - } - } - } - - public DefaultThreadFactory(String poolName, boolean daemon, int priority) { - if (poolName == null) { - throw new NullPointerException("poolName"); - } - if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) { - throw new IllegalArgumentException( - "priority: " + priority + " (expected: Thread.MIN_PRIORITY <= priority <= Thread.MAX_PRIORITY)"); - } - - prefix = poolName + '-' + poolId.incrementAndGet() + '-'; - this.daemon = daemon; - this.priority = priority; - } - - @Override - public Thread newThread(Runnable r) { - Thread t = newThread(new DefaultRunnableDecorator(r), prefix + nextId.incrementAndGet()); - try { - if (t.isDaemon()) { - if (!daemon) { - t.setDaemon(false); - } - } else { - if (daemon) { - t.setDaemon(true); - } - } - - if (t.getPriority() != priority) { - t.setPriority(priority); - } - } catch (Exception ignored) { - // Doesn't matter even if failed to set. - } - return t; - } - - protected Thread newThread(Runnable r, String name) { - return new FastThreadLocalThread(r, name); - } - - private static final class DefaultRunnableDecorator implements Runnable { - - private final Runnable r; - - DefaultRunnableDecorator(Runnable r) { - this.r = r; - } - - @Override - public void run() { - try { - r.run(); - } finally { - FastThreadLocal.removeAll(); - } - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/EventExecutor.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/EventExecutor.java deleted file mode 100755 index 77cf539ce4..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/EventExecutor.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.concurrent; - -/** - * The {@link EventExecutor} is a special {@link EventExecutorGroup} which comes - * with some handy methods to see if a {@link Thread} is executed in a event loop. - * Besides this, it also extends the {@link EventExecutorGroup} to allow for a generic - * way to access methods. - * - */ -public interface EventExecutor extends EventExecutorGroup { - - /** - * Returns a reference to itself. - */ - @Override - EventExecutor next(); - - /** - * Return the {@link EventExecutorGroup} which is the parent of this {@link EventExecutor}, - */ - EventExecutorGroup parent(); - - /** - * Calls {@link #inEventLoop(Thread)} with {@link Thread#currentThread()} as argument - */ - boolean inEventLoop(); - - /** - * Return {@code true} if the given {@link Thread} is executed in the event loop, - * {@code false} otherwise. - */ - boolean inEventLoop(Thread thread); - - /** - * Return a new {@link Promise}. - */ - Promise newPromise(); - - /** - * Create a new {@link ProgressivePromise}. - */ - ProgressivePromise newProgressivePromise(); - - /** - * Create a new {@link Future} which is marked as successes already. So {@link Future#isSuccess()} - * will return {@code true}. All {@link FutureListener} added to it will be notified directly. Also - * every call of blocking methods will just return without blocking. - */ - Future newSucceededFuture(V result); - - /** - * Create a new {@link Future} which is marked as fakued already. So {@link Future#isSuccess()} - * will return {@code false}. All {@link FutureListener} added to it will be notified directly. Also - * every call of blocking methods will just return without blocking. - */ - Future newFailedFuture(Throwable cause); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/EventExecutorGroup.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/EventExecutorGroup.java deleted file mode 100755 index c3239ed228..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/EventExecutorGroup.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.concurrent; - -import java.util.Iterator; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -/** - * The {@link EventExecutorGroup} is responsible for providing the {@link EventExecutor}'s to use - * via its {@link #next()} method. Besides this, it is also responsible for handling their - * life-cycle and allows shutting them down in a global fashion. - * - */ -public interface EventExecutorGroup extends ScheduledExecutorService, Iterable { - - /** - * Returns {@code true} if and only if this executor was started to be - * {@linkplain #shutdownGracefully() shut down gracefuclly} or was {@linkplain #isShutdown() shut down}. - */ - boolean isShuttingDown(); - - /** - * Shortcut method for {@link #shutdownGracefully(long, long, TimeUnit)} with sensible default values. - * - * @return the {@link #terminationFuture()} - */ - Future shutdownGracefully(); - - /** - * Signals this executor that the caller wants the executor to be shut down. Once this method is called, - * {@link #isShuttingDown()} starts to return {@code true}, and the executor prepares to shut itself down. - * Unlike {@link #shutdown()}, graceful shutdown ensures that no tasks are submitted for 'the quiet period' - * (usually a couple seconds) before it shuts itself down. If a task is submitted during the quiet period, - * it is guaranteed to be accepted and the quiet period will start over. - * - * @param quietPeriod the quiet period as described in the documentation - * @param timeout the maximum amount of time to wait until the executor is {@linkplain #shutdown()} - * regardless if a task was submitted during the quiet period - * @param unit the unit of {@code quietPeriod} and {@code timeout} - * - * @return the {@link #terminationFuture()} - */ - Future shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit); - - /** - * Returns the {@link Future} which is notified when this executor has been terminated. - */ - Future terminationFuture(); - - /** - * @deprecated {@link #shutdownGracefully(long, long, TimeUnit)} or {@link #shutdownGracefully()} instead. - */ - @Override - @Deprecated - void shutdown(); - - /** - * @deprecated {@link #shutdownGracefully(long, long, TimeUnit)} or {@link #shutdownGracefully()} instead. - */ - @Override - @Deprecated - List shutdownNow(); - - /** - * Returns one of the {@link EventExecutor}s that belong to this group. - */ - EventExecutor next(); - - /** - * Returns a read-only {@link Iterator} over all {@link EventExecutor}, which are handled by this - * {@link EventExecutorGroup} at the time of invoke this method. - */ - @Override - Iterator iterator(); - - @Override - Future submit(Runnable task); - - @Override - Future submit(Runnable task, T result); - - @Override - Future submit(Callable task); - - @Override - ScheduledFuture schedule(Runnable command, long delay, TimeUnit unit); - - @Override - ScheduledFuture schedule(Callable callable, long delay, TimeUnit unit); - - @Override - ScheduledFuture scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit); - - @Override - ScheduledFuture scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/FailedFuture.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/FailedFuture.java deleted file mode 100755 index 5d055ee79e..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/FailedFuture.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.concurrent; - -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - -/** - * The {@link CompleteFuture} which is failed already. It is - * recommended to use {@link EventExecutor#newFailedFuture(Throwable)} - * instead of calling the constructor of this future. - */ -public final class FailedFuture extends CompleteFuture { - - private final Throwable cause; - - /** - * Creates a new instance. - * - * @param executor the {@link EventExecutor} associated with this future - * @param cause the cause of failure - */ - public FailedFuture(EventExecutor executor, Throwable cause) { - super(executor); - if (cause == null) { - throw new NullPointerException("cause"); - } - this.cause = cause; - } - - @Override - public Throwable cause() { - return cause; - } - - @Override - public boolean isSuccess() { - return false; - } - - @Override - public Future sync() { - PlatformDependent.throwException(cause); - return this; - } - - @Override - public Future syncUninterruptibly() { - PlatformDependent.throwException(cause); - return this; - } - - @Override - public V getNow() { - return null; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/FastThreadLocal.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/FastThreadLocal.java deleted file mode 100755 index 0bde68f11c..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/FastThreadLocal.java +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.concurrent; - -import java.util.Collections; -import java.util.IdentityHashMap; -import java.util.Set; - -import com.ai.cloud.io.netty.util.internal.InternalThreadLocalMap; -import com.ai.cloud.io.netty.util.internal.PlatformDependent; - -/** - * A special variant of {@link ThreadLocal} that yields higher access performance when accessed from a - * {@link FastThreadLocalThread}. - *

- * Internally, a {@link FastThreadLocal} uses a constant index in an array, instead of using hash code and hash table, - * to look for a variable. Although seemingly very subtle, it yields slight performance advantage over using a hash - * table, and it is useful when accessed frequently. - *

- * To take advantage of this thread-local variable, your thread must be a {@link FastThreadLocalThread} or its subtype. - * By default, all threads created by {@link DefaultThreadFactory} are {@link FastThreadLocalThread} due to this reason. - *

- * Note that the fast path is only possible on threads that extend {@link FastThreadLocalThread}, because it requires - * a special field to store the necessary state. An access by any other kind of thread falls back to a regular - * {@link ThreadLocal}. - *

- * - * @param the type of the thread-local variable - * @see ThreadLocal - */ -public class FastThreadLocal { - - private static final int variablesToRemoveIndex = InternalThreadLocalMap.nextVariableIndex(); - - /** - * Removes all {@link FastThreadLocal} variables bound to the current thread. This operation is useful when you - * are in a container environment, and you don't want to leave the thread local variables in the threads you do not - * manage. - */ - public static void removeAll() { - InternalThreadLocalMap threadLocalMap = InternalThreadLocalMap.getIfSet(); - if (threadLocalMap == null) { - return; - } - - try { - Object v = threadLocalMap.indexedVariable(variablesToRemoveIndex); - if (v != null && v != InternalThreadLocalMap.UNSET) { - @SuppressWarnings("unchecked") - Set> variablesToRemove = (Set>) v; - FastThreadLocal[] variablesToRemoveArray = - variablesToRemove.toArray(new FastThreadLocal[variablesToRemove.size()]); - for (FastThreadLocal tlv: variablesToRemoveArray) { - tlv.remove(threadLocalMap); - } - } - } finally { - InternalThreadLocalMap.remove(); - } - } - - /** - * Returns the number of thread local variables bound to the current thread. - */ - public static int size() { - InternalThreadLocalMap threadLocalMap = InternalThreadLocalMap.getIfSet(); - if (threadLocalMap == null) { - return 0; - } else { - return threadLocalMap.size(); - } - } - - /** - * Destroys the data structure that keeps all {@link FastThreadLocal} variables accessed from - * non-{@link FastThreadLocalThread}s. This operation is useful when you are in a container environment, and you - * do not want to leave the thread local variables in the threads you do not manage. Call this method when your - * application is being unloaded from the container. - */ - public static void destroy() { - InternalThreadLocalMap.destroy(); - } - - @SuppressWarnings("unchecked") - private static void addToVariablesToRemove(InternalThreadLocalMap threadLocalMap, FastThreadLocal variable) { - Object v = threadLocalMap.indexedVariable(variablesToRemoveIndex); - Set> variablesToRemove; - if (v == InternalThreadLocalMap.UNSET || v == null) { - variablesToRemove = Collections.newSetFromMap(new IdentityHashMap, Boolean>()); - threadLocalMap.setIndexedVariable(variablesToRemoveIndex, variablesToRemove); - } else { - variablesToRemove = (Set>) v; - } - - variablesToRemove.add(variable); - } - - private static void removeFromVariablesToRemove( - InternalThreadLocalMap threadLocalMap, FastThreadLocal variable) { - - Object v = threadLocalMap.indexedVariable(variablesToRemoveIndex); - - if (v == InternalThreadLocalMap.UNSET || v == null) { - return; - } - - @SuppressWarnings("unchecked") - Set> variablesToRemove = (Set>) v; - variablesToRemove.remove(variable); - } - - private final int index; - - public FastThreadLocal() { - index = InternalThreadLocalMap.nextVariableIndex(); - } - - /** - * Returns the current value for the current thread - */ - public final V get() { - return get(InternalThreadLocalMap.get()); - } - - /** - * Returns the current value for the specified thread local map. - * The specified thread local map must be for the current thread. - */ - @SuppressWarnings("unchecked") - public final V get(InternalThreadLocalMap threadLocalMap) { - Object v = threadLocalMap.indexedVariable(index); - if (v != InternalThreadLocalMap.UNSET) { - return (V) v; - } - - return initialize(threadLocalMap); - } - - private V initialize(InternalThreadLocalMap threadLocalMap) { - V v = null; - try { - v = initialValue(); - } catch (Exception e) { - PlatformDependent.throwException(e); - } - - threadLocalMap.setIndexedVariable(index, v); - addToVariablesToRemove(threadLocalMap, this); - return v; - } - - /** - * Set the value for the current thread. - */ - public final void set(V value) { - if (value != InternalThreadLocalMap.UNSET) { - set(InternalThreadLocalMap.get(), value); - } else { - remove(); - } - } - - /** - * Set the value for the specified thread local map. The specified thread local map must be for the current thread. - */ - public final void set(InternalThreadLocalMap threadLocalMap, V value) { - if (value != InternalThreadLocalMap.UNSET) { - if (threadLocalMap.setIndexedVariable(index, value)) { - addToVariablesToRemove(threadLocalMap, this); - } - } else { - remove(threadLocalMap); - } - } - - /** - * Returns {@code true} if and only if this thread-local variable is set. - */ - public final boolean isSet() { - return isSet(InternalThreadLocalMap.getIfSet()); - } - - /** - * Returns {@code true} if and only if this thread-local variable is set. - * The specified thread local map must be for the current thread. - */ - public final boolean isSet(InternalThreadLocalMap threadLocalMap) { - return threadLocalMap != null && threadLocalMap.isIndexedVariableSet(index); - } - /** - * Sets the value to uninitialized; a proceeding call to get() will trigger a call to initialValue(). - */ - public final void remove() { - remove(InternalThreadLocalMap.getIfSet()); - } - - /** - * Sets the value to uninitialized for the specified thread local map; - * a proceeding call to get() will trigger a call to initialValue(). - * The specified thread local map must be for the current thread. - */ - @SuppressWarnings("unchecked") - public final void remove(InternalThreadLocalMap threadLocalMap) { - if (threadLocalMap == null) { - return; - } - - Object v = threadLocalMap.removeIndexedVariable(index); - removeFromVariablesToRemove(threadLocalMap, this); - - if (v != InternalThreadLocalMap.UNSET) { - try { - onRemoval((V) v); - } catch (Exception e) { - PlatformDependent.throwException(e); - } - } - } - - /** - * Returns the initial value for this thread-local variable. - */ - protected V initialValue() throws Exception { - return null; - } - - /** - * Invoked when this thread local variable is removed by {@link #remove()}. - */ - protected void onRemoval(@SuppressWarnings("UnusedParameters") V value) throws Exception { } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/FastThreadLocalThread.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/FastThreadLocalThread.java deleted file mode 100755 index c06443cd14..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/FastThreadLocalThread.java +++ /dev/null @@ -1,72 +0,0 @@ -/* -* Copyright 2014 The Netty Project -* -* The Netty Project licenses this file to you under the Apache License, -* version 2.0 (the "License"); you may not use this file except in compliance -* with the License. You may obtain a copy of the License at: -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -* License for the specific language governing permissions and limitations -* under the License. -*/ -package com.ai.cloud.io.netty.util.concurrent; - -import com.ai.cloud.io.netty.util.internal.InternalThreadLocalMap; - -/** - * A special {@link Thread} that provides fast access to {@link FastThreadLocal} variables. - */ -public class FastThreadLocalThread extends Thread { - - private InternalThreadLocalMap threadLocalMap; - - public FastThreadLocalThread() { } - - public FastThreadLocalThread(Runnable target) { - super(target); - } - - public FastThreadLocalThread(ThreadGroup group, Runnable target) { - super(group, target); - } - - public FastThreadLocalThread(String name) { - super(name); - } - - public FastThreadLocalThread(ThreadGroup group, String name) { - super(group, name); - } - - public FastThreadLocalThread(Runnable target, String name) { - super(target, name); - } - - public FastThreadLocalThread(ThreadGroup group, Runnable target, String name) { - super(group, target, name); - } - - public FastThreadLocalThread(ThreadGroup group, Runnable target, String name, long stackSize) { - super(group, target, name, stackSize); - } - - /** - * Returns the internal data structure that keeps the thread-local variables bound to this thread. - * Note that this method is for internal use only, and thus is subject to change at any time. - */ - public final InternalThreadLocalMap threadLocalMap() { - return threadLocalMap; - } - - /** - * Sets the internal data structure that keeps the thread-local variables bound to this thread. - * Note that this method is for internal use only, and thus is subject to change at any time. - */ - public final void setThreadLocalMap(InternalThreadLocalMap threadLocalMap) { - this.threadLocalMap = threadLocalMap; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/Future.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/Future.java deleted file mode 100755 index a22c0a317f..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/Future.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.concurrent; - -import java.util.concurrent.CancellationException; -import java.util.concurrent.TimeUnit; - - -/** - * The result of an asynchronous operation. - */ -@SuppressWarnings("ClassNameSameAsAncestorName") -public interface Future extends java.util.concurrent.Future { - - /** - * Returns {@code true} if and only if the I/O operation was completed - * successfully. - */ - boolean isSuccess(); - - /** - * returns {@code true} if and only if the operation can be cancelled via {@link #cancel(boolean)}. - */ - boolean isCancellable(); - - /** - * Returns the cause of the failed I/O operation if the I/O operation has - * failed. - * - * @return the cause of the failure. - * {@code null} if succeeded or this future is not - * completed yet. - */ - Throwable cause(); - - /** - * Adds the specified listener to this future. The - * specified listener is notified when this future is - * {@linkplain #isDone() done}. If this future is already - * completed, the specified listener is notified immediately. - */ - Future addListener(GenericFutureListener> listener); - - /** - * Adds the specified listeners to this future. The - * specified listeners are notified when this future is - * {@linkplain #isDone() done}. If this future is already - * completed, the specified listeners are notified immediately. - */ - Future addListeners(GenericFutureListener>... listeners); - - /** - * Removes the specified listener from this future. - * The specified listener is no longer notified when this - * future is {@linkplain #isDone() done}. If the specified - * listener is not associated with this future, this method - * does nothing and returns silently. - */ - Future removeListener(GenericFutureListener> listener); - - /** - * Removes the specified listeners from this future. - * The specified listeners are no longer notified when this - * future is {@linkplain #isDone() done}. If the specified - * listeners are not associated with this future, this method - * does nothing and returns silently. - */ - Future removeListeners(GenericFutureListener>... listeners); - - /** - * Waits for this future until it is done, and rethrows the cause of the failure if this future - * failed. - */ - Future sync() throws InterruptedException; - - /** - * Waits for this future until it is done, and rethrows the cause of the failure if this future - * failed. - */ - Future syncUninterruptibly(); - - /** - * Waits for this future to be completed. - * - * @throws InterruptedException - * if the current thread was interrupted - */ - Future await() throws InterruptedException; - - /** - * Waits for this future to be completed without - * interruption. This method catches an {@link InterruptedException} and - * discards it silently. - */ - Future awaitUninterruptibly(); - - /** - * Waits for this future to be completed within the - * specified time limit. - * - * @return {@code true} if and only if the future was completed within - * the specified time limit - * - * @throws InterruptedException - * if the current thread was interrupted - */ - boolean await(long timeout, TimeUnit unit) throws InterruptedException; - - /** - * Waits for this future to be completed within the - * specified time limit. - * - * @return {@code true} if and only if the future was completed within - * the specified time limit - * - * @throws InterruptedException - * if the current thread was interrupted - */ - boolean await(long timeoutMillis) throws InterruptedException; - - /** - * Waits for this future to be completed within the - * specified time limit without interruption. This method catches an - * {@link InterruptedException} and discards it silently. - * - * @return {@code true} if and only if the future was completed within - * the specified time limit - */ - boolean awaitUninterruptibly(long timeout, TimeUnit unit); - - /** - * Waits for this future to be completed within the - * specified time limit without interruption. This method catches an - * {@link InterruptedException} and discards it silently. - * - * @return {@code true} if and only if the future was completed within - * the specified time limit - */ - boolean awaitUninterruptibly(long timeoutMillis); - - /** - * Return the result without blocking. If the future is not done yet this will return {@code null}. - * - * As it is possible that a {@code null} value is used to mark the future as successful you also need to check - * if the future is really done with {@link #isDone()} and not relay on the returned {@code null} value. - */ - V getNow(); - - /** - * {@inheritDoc} - * - * If the cancellation was successful it will fail the future with an {@link CancellationException}. - */ - @Override - boolean cancel(boolean mayInterruptIfRunning); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/FutureListener.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/FutureListener.java deleted file mode 100755 index a50ade96e9..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/FutureListener.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.util.concurrent; - -/** - * A subtype of {@link GenericFutureListener} that hides type parameter for convenience. - *
- * Future f = new DefaultPromise(..);
- * f.addListener(new FutureListener() {
- *     public void operationComplete(Future f) { .. }
- * });
- * 
- */ -public interface FutureListener extends GenericFutureListener> { } diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/GenericFutureListener.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/GenericFutureListener.java deleted file mode 100755 index 2e768ac3a4..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/GenericFutureListener.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.concurrent; - -import java.util.EventListener; - -/** - * Listens to the result of a {@link Future}. The result of the asynchronous operation is notified once this listener - * is added by calling {@link Future#addListener(GenericFutureListener)}. - */ -public interface GenericFutureListener> extends EventListener { - - /** - * Invoked when the operation associated with the {@link Future} has been completed. - * - * @param future the source {@link Future} which called this callback - */ - void operationComplete(F future) throws Exception; -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/GenericProgressiveFutureListener.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/GenericProgressiveFutureListener.java deleted file mode 100755 index a46f223f4c..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/GenericProgressiveFutureListener.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.util.concurrent; - -public interface GenericProgressiveFutureListener> extends GenericFutureListener { - /** - * Invoked when the operation has progressed. - * - * @param progress the progress of the operation so far (cumulative) - * @param total the number that signifies the end of the operation when {@code progress} reaches at it. - * {@code -1} if the end of operation is unknown. - */ - void operationProgressed(F future, long progress, long total) throws Exception; -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/GlobalEventExecutor.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/GlobalEventExecutor.java deleted file mode 100755 index 54723006f0..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/GlobalEventExecutor.java +++ /dev/null @@ -1,278 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.concurrent; - -import java.util.Queue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.Executors; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * Single-thread singleton {@link EventExecutor}. It starts the thread automatically and stops it when there is no - * task pending in the task queue for 1 second. Please note it is not scalable to schedule large number of tasks to - * this executor; use a dedicated executor. - */ -public final class GlobalEventExecutor extends AbstractScheduledEventExecutor { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(GlobalEventExecutor.class); - - private static final long SCHEDULE_QUIET_PERIOD_INTERVAL = TimeUnit.SECONDS.toNanos(1); - - public static final GlobalEventExecutor INSTANCE = new GlobalEventExecutor(); - - final BlockingQueue taskQueue = new LinkedBlockingQueue(); - final ScheduledFutureTask quietPeriodTask = new ScheduledFutureTask( - this, Executors.callable(new Runnable() { - @Override - public void run() { - // NOOP - } - }, null), ScheduledFutureTask.deadlineNanos(SCHEDULE_QUIET_PERIOD_INTERVAL), -SCHEDULE_QUIET_PERIOD_INTERVAL); - - private final ThreadFactory threadFactory = new DefaultThreadFactory(getClass()); - private final TaskRunner taskRunner = new TaskRunner(); - private final AtomicBoolean started = new AtomicBoolean(); - volatile Thread thread; - - private final Future terminationFuture = new FailedFuture(this, new UnsupportedOperationException()); - - private GlobalEventExecutor() { - scheduledTaskQueue().add(quietPeriodTask); - } - - @Override - public EventExecutorGroup parent() { - return null; - } - - /** - * Take the next {@link Runnable} from the task queue and so will block if no task is currently present. - * - * @return {@code null} if the executor thread has been interrupted or waken up. - */ - Runnable takeTask() { - BlockingQueue taskQueue = this.taskQueue; - for (;;) { - ScheduledFutureTask scheduledTask = peekScheduledTask(); - if (scheduledTask == null) { - Runnable task = null; - try { - task = taskQueue.take(); - } catch (InterruptedException e) { - // Ignore - } - return task; - } else { - long delayNanos = scheduledTask.delayNanos(); - Runnable task; - if (delayNanos > 0) { - try { - task = taskQueue.poll(delayNanos, TimeUnit.NANOSECONDS); - } catch (InterruptedException e) { - return null; - } - } else { - task = taskQueue.poll(); - } - - if (task == null) { - fetchFromScheduledTaskQueue(); - task = taskQueue.poll(); - } - - if (task != null) { - return task; - } - } - } - } - - private void fetchFromScheduledTaskQueue() { - if (hasScheduledTasks()) { - long nanoTime = AbstractScheduledEventExecutor.nanoTime(); - for (;;) { - Runnable scheduledTask = pollScheduledTask(nanoTime); - if (scheduledTask == null) { - break; - } - taskQueue.add(scheduledTask); - } - } - } - - /** - * Return the number of tasks that are pending for processing. - * - * Be aware that this operation may be expensive as it depends on the internal implementation of the - * SingleThreadEventExecutor. So use it was care! - */ - public int pendingTasks() { - return taskQueue.size(); - } - - /** - * Add a task to the task queue, or throws a {@link RejectedExecutionException} if this instance was shutdown - * before. - */ - private void addTask(Runnable task) { - if (task == null) { - throw new NullPointerException("task"); - } - taskQueue.add(task); - } - - @Override - public boolean inEventLoop(Thread thread) { - return thread == this.thread; - } - - @Override - public Future shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit) { - return terminationFuture(); - } - - @Override - public Future terminationFuture() { - return terminationFuture; - } - - @Override - @Deprecated - public void shutdown() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isShuttingDown() { - return false; - } - - @Override - public boolean isShutdown() { - return false; - } - - @Override - public boolean isTerminated() { - return false; - } - - @Override - public boolean awaitTermination(long timeout, TimeUnit unit) { - return false; - } - - /** - * Waits until the worker thread of this executor has no tasks left in its task queue and terminates itself. - * Because a new worker thread will be started again when a new task is submitted, this operation is only useful - * when you want to ensure that the worker thread is terminated after your application is shut - * down and there's no chance of submitting a new task afterwards. - * - * @return {@code true} if and only if the worker thread has been terminated - */ - public boolean awaitInactivity(long timeout, TimeUnit unit) throws InterruptedException { - if (unit == null) { - throw new NullPointerException("unit"); - } - - final Thread thread = this.thread; - if (thread == null) { - throw new IllegalStateException("thread was not started"); - } - thread.join(unit.toMillis(timeout)); - return !thread.isAlive(); - } - - @Override - public void execute(Runnable task) { - if (task == null) { - throw new NullPointerException("task"); - } - - addTask(task); - if (!inEventLoop()) { - startThread(); - } - } - - private void startThread() { - if (started.compareAndSet(false, true)) { - Thread t = threadFactory.newThread(taskRunner); - // Set the thread before starting it as otherwise inEventLoop() may return false and so produce - // an assert error. - // See https://github.com/netty/netty/issues/4357 - thread = t; - t.start(); - } - } - - final class TaskRunner implements Runnable { - @Override - public void run() { - for (;;) { - Runnable task = takeTask(); - if (task != null) { - try { - task.run(); - } catch (Throwable t) { - logger.warn("Unexpected exception from the global event executor: ", t); - } - - if (task != quietPeriodTask) { - continue; - } - } - - Queue> scheduledTaskQueue = GlobalEventExecutor.this.scheduledTaskQueue; - // Terminate if there is no task in the queue (except the noop task). - if (taskQueue.isEmpty() && (scheduledTaskQueue == null || scheduledTaskQueue.size() == 1)) { - // Mark the current thread as stopped. - // The following CAS must always success and must be uncontended, - // because only one thread should be running at the same time. - boolean stopped = started.compareAndSet(true, false); - assert stopped; - - // Check if there are pending entries added by execute() or schedule*() while we do CAS above. - if (taskQueue.isEmpty() && (scheduledTaskQueue == null || scheduledTaskQueue.size() == 1)) { - // A) No new task was added and thus there's nothing to handle - // -> safe to terminate because there's nothing left to do - // B) A new thread started and handled all the new tasks. - // -> safe to terminate the new thread will take care the rest - break; - } - - // There are pending tasks added again. - if (!started.compareAndSet(false, true)) { - // startThread() started a new thread and set 'started' to true. - // -> terminate this thread so that the new thread reads from taskQueue exclusively. - break; - } - - // New tasks were added, but this worker was faster to set 'started' to true. - // i.e. a new worker thread was not started by startThread(). - // -> keep this thread alive to handle the newly added entries. - } - } - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/ImmediateEventExecutor.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/ImmediateEventExecutor.java deleted file mode 100755 index ad97a19eb2..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/ImmediateEventExecutor.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.concurrent; - -import java.util.concurrent.TimeUnit; - -/** - * {@link AbstractEventExecutor} which execute tasks in the callers thread. - */ -public final class ImmediateEventExecutor extends AbstractEventExecutor { - public static final ImmediateEventExecutor INSTANCE = new ImmediateEventExecutor(); - - private final Future terminationFuture = new FailedFuture( - GlobalEventExecutor.INSTANCE, new UnsupportedOperationException()); - - private ImmediateEventExecutor() { - // use static instance - } - - @Override - public EventExecutorGroup parent() { - return null; - } - - @Override - public boolean inEventLoop() { - return true; - } - - @Override - public boolean inEventLoop(Thread thread) { - return true; - } - - @Override - public Future shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit) { - return terminationFuture(); - } - - @Override - public Future terminationFuture() { - return terminationFuture; - } - - @Override - @Deprecated - public void shutdown() { } - - @Override - public boolean isShuttingDown() { - return false; - } - - @Override - public boolean isShutdown() { - return false; - } - - @Override - public boolean isTerminated() { - return false; - } - - @Override - public boolean awaitTermination(long timeout, TimeUnit unit) { - return false; - } - - @Override - public void execute(Runnable command) { - if (command == null) { - throw new NullPointerException("command"); - } - command.run(); - } - - @Override - public Promise newPromise() { - return new ImmediatePromise(this); - } - - @Override - public ProgressivePromise newProgressivePromise() { - return new ImmediateProgressivePromise(this); - } - - static class ImmediatePromise extends DefaultPromise { - ImmediatePromise(EventExecutor executor) { - super(executor); - } - - @Override - protected void checkDeadLock() { - // No check - } - } - - static class ImmediateProgressivePromise extends DefaultProgressivePromise { - ImmediateProgressivePromise(EventExecutor executor) { - super(executor); - } - - @Override - protected void checkDeadLock() { - // No check - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/ImmediateExecutor.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/ImmediateExecutor.java deleted file mode 100755 index 1f728977f3..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/ImmediateExecutor.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.concurrent; - -import java.util.concurrent.Executor; - -/** - * {@link Executor} which execute tasks in the callers thread. - */ -public final class ImmediateExecutor implements Executor { - public static final ImmediateExecutor INSTANCE = new ImmediateExecutor(); - - private ImmediateExecutor() { - // use static instance - } - - @Override - public void execute(Runnable command) { - if (command == null) { - throw new NullPointerException("command"); - } - command.run(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/MultithreadEventExecutorGroup.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/MultithreadEventExecutorGroup.java deleted file mode 100755 index a10a02b08e..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/MultithreadEventExecutorGroup.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.concurrent; - -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Set; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * Abstract base class for {@link EventExecutorGroup} implementations that handles their tasks with multiple threads at - * the same time. - */ -public abstract class MultithreadEventExecutorGroup extends AbstractEventExecutorGroup { - - private final EventExecutor[] children; - private final AtomicInteger childIndex = new AtomicInteger(); - private final AtomicInteger terminatedChildren = new AtomicInteger(); - private final Promise terminationFuture = new DefaultPromise(GlobalEventExecutor.INSTANCE); - private final EventExecutorChooser chooser; - - /** - * Create a new instance. - * - * @param nThreads the number of threads that will be used by this instance. - * @param threadFactory the ThreadFactory to use, or {@code null} if the default should be used. - * @param args arguments which will passed to each {@link #newChild(ThreadFactory, Object...)} call - */ - protected MultithreadEventExecutorGroup(int nThreads, ThreadFactory threadFactory, Object... args) { - if (nThreads <= 0) { - throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads)); - } - - if (threadFactory == null) { - threadFactory = newDefaultThreadFactory(); - } - - children = new SingleThreadEventExecutor[nThreads]; - if (isPowerOfTwo(children.length)) { - chooser = new PowerOfTwoEventExecutorChooser(); - } else { - chooser = new GenericEventExecutorChooser(); - } - - for (int i = 0; i < nThreads; i ++) { - boolean success = false; - try { - children[i] = newChild(threadFactory, args); - success = true; - } catch (Exception e) { - // TODO: Think about if this is a good exception type - throw new IllegalStateException("failed to create a child event loop", e); - } finally { - if (!success) { - for (int j = 0; j < i; j ++) { - children[j].shutdownGracefully(); - } - - for (int j = 0; j < i; j ++) { - EventExecutor e = children[j]; - try { - while (!e.isTerminated()) { - e.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS); - } - } catch (InterruptedException interrupted) { - Thread.currentThread().interrupt(); - break; - } - } - } - } - } - - final FutureListener terminationListener = new FutureListener() { - @Override - public void operationComplete(Future future) throws Exception { - if (terminatedChildren.incrementAndGet() == children.length) { - terminationFuture.setSuccess(null); - } - } - }; - - for (EventExecutor e: children) { - e.terminationFuture().addListener(terminationListener); - } - } - - protected ThreadFactory newDefaultThreadFactory() { - return new DefaultThreadFactory(getClass()); - } - - @Override - public EventExecutor next() { - return chooser.next(); - } - - @Override - public Iterator iterator() { - return children().iterator(); - } - - /** - * Return the number of {@link EventExecutor} this implementation uses. This number is the maps - * 1:1 to the threads it use. - */ - public final int executorCount() { - return children.length; - } - - /** - * Return a safe-copy of all of the children of this group. - */ - protected Set children() { - Set children = Collections.newSetFromMap(new LinkedHashMap()); - Collections.addAll(children, this.children); - return children; - } - - /** - * Create a new EventExecutor which will later then accessible via the {@link #next()} method. This method will be - * called for each thread that will serve this {@link MultithreadEventExecutorGroup}. - * - */ - protected abstract EventExecutor newChild( - ThreadFactory threadFactory, Object... args) throws Exception; - - @Override - public Future shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit) { - for (EventExecutor l: children) { - l.shutdownGracefully(quietPeriod, timeout, unit); - } - return terminationFuture(); - } - - @Override - public Future terminationFuture() { - return terminationFuture; - } - - @Override - @Deprecated - public void shutdown() { - for (EventExecutor l: children) { - l.shutdown(); - } - } - - @Override - public boolean isShuttingDown() { - for (EventExecutor l: children) { - if (!l.isShuttingDown()) { - return false; - } - } - return true; - } - - @Override - public boolean isShutdown() { - for (EventExecutor l: children) { - if (!l.isShutdown()) { - return false; - } - } - return true; - } - - @Override - public boolean isTerminated() { - for (EventExecutor l: children) { - if (!l.isTerminated()) { - return false; - } - } - return true; - } - - @Override - public boolean awaitTermination(long timeout, TimeUnit unit) - throws InterruptedException { - long deadline = System.nanoTime() + unit.toNanos(timeout); - loop: for (EventExecutor l: children) { - for (;;) { - long timeLeft = deadline - System.nanoTime(); - if (timeLeft <= 0) { - break loop; - } - if (l.awaitTermination(timeLeft, TimeUnit.NANOSECONDS)) { - break; - } - } - } - return isTerminated(); - } - - private static boolean isPowerOfTwo(int val) { - return (val & -val) == val; - } - - private interface EventExecutorChooser { - EventExecutor next(); - } - - private final class PowerOfTwoEventExecutorChooser implements EventExecutorChooser { - @Override - public EventExecutor next() { - return children[childIndex.getAndIncrement() & children.length - 1]; - } - } - - private final class GenericEventExecutorChooser implements EventExecutorChooser { - @Override - public EventExecutor next() { - return children[Math.abs(childIndex.getAndIncrement() % children.length)]; - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/ProgressiveFuture.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/ProgressiveFuture.java deleted file mode 100755 index e1f0b64e1a..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/ProgressiveFuture.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.util.concurrent; - -/** - * A {@link Future} which is used to indicate the progress of an operation. - */ -public interface ProgressiveFuture extends Future { - - @Override - ProgressiveFuture addListener(GenericFutureListener> listener); - - @Override - ProgressiveFuture addListeners(GenericFutureListener>... listeners); - - @Override - ProgressiveFuture removeListener(GenericFutureListener> listener); - - @Override - ProgressiveFuture removeListeners(GenericFutureListener>... listeners); - - @Override - ProgressiveFuture sync() throws InterruptedException; - - @Override - ProgressiveFuture syncUninterruptibly(); - - @Override - ProgressiveFuture await() throws InterruptedException; - - @Override - ProgressiveFuture awaitUninterruptibly(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/ProgressivePromise.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/ProgressivePromise.java deleted file mode 100755 index a9c08cb782..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/ProgressivePromise.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.concurrent; - -/** - * Special {@link ProgressiveFuture} which is writable. - */ -public interface ProgressivePromise extends Promise, ProgressiveFuture { - - /** - * Sets the current progress of the operation and notifies the listeners that implement - * {@link GenericProgressiveFutureListener}. - */ - ProgressivePromise setProgress(long progress, long total); - - /** - * Tries to set the current progress of the operation and notifies the listeners that implement - * {@link GenericProgressiveFutureListener}. If the operation is already complete or the progress is out of range, - * this method does nothing but returning {@code false}. - */ - boolean tryProgress(long progress, long total); - - @Override - ProgressivePromise setSuccess(V result); - - @Override - ProgressivePromise setFailure(Throwable cause); - - @Override - ProgressivePromise addListener(GenericFutureListener> listener); - - @Override - ProgressivePromise addListeners(GenericFutureListener>... listeners); - - @Override - ProgressivePromise removeListener(GenericFutureListener> listener); - - @Override - ProgressivePromise removeListeners(GenericFutureListener>... listeners); - - @Override - ProgressivePromise await() throws InterruptedException; - - @Override - ProgressivePromise awaitUninterruptibly(); - - @Override - ProgressivePromise sync() throws InterruptedException; - - @Override - ProgressivePromise syncUninterruptibly(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/Promise.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/Promise.java deleted file mode 100755 index a6e3ba0853..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/Promise.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.concurrent; - -/** - * Special {@link Future} which is writable. - */ -public interface Promise extends Future { - - /** - * Marks this future as a success and notifies all - * listeners. - * - * If it is success or failed already it will throw an {@link IllegalStateException}. - */ - Promise setSuccess(V result); - - /** - * Marks this future as a success and notifies all - * listeners. - * - * @return {@code true} if and only if successfully marked this future as - * a success. Otherwise {@code false} because this future is - * already marked as either a success or a failure. - */ - boolean trySuccess(V result); - - /** - * Marks this future as a failure and notifies all - * listeners. - * - * If it is success or failed already it will throw an {@link IllegalStateException}. - */ - Promise setFailure(Throwable cause); - - /** - * Marks this future as a failure and notifies all - * listeners. - * - * @return {@code true} if and only if successfully marked this future as - * a failure. Otherwise {@code false} because this future is - * already marked as either a success or a failure. - */ - boolean tryFailure(Throwable cause); - - /** - * Make this future impossible to cancel. - * - * @return {@code true} if and only if successfully marked this future as uncancellable or it is already done - * without being cancelled. {@code false} if this future has been cancelled already. - */ - boolean setUncancellable(); - - @Override - Promise addListener(GenericFutureListener> listener); - - @Override - Promise addListeners(GenericFutureListener>... listeners); - - @Override - Promise removeListener(GenericFutureListener> listener); - - @Override - Promise removeListeners(GenericFutureListener>... listeners); - - @Override - Promise await() throws InterruptedException; - - @Override - Promise awaitUninterruptibly(); - - @Override - Promise sync() throws InterruptedException; - - @Override - Promise syncUninterruptibly(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/PromiseAggregator.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/PromiseAggregator.java deleted file mode 100755 index 0d15a39ac6..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/PromiseAggregator.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.util.concurrent; - -import java.util.LinkedHashSet; -import java.util.Set; - -/** - * {@link GenericFutureListener} implementation which consolidates multiple {@link Future}s - * into one, by listening to individual {@link Future}s and producing an aggregated result - * (success/failure) when all {@link Future}s have completed. - * - * @param V the type of value returned by the {@link Future} - * @param F the type of {@link Future} - */ -public class PromiseAggregator> implements GenericFutureListener { - - private final Promise aggregatePromise; - private final boolean failPending; - private Set> pendingPromises; - - /** - * Creates a new instance. - * - * @param aggregatePromise the {@link Promise} to notify - * @param failPending {@code true} to fail pending promises, false to leave them unaffected - */ - public PromiseAggregator(Promise aggregatePromise, boolean failPending) { - if (aggregatePromise == null) { - throw new NullPointerException("aggregatePromise"); - } - this.aggregatePromise = aggregatePromise; - this.failPending = failPending; - } - - /** - * See {@link PromiseAggregator#PromiseAggregator(Promise, boolean)}. - * Defaults {@code failPending} to true. - */ - public PromiseAggregator(Promise aggregatePromise) { - this(aggregatePromise, true); - } - - /** - * Add the given {@link Promise}s to the aggregator. - */ - @SafeVarargs - public final PromiseAggregator add(Promise... promises) { - if (promises == null) { - throw new NullPointerException("promises"); - } - if (promises.length == 0) { - return this; - } - synchronized (this) { - if (pendingPromises == null) { - int size; - if (promises.length > 1) { - size = promises.length; - } else { - size = 2; - } - pendingPromises = new LinkedHashSet>(size); - } - for (Promise p : promises) { - if (p == null) { - continue; - } - pendingPromises.add(p); - p.addListener(this); - } - } - return this; - } - - @Override - public synchronized void operationComplete(F future) throws Exception { - if (pendingPromises == null) { - aggregatePromise.setSuccess(null); - } else { - pendingPromises.remove(future); - if (!future.isSuccess()) { - Throwable cause = future.cause(); - aggregatePromise.setFailure(cause); - if (failPending) { - for (Promise pendingFuture : pendingPromises) { - pendingFuture.setFailure(cause); - } - } - } else { - if (pendingPromises.isEmpty()) { - aggregatePromise.setSuccess(null); - } - } - } - } - -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/PromiseNotifier.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/PromiseNotifier.java deleted file mode 100755 index 45c525d282..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/PromiseNotifier.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.concurrent; - -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -import static com.ai.cloud.io.netty.util.internal.ObjectUtil.checkNotNull; - -/** - * {@link GenericFutureListener} implementation which takes other {@link Future}s - * and notifies them on completion. - * - * @param the type of value returned by the future - * @param the type of future - */ -public class PromiseNotifier> implements GenericFutureListener { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(PromiseNotifier.class); - private final Promise[] promises; - - /** - * Create a new instance. - * - * @param promises the {@link Promise}s to notify once this {@link GenericFutureListener} is notified. - */ - @SafeVarargs - public PromiseNotifier(Promise... promises) { - checkNotNull(promises, "promises"); - for (Promise promise: promises) { - if (promise == null) { - throw new IllegalArgumentException("promises contains null Promise"); - } - } - this.promises = promises.clone(); - } - - @Override - public void operationComplete(F future) throws Exception { - if (future.isSuccess()) { - V result = future.get(); - for (Promise p: promises) { - if (!p.trySuccess(result)) { - logger.warn("Failed to mark a promise as success because it is done already: {}", p); - } - } - return; - } - - Throwable cause = future.cause(); - for (Promise p: promises) { - if (!p.tryFailure(cause)) { - logger.warn("Failed to mark a promise as failure because it's done already: {}", p, cause); - } - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/PromiseTask.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/PromiseTask.java deleted file mode 100755 index 8fdbf0d493..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/PromiseTask.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.concurrent; - -import java.util.concurrent.Callable; -import java.util.concurrent.RunnableFuture; - -class PromiseTask extends DefaultPromise implements RunnableFuture { - - static Callable toCallable(Runnable runnable, T result) { - return new RunnableAdapter(runnable, result); - } - - private static final class RunnableAdapter implements Callable { - final Runnable task; - final T result; - - RunnableAdapter(Runnable task, T result) { - this.task = task; - this.result = result; - } - - @Override - public T call() { - task.run(); - return result; - } - - @Override - public String toString() { - return "Callable(task: " + task + ", result: " + result + ')'; - } - } - - protected final Callable task; - - PromiseTask(EventExecutor executor, Runnable runnable, V result) { - this(executor, toCallable(runnable, result)); - } - - PromiseTask(EventExecutor executor, Callable callable) { - super(executor); - task = callable; - } - - @Override - public final int hashCode() { - return System.identityHashCode(this); - } - - @Override - public final boolean equals(Object obj) { - return this == obj; - } - - @Override - public void run() { - try { - if (setUncancellableInternal()) { - V result = task.call(); - setSuccessInternal(result); - } - } catch (Throwable e) { - setFailureInternal(e); - } - } - - @Override - public final Promise setFailure(Throwable cause) { - throw new IllegalStateException(); - } - - protected final Promise setFailureInternal(Throwable cause) { - super.setFailure(cause); - return this; - } - - @Override - public final boolean tryFailure(Throwable cause) { - return false; - } - - protected final boolean tryFailureInternal(Throwable cause) { - return super.tryFailure(cause); - } - - @Override - public final Promise setSuccess(V result) { - throw new IllegalStateException(); - } - - protected final Promise setSuccessInternal(V result) { - super.setSuccess(result); - return this; - } - - @Override - public final boolean trySuccess(V result) { - return false; - } - - protected final boolean trySuccessInternal(V result) { - return super.trySuccess(result); - } - - @Override - public final boolean setUncancellable() { - throw new IllegalStateException(); - } - - protected final boolean setUncancellableInternal() { - return super.setUncancellable(); - } - - @Override - protected StringBuilder toStringBuilder() { - StringBuilder buf = super.toStringBuilder(); - buf.setCharAt(buf.length() - 1, ','); - - return buf.append(" task: ") - .append(task) - .append(')'); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/ScheduledFuture.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/ScheduledFuture.java deleted file mode 100755 index d68211b3e0..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/ScheduledFuture.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.concurrent; - -/** - * The result of an scheduled asynchronous operation. - */ -@SuppressWarnings("ClassNameSameAsAncestorName") -public interface ScheduledFuture extends Future, java.util.concurrent.ScheduledFuture { -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/ScheduledFutureTask.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/ScheduledFutureTask.java deleted file mode 100755 index 0a66e82851..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/ScheduledFutureTask.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.util.concurrent; - -import java.util.Queue; -import java.util.concurrent.Callable; -import java.util.concurrent.Delayed; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; - -@SuppressWarnings("ComparableImplementedButEqualsNotOverridden") -final class ScheduledFutureTask extends PromiseTask implements ScheduledFuture { - private static final AtomicLong nextTaskId = new AtomicLong(); - private static final long START_TIME = System.nanoTime(); - - static long nanoTime() { - return System.nanoTime() - START_TIME; - } - - static long deadlineNanos(long delay) { - return nanoTime() + delay; - } - - private final long id = nextTaskId.getAndIncrement(); - private long deadlineNanos; - /* 0 - no repeat, >0 - repeat at fixed rate, <0 - repeat with fixed delay */ - private final long periodNanos; - - ScheduledFutureTask( - AbstractScheduledEventExecutor executor, - Runnable runnable, V result, long nanoTime) { - - this(executor, toCallable(runnable, result), nanoTime); - } - - ScheduledFutureTask( - AbstractScheduledEventExecutor executor, - Callable callable, long nanoTime, long period) { - - super(executor, callable); - if (period == 0) { - throw new IllegalArgumentException("period: 0 (expected: != 0)"); - } - deadlineNanos = nanoTime; - periodNanos = period; - } - - ScheduledFutureTask( - AbstractScheduledEventExecutor executor, - Callable callable, long nanoTime) { - - super(executor, callable); - deadlineNanos = nanoTime; - periodNanos = 0; - } - - @Override - protected EventExecutor executor() { - return super.executor(); - } - - public long deadlineNanos() { - return deadlineNanos; - } - - public long delayNanos() { - return Math.max(0, deadlineNanos() - nanoTime()); - } - - public long delayNanos(long currentTimeNanos) { - return Math.max(0, deadlineNanos() - (currentTimeNanos - START_TIME)); - } - - @Override - public long getDelay(TimeUnit unit) { - return unit.convert(delayNanos(), TimeUnit.NANOSECONDS); - } - - @Override - public int compareTo(Delayed o) { - if (this == o) { - return 0; - } - - ScheduledFutureTask that = (ScheduledFutureTask) o; - long d = deadlineNanos() - that.deadlineNanos(); - if (d < 0) { - return -1; - } else if (d > 0) { - return 1; - } else if (id < that.id) { - return -1; - } else if (id == that.id) { - throw new Error(); - } else { - return 1; - } - } - - @Override - public void run() { - assert executor().inEventLoop(); - try { - if (periodNanos == 0) { - if (setUncancellableInternal()) { - V result = task.call(); - setSuccessInternal(result); - } - } else { - // check if is done as it may was cancelled - if (!isCancelled()) { - task.call(); - if (!executor().isShutdown()) { - long p = periodNanos; - if (p > 0) { - deadlineNanos += p; - } else { - deadlineNanos = nanoTime() - p; - } - if (!isCancelled()) { - // scheduledTaskQueue can never be null as we lazy init it before submit the task! - Queue> scheduledTaskQueue = - ((AbstractScheduledEventExecutor) executor()).scheduledTaskQueue; - assert scheduledTaskQueue != null; - scheduledTaskQueue.add(this); - } - } - } - } - } catch (Throwable cause) { - setFailureInternal(cause); - } - } - - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - boolean canceled = super.cancel(mayInterruptIfRunning); - if (canceled) { - ((AbstractScheduledEventExecutor) executor()).removeScheduled(this); - } - return canceled; - } - - boolean cancelWithoutRemove(boolean mayInterruptIfRunning) { - return super.cancel(mayInterruptIfRunning); - } - - @Override - protected StringBuilder toStringBuilder() { - StringBuilder buf = super.toStringBuilder(); - buf.setCharAt(buf.length() - 1, ','); - - return buf.append(" id: ") - .append(id) - .append(", deadline: ") - .append(deadlineNanos) - .append(", period: ") - .append(periodNanos) - .append(')'); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/SingleThreadEventExecutor.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/SingleThreadEventExecutor.java deleted file mode 100755 index 3753f910d2..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/SingleThreadEventExecutor.java +++ /dev/null @@ -1,777 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.concurrent; - -import java.lang.Thread.State; -import java.util.ArrayList; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Queue; -import java.util.Set; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.Semaphore; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; - -import com.ai.cloud.io.netty.util.internal.PlatformDependent; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * Abstract base class for {@link EventExecutor}'s that execute all its submitted tasks in a single thread. - * - */ -public abstract class SingleThreadEventExecutor extends AbstractScheduledEventExecutor { - - private static final InternalLogger logger = - InternalLoggerFactory.getInstance(SingleThreadEventExecutor.class); - - private static final int ST_NOT_STARTED = 1; - private static final int ST_STARTED = 2; - private static final int ST_SHUTTING_DOWN = 3; - private static final int ST_SHUTDOWN = 4; - private static final int ST_TERMINATED = 5; - - private static final Runnable WAKEUP_TASK = new Runnable() { - @Override - public void run() { - // Do nothing. - } - }; - - private static final AtomicIntegerFieldUpdater STATE_UPDATER; - - static { - AtomicIntegerFieldUpdater updater = - PlatformDependent.newAtomicIntegerFieldUpdater(SingleThreadEventExecutor.class, "state"); - if (updater == null) { - updater = AtomicIntegerFieldUpdater.newUpdater(SingleThreadEventExecutor.class, "state"); - } - STATE_UPDATER = updater; - } - - private final EventExecutorGroup parent; - private final Queue taskQueue; - private final Thread thread; - private final ThreadProperties threadProperties; - private final Semaphore threadLock = new Semaphore(0); - private final Set shutdownHooks = new LinkedHashSet(); - private final boolean addTaskWakesUp; - - private long lastExecutionTime; - - @SuppressWarnings({ "FieldMayBeFinal", "unused" }) - private volatile int state = ST_NOT_STARTED; - - private volatile long gracefulShutdownQuietPeriod; - private volatile long gracefulShutdownTimeout; - private long gracefulShutdownStartTime; - - private final Promise terminationFuture = new DefaultPromise(GlobalEventExecutor.INSTANCE); - - /** - * Create a new instance - * - * @param parent the {@link EventExecutorGroup} which is the parent of this instance and belongs to it - * @param threadFactory the {@link ThreadFactory} which will be used for the used {@link Thread} - * @param addTaskWakesUp {@code true} if and only if invocation of {@link #addTask(Runnable)} will wake up the - * executor thread - */ - protected SingleThreadEventExecutor( - EventExecutorGroup parent, ThreadFactory threadFactory, boolean addTaskWakesUp) { - - if (threadFactory == null) { - throw new NullPointerException("threadFactory"); - } - - this.parent = parent; - this.addTaskWakesUp = addTaskWakesUp; - - thread = threadFactory.newThread(new Runnable() { - @Override - public void run() { - boolean success = false; - updateLastExecutionTime(); - try { - SingleThreadEventExecutor.this.run(); - success = true; - } catch (Throwable t) { - logger.warn("Unexpected exception from an event executor: ", t); - } finally { - for (;;) { - int oldState = STATE_UPDATER.get(SingleThreadEventExecutor.this); - if (oldState >= ST_SHUTTING_DOWN || STATE_UPDATER.compareAndSet( - SingleThreadEventExecutor.this, oldState, ST_SHUTTING_DOWN)) { - break; - } - } - // Check if confirmShutdown() was called at the end of the loop. - if (success && gracefulShutdownStartTime == 0) { - logger.error( - "Buggy " + EventExecutor.class.getSimpleName() + " implementation; " + - SingleThreadEventExecutor.class.getSimpleName() + ".confirmShutdown() must be called " + - "before run() implementation terminates."); - } - - try { - // Run all remaining tasks and shutdown hooks. - for (;;) { - if (confirmShutdown()) { - break; - } - } - } finally { - try { - cleanup(); - } finally { - STATE_UPDATER.set(SingleThreadEventExecutor.this, ST_TERMINATED); - threadLock.release(); - if (!taskQueue.isEmpty()) { - logger.warn( - "An event executor terminated with " + - "non-empty task queue (" + taskQueue.size() + ')'); - } - - terminationFuture.setSuccess(null); - } - } - } - } - }); - threadProperties = new DefaultThreadProperties(thread); - taskQueue = newTaskQueue(); - } - - /** - * Create a new {@link Queue} which will holds the tasks to execute. This default implementation will return a - * {@link LinkedBlockingQueue} but if your sub-class of {@link SingleThreadEventExecutor} will not do any blocking - * calls on the this {@link Queue} it may make sense to {@code @Override} this and return some more performant - * implementation that does not support blocking operations at all. - */ - protected Queue newTaskQueue() { - return new LinkedBlockingQueue(); - } - - @Override - public EventExecutorGroup parent() { - return parent; - } - - /** - * Interrupt the current running {@link Thread}. - */ - protected void interruptThread() { - thread.interrupt(); - } - - /** - * @see {@link Queue#poll()} - */ - protected Runnable pollTask() { - assert inEventLoop(); - for (;;) { - Runnable task = taskQueue.poll(); - if (task == WAKEUP_TASK) { - continue; - } - return task; - } - } - - /** - * Take the next {@link Runnable} from the task queue and so will block if no task is currently present. - *

- * Be aware that this method will throw an {@link UnsupportedOperationException} if the task queue, which was - * created via {@link #newTaskQueue()}, does not implement {@link BlockingQueue}. - *

- * - * @return {@code null} if the executor thread has been interrupted or waken up. - */ - protected Runnable takeTask() { - assert inEventLoop(); - if (!(taskQueue instanceof BlockingQueue)) { - throw new UnsupportedOperationException(); - } - - BlockingQueue taskQueue = (BlockingQueue) this.taskQueue; - for (;;) { - ScheduledFutureTask scheduledTask = peekScheduledTask(); - if (scheduledTask == null) { - Runnable task = null; - try { - task = taskQueue.take(); - if (task == WAKEUP_TASK) { - task = null; - } - } catch (InterruptedException e) { - // Ignore - } - return task; - } else { - long delayNanos = scheduledTask.delayNanos(); - Runnable task = null; - if (delayNanos > 0) { - try { - task = taskQueue.poll(delayNanos, TimeUnit.NANOSECONDS); - } catch (InterruptedException e) { - return null; - } - } - if (task == null) { - // We need to fetch the scheduled tasks now as otherwise there may be a chance that - // scheduled tasks are never executed if there is always one task in the taskQueue. - // This is for example true for the read task of OIO Transport - // See https://github.com/netty/netty/issues/1614 - fetchFromScheduledTaskQueue(); - task = taskQueue.poll(); - } - - if (task != null) { - return task; - } - } - } - } - - private void fetchFromScheduledTaskQueue() { - if (hasScheduledTasks()) { - long nanoTime = AbstractScheduledEventExecutor.nanoTime(); - for (;;) { - Runnable scheduledTask = pollScheduledTask(nanoTime); - if (scheduledTask == null) { - break; - } - taskQueue.add(scheduledTask); - } - } - } - - /** - * @see {@link Queue#peek()} - */ - protected Runnable peekTask() { - assert inEventLoop(); - return taskQueue.peek(); - } - - /** - * @see {@link Queue#isEmpty()} - */ - protected boolean hasTasks() { - assert inEventLoop(); - return !taskQueue.isEmpty(); - } - - /** - * Return the number of tasks that are pending for processing. - * - * Be aware that this operation may be expensive as it depends on the internal implementation of the - * SingleThreadEventExecutor. So use it was care! - */ - public final int pendingTasks() { - return taskQueue.size(); - } - - /** - * Add a task to the task queue, or throws a {@link RejectedExecutionException} if this instance was shutdown - * before. - */ - protected void addTask(Runnable task) { - if (task == null) { - throw new NullPointerException("task"); - } - if (isShutdown()) { - reject(); - } - taskQueue.add(task); - } - - /** - * @see {@link Queue#remove(Object)} - */ - protected boolean removeTask(Runnable task) { - if (task == null) { - throw new NullPointerException("task"); - } - return taskQueue.remove(task); - } - - /** - * Poll all tasks from the task queue and run them via {@link Runnable#run()} method. - * - * @return {@code true} if and only if at least one task was run - */ - protected boolean runAllTasks() { - fetchFromScheduledTaskQueue(); - Runnable task = pollTask(); - if (task == null) { - return false; - } - - for (;;) { - try { - task.run(); - } catch (Throwable t) { - logger.warn("A task raised an exception.", t); - } - - task = pollTask(); - if (task == null) { - lastExecutionTime = ScheduledFutureTask.nanoTime(); - return true; - } - } - } - - /** - * Poll all tasks from the task queue and run them via {@link Runnable#run()} method. This method stops running - * the tasks in the task queue and returns if it ran longer than {@code timeoutNanos}. - */ - protected boolean runAllTasks(long timeoutNanos) { - fetchFromScheduledTaskQueue(); - Runnable task = pollTask(); - if (task == null) { - return false; - } - - final long deadline = ScheduledFutureTask.nanoTime() + timeoutNanos; - long runTasks = 0; - long lastExecutionTime; - for (;;) { - try { - task.run(); - } catch (Throwable t) { - logger.warn("A task raised an exception.", t); - } - - runTasks ++; - - // Check timeout every 64 tasks because nanoTime() is relatively expensive. - // XXX: Hard-coded value - will make it configurable if it is really a problem. - if ((runTasks & 0x3F) == 0) { - lastExecutionTime = ScheduledFutureTask.nanoTime(); - if (lastExecutionTime >= deadline) { - break; - } - } - - task = pollTask(); - if (task == null) { - lastExecutionTime = ScheduledFutureTask.nanoTime(); - break; - } - } - - this.lastExecutionTime = lastExecutionTime; - return true; - } - - /** - * Returns the amount of time left until the scheduled task with the closest dead line is executed. - */ - protected long delayNanos(long currentTimeNanos) { - ScheduledFutureTask scheduledTask = peekScheduledTask(); - if (scheduledTask == null) { - return SCHEDULE_PURGE_INTERVAL; - } - - return scheduledTask.delayNanos(currentTimeNanos); - } - - /** - * Updates the internal timestamp that tells when a submitted task was executed most recently. - * {@link #runAllTasks()} and {@link #runAllTasks(long)} updates this timestamp automatically, and thus there's - * usually no need to call this method. However, if you take the tasks manually using {@link #takeTask()} or - * {@link #pollTask()}, you have to call this method at the end of task execution loop for accurate quiet period - * checks. - */ - protected void updateLastExecutionTime() { - lastExecutionTime = ScheduledFutureTask.nanoTime(); - } - - /** - * - */ - protected abstract void run(); - - /** - * Do nothing, sub-classes may override - */ - protected void cleanup() { - // NOOP - } - - protected void wakeup(boolean inEventLoop) { - if (!inEventLoop || STATE_UPDATER.get(this) == ST_SHUTTING_DOWN) { - taskQueue.add(WAKEUP_TASK); - } - } - - @Override - public boolean inEventLoop(Thread thread) { - return thread == this.thread; - } - - /** - * Add a {@link Runnable} which will be executed on shutdown of this instance - */ - public void addShutdownHook(final Runnable task) { - if (inEventLoop()) { - shutdownHooks.add(task); - } else { - execute(new Runnable() { - @Override - public void run() { - shutdownHooks.add(task); - } - }); - } - } - - /** - * Remove a previous added {@link Runnable} as a shutdown hook - */ - public void removeShutdownHook(final Runnable task) { - if (inEventLoop()) { - shutdownHooks.remove(task); - } else { - execute(new Runnable() { - @Override - public void run() { - shutdownHooks.remove(task); - } - }); - } - } - - private boolean runShutdownHooks() { - boolean ran = false; - // Note shutdown hooks can add / remove shutdown hooks. - while (!shutdownHooks.isEmpty()) { - List copy = new ArrayList(shutdownHooks); - shutdownHooks.clear(); - for (Runnable task: copy) { - try { - task.run(); - } catch (Throwable t) { - logger.warn("Shutdown hook raised an exception.", t); - } finally { - ran = true; - } - } - } - - if (ran) { - lastExecutionTime = ScheduledFutureTask.nanoTime(); - } - - return ran; - } - - @Override - public Future shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit) { - if (quietPeriod < 0) { - throw new IllegalArgumentException("quietPeriod: " + quietPeriod + " (expected >= 0)"); - } - if (timeout < quietPeriod) { - throw new IllegalArgumentException( - "timeout: " + timeout + " (expected >= quietPeriod (" + quietPeriod + "))"); - } - if (unit == null) { - throw new NullPointerException("unit"); - } - - if (isShuttingDown()) { - return terminationFuture(); - } - - boolean inEventLoop = inEventLoop(); - boolean wakeup; - int oldState; - for (;;) { - if (isShuttingDown()) { - return terminationFuture(); - } - int newState; - wakeup = true; - oldState = STATE_UPDATER.get(this); - if (inEventLoop) { - newState = ST_SHUTTING_DOWN; - } else { - switch (oldState) { - case ST_NOT_STARTED: - case ST_STARTED: - newState = ST_SHUTTING_DOWN; - break; - default: - newState = oldState; - wakeup = false; - } - } - if (STATE_UPDATER.compareAndSet(this, oldState, newState)) { - break; - } - } - gracefulShutdownQuietPeriod = unit.toNanos(quietPeriod); - gracefulShutdownTimeout = unit.toNanos(timeout); - - if (oldState == ST_NOT_STARTED) { - thread.start(); - } - - if (wakeup) { - wakeup(inEventLoop); - } - - return terminationFuture(); - } - - @Override - public Future terminationFuture() { - return terminationFuture; - } - - @Override - @Deprecated - public void shutdown() { - if (isShutdown()) { - return; - } - - boolean inEventLoop = inEventLoop(); - boolean wakeup; - int oldState; - for (;;) { - if (isShuttingDown()) { - return; - } - int newState; - wakeup = true; - oldState = STATE_UPDATER.get(this); - if (inEventLoop) { - newState = ST_SHUTDOWN; - } else { - switch (oldState) { - case ST_NOT_STARTED: - case ST_STARTED: - case ST_SHUTTING_DOWN: - newState = ST_SHUTDOWN; - break; - default: - newState = oldState; - wakeup = false; - } - } - if (STATE_UPDATER.compareAndSet(this, oldState, newState)) { - break; - } - } - - if (oldState == ST_NOT_STARTED) { - thread.start(); - } - - if (wakeup) { - wakeup(inEventLoop); - } - } - - @Override - public boolean isShuttingDown() { - return STATE_UPDATER.get(this) >= ST_SHUTTING_DOWN; - } - - @Override - public boolean isShutdown() { - return STATE_UPDATER.get(this) >= ST_SHUTDOWN; - } - - @Override - public boolean isTerminated() { - return STATE_UPDATER.get(this) == ST_TERMINATED; - } - - /** - * Confirm that the shutdown if the instance should be done now! - */ - protected boolean confirmShutdown() { - if (!isShuttingDown()) { - return false; - } - - if (!inEventLoop()) { - throw new IllegalStateException("must be invoked from an event loop"); - } - - cancelScheduledTasks(); - - if (gracefulShutdownStartTime == 0) { - gracefulShutdownStartTime = ScheduledFutureTask.nanoTime(); - } - - if (runAllTasks() || runShutdownHooks()) { - if (isShutdown()) { - // Executor shut down - no new tasks anymore. - return true; - } - - // There were tasks in the queue. Wait a little bit more until no tasks are queued for the quiet period. - wakeup(true); - return false; - } - - final long nanoTime = ScheduledFutureTask.nanoTime(); - - if (isShutdown() || nanoTime - gracefulShutdownStartTime > gracefulShutdownTimeout) { - return true; - } - - if (nanoTime - lastExecutionTime <= gracefulShutdownQuietPeriod) { - // Check if any tasks were added to the queue every 100ms. - // TODO: Change the behavior of takeTask() so that it returns on timeout. - wakeup(true); - try { - Thread.sleep(100); - } catch (InterruptedException e) { - // Ignore - } - - return false; - } - - // No tasks were added for last quiet period - hopefully safe to shut down. - // (Hopefully because we really cannot make a guarantee that there will be no execute() calls by a user.) - return true; - } - - @Override - public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { - if (unit == null) { - throw new NullPointerException("unit"); - } - - if (inEventLoop()) { - throw new IllegalStateException("cannot await termination of the current thread"); - } - - if (threadLock.tryAcquire(timeout, unit)) { - threadLock.release(); - } - - return isTerminated(); - } - - @Override - public void execute(Runnable task) { - if (task == null) { - throw new NullPointerException("task"); - } - - boolean inEventLoop = inEventLoop(); - if (inEventLoop) { - addTask(task); - } else { - startThread(); - addTask(task); - if (isShutdown() && removeTask(task)) { - reject(); - } - } - - if (!addTaskWakesUp && wakesUpForTask(task)) { - wakeup(inEventLoop); - } - } - - /** - * Returns the {@link ThreadProperties} of the {@link Thread} that powers the {@link SingleThreadEventExecutor}. - */ - public final ThreadProperties threadProperties() { - return threadProperties; - } - - @SuppressWarnings("unused") - protected boolean wakesUpForTask(Runnable task) { - return true; - } - - protected static void reject() { - throw new RejectedExecutionException("event executor terminated"); - } - - // ScheduledExecutorService implementation - - private static final long SCHEDULE_PURGE_INTERVAL = TimeUnit.SECONDS.toNanos(1); - - private void startThread() { - if (STATE_UPDATER.get(this) == ST_NOT_STARTED) { - if (STATE_UPDATER.compareAndSet(this, ST_NOT_STARTED, ST_STARTED)) { - thread.start(); - } - } - } - - private static final class DefaultThreadProperties implements ThreadProperties { - private final Thread t; - - DefaultThreadProperties(Thread t) { - this.t = t; - } - - @Override - public State state() { - return t.getState(); - } - - @Override - public int priority() { - return t.getPriority(); - } - - @Override - public boolean isInterrupted() { - return t.isInterrupted(); - } - - @Override - public boolean isDaemon() { - return t.isDaemon(); - } - - @Override - public String name() { - return t.getName(); - } - - @Override - public long id() { - return t.getId(); - } - - @Override - public StackTraceElement[] stackTrace() { - return t.getStackTrace(); - } - - @Override - public boolean isAlive() { - return t.isAlive(); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/SucceededFuture.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/SucceededFuture.java deleted file mode 100755 index 4179ef9837..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/SucceededFuture.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.concurrent; - -/** - * The {@link CompleteFuture} which is succeeded already. It is - * recommended to use {@link EventExecutor#newSucceededFuture(Object)} instead of - * calling the constructor of this future. - */ -public final class SucceededFuture extends CompleteFuture { - private final V result; - - /** - * Creates a new instance. - * - * @param executor the {@link EventExecutor} associated with this future - */ - public SucceededFuture(EventExecutor executor, V result) { - super(executor); - this.result = result; - } - - @Override - public Throwable cause() { - return null; - } - - @Override - public boolean isSuccess() { - return true; - } - - @Override - public V getNow() { - return result; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/ThreadProperties.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/ThreadProperties.java deleted file mode 100755 index f9893203c4..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/ThreadProperties.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.concurrent; - -/** - * Expose details for a {@link Thread}. - */ -public interface ThreadProperties { - /** - * @see {@link Thread#getState()}. - */ - Thread.State state(); - - /** - * @see {@link Thread#getPriority()}. - */ - int priority(); - - /** - * @see {@link Thread#isInterrupted()}. - */ - boolean isInterrupted(); - - /** - * @see {@link Thread#isDaemon()} ()}. - */ - boolean isDaemon(); - - /** - * @see {@link Thread#getName()} ()}. - */ - String name(); - - /** - * @see {@link Thread#getId()}. - */ - long id(); - - /** - * @see {@link Thread#getStackTrace()}. - */ - StackTraceElement[] stackTrace(); - - /** - * @see {@link Thread#isAlive()}. - */ - boolean isAlive(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/package-info.java deleted file mode 100755 index c374e3b633..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/concurrent/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * Utility classes for concurrent / async tasks. - */ -package com.ai.cloud.io.netty.util.concurrent; diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/AppendableCharSequence.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/AppendableCharSequence.java deleted file mode 100755 index ad6088d2f2..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/AppendableCharSequence.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.internal; - - -import java.util.Arrays; - -public final class AppendableCharSequence implements CharSequence, Appendable { - private char[] chars; - private int pos; - - public AppendableCharSequence(int length) { - if (length < 1) { - throw new IllegalArgumentException("length: " + length + " (length: >= 1)"); - } - chars = new char[length]; - } - - private AppendableCharSequence(char[] chars) { - if (chars.length < 1) { - throw new IllegalArgumentException("length: " + chars.length + " (length: >= 1)"); - } - this.chars = chars; - pos = chars.length; - } - - @Override - public int length() { - return pos; - } - - @Override - public char charAt(int index) { - if (index > pos) { - throw new IndexOutOfBoundsException(); - } - return chars[index]; - } - - /** - * Access a value in this {@link CharSequence}. - * This method is considered unsafe as index values are assumed to be legitimate. - * Only underlying array bounds checking is done. - * @param index The index to access the underlying array at. - * @return The value at {@code index}. - */ - public char charAtUnsafe(int index) { - return chars[index]; - } - - @Override - public AppendableCharSequence subSequence(int start, int end) { - return new AppendableCharSequence(Arrays.copyOfRange(chars, start, end)); - } - - @Override - public AppendableCharSequence append(char c) { - try { - chars[pos++] = c; - } catch (IndexOutOfBoundsException e) { - expand(); - chars[pos - 1] = c; - } - return this; - } - - @Override - public AppendableCharSequence append(CharSequence csq) { - return append(csq, 0, csq.length()); - } - - @Override - public AppendableCharSequence append(CharSequence csq, int start, int end) { - if (csq.length() < end) { - throw new IndexOutOfBoundsException(); - } - int length = end - start; - if (length > chars.length - pos) { - chars = expand(chars, pos + length, pos); - } - if (csq instanceof AppendableCharSequence) { - // Optimize append operations via array copy - AppendableCharSequence seq = (AppendableCharSequence) csq; - char[] src = seq.chars; - System.arraycopy(src, start, chars, pos, length); - pos += length; - return this; - } - for (int i = start; i < end; i++) { - chars[pos++] = csq.charAt(i); - } - - return this; - } - - /** - * Reset the {@link AppendableCharSequence}. Be aware this will only reset the current internal position and not - * shrink the internal char array. - */ - public void reset() { - pos = 0; - } - - @Override - public String toString() { - return new String(chars, 0, pos); - } - - /** - * Create a new {@link String} from the given start to end. - */ - public String substring(int start, int end) { - int length = end - start; - if (start > pos || length > pos) { - throw new IndexOutOfBoundsException(); - } - return new String(chars, start, length); - } - - /** - * Create a new {@link String} from the given start to end. - * This method is considered unsafe as index values are assumed to be legitimate. - * Only underlying array bounds checking is done. - */ - public String subStringUnsafe(int start, int end) { - return new String(chars, start, end - start); - } - - private void expand() { - char[] old = chars; - // double it - int len = old.length << 1; - if (len < 0) { - throw new IllegalStateException(); - } - chars = new char[len]; - System.arraycopy(old, 0, chars, 0, old.length); - } - - private static char[] expand(char[] array, int neededSpace, int size) { - int newCapacity = array.length; - do { - // double capacity until it is big enough - newCapacity <<= 1; - - if (newCapacity < 0) { - throw new IllegalStateException(); - } - - } while (neededSpace > newCapacity); - - char[] newArray = new char[newCapacity]; - System.arraycopy(array, 0, newArray, 0, size); - - return newArray; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/Cleaner0.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/Cleaner0.java deleted file mode 100755 index ddc742c368..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/Cleaner0.java +++ /dev/null @@ -1,75 +0,0 @@ -/* -* Copyright 2014 The Netty Project -* -* The Netty Project licenses this file to you under the Apache License, -* version 2.0 (the "License"); you may not use this file except in compliance -* with the License. You may obtain a copy of the License at: -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -* License for the specific language governing permissions and limitations -* under the License. -*/ -package com.ai.cloud.io.netty.util.internal; - -import sun.misc.Cleaner; - -import java.lang.reflect.Field; -import java.nio.ByteBuffer; - -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - - -/** - * Allows to free direct {@link ByteBuffer} by using {@link Cleaner}. This is encapsulated in an extra class to be able - * to use {@link PlatformDependent0} on Android without problems. - * - * For more details see #2604. - */ -final class Cleaner0 { - private static final long CLEANER_FIELD_OFFSET; - private static final InternalLogger logger = InternalLoggerFactory.getInstance(Cleaner0.class); - - static { - ByteBuffer direct = ByteBuffer.allocateDirect(1); - Field cleanerField; - long fieldOffset = -1; - if (PlatformDependent0.hasUnsafe()) { - try { - cleanerField = direct.getClass().getDeclaredField("cleaner"); - cleanerField.setAccessible(true); - Cleaner cleaner = (Cleaner) cleanerField.get(direct); - cleaner.clean(); - fieldOffset = PlatformDependent0.objectFieldOffset(cleanerField); - } catch (Throwable t) { - // We don't have ByteBuffer.cleaner(). - fieldOffset = -1; - } - } - logger.debug("java.nio.ByteBuffer.cleaner(): {}", fieldOffset != -1? "available" : "unavailable"); - CLEANER_FIELD_OFFSET = fieldOffset; - - // free buffer if possible - freeDirectBuffer(direct); - } - - static void freeDirectBuffer(ByteBuffer buffer) { - if (CLEANER_FIELD_OFFSET == -1 || !buffer.isDirect()) { - return; - } - try { - Cleaner cleaner = (Cleaner) PlatformDependent0.getObject(buffer, CLEANER_FIELD_OFFSET); - if (cleaner != null) { - cleaner.clean(); - } - } catch (Throwable t) { - // Nothing we can do here. - } - } - - private Cleaner0() { } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/ConcurrentCircularArrayQueue.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/ConcurrentCircularArrayQueue.java deleted file mode 100755 index cb45713189..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/ConcurrentCircularArrayQueue.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.ai.cloud.io.netty.util.internal; - - -import java.util.AbstractQueue; -import java.util.Iterator; - -/** - * Forked from JCTools. - * - * A concurrent access enabling class used by circular array based queues this class exposes an offset computation - * method along with differently memory fenced load/store methods into the underlying array. The class is pre-padded and - * the array is padded on either side to help with False sharing prvention. It is expected theat subclasses handle post - * padding. - *

- * Offset calculation is separate from access to enable the reuse of a give compute offset. - *

- * Load/Store methods using a buffer parameter are provided to allow the prevention of final field reload after a - * LoadLoad barrier. - *

- * - * @param - */ -abstract class ConcurrentCircularArrayQueue extends ConcurrentCircularArrayQueueL0Pad { - protected static final int REF_BUFFER_PAD; - private static final long REF_ARRAY_BASE; - private static final int REF_ELEMENT_SHIFT; - static { - final int scale = PlatformDependent0.UNSAFE.arrayIndexScale(Object[].class); - if (4 == scale) { - REF_ELEMENT_SHIFT = 2; - } else if (8 == scale) { - REF_ELEMENT_SHIFT = 3; - } else { - throw new IllegalStateException("Unknown pointer size"); - } - // 2 cache lines pad - // TODO: replace 64 with the value we can detect - REF_BUFFER_PAD = (64 * 2) / scale; - // Including the buffer pad in the array base offset - REF_ARRAY_BASE = PlatformDependent0.UNSAFE.arrayBaseOffset(Object[].class) + (REF_BUFFER_PAD * scale); - } - protected final long mask; - // @Stable :( - protected final E[] buffer; - - @SuppressWarnings("unchecked") - public ConcurrentCircularArrayQueue(int capacity) { - int actualCapacity = roundToPowerOfTwo(capacity); - mask = actualCapacity - 1; - // pad data on either end with some empty slots. - buffer = (E[]) new Object[actualCapacity + REF_BUFFER_PAD * 2]; - } - - private static int roundToPowerOfTwo(final int value) { - return 1 << (32 - Integer.numberOfLeadingZeros(value - 1)); - } - /** - * @param index desirable element index - * @return the offset in bytes within the array for a given index. - */ - protected final long calcElementOffset(long index) { - return calcElementOffset(index, mask); - } - /** - * @param index desirable element index - * @param mask - * @return the offset in bytes within the array for a given index. - */ - protected static final long calcElementOffset(long index, long mask) { - return REF_ARRAY_BASE + ((index & mask) << REF_ELEMENT_SHIFT); - } - /** - * A plain store (no ordering/fences) of an element to a given offset - * - * @param offset computed via {@link ConcurrentCircularArrayQueue#calcElementOffset(long)} - * @param e a kitty - */ - protected final void spElement(long offset, E e) { - spElement(buffer, offset, e); - } - - /** - * A plain store (no ordering/fences) of an element to a given offset - * - * @param buffer this.buffer - * @param offset computed via {@link ConcurrentCircularArrayQueue#calcElementOffset(long)} - * @param e an orderly kitty - */ - protected static final void spElement(E[] buffer, long offset, E e) { - PlatformDependent0.UNSAFE.putObject(buffer, offset, e); - } - - /** - * An ordered store(store + StoreStore barrier) of an element to a given offset - * - * @param offset computed via {@link ConcurrentCircularArrayQueue#calcElementOffset(long)} - * @param e an orderly kitty - */ - protected final void soElement(long offset, E e) { - soElement(buffer, offset, e); - } - - /** - * An ordered store(store + StoreStore barrier) of an element to a given offset - * - * @param buffer this.buffer - * @param offset computed via {@link ConcurrentCircularArrayQueue#calcElementOffset(long)} - * @param e an orderly kitty - */ - protected static final void soElement(E[] buffer, long offset, E e) { - PlatformDependent0.UNSAFE.putOrderedObject(buffer, offset, e); - } - - /** - * A plain load (no ordering/fences) of an element from a given offset. - * - * @param offset computed via {@link ConcurrentCircularArrayQueue#calcElementOffset(long)} - * @return the element at the offset - */ - protected final E lpElement(long offset) { - return lpElement(buffer, offset); - } - - /** - * A plain load (no ordering/fences) of an element from a given offset. - * - * @param buffer this.buffer - * @param offset computed via {@link ConcurrentCircularArrayQueue#calcElementOffset(long)} - * @return the element at the offset - */ - @SuppressWarnings("unchecked") - protected static final E lpElement(E[] buffer, long offset) { - return (E) PlatformDependent0.UNSAFE.getObject(buffer, offset); - } - - /** - * A volatile load (load + LoadLoad barrier) of an element from a given offset. - * - * @param offset computed via {@link ConcurrentCircularArrayQueue#calcElementOffset(long)} - * @return the element at the offset - */ - protected final E lvElement(long offset) { - return lvElement(buffer, offset); - } - - /** - * A volatile load (load + LoadLoad barrier) of an element from a given offset. - * - * @param buffer this.buffer - * @param offset computed via {@link ConcurrentCircularArrayQueue#calcElementOffset(long)} - * @return the element at the offset - */ - @SuppressWarnings("unchecked") - protected static final E lvElement(E[] buffer, long offset) { - return (E) PlatformDependent0.UNSAFE.getObjectVolatile(buffer, offset); - } - - @Override - public Iterator iterator() { - throw new UnsupportedOperationException(); - } - - @Override - public void clear() { - while (poll() != null || !isEmpty()) { - // looping - } - } - - public int capacity() { - return (int) (mask + 1); - } -} - -abstract class ConcurrentCircularArrayQueueL0Pad extends AbstractQueue { - long p00, p01, p02, p03, p04, p05, p06, p07; - long p30, p31, p32, p33, p34, p35, p36, p37; -} - diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/ConcurrentSet.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/ConcurrentSet.java deleted file mode 100755 index 6587d4be7d..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/ConcurrentSet.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.internal; - -import java.io.Serializable; -import java.util.AbstractSet; -import java.util.Iterator; -import java.util.concurrent.ConcurrentMap; - -public final class ConcurrentSet extends AbstractSet implements Serializable { - - private static final long serialVersionUID = -6761513279741915432L; - - private final ConcurrentMap map; - - /** - * Creates a new instance which wraps the specified {@code map}. - */ - public ConcurrentSet() { - map = PlatformDependent.newConcurrentHashMap(); - } - - @Override - public int size() { - return map.size(); - } - - @Override - public boolean contains(Object o) { - return map.containsKey(o); - } - - @Override - public boolean add(E o) { - return map.putIfAbsent(o, Boolean.TRUE) == null; - } - - @Override - public boolean remove(Object o) { - return map.remove(o) != null; - } - - @Override - public void clear() { - map.clear(); - } - - @Override - public Iterator iterator() { - return map.keySet().iterator(); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/EmptyArrays.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/EmptyArrays.java deleted file mode 100755 index a23e1e4ae2..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/EmptyArrays.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.util.internal; - -import java.nio.ByteBuffer; -import java.security.cert.Certificate; -import java.security.cert.X509Certificate; - -public final class EmptyArrays { - - public static final byte[] EMPTY_BYTES = new byte[0]; - public static final char[] EMPTY_CHARS = new char[0]; - public static final boolean[] EMPTY_BOOLEANS = new boolean[0]; - public static final double[] EMPTY_DOUBLES = new double[0]; - public static final float[] EMPTY_FLOATS = new float[0]; - public static final int[] EMPTY_INTS = new int[0]; - public static final short[] EMPTY_SHORTS = new short[0]; - public static final long[] EMPTY_LONGS = new long[0]; - public static final Object[] EMPTY_OBJECTS = new Object[0]; - public static final Class[] EMPTY_CLASSES = new Class[0]; - public static final String[] EMPTY_STRINGS = new String[0]; - public static final StackTraceElement[] EMPTY_STACK_TRACE = new StackTraceElement[0]; - public static final ByteBuffer[] EMPTY_BYTE_BUFFERS = new ByteBuffer[0]; - public static final Certificate[] EMPTY_CERTIFICATES = new Certificate[0]; - public static final X509Certificate[] EMPTY_X509_CERTIFICATES = new X509Certificate[0]; - public static final javax.security.cert.X509Certificate[] EMPTY_JAVAX_X509_CERTIFICATES = - new javax.security.cert.X509Certificate[0]; - - private EmptyArrays() { } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/IntegerHolder.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/IntegerHolder.java deleted file mode 100755 index 1334a7126b..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/IntegerHolder.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.util.internal; - -public final class IntegerHolder { - public int value; -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/InternalThreadLocalMap.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/InternalThreadLocalMap.java deleted file mode 100755 index 067c054bd2..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/InternalThreadLocalMap.java +++ /dev/null @@ -1,310 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.util.internal; - -import java.nio.charset.Charset; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CharsetEncoder; -import java.util.Arrays; -import java.util.IdentityHashMap; -import java.util.Map; -import java.util.WeakHashMap; - -import com.ai.cloud.io.netty.util.concurrent.FastThreadLocal; -import com.ai.cloud.io.netty.util.concurrent.FastThreadLocalThread; - -/** - * The internal data structure that stores the thread-local variables for Netty and all {@link FastThreadLocal}s. - * Note that this class is for internal use only and is subject to change at any time. Use {@link FastThreadLocal} - * unless you know what you are doing. - */ -public final class InternalThreadLocalMap extends UnpaddedInternalThreadLocalMap { - - public static final Object UNSET = new Object(); - - public static InternalThreadLocalMap getIfSet() { - Thread thread = Thread.currentThread(); - InternalThreadLocalMap threadLocalMap; - if (thread instanceof FastThreadLocalThread) { - threadLocalMap = ((FastThreadLocalThread) thread).threadLocalMap(); - } else { - ThreadLocal slowThreadLocalMap = UnpaddedInternalThreadLocalMap.slowThreadLocalMap; - if (slowThreadLocalMap == null) { - threadLocalMap = null; - } else { - threadLocalMap = slowThreadLocalMap.get(); - } - } - return threadLocalMap; - } - - public static InternalThreadLocalMap get() { - Thread thread = Thread.currentThread(); - if (thread instanceof FastThreadLocalThread) { - return fastGet((FastThreadLocalThread) thread); - } else { - return slowGet(); - } - } - - private static InternalThreadLocalMap fastGet(FastThreadLocalThread thread) { - InternalThreadLocalMap threadLocalMap = thread.threadLocalMap(); - if (threadLocalMap == null) { - thread.setThreadLocalMap(threadLocalMap = new InternalThreadLocalMap()); - } - return threadLocalMap; - } - - private static InternalThreadLocalMap slowGet() { - ThreadLocal slowThreadLocalMap = UnpaddedInternalThreadLocalMap.slowThreadLocalMap; - if (slowThreadLocalMap == null) { - UnpaddedInternalThreadLocalMap.slowThreadLocalMap = - slowThreadLocalMap = new ThreadLocal(); - } - - InternalThreadLocalMap ret = slowThreadLocalMap.get(); - if (ret == null) { - ret = new InternalThreadLocalMap(); - slowThreadLocalMap.set(ret); - } - return ret; - } - - public static void remove() { - Thread thread = Thread.currentThread(); - if (thread instanceof FastThreadLocalThread) { - ((FastThreadLocalThread) thread).setThreadLocalMap(null); - } else { - ThreadLocal slowThreadLocalMap = UnpaddedInternalThreadLocalMap.slowThreadLocalMap; - if (slowThreadLocalMap != null) { - slowThreadLocalMap.remove(); - } - } - } - - public static void destroy() { - slowThreadLocalMap = null; - } - - public static int nextVariableIndex() { - int index = nextIndex.getAndIncrement(); - if (index < 0) { - nextIndex.decrementAndGet(); - throw new IllegalStateException("too many thread-local indexed variables"); - } - return index; - } - - public static int lastVariableIndex() { - return nextIndex.get() - 1; - } - - // Cache line padding (must be public) - // With CompressedOops enabled, an instance of this class should occupy at least 128 bytes. - public long rp1, rp2, rp3, rp4, rp5, rp6, rp7, rp8, rp9; - - private InternalThreadLocalMap() { - super(newIndexedVariableTable()); - } - - private static Object[] newIndexedVariableTable() { - Object[] array = new Object[32]; - Arrays.fill(array, UNSET); - return array; - } - - public int size() { - int count = 0; - - if (futureListenerStackDepth != 0) { - count ++; - } - if (localChannelReaderStackDepth != 0) { - count ++; - } - if (handlerSharableCache != null) { - count ++; - } - if (counterHashCode != null) { - count ++; - } - if (random != null) { - count ++; - } - if (typeParameterMatcherGetCache != null) { - count ++; - } - if (typeParameterMatcherFindCache != null) { - count ++; - } - if (stringBuilder != null) { - count ++; - } - if (charsetEncoderCache != null) { - count ++; - } - if (charsetDecoderCache != null) { - count ++; - } - - for (Object o: indexedVariables) { - if (o != UNSET) { - count ++; - } - } - - // We should subtract 1 from the count because the first element in 'indexedVariables' is reserved - // by 'FastThreadLocal' to keep the list of 'FastThreadLocal's to remove on 'FastThreadLocal.removeAll()'. - return count - 1; - } - - public StringBuilder stringBuilder() { - StringBuilder builder = stringBuilder; - if (builder == null) { - stringBuilder = builder = new StringBuilder(512); - } else { - builder.setLength(0); - } - return builder; - } - - public Map charsetEncoderCache() { - Map cache = charsetEncoderCache; - if (cache == null) { - charsetEncoderCache = cache = new IdentityHashMap(); - } - return cache; - } - - public Map charsetDecoderCache() { - Map cache = charsetDecoderCache; - if (cache == null) { - charsetDecoderCache = cache = new IdentityHashMap(); - } - return cache; - } - - public int futureListenerStackDepth() { - return futureListenerStackDepth; - } - - public void setFutureListenerStackDepth(int futureListenerStackDepth) { - this.futureListenerStackDepth = futureListenerStackDepth; - } - - public ThreadLocalRandom random() { - ThreadLocalRandom r = random; - if (r == null) { - random = r = new ThreadLocalRandom(); - } - return r; - } - - public Map, TypeParameterMatcher> typeParameterMatcherGetCache() { - Map, TypeParameterMatcher> cache = typeParameterMatcherGetCache; - if (cache == null) { - typeParameterMatcherGetCache = cache = new IdentityHashMap, TypeParameterMatcher>(); - } - return cache; - } - - public Map, Map> typeParameterMatcherFindCache() { - Map, Map> cache = typeParameterMatcherFindCache; - if (cache == null) { - typeParameterMatcherFindCache = cache = new IdentityHashMap, Map>(); - } - return cache; - } - - public IntegerHolder counterHashCode() { - return counterHashCode; - } - - public void setCounterHashCode(IntegerHolder counterHashCode) { - this.counterHashCode = counterHashCode; - } - - public Map, Boolean> handlerSharableCache() { - Map, Boolean> cache = handlerSharableCache; - if (cache == null) { - // Start with small capacity to keep memory overhead as low as possible. - handlerSharableCache = cache = new WeakHashMap, Boolean>(4); - } - return cache; - } - - public int localChannelReaderStackDepth() { - return localChannelReaderStackDepth; - } - - public void setLocalChannelReaderStackDepth(int localChannelReaderStackDepth) { - this.localChannelReaderStackDepth = localChannelReaderStackDepth; - } - - public Object indexedVariable(int index) { - Object[] lookup = indexedVariables; - return index < lookup.length? lookup[index] : UNSET; - } - - /** - * @return {@code true} if and only if a new thread-local variable has been created - */ - public boolean setIndexedVariable(int index, Object value) { - Object[] lookup = indexedVariables; - if (index < lookup.length) { - Object oldValue = lookup[index]; - lookup[index] = value; - return oldValue == UNSET; - } else { - expandIndexedVariableTableAndSet(index, value); - return true; - } - } - - private void expandIndexedVariableTableAndSet(int index, Object value) { - Object[] oldArray = indexedVariables; - final int oldCapacity = oldArray.length; - int newCapacity = index; - newCapacity |= newCapacity >>> 1; - newCapacity |= newCapacity >>> 2; - newCapacity |= newCapacity >>> 4; - newCapacity |= newCapacity >>> 8; - newCapacity |= newCapacity >>> 16; - newCapacity ++; - - Object[] newArray = Arrays.copyOf(oldArray, newCapacity); - Arrays.fill(newArray, oldCapacity, newArray.length, UNSET); - newArray[index] = value; - indexedVariables = newArray; - } - - public Object removeIndexedVariable(int index) { - Object[] lookup = indexedVariables; - if (index < lookup.length) { - Object v = lookup[index]; - lookup[index] = UNSET; - return v; - } else { - return UNSET; - } - } - - public boolean isIndexedVariableSet(int index) { - Object[] lookup = indexedVariables; - return index < lookup.length && lookup[index] != UNSET; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/JavassistTypeParameterMatcherGenerator.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/JavassistTypeParameterMatcherGenerator.java deleted file mode 100755 index 94ac9c657b..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/JavassistTypeParameterMatcherGenerator.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.util.internal; - -import javassist.ClassClassPath; -import javassist.ClassPath; -import javassist.ClassPool; -import javassist.CtClass; -import javassist.Modifier; -import javassist.NotFoundException; - -import java.lang.reflect.Method; - -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -public final class JavassistTypeParameterMatcherGenerator { - - private static final InternalLogger logger = - InternalLoggerFactory.getInstance(JavassistTypeParameterMatcherGenerator.class); - - private static final ClassPool classPool = new ClassPool(true); - - static { - classPool.appendClassPath(new ClassClassPath(NoOpTypeParameterMatcher.class)); - } - - public static void appendClassPath(ClassPath classpath) { - classPool.appendClassPath(classpath); - } - - public static void appendClassPath(String pathname) throws NotFoundException { - classPool.appendClassPath(pathname); - } - - public static TypeParameterMatcher generate(Class type) { - ClassLoader classLoader = PlatformDependent.getContextClassLoader(); - if (classLoader == null) { - classLoader = PlatformDependent.getSystemClassLoader(); - } - return generate(type, classLoader); - } - - public static TypeParameterMatcher generate(Class type, ClassLoader classLoader) { - final String typeName = typeName(type); - final String className = "io.netty.util.internal.__matchers__." + typeName + "Matcher"; - try { - try { - return (TypeParameterMatcher) Class.forName(className, true, classLoader).newInstance(); - } catch (Exception e) { - // Not defined in the specified class loader. - } - - CtClass c = classPool.getAndRename(NoOpTypeParameterMatcher.class.getName(), className); - c.setModifiers(c.getModifiers() | Modifier.FINAL); - c.getDeclaredMethod("match").setBody("{ return $1 instanceof " + typeName + "; }"); - byte[] byteCode = c.toBytecode(); - c.detach(); - Method method = ClassLoader.class.getDeclaredMethod( - "defineClass", String.class, byte[].class, int.class, int.class); - method.setAccessible(true); - - Class generated = (Class) method.invoke(classLoader, className, byteCode, 0, byteCode.length); - if (type != Object.class) { - logger.debug("Generated: {}", generated.getName()); - } else { - // Object.class is only used when checking if Javassist is available. - } - return (TypeParameterMatcher) generated.newInstance(); - } catch (RuntimeException e) { - throw e; - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - private static String typeName(Class type) { - if (type.isArray()) { - return typeName(type.getComponentType()) + "[]"; - } - - return type.getName(); - } - - private JavassistTypeParameterMatcherGenerator() { } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/LongCounter.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/LongCounter.java deleted file mode 100755 index b70c58e366..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/LongCounter.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.internal; - -/** - * Counter for long. - */ -public interface LongCounter { - void add(long delta); - void increment(); - void decrement(); - long value(); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/MathUtil.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/MathUtil.java deleted file mode 100755 index 7245da1e43..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/MathUtil.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, version 2.0 (the - * "License"); you may not use this file except in compliance with the License. You may obtain a - * copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package com.ai.cloud.io.netty.util.internal; - -/** - * Math utility methods. - */ -public final class MathUtil { - - private MathUtil() { - } - - /** - * Fast method of finding the next power of 2 greater than or equal to the supplied value. - * - * If the value is {@code <= 0} then 1 will be returned. - * - * This method is not suitable for {@link Integer#MIN_VALUE} or numbers greater than 2^30. - * - * @param value from which to search for next power of 2 - * @return The next power of 2 or the value itself if it is a power of 2 - */ - public static int findNextPositivePowerOfTwo(final int value) { - assert value > Integer.MIN_VALUE && value < 0x40000000; - return 1 << (32 - Integer.numberOfLeadingZeros(value - 1)); - } - - /** - * Determine if the requested {@code index} and {@code length} will fit within {@code capacity}. - * @param index The starting index. - * @param length The length which will be utilized (starting from {@code index}). - * @param capacity The capacity that {@code index + length} is allowed to be within. - * @return {@code true} if the requested {@code index} and {@code length} will fit within {@code capacity}. - * {@code false} if this would result in an index out of bounds exception. - */ - public static boolean isOutOfBounds(int index, int length, int capacity) { - return (index | length | (index + length) | (capacity - (index + length))) < 0; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/MpscArrayQueue.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/MpscArrayQueue.java deleted file mode 100755 index 0e7218d1c5..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/MpscArrayQueue.java +++ /dev/null @@ -1,331 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.ai.cloud.io.netty.util.internal; - -/** - * Forked from JCTools. - * - * A Multi-Producer-Single-Consumer queue based on a {@link ConcurrentCircularArrayQueue}. This implies that - * any thread may call the offer method, but only a single thread may call poll/peek for correctness to - * maintained.
- * This implementation follows patterns documented on the package level for False Sharing protection.
- * This implementation is using the Fast Flow - * method for polling from the queue (with minor change to correctly publish the index) and an extension of - * the Leslie Lamport concurrent queue algorithm (originated by Martin Thompson) on the producer side.
- * - * @param - */ -final class MpscArrayQueue extends MpscArrayQueueConsumerField { - long p40, p41, p42, p43, p44, p45, p46; - long p30, p31, p32, p33, p34, p35, p36, p37; - - public MpscArrayQueue(final int capacity) { - super(capacity); - } - - /** - * {@inheritDoc}
- * - * IMPLEMENTATION NOTES:
- * Lock free offer using a single CAS. As class name suggests access is permitted to many threads - * concurrently. - * - * @see java.util.Queue#offer(java.lang.Object) - */ - @Override - public boolean offer(final E e) { - if (null == e) { - throw new NullPointerException("Null is not a valid element"); - } - - // use a cached view on consumer index (potentially updated in loop) - final long mask = this.mask; - final long capacity = mask + 1; - long consumerIndexCache = lvConsumerIndexCache(); // LoadLoad - long currentProducerIndex; - do { - currentProducerIndex = lvProducerIndex(); // LoadLoad - final long wrapPoint = currentProducerIndex - capacity; - if (consumerIndexCache <= wrapPoint) { - final long currHead = lvConsumerIndex(); // LoadLoad - if (currHead <= wrapPoint) { - return false; // FULL :( - } else { - // update shared cached value of the consumerIndex - svConsumerIndexCache(currHead); // StoreLoad - // update on stack copy, we might need this value again if we lose the CAS. - consumerIndexCache = currHead; - } - } - } while (!casProducerIndex(currentProducerIndex, currentProducerIndex + 1)); - /* - * NOTE: the new producer index value is made visible BEFORE the element in the array. If we relied on - * the index visibility to poll() we would need to handle the case where the element is not visible. - */ - - // Won CAS, move on to storing - final long offset = calcElementOffset(currentProducerIndex, mask); - soElement(offset, e); // StoreStore - return true; // AWESOME :) - } - - /** - * A wait free alternative to offer which fails on CAS failure. - * - * @param e new element, not null - * @return 1 if next element cannot be filled, -1 if CAS failed, 0 if successful - */ - public int weakOffer(final E e) { - if (null == e) { - throw new NullPointerException("Null is not a valid element"); - } - final long mask = this.mask; - final long capacity = mask + 1; - final long currentTail = lvProducerIndex(); // LoadLoad - final long consumerIndexCache = lvConsumerIndexCache(); // LoadLoad - final long wrapPoint = currentTail - capacity; - if (consumerIndexCache <= wrapPoint) { - long currHead = lvConsumerIndex(); // LoadLoad - if (currHead <= wrapPoint) { - return 1; // FULL :( - } else { - svConsumerIndexCache(currHead); // StoreLoad - } - } - - // look Ma, no loop! - if (!casProducerIndex(currentTail, currentTail + 1)) { - return -1; // CAS FAIL :( - } - - // Won CAS, move on to storing - final long offset = calcElementOffset(currentTail, mask); - soElement(offset, e); - return 0; // AWESOME :) - } - - /** - * {@inheritDoc} - *

- * IMPLEMENTATION NOTES:
- * Lock free poll using ordered loads/stores. As class name suggests access is limited to a single thread. - * - * @see java.util.Queue#poll() - */ - @Override - public E poll() { - final long consumerIndex = lvConsumerIndex(); // LoadLoad - final long offset = calcElementOffset(consumerIndex); - // Copy field to avoid re-reading after volatile load - final E[] buffer = this.buffer; - - // If we can't see the next available element we can't poll - E e = lvElement(buffer, offset); // LoadLoad - if (null == e) { - /* - * NOTE: Queue may not actually be empty in the case of a producer (P1) being interrupted after - * winning the CAS on offer but before storing the element in the queue. Other producers may go on - * to fill up the queue after this element. - */ - if (consumerIndex != lvProducerIndex()) { - do { - e = lvElement(buffer, offset); - } while (e == null); - } else { - return null; - } - } - - spElement(buffer, offset, null); - soConsumerIndex(consumerIndex + 1); // StoreStore - return e; - } - - /** - * {@inheritDoc} - *

- * IMPLEMENTATION NOTES:
- * Lock free peek using ordered loads. As class name suggests access is limited to a single thread. - * - * @see java.util.Queue#poll() - */ - @Override - public E peek() { - // Copy field to avoid re-reading after volatile load - final E[] buffer = this.buffer; - - final long consumerIndex = lvConsumerIndex(); // LoadLoad - final long offset = calcElementOffset(consumerIndex); - E e = lvElement(buffer, offset); - if (null == e) { - /* - * NOTE: Queue may not actually be empty in the case of a producer (P1) being interrupted after - * winning the CAS on offer but before storing the element in the queue. Other producers may go on - * to fill up the queue after this element. - */ - if (consumerIndex != lvProducerIndex()) { - do { - e = lvElement(buffer, offset); - } while (e == null); - } else { - return null; - } - } - return e; - } - - /** - * {@inheritDoc} - *

- * - */ - @Override - public int size() { - /* - * It is possible for a thread to be interrupted or reschedule between the read of the producer and - * consumer indices, therefore protection is required to ensure size is within valid range. In the - * event of concurrent polls/offers to this method the size is OVER estimated as we read consumer - * index BEFORE the producer index. - */ - long after = lvConsumerIndex(); - while (true) { - final long before = after; - final long currentProducerIndex = lvProducerIndex(); - after = lvConsumerIndex(); - if (before == after) { - return (int) (currentProducerIndex - after); - } - } - } - - @Override - public boolean isEmpty() { - // Order matters! - // Loading consumer before producer allows for producer increments after consumer index is read. - // This ensures the correctness of this method at least for the consumer thread. Other threads POV is - // not really - // something we can fix here. - return lvConsumerIndex() == lvProducerIndex(); - } -} - -abstract class MpscArrayQueueL1Pad extends ConcurrentCircularArrayQueue { - long p10, p11, p12, p13, p14, p15, p16; - long p30, p31, p32, p33, p34, p35, p36, p37; - - public MpscArrayQueueL1Pad(int capacity) { - super(capacity); - } -} - -abstract class MpscArrayQueueTailField extends MpscArrayQueueL1Pad { - private static final long P_INDEX_OFFSET; - - static { - try { - P_INDEX_OFFSET = PlatformDependent0.UNSAFE.objectFieldOffset(MpscArrayQueueTailField.class - .getDeclaredField("producerIndex")); - } catch (NoSuchFieldException e) { - throw new RuntimeException(e); - } - } - private volatile long producerIndex; - - public MpscArrayQueueTailField(int capacity) { - super(capacity); - } - - protected final long lvProducerIndex() { - return producerIndex; - } - - protected final boolean casProducerIndex(long expect, long newValue) { - return PlatformDependent0.UNSAFE.compareAndSwapLong(this, P_INDEX_OFFSET, expect, newValue); - } -} - -abstract class MpscArrayQueueMidPad extends MpscArrayQueueTailField { - long p20, p21, p22, p23, p24, p25, p26; - long p30, p31, p32, p33, p34, p35, p36, p37; - - public MpscArrayQueueMidPad(int capacity) { - super(capacity); - } -} - -abstract class MpscArrayQueueHeadCacheField extends MpscArrayQueueMidPad { - private volatile long headCache; - - public MpscArrayQueueHeadCacheField(int capacity) { - super(capacity); - } - - protected final long lvConsumerIndexCache() { - return headCache; - } - - protected final void svConsumerIndexCache(long v) { - headCache = v; - } -} - -abstract class MpscArrayQueueL2Pad extends MpscArrayQueueHeadCacheField { - long p20, p21, p22, p23, p24, p25, p26; - long p30, p31, p32, p33, p34, p35, p36, p37; - - public MpscArrayQueueL2Pad(int capacity) { - super(capacity); - } -} - -abstract class MpscArrayQueueConsumerField extends MpscArrayQueueL2Pad { - private static final long C_INDEX_OFFSET; - static { - try { - C_INDEX_OFFSET = PlatformDependent0.UNSAFE.objectFieldOffset(MpscArrayQueueConsumerField.class - .getDeclaredField("consumerIndex")); - } catch (NoSuchFieldException e) { - throw new RuntimeException(e); - } - } - private volatile long consumerIndex; - - public MpscArrayQueueConsumerField(int capacity) { - super(capacity); - } - - protected final long lvConsumerIndex() { - return consumerIndex; - } - - protected void soConsumerIndex(long l) { - PlatformDependent0.UNSAFE.putOrderedLong(this, C_INDEX_OFFSET, l); - } -} - diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/MpscLinkedQueue.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/MpscLinkedQueue.java deleted file mode 100755 index f927bb2e05..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/MpscLinkedQueue.java +++ /dev/null @@ -1,378 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -/** - * Copyright (C) 2009-2013 Typesafe Inc. - */ -package com.ai.cloud.io.netty.util.internal; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.Queue; - -/** - * A lock-free concurrent single-consumer multi-producer {@link Queue}. - * It allows multiple producer threads to perform the following operations simultaneously: - *

    - *
  • {@link #offer(Object)}, {@link #add(Object)}, {@link #addAll(Collection)}
  • - *
  • {@link #isEmpty()}
  • - *
- * .. while only one consumer thread is allowed to perform the following operations exclusively: - *
    - *
  • {@link #poll()} and {@link #remove()}
  • - *
  • {@link #element()}, {@link #peek()}
  • - *
  • {@link #remove(Object)}, {@link #removeAll(Collection)}, and {@link #retainAll(Collection)}
  • - *
  • {@link #clear()}
  • {@link #} - *
  • {@link #iterator()}
  • - *
  • {@link #toArray()} and {@link #toArray(Object[])}
  • - *
  • {@link #contains(Object)} and {@link #containsAll(Collection)}
  • - *
  • {@link #size()}
  • - *
- * - * The behavior of this implementation is undefined if you perform the operations for a consumer thread only - * from multiple threads. - * - * The initial implementation is based on: - * - * and adopted padded head node changes from: - * - * data structure modified to avoid false sharing between head and tail Ref as per implementation of MpscLinkedQueue - * on JCTools project. - */ -final class MpscLinkedQueue extends MpscLinkedQueueTailRef implements Queue { - - private static final long serialVersionUID = -1878402552271506449L; - - long p00, p01, p02, p03, p04, p05, p06, p07; - long p30, p31, p32, p33, p34, p35, p36, p37; - - // offer() occurs at the tail of the linked list. - // poll() occurs at the head of the linked list. - // - // Resulting layout is: - // - // head --next--> 1st element --next--> 2nd element --next--> ... tail (last element) - // - // where the head is a dummy node whose value is null. - // - // offer() appends a new node next to the tail using AtomicReference.getAndSet() - // poll() removes head from the linked list and promotes the 1st element to the head, - // setting its value to null if possible. - // - // Also note that this class extends AtomicReference for the "tail" slot (which is the one that is appended to) - // since Unsafe does not expose XCHG operation intrinsically. - MpscLinkedQueue() { - MpscLinkedQueueNode tombstone = new DefaultNode(null); - setHeadRef(tombstone); - setTailRef(tombstone); - } - - /** - * Returns the node right next to the head, which contains the first element of this queue. - */ - private MpscLinkedQueueNode peekNode() { - MpscLinkedQueueNode head = headRef(); - MpscLinkedQueueNode next = head.next(); - if (next == null && head != tailRef()) { - // if tail != head this is not going to change until consumer makes progress - // we can avoid reading the head and just spin on next until it shows up - // - // See https://github.com/akka/akka/pull/15596 - do { - next = head.next(); - } while (next == null); - } - return next; - } - - @Override - @SuppressWarnings("unchecked") - public boolean offer(E value) { - if (value == null) { - throw new NullPointerException("value"); - } - - final MpscLinkedQueueNode newTail; - if (value instanceof MpscLinkedQueueNode) { - newTail = (MpscLinkedQueueNode) value; - newTail.setNext(null); - } else { - newTail = new DefaultNode(value); - } - - MpscLinkedQueueNode oldTail = getAndSetTailRef(newTail); - oldTail.setNext(newTail); - return true; - } - - @Override - public E poll() { - final MpscLinkedQueueNode next = peekNode(); - if (next == null) { - return null; - } - - // next becomes a new head. - MpscLinkedQueueNode oldHead = headRef(); - // Similar to 'headRef.node = next', but slightly faster (storestore vs loadstore) - // See: http://robsjava.blogspot.com/2013/06/a-faster-volatile.html - // See: http://psy-lob-saw.blogspot.com/2012/12/atomiclazyset-is-performance-win-for.html - lazySetHeadRef(next); - - // Break the linkage between the old head and the new head. - oldHead.unlink(); - - return next.clearMaybe(); - } - - @Override - public E peek() { - final MpscLinkedQueueNode next = peekNode(); - if (next == null) { - return null; - } - return next.value(); - } - - @Override - public int size() { - int count = 0; - MpscLinkedQueueNode n = peekNode(); - for (;;) { - // If value == null it means that clearMaybe() was called on the MpscLinkedQueueNode. - if (n == null || n.value() == null) { - break; - } - MpscLinkedQueueNode next = n.next(); - if (n == next) { - break; - } - n = next; - if (++ count == Integer.MAX_VALUE) { - // Guard against overflow of integer. - break; - } - } - return count; - } - - @Override - public boolean isEmpty() { - return headRef() == tailRef(); - } - - @Override - public boolean contains(Object o) { - MpscLinkedQueueNode n = peekNode(); - for (;;) { - if (n == null) { - break; - } - E value = n.value(); - // If value == null it means that clearMaybe() was called on the MpscLinkedQueueNode. - if (value == null) { - return false; - } - if (value == o) { - return true; - } - MpscLinkedQueueNode next = n.next(); - if (n == next) { - break; - } - n = next; - } - return false; - } - - @Override - public Iterator iterator() { - return new ReadOnlyIterator(toList().iterator()); - } - - @Override - public boolean add(E e) { - if (offer(e)) { - return true; - } - throw new IllegalStateException("queue full"); - } - - @Override - public E remove() { - E e = poll(); - if (e != null) { - return e; - } - throw new NoSuchElementException(); - } - - @Override - public E element() { - E e = peek(); - if (e != null) { - return e; - } - throw new NoSuchElementException(); - } - - private List toList(int initialCapacity) { - return toList(new ArrayList(initialCapacity)); - } - - private List toList() { - return toList(new ArrayList()); - } - - private List toList(List elements) { - MpscLinkedQueueNode n = peekNode(); - for (;;) { - if (n == null) { - break; - } - E value = n.value(); - if (value == null) { - break; - } - if (!elements.add(value)) { - // Seems like there is no space left, break here. - break; - } - MpscLinkedQueueNode next = n.next(); - if (n == next) { - break; - } - n = next; - } - return elements; - } - - @Override - public Object[] toArray() { - return toList().toArray(); - } - - @Override - @SuppressWarnings("unchecked") - public T[] toArray(T[] a) { - return toList(a.length).toArray(a); - } - - @Override - public boolean remove(Object o) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean containsAll(Collection c) { - for (Object e: c) { - if (!contains(e)) { - return false; - } - } - return true; - } - - @Override - public boolean addAll(Collection c) { - if (c == null) { - throw new NullPointerException("c"); - } - if (c == this) { - throw new IllegalArgumentException("c == this"); - } - - boolean modified = false; - for (E e: c) { - add(e); - modified = true; - } - return modified; - } - - @Override - public boolean removeAll(Collection c) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean retainAll(Collection c) { - throw new UnsupportedOperationException(); - } - - @Override - public void clear() { - while (poll() != null) { - continue; - } - } - - private void writeObject(ObjectOutputStream out) throws IOException { - out.defaultWriteObject(); - for (E e: this) { - out.writeObject(e); - } - out.writeObject(null); - } - - private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { - in.defaultReadObject(); - - final MpscLinkedQueueNode tombstone = new DefaultNode(null); - setHeadRef(tombstone); - setTailRef(tombstone); - - for (;;) { - @SuppressWarnings("unchecked") - E e = (E) in.readObject(); - if (e == null) { - break; - } - add(e); - } - } - - private static final class DefaultNode extends MpscLinkedQueueNode { - - private T value; - - DefaultNode(T value) { - this.value = value; - } - - @Override - public T value() { - return value; - } - - @Override - protected T clearMaybe() { - T value = this.value; - this.value = null; - return value; - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/MpscLinkedQueueHeadRef.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/MpscLinkedQueueHeadRef.java deleted file mode 100755 index 3ea8a4bf14..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/MpscLinkedQueueHeadRef.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.util.internal; - -import java.io.Serializable; -import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; - - -abstract class MpscLinkedQueueHeadRef extends MpscLinkedQueuePad0 implements Serializable { - - private static final long serialVersionUID = 8467054865577874285L; - - @SuppressWarnings("rawtypes") - private static final AtomicReferenceFieldUpdater UPDATER; - - static { - @SuppressWarnings("rawtypes") - AtomicReferenceFieldUpdater updater; - updater = PlatformDependent.newAtomicReferenceFieldUpdater(MpscLinkedQueueHeadRef.class, "headRef"); - if (updater == null) { - updater = AtomicReferenceFieldUpdater.newUpdater( - MpscLinkedQueueHeadRef.class, MpscLinkedQueueNode.class, "headRef"); - } - UPDATER = updater; - } - - private transient volatile MpscLinkedQueueNode headRef; - - protected final MpscLinkedQueueNode headRef() { - return headRef; - } - - protected final void setHeadRef(MpscLinkedQueueNode headRef) { - this.headRef = headRef; - } - - protected final void lazySetHeadRef(MpscLinkedQueueNode headRef) { - UPDATER.lazySet(this, headRef); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/MpscLinkedQueueNode.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/MpscLinkedQueueNode.java deleted file mode 100755 index 5cf527d152..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/MpscLinkedQueueNode.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.util.internal; - -import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; - -public abstract class MpscLinkedQueueNode { - - @SuppressWarnings("rawtypes") - private static final AtomicReferenceFieldUpdater nextUpdater; - - static { - @SuppressWarnings("rawtypes") - AtomicReferenceFieldUpdater u; - - u = PlatformDependent.newAtomicReferenceFieldUpdater(MpscLinkedQueueNode.class, "next"); - if (u == null) { - u = AtomicReferenceFieldUpdater.newUpdater(MpscLinkedQueueNode.class, MpscLinkedQueueNode.class, "next"); - } - nextUpdater = u; - } - - @SuppressWarnings("unused") - private volatile MpscLinkedQueueNode next; - - final MpscLinkedQueueNode next() { - return next; - } - - final void setNext(final MpscLinkedQueueNode newNext) { - // Similar to 'next = newNext', but slightly faster (storestore vs loadstore) - // See: http://robsjava.blogspot.com/2013/06/a-faster-volatile.html - nextUpdater.lazySet(this, newNext); - } - - public abstract T value(); - - /** - * Sets the element this node contains to {@code null} so that the node can be used as a tombstone. - */ - protected T clearMaybe() { - return value(); - } - - /** - * Unlink to allow GC'ed - */ - void unlink() { - setNext(null); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/MpscLinkedQueuePad0.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/MpscLinkedQueuePad0.java deleted file mode 100755 index 01f0ada295..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/MpscLinkedQueuePad0.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.util.internal; - -abstract class MpscLinkedQueuePad0 { - long p00, p01, p02, p03, p04, p05, p06, p07; - long p30, p31, p32, p33, p34, p35, p36, p37; -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/MpscLinkedQueuePad1.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/MpscLinkedQueuePad1.java deleted file mode 100755 index ba8dee93af..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/MpscLinkedQueuePad1.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.util.internal; - -abstract class MpscLinkedQueuePad1 extends MpscLinkedQueueHeadRef { - - private static final long serialVersionUID = 2886694927079691637L; - - long p00, p01, p02, p03, p04, p05, p06, p07; - long p30, p31, p32, p33, p34, p35, p36, p37; -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/MpscLinkedQueueTailRef.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/MpscLinkedQueueTailRef.java deleted file mode 100755 index 2927e91f8e..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/MpscLinkedQueueTailRef.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.util.internal; - -import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; - -abstract class MpscLinkedQueueTailRef extends MpscLinkedQueuePad1 { - - private static final long serialVersionUID = 8717072462993327429L; - - @SuppressWarnings("rawtypes") - private static final AtomicReferenceFieldUpdater UPDATER; - - static { - @SuppressWarnings("rawtypes") - AtomicReferenceFieldUpdater updater; - updater = PlatformDependent.newAtomicReferenceFieldUpdater(MpscLinkedQueueTailRef.class, "tailRef"); - if (updater == null) { - updater = AtomicReferenceFieldUpdater.newUpdater( - MpscLinkedQueueTailRef.class, MpscLinkedQueueNode.class, "tailRef"); - } - UPDATER = updater; - } - - private transient volatile MpscLinkedQueueNode tailRef; - - protected final MpscLinkedQueueNode tailRef() { - return tailRef; - } - - protected final void setTailRef(MpscLinkedQueueNode tailRef) { - this.tailRef = tailRef; - } - - @SuppressWarnings("unchecked") - protected final MpscLinkedQueueNode getAndSetTailRef(MpscLinkedQueueNode tailRef) { - // LOCK XCHG in JDK8, a CAS loop in JDK 7/6 - return (MpscLinkedQueueNode) UPDATER.getAndSet(this, tailRef); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/NativeLibraryLoader.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/NativeLibraryLoader.java deleted file mode 100755 index a6fc843457..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/NativeLibraryLoader.java +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.internal; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.URL; -import java.util.Locale; - -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * Helper class to load JNI resources. - * - */ -public final class NativeLibraryLoader { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(NativeLibraryLoader.class); - - private static final String NATIVE_RESOURCE_HOME = "META-INF/native/"; - private static final String OSNAME; - private static final File WORKDIR; - - static { - OSNAME = SystemPropertyUtil.get("os.name", "").toLowerCase(Locale.US).replaceAll("[^a-z0-9]+", ""); - - String workdir = SystemPropertyUtil.get("io.netty.native.workdir"); - if (workdir != null) { - File f = new File(workdir); - f.mkdirs(); - - try { - f = f.getAbsoluteFile(); - } catch (Exception ignored) { - // Good to have an absolute path, but it's OK. - } - - WORKDIR = f; - logger.debug("-Dio.netty.native.workdir: " + WORKDIR); - } else { - WORKDIR = tmpdir(); - logger.debug("-Dio.netty.native.workdir: " + WORKDIR + " (io.netty.tmpdir)"); - } - } - - private static File tmpdir() { - File f; - try { - f = toDirectory(SystemPropertyUtil.get("io.netty.tmpdir")); - if (f != null) { - logger.debug("-Dio.netty.tmpdir: " + f); - return f; - } - - f = toDirectory(SystemPropertyUtil.get("java.io.tmpdir")); - if (f != null) { - logger.debug("-Dio.netty.tmpdir: " + f + " (java.io.tmpdir)"); - return f; - } - - // This shouldn't happen, but just in case .. - if (isWindows()) { - f = toDirectory(System.getenv("TEMP")); - if (f != null) { - logger.debug("-Dio.netty.tmpdir: " + f + " (%TEMP%)"); - return f; - } - - String userprofile = System.getenv("USERPROFILE"); - if (userprofile != null) { - f = toDirectory(userprofile + "\\AppData\\Local\\Temp"); - if (f != null) { - logger.debug("-Dio.netty.tmpdir: " + f + " (%USERPROFILE%\\AppData\\Local\\Temp)"); - return f; - } - - f = toDirectory(userprofile + "\\Local Settings\\Temp"); - if (f != null) { - logger.debug("-Dio.netty.tmpdir: " + f + " (%USERPROFILE%\\Local Settings\\Temp)"); - return f; - } - } - } else { - f = toDirectory(System.getenv("TMPDIR")); - if (f != null) { - logger.debug("-Dio.netty.tmpdir: " + f + " ($TMPDIR)"); - return f; - } - } - } catch (Exception ignored) { - // Environment variable inaccessible - } - - // Last resort. - if (isWindows()) { - f = new File("C:\\Windows\\Temp"); - } else { - f = new File("/tmp"); - } - - logger.warn("Failed to get the temporary directory; falling back to: " + f); - return f; - } - - @SuppressWarnings("ResultOfMethodCallIgnored") - private static File toDirectory(String path) { - if (path == null) { - return null; - } - - File f = new File(path); - f.mkdirs(); - - if (!f.isDirectory()) { - return null; - } - - try { - return f.getAbsoluteFile(); - } catch (Exception ignored) { - return f; - } - } - - private static boolean isWindows() { - return OSNAME.startsWith("windows"); - } - - private static boolean isOSX() { - return OSNAME.startsWith("macosx") || OSNAME.startsWith("osx"); - } - - /** - * Load the given library with the specified {@link java.lang.ClassLoader} - */ - public static void load(String name, ClassLoader loader) { - String libname = System.mapLibraryName(name); - String path = NATIVE_RESOURCE_HOME + libname; - - URL url = loader.getResource(path); - if (url == null && isOSX()) { - if (path.endsWith(".jnilib")) { - url = loader.getResource(NATIVE_RESOURCE_HOME + "lib" + name + ".dynlib"); - } else { - url = loader.getResource(NATIVE_RESOURCE_HOME + "lib" + name + ".jnilib"); - } - } - - if (url == null) { - // Fall back to normal loading of JNI stuff - System.loadLibrary(name); - return; - } - - int index = libname.lastIndexOf('.'); - String prefix = libname.substring(0, index); - String suffix = libname.substring(index, libname.length()); - InputStream in = null; - OutputStream out = null; - File tmpFile = null; - boolean loaded = false; - try { - tmpFile = File.createTempFile(prefix, suffix, WORKDIR); - in = url.openStream(); - out = new FileOutputStream(tmpFile); - - byte[] buffer = new byte[8192]; - int length; - while ((length = in.read(buffer)) > 0) { - out.write(buffer, 0, length); - } - out.flush(); - out.close(); - out = null; - - System.load(tmpFile.getPath()); - loaded = true; - } catch (Exception e) { - throw (UnsatisfiedLinkError) new UnsatisfiedLinkError( - "could not load a native library: " + name).initCause(e); - } finally { - if (in != null) { - try { - in.close(); - } catch (IOException ignore) { - // ignore - } - } - if (out != null) { - try { - out.close(); - } catch (IOException ignore) { - // ignore - } - } - if (tmpFile != null) { - if (loaded) { - tmpFile.deleteOnExit(); - } else { - if (!tmpFile.delete()) { - tmpFile.deleteOnExit(); - } - } - } - } - } - - private NativeLibraryLoader() { - // Utility - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/NoOpTypeParameterMatcher.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/NoOpTypeParameterMatcher.java deleted file mode 100755 index 6c415e0a4f..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/NoOpTypeParameterMatcher.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.util.internal; - -public final class NoOpTypeParameterMatcher extends TypeParameterMatcher { - @Override - public boolean match(Object msg) { - return true; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/ObjectUtil.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/ObjectUtil.java deleted file mode 100755 index c191d5e723..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/ObjectUtil.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, version 2.0 (the - * "License"); you may not use this file except in compliance with the License. You may obtain a - * copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package com.ai.cloud.io.netty.util.internal; - -/** - * A grab-bag of useful utility methods. - */ -public final class ObjectUtil { - - private ObjectUtil() { - } - - /** - * Checks that the given argument is not null. If it is, throws {@link NullPointerException}. - * Otherwise, returns the argument. - */ - public static T checkNotNull(T arg, String text) { - if (arg == null) { - throw new NullPointerException(text); - } - return arg; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/OneTimeTask.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/OneTimeTask.java deleted file mode 100755 index 8d363f92c2..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/OneTimeTask.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.internal; - -import com.ai.cloud.io.netty.util.concurrent.EventExecutor; - -/** - * {@link Runnable} which represent a one time task which may allow the {@link EventExecutor} to reduce the amount of - * produced garbage when queue it for execution. - * - * It is important this will not be reused. After submitted it is not allowed to get submitted again! - */ -public abstract class OneTimeTask extends MpscLinkedQueueNode implements Runnable { - - @Override - public Runnable value() { - return this; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/PendingWrite.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/PendingWrite.java deleted file mode 100755 index 7eb173b881..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/PendingWrite.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.internal; - -import com.ai.cloud.io.netty.util.Recycler; -import com.ai.cloud.io.netty.util.ReferenceCountUtil; -import com.ai.cloud.io.netty.util.concurrent.Promise; - -/** - * Some pending write which should be picked up later. - */ -public final class PendingWrite { - private static final Recycler RECYCLER = new Recycler() { - @Override - protected PendingWrite newObject(Handle handle) { - return new PendingWrite(handle); - } - }; - - /** - * Create a new empty {@link RecyclableArrayList} instance - */ - public static PendingWrite newInstance(Object msg, Promise promise) { - PendingWrite pending = RECYCLER.get(); - pending.msg = msg; - pending.promise = promise; - return pending; - } - - private final Recycler.Handle handle; - private Object msg; - private Promise promise; - - private PendingWrite(Recycler.Handle handle) { - this.handle = handle; - } - - /** - * Clear and recycle this instance. - */ - public boolean recycle() { - msg = null; - promise = null; - return RECYCLER.recycle(this, handle); - } - - /** - * Fails the underlying {@link Promise} with the given cause and reycle this instance. - */ - public boolean failAndRecycle(Throwable cause) { - ReferenceCountUtil.release(msg); - if (promise != null) { - promise.setFailure(cause); - } - return recycle(); - } - - /** - * Mark the underlying {@link Promise} successed and reycle this instance. - */ - public boolean successAndRecycle() { - if (promise != null) { - promise.setSuccess(null); - } - return recycle(); - } - - public Object msg() { - return msg; - } - - public Promise promise() { - return promise; - } - - /** - * Recycle this instance and return the {@link Promise}. - */ - public Promise recycleAndGet() { - Promise promise = this.promise; - recycle(); - return promise; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/PlatformDependent.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/PlatformDependent.java deleted file mode 100755 index 8dd56721c7..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/PlatformDependent.java +++ /dev/null @@ -1,958 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.internal; - -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.net.InetSocketAddress; -import java.net.ServerSocket; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.Deque; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Queue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedDeque; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.LinkedBlockingDeque; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.atomic.AtomicLongFieldUpdater; -import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import com.ai.cloud.io.netty.util.CharsetUtil; -import com.ai.cloud.io.netty.util.internal.chmv8.ConcurrentHashMapV8; -import com.ai.cloud.io.netty.util.internal.chmv8.LongAdderV8; -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - - -/** - * Utility that detects various properties specific to the current runtime - * environment, such as Java version and the availability of the - * {@code sun.misc.Unsafe} object. - *

- * You can disable the use of {@code sun.misc.Unsafe} if you specify - * the system property io.netty.noUnsafe. - */ -public final class PlatformDependent { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(PlatformDependent.class); - - private static final Pattern MAX_DIRECT_MEMORY_SIZE_ARG_PATTERN = Pattern.compile( - "\\s*-XX:MaxDirectMemorySize\\s*=\\s*([0-9]+)\\s*([kKmMgG]?)\\s*$"); - - private static final boolean IS_ANDROID = isAndroid0(); - private static final boolean IS_WINDOWS = isWindows0(); - private static volatile Boolean IS_ROOT; - - private static final int JAVA_VERSION = javaVersion0(); - - private static final boolean CAN_ENABLE_TCP_NODELAY_BY_DEFAULT = !isAndroid(); - - private static final boolean HAS_UNSAFE = hasUnsafe0(); - private static final boolean CAN_USE_CHM_V8 = HAS_UNSAFE && JAVA_VERSION < 8; - private static final boolean DIRECT_BUFFER_PREFERRED = - HAS_UNSAFE && !SystemPropertyUtil.getBoolean("io.netty.noPreferDirect", false); - private static final long MAX_DIRECT_MEMORY = maxDirectMemory0(); - - private static final long ARRAY_BASE_OFFSET = arrayBaseOffset0(); - - private static final boolean HAS_JAVASSIST = hasJavassist0(); - - private static final File TMPDIR = tmpdir0(); - - private static final int BIT_MODE = bitMode0(); - - private static final int ADDRESS_SIZE = addressSize0(); - private static final boolean NATIVE_ORDER = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN; - - static { - if (logger.isDebugEnabled()) { - logger.debug("-Dio.netty.noPreferDirect: {}", !DIRECT_BUFFER_PREFERRED); - } - - if (!hasUnsafe() && !isAndroid()) { - logger.info( - "Your platform does not provide complete low-level API for accessing direct buffers reliably. " + - "Unless explicitly requested, heap buffer will always be preferred to avoid potential system " + - "unstability."); - } - } - - /** - * Returns {@code true} if and only if the current platform is Android - */ - public static boolean isAndroid() { - return IS_ANDROID; - } - - /** - * Return {@code true} if the JVM is running on Windows - */ - public static boolean isWindows() { - return IS_WINDOWS; - } - - /** - * Return {@code true} if the current user is root. Note that this method returns - * {@code false} if on Windows. - */ - public static boolean isRoot() { - if (IS_ROOT == null) { - synchronized (PlatformDependent.class) { - if (IS_ROOT == null) { - IS_ROOT = isRoot0(); - } - } - } - return IS_ROOT; - } - - /** - * Return the version of Java under which this library is used. - */ - public static int javaVersion() { - return JAVA_VERSION; - } - - /** - * Returns {@code true} if and only if it is fine to enable TCP_NODELAY socket option by default. - */ - public static boolean canEnableTcpNoDelayByDefault() { - return CAN_ENABLE_TCP_NODELAY_BY_DEFAULT; - } - - /** - * Return {@code true} if {@code sun.misc.Unsafe} was found on the classpath and can be used for acclerated - * direct memory access. - */ - public static boolean hasUnsafe() { - return HAS_UNSAFE; - } - - /** - * {@code true} if and only if the platform supports unaligned access. - * - * @see Wikipedia on segfault - */ - public static boolean isUnaligned() { - return PlatformDependent0.isUnaligned(); - } - - /** - * Returns {@code true} if the platform has reliable low-level direct buffer access API and a user has not specified - * {@code -Dio.netty.noPreferDirect} option. - */ - public static boolean directBufferPreferred() { - return DIRECT_BUFFER_PREFERRED; - } - - /** - * Returns the maximum memory reserved for direct buffer allocation. - */ - public static long maxDirectMemory() { - return MAX_DIRECT_MEMORY; - } - - /** - * Returns {@code true} if and only if Javassist is available. - */ - public static boolean hasJavassist() { - return HAS_JAVASSIST; - } - - /** - * Returns the temporary directory. - */ - public static File tmpdir() { - return TMPDIR; - } - - /** - * Returns the bit mode of the current VM (usually 32 or 64.) - */ - public static int bitMode() { - return BIT_MODE; - } - - /** - * Return the address size of the OS. - * 4 (for 32 bits systems ) and 8 (for 64 bits systems). - */ - public static int addressSize() { - return ADDRESS_SIZE; - } - - public static long allocateMemory(long size) { - return PlatformDependent0.allocateMemory(size); - } - - public static void freeMemory(long address) { - PlatformDependent0.freeMemory(address); - } - - /** - * Raises an exception bypassing compiler checks for checked exceptions. - */ - public static void throwException(Throwable t) { - if (hasUnsafe()) { - PlatformDependent0.throwException(t); - } else { - PlatformDependent.throwException0(t); - } - } - - @SuppressWarnings("unchecked") - private static void throwException0(Throwable t) throws E { - throw (E) t; - } - - /** - * Creates a new fastest {@link ConcurrentMap} implementaion for the current platform. - */ - public static ConcurrentMap newConcurrentHashMap() { - if (CAN_USE_CHM_V8) { - return new ConcurrentHashMapV8(); - } else { - return new ConcurrentHashMap(); - } - } - - /** - * Creates a new fastest {@link LongCounter} implementaion for the current platform. - */ - public static LongCounter newLongCounter() { - if (HAS_UNSAFE) { - return new LongAdderV8(); - } else { - return new AtomicLongCounter(); - } - } - - /** - * Creates a new fastest {@link ConcurrentMap} implementaion for the current platform. - */ - public static ConcurrentMap newConcurrentHashMap(int initialCapacity) { - if (CAN_USE_CHM_V8) { - return new ConcurrentHashMapV8(initialCapacity); - } else { - return new ConcurrentHashMap(initialCapacity); - } - } - - /** - * Creates a new fastest {@link ConcurrentMap} implementaion for the current platform. - */ - public static ConcurrentMap newConcurrentHashMap(int initialCapacity, float loadFactor) { - if (CAN_USE_CHM_V8) { - return new ConcurrentHashMapV8(initialCapacity, loadFactor); - } else { - return new ConcurrentHashMap(initialCapacity, loadFactor); - } - } - - /** - * Creates a new fastest {@link ConcurrentMap} implementaion for the current platform. - */ - public static ConcurrentMap newConcurrentHashMap( - int initialCapacity, float loadFactor, int concurrencyLevel) { - if (CAN_USE_CHM_V8) { - return new ConcurrentHashMapV8(initialCapacity, loadFactor, concurrencyLevel); - } else { - return new ConcurrentHashMap(initialCapacity, loadFactor, concurrencyLevel); - } - } - - /** - * Creates a new fastest {@link ConcurrentMap} implementaion for the current platform. - */ - public static ConcurrentMap newConcurrentHashMap(Map map) { - if (CAN_USE_CHM_V8) { - return new ConcurrentHashMapV8(map); - } else { - return new ConcurrentHashMap(map); - } - } - - /** - * Try to deallocate the specified direct {@link ByteBuffer}. Please note this method does nothing if - * the current platform does not support this operation or the specified buffer is not a direct buffer. - */ - public static void freeDirectBuffer(ByteBuffer buffer) { - if (hasUnsafe() && !isAndroid()) { - // only direct to method if we are not running on android. - // See https://github.com/netty/netty/issues/2604 - PlatformDependent0.freeDirectBuffer(buffer); - } - } - - public static long directBufferAddress(ByteBuffer buffer) { - return PlatformDependent0.directBufferAddress(buffer); - } - - public static Object getObject(Object object, long fieldOffset) { - return PlatformDependent0.getObject(object, fieldOffset); - } - - public static Object getObjectVolatile(Object object, long fieldOffset) { - return PlatformDependent0.getObjectVolatile(object, fieldOffset); - } - - public static int getInt(Object object, long fieldOffset) { - return PlatformDependent0.getInt(object, fieldOffset); - } - - public static long objectFieldOffset(Field field) { - return PlatformDependent0.objectFieldOffset(field); - } - - public static byte getByte(long address) { - return PlatformDependent0.getByte(address); - } - - public static short getShort(long address) { - return PlatformDependent0.getShort(address); - } - - public static int getInt(long address) { - return PlatformDependent0.getInt(address); - } - - public static long getLong(long address) { - return PlatformDependent0.getLong(address); - } - - public static byte getByte(byte[] data, int index) { - return PlatformDependent0.getByte(data, index); - } - - public static short getShort(byte[] data, int index) { - return PlatformDependent0.getShort(data, index); - } - - public static int getInt(byte[] data, int index) { - return PlatformDependent0.getInt(data, index); - } - - public static long getLong(byte[] data, int index) { - return PlatformDependent0.getLong(data, index); - } - - public static void putOrderedObject(Object object, long address, Object value) { - PlatformDependent0.putOrderedObject(object, address, value); - } - - public static void putByte(long address, byte value) { - PlatformDependent0.putByte(address, value); - } - - public static void putShort(long address, short value) { - PlatformDependent0.putShort(address, value); - } - - public static void putInt(long address, int value) { - PlatformDependent0.putInt(address, value); - } - - public static void putLong(long address, long value) { - PlatformDependent0.putLong(address, value); - } - - public static void putByte(byte[] data, int index, byte value) { - PlatformDependent0.putByte(data, index, value); - } - - public static void putShort(byte[] data, int index, short value) { - PlatformDependent0.putShort(data, index, value); - } - - public static void putInt(byte[] data, int index, int value) { - PlatformDependent0.putInt(data, index, value); - } - - public static void putLong(byte[] data, int index, long value) { - PlatformDependent0.putLong(data, index, value); - } - - public static void copyMemory(long srcAddr, long dstAddr, long length) { - PlatformDependent0.copyMemory(srcAddr, dstAddr, length); - } - - public static void copyMemory(byte[] src, int srcIndex, long dstAddr, long length) { - PlatformDependent0.copyMemory(src, ARRAY_BASE_OFFSET + srcIndex, null, dstAddr, length); - } - - public static void copyMemory(long srcAddr, byte[] dst, int dstIndex, long length) { - PlatformDependent0.copyMemory(null, srcAddr, dst, ARRAY_BASE_OFFSET + dstIndex, length); - } - - /** - * Create a new optimized {@link AtomicReferenceFieldUpdater} or {@code null} if it - * could not be created. Because of this the caller need to check for {@code null} and if {@code null} is returned - * use {@link AtomicReferenceFieldUpdater#newUpdater(Class, Class, String)} as fallback. - */ - public static AtomicReferenceFieldUpdater newAtomicReferenceFieldUpdater( - Class tclass, String fieldName) { - if (hasUnsafe()) { - try { - return PlatformDependent0.newAtomicReferenceFieldUpdater(tclass, fieldName); - } catch (Throwable ignore) { - // ignore - } - } - return null; - } - - /** - * Create a new optimized {@link AtomicIntegerFieldUpdater} or {@code null} if it - * could not be created. Because of this the caller need to check for {@code null} and if {@code null} is returned - * use {@link AtomicIntegerFieldUpdater#newUpdater(Class, String)} as fallback. - */ - public static AtomicIntegerFieldUpdater newAtomicIntegerFieldUpdater( - Class tclass, String fieldName) { - if (hasUnsafe()) { - try { - return PlatformDependent0.newAtomicIntegerFieldUpdater(tclass, fieldName); - } catch (Throwable ignore) { - // ignore - } - } - return null; - } - - /** - * Create a new optimized {@link AtomicLongFieldUpdater} or {@code null} if it - * could not be created. Because of this the caller need to check for {@code null} and if {@code null} is returned - * use {@link AtomicLongFieldUpdater#newUpdater(Class, String)} as fallback. - */ - public static AtomicLongFieldUpdater newAtomicLongFieldUpdater( - Class tclass, String fieldName) { - if (hasUnsafe()) { - try { - return PlatformDependent0.newAtomicLongFieldUpdater(tclass, fieldName); - } catch (Throwable ignore) { - // ignore - } - } - return null; - } - - /** - * Create a new {@link Queue} which is safe to use for multiple producers (different threads) and a single - * consumer (one thread!). - */ - public static Queue newMpscQueue() { - return new MpscLinkedQueue(); - } - - /** - * Create a new {@link Queue} which is safe to use for multiple producers (different threads) and a single - * consumer (one thread!) with the given fixes {@code capacity}. - */ - public static Queue newFixedMpscQueue(int capacity) { - if (hasUnsafe()) { - return new MpscArrayQueue(capacity); - } else { - return new LinkedBlockingQueue(capacity); - } - } - - /** - * Return the {@link ClassLoader} for the given {@link Class}. - */ - public static ClassLoader getClassLoader(final Class clazz) { - return PlatformDependent0.getClassLoader(clazz); - } - - /** - * Return the context {@link ClassLoader} for the current {@link Thread}. - */ - public static ClassLoader getContextClassLoader() { - return PlatformDependent0.getContextClassLoader(); - } - - /** - * Return the system {@link ClassLoader}. - */ - public static ClassLoader getSystemClassLoader() { - return PlatformDependent0.getSystemClassLoader(); - } - - /** - * Returns a new concurrent {@link Deque}. - */ - public static Deque newConcurrentDeque() { - if (javaVersion() < 7) { - return new LinkedBlockingDeque(); - } else { - return new ConcurrentLinkedDeque(); - } - } - - private static boolean isAndroid0() { - boolean android; - try { - Class.forName("android.app.Application", false, getSystemClassLoader()); - android = true; - } catch (Exception e) { - // Failed to load the class uniquely available in Android. - android = false; - } - - if (android) { - logger.debug("Platform: Android"); - } - return android; - } - - private static boolean isWindows0() { - boolean windows = SystemPropertyUtil.get("os.name", "").toLowerCase(Locale.US).contains("win"); - if (windows) { - logger.debug("Platform: Windows"); - } - return windows; - } - - private static boolean isRoot0() { - if (isWindows()) { - return false; - } - - String[] ID_COMMANDS = { "/usr/bin/id", "/bin/id", "/usr/xpg4/bin/id", "id"}; - Pattern UID_PATTERN = Pattern.compile("^(?:0|[1-9][0-9]*)$"); - for (String idCmd: ID_COMMANDS) { - Process p = null; - BufferedReader in = null; - String uid = null; - try { - p = Runtime.getRuntime().exec(new String[] { idCmd, "-u" }); - in = new BufferedReader(new InputStreamReader(p.getInputStream(), CharsetUtil.US_ASCII)); - uid = in.readLine(); - in.close(); - - for (;;) { - try { - int exitCode = p.waitFor(); - if (exitCode != 0) { - uid = null; - } - break; - } catch (InterruptedException e) { - // Ignore - } - } - } catch (Exception e) { - // Failed to run the command. - uid = null; - } finally { - if (in != null) { - try { - in.close(); - } catch (IOException e) { - // Ignore - } - } - if (p != null) { - try { - p.destroy(); - } catch (Exception e) { - // Android sometimes triggers an ErrnoException. - } - } - } - - if (uid != null && UID_PATTERN.matcher(uid).matches()) { - logger.debug("UID: {}", uid); - return "0".equals(uid); - } - } - - logger.debug("Could not determine the current UID using /usr/bin/id; attempting to bind at privileged ports."); - - Pattern PERMISSION_DENIED = Pattern.compile(".*(?:denied|not.*permitted).*"); - for (int i = 1023; i > 0; i --) { - ServerSocket ss = null; - try { - ss = new ServerSocket(); - ss.setReuseAddress(true); - ss.bind(new InetSocketAddress(i)); - if (logger.isDebugEnabled()) { - logger.debug("UID: 0 (succeded to bind at port {})", i); - } - return true; - } catch (Exception e) { - // Failed to bind. - // Check the error message so that we don't always need to bind 1023 times. - String message = e.getMessage(); - if (message == null) { - message = ""; - } - message = message.toLowerCase(); - if (PERMISSION_DENIED.matcher(message).matches()) { - break; - } - } finally { - if (ss != null) { - try { - ss.close(); - } catch (Exception e) { - // Ignore. - } - } - } - } - - logger.debug("UID: non-root (failed to bind at any privileged ports)"); - return false; - } - - @SuppressWarnings("LoopStatementThatDoesntLoop") - private static int javaVersion0() { - int javaVersion; - - // Not really a loop - for (;;) { - // Android - if (isAndroid()) { - javaVersion = 6; - break; - } - - try { - Class.forName("java.time.Clock", false, getClassLoader(Object.class)); - javaVersion = 8; - break; - } catch (Exception e) { - // Ignore - } - - try { - Class.forName("java.util.concurrent.LinkedTransferQueue", false, getClassLoader(BlockingQueue.class)); - javaVersion = 7; - break; - } catch (Exception e) { - // Ignore - } - - javaVersion = 6; - break; - } - - if (logger.isDebugEnabled()) { - logger.debug("Java version: {}", javaVersion); - } - return javaVersion; - } - - private static boolean hasUnsafe0() { - boolean noUnsafe = SystemPropertyUtil.getBoolean("io.netty.noUnsafe", false); - logger.debug("-Dio.netty.noUnsafe: {}", noUnsafe); - - if (isAndroid()) { - logger.debug("sun.misc.Unsafe: unavailable (Android)"); - return false; - } - - if (noUnsafe) { - logger.debug("sun.misc.Unsafe: unavailable (io.netty.noUnsafe)"); - return false; - } - - // Legacy properties - boolean tryUnsafe; - if (SystemPropertyUtil.contains("io.netty.tryUnsafe")) { - tryUnsafe = SystemPropertyUtil.getBoolean("io.netty.tryUnsafe", true); - } else { - tryUnsafe = SystemPropertyUtil.getBoolean("org.jboss.netty.tryUnsafe", true); - } - - if (!tryUnsafe) { - logger.debug("sun.misc.Unsafe: unavailable (io.netty.tryUnsafe/org.jboss.netty.tryUnsafe)"); - return false; - } - - try { - boolean hasUnsafe = PlatformDependent0.hasUnsafe(); - logger.debug("sun.misc.Unsafe: {}", hasUnsafe ? "available" : "unavailable"); - return hasUnsafe; - } catch (Throwable t) { - // Probably failed to initialize PlatformDependent0. - return false; - } - } - - private static long arrayBaseOffset0() { - if (!hasUnsafe()) { - return -1; - } - - return PlatformDependent0.arrayBaseOffset(); - } - - private static long maxDirectMemory0() { - long maxDirectMemory = 0; - try { - // Try to get from sun.misc.VM.maxDirectMemory() which should be most accurate. - Class vmClass = Class.forName("sun.misc.VM", true, getSystemClassLoader()); - Method m = vmClass.getDeclaredMethod("maxDirectMemory"); - maxDirectMemory = ((Number) m.invoke(null)).longValue(); - } catch (Throwable t) { - // Ignore - } - - if (maxDirectMemory > 0) { - return maxDirectMemory; - } - - try { - // Now try to get the JVM option (-XX:MaxDirectMemorySize) and parse it. - // Note that we are using reflection because Android doesn't have these classes. - Class mgmtFactoryClass = Class.forName( - "java.lang.management.ManagementFactory", true, getSystemClassLoader()); - Class runtimeClass = Class.forName( - "java.lang.management.RuntimeMXBean", true, getSystemClassLoader()); - - Object runtime = mgmtFactoryClass.getDeclaredMethod("getRuntimeMXBean").invoke(null); - - @SuppressWarnings("unchecked") - List vmArgs = (List) runtimeClass.getDeclaredMethod("getInputArguments").invoke(runtime); - for (int i = vmArgs.size() - 1; i >= 0; i --) { - Matcher m = MAX_DIRECT_MEMORY_SIZE_ARG_PATTERN.matcher(vmArgs.get(i)); - if (!m.matches()) { - continue; - } - - maxDirectMemory = Long.parseLong(m.group(1)); - switch (m.group(2).charAt(0)) { - case 'k': case 'K': - maxDirectMemory *= 1024; - break; - case 'm': case 'M': - maxDirectMemory *= 1024 * 1024; - break; - case 'g': case 'G': - maxDirectMemory *= 1024 * 1024 * 1024; - break; - } - break; - } - } catch (Throwable t) { - // Ignore - } - - if (maxDirectMemory <= 0) { - maxDirectMemory = Runtime.getRuntime().maxMemory(); - logger.debug("maxDirectMemory: {} bytes (maybe)", maxDirectMemory); - } else { - logger.debug("maxDirectMemory: {} bytes", maxDirectMemory); - } - - return maxDirectMemory; - } - - private static boolean hasJavassist0() { - if (isAndroid()) { - return false; - } - - boolean noJavassist = SystemPropertyUtil.getBoolean("io.netty.noJavassist", false); - logger.debug("-Dio.netty.noJavassist: {}", noJavassist); - - if (noJavassist) { - logger.debug("Javassist: unavailable (io.netty.noJavassist)"); - return false; - } - - try { - JavassistTypeParameterMatcherGenerator.generate(Object.class, getClassLoader(PlatformDependent.class)); - logger.debug("Javassist: available"); - return true; - } catch (Throwable t) { - // Failed to generate a Javassist-based matcher. - logger.debug("Javassist: unavailable"); - logger.debug( - "You don't have Javassist in your class path or you don't have enough permission " + - "to load dynamically generated classes. Please check the configuration for better performance."); - return false; - } - } - - private static File tmpdir0() { - File f; - try { - f = toDirectory(SystemPropertyUtil.get("io.netty.tmpdir")); - if (f != null) { - logger.debug("-Dio.netty.tmpdir: {}", f); - return f; - } - - f = toDirectory(SystemPropertyUtil.get("java.io.tmpdir")); - if (f != null) { - logger.debug("-Dio.netty.tmpdir: {} (java.io.tmpdir)", f); - return f; - } - - // This shouldn't happen, but just in case .. - if (isWindows()) { - f = toDirectory(System.getenv("TEMP")); - if (f != null) { - logger.debug("-Dio.netty.tmpdir: {} (%TEMP%)", f); - return f; - } - - String userprofile = System.getenv("USERPROFILE"); - if (userprofile != null) { - f = toDirectory(userprofile + "\\AppData\\Local\\Temp"); - if (f != null) { - logger.debug("-Dio.netty.tmpdir: {} (%USERPROFILE%\\AppData\\Local\\Temp)", f); - return f; - } - - f = toDirectory(userprofile + "\\Local Settings\\Temp"); - if (f != null) { - logger.debug("-Dio.netty.tmpdir: {} (%USERPROFILE%\\Local Settings\\Temp)", f); - return f; - } - } - } else { - f = toDirectory(System.getenv("TMPDIR")); - if (f != null) { - logger.debug("-Dio.netty.tmpdir: {} ($TMPDIR)", f); - return f; - } - } - } catch (Exception ignored) { - // Environment variable inaccessible - } - - // Last resort. - if (isWindows()) { - f = new File("C:\\Windows\\Temp"); - } else { - f = new File("/tmp"); - } - - logger.warn("Failed to get the temporary directory; falling back to: {}", f); - return f; - } - - @SuppressWarnings("ResultOfMethodCallIgnored") - private static File toDirectory(String path) { - if (path == null) { - return null; - } - - File f = new File(path); - f.mkdirs(); - - if (!f.isDirectory()) { - return null; - } - - try { - return f.getAbsoluteFile(); - } catch (Exception ignored) { - return f; - } - } - - private static int bitMode0() { - // Check user-specified bit mode first. - int bitMode = SystemPropertyUtil.getInt("io.netty.bitMode", 0); - if (bitMode > 0) { - logger.debug("-Dio.netty.bitMode: {}", bitMode); - return bitMode; - } - - // And then the vendor specific ones which is probably most reliable. - bitMode = SystemPropertyUtil.getInt("sun.arch.data.model", 0); - if (bitMode > 0) { - logger.debug("-Dio.netty.bitMode: {} (sun.arch.data.model)", bitMode); - return bitMode; - } - bitMode = SystemPropertyUtil.getInt("com.ibm.vm.bitmode", 0); - if (bitMode > 0) { - logger.debug("-Dio.netty.bitMode: {} (com.ibm.vm.bitmode)", bitMode); - return bitMode; - } - - // os.arch also gives us a good hint. - String arch = SystemPropertyUtil.get("os.arch", "").toLowerCase(Locale.US).trim(); - if ("amd64".equals(arch) || "x86_64".equals(arch)) { - bitMode = 64; - } else if ("i386".equals(arch) || "i486".equals(arch) || "i586".equals(arch) || "i686".equals(arch)) { - bitMode = 32; - } - - if (bitMode > 0) { - logger.debug("-Dio.netty.bitMode: {} (os.arch: {})", bitMode, arch); - } - - // Last resort: guess from VM name and then fall back to most common 64-bit mode. - String vm = SystemPropertyUtil.get("java.vm.name", "").toLowerCase(Locale.US); - Pattern BIT_PATTERN = Pattern.compile("([1-9][0-9]+)-?bit"); - Matcher m = BIT_PATTERN.matcher(vm); - if (m.find()) { - return Integer.parseInt(m.group(1)); - } else { - return 64; - } - } - - private static int addressSize0() { - if (!hasUnsafe()) { - return -1; - } - return PlatformDependent0.addressSize(); - } - - private static final class AtomicLongCounter extends AtomicLong implements LongCounter { - @Override - public void add(long delta) { - addAndGet(delta); - } - - @Override - public void increment() { - incrementAndGet(); - } - - @Override - public void decrement() { - decrementAndGet(); - } - - @Override - public long value() { - return get(); - } - } - - private PlatformDependent() { - // only static method supported - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/PlatformDependent0.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/PlatformDependent0.java deleted file mode 100755 index 4cb0340927..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/PlatformDependent0.java +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.internal; - -import sun.misc.Unsafe; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.nio.Buffer; -import java.nio.ByteBuffer; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; -import java.util.concurrent.atomic.AtomicLongFieldUpdater; -import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; - -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -import static com.ai.cloud.io.netty.util.internal.ObjectUtil.checkNotNull; - -/** - * The {@link PlatformDependent} operations which requires access to {@code sun.misc.*}. - */ -final class PlatformDependent0 { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(PlatformDependent0.class); - static final Unsafe UNSAFE; - private static final long ADDRESS_FIELD_OFFSET; - private static final long BYTE_ARRAY_BASE_OFFSET; - - /** - * Limits the number of bytes to copy per {@link Unsafe#copyMemory(long, long, long)} to allow safepoint polling - * during a large copy. - */ - private static final long UNSAFE_COPY_THRESHOLD = 1024L * 1024L; - - private static final boolean UNALIGNED; - - static { - ByteBuffer direct = ByteBuffer.allocateDirect(1); - Field addressField; - try { - addressField = Buffer.class.getDeclaredField("address"); - addressField.setAccessible(true); - if (addressField.getLong(ByteBuffer.allocate(1)) != 0) { - // A heap buffer must have 0 address. - addressField = null; - } else { - if (addressField.getLong(direct) == 0) { - // A direct buffer must have non-zero address. - addressField = null; - } - } - } catch (Throwable t) { - // Failed to access the address field. - addressField = null; - } - logger.debug("java.nio.Buffer.address: {}", addressField != null? "available" : "unavailable"); - - Unsafe unsafe; - if (addressField != null) { - try { - Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe"); - unsafeField.setAccessible(true); - unsafe = (Unsafe) unsafeField.get(null); - logger.debug("sun.misc.Unsafe.theUnsafe: {}", unsafe != null ? "available" : "unavailable"); - - // Ensure the unsafe supports all necessary methods to work around the mistake in the latest OpenJDK. - // https://github.com/netty/netty/issues/1061 - // http://www.mail-archive.com/jdk6-dev@openjdk.java.net/msg00698.html - try { - if (unsafe != null) { - unsafe.getClass().getDeclaredMethod( - "copyMemory", Object.class, long.class, Object.class, long.class, long.class); - logger.debug("sun.misc.Unsafe.copyMemory: available"); - } - } catch (NoSuchMethodError t) { - logger.debug("sun.misc.Unsafe.copyMemory: unavailable"); - throw t; - } catch (NoSuchMethodException e) { - logger.debug("sun.misc.Unsafe.copyMemory: unavailable"); - throw e; - } - } catch (Throwable cause) { - // Unsafe.copyMemory(Object, long, Object, long, long) unavailable. - unsafe = null; - } - } else { - // If we cannot access the address of a direct buffer, there's no point of using unsafe. - // Let's just pretend unsafe is unavailable for overall simplicity. - unsafe = null; - } - - UNSAFE = unsafe; - - if (unsafe == null) { - BYTE_ARRAY_BASE_OFFSET = -1; - ADDRESS_FIELD_OFFSET = -1; - UNALIGNED = false; - } else { - ADDRESS_FIELD_OFFSET = objectFieldOffset(addressField); - boolean unaligned; - try { - Class bitsClass = Class.forName("java.nio.Bits", false, ClassLoader.getSystemClassLoader()); - Method unalignedMethod = bitsClass.getDeclaredMethod("unaligned"); - unalignedMethod.setAccessible(true); - unaligned = Boolean.TRUE.equals(unalignedMethod.invoke(null)); - } catch (Throwable t) { - // We at least know x86 and x64 support unaligned access. - String arch = SystemPropertyUtil.get("os.arch", ""); - //noinspection DynamicRegexReplaceableByCompiledPattern - unaligned = arch.matches("^(i[3-6]86|x86(_64)?|x64|amd64)$"); - } - - UNALIGNED = unaligned; - logger.debug("java.nio.Bits.unaligned: {}", UNALIGNED); - BYTE_ARRAY_BASE_OFFSET = arrayBaseOffset(); - } - } - - static boolean isUnaligned() { - return UNALIGNED; - } - - static boolean hasUnsafe() { - return UNSAFE != null; - } - - static void throwException(Throwable cause) { - // JVM has been observed to crash when passing a null argument. See https://github.com/netty/netty/issues/4131. - UNSAFE.throwException(checkNotNull(cause, "cause")); - } - - static void freeDirectBuffer(ByteBuffer buffer) { - // Delegate to other class to not break on android - // See https://github.com/netty/netty/issues/2604 - Cleaner0.freeDirectBuffer(buffer); - } - - static long directBufferAddress(ByteBuffer buffer) { - return getLong(buffer, ADDRESS_FIELD_OFFSET); - } - - static long arrayBaseOffset() { - return UNSAFE.arrayBaseOffset(byte[].class); - } - - static Object getObject(Object object, long fieldOffset) { - return UNSAFE.getObject(object, fieldOffset); - } - - static Object getObjectVolatile(Object object, long fieldOffset) { - return UNSAFE.getObjectVolatile(object, fieldOffset); - } - - static int getInt(Object object, long fieldOffset) { - return UNSAFE.getInt(object, fieldOffset); - } - - private static long getLong(Object object, long fieldOffset) { - return UNSAFE.getLong(object, fieldOffset); - } - - static long objectFieldOffset(Field field) { - return UNSAFE.objectFieldOffset(field); - } - - static byte getByte(long address) { - return UNSAFE.getByte(address); - } - - static short getShort(long address) { - return UNSAFE.getShort(address); - } - - static int getInt(long address) { - return UNSAFE.getInt(address); - } - - static long getLong(long address) { - return UNSAFE.getLong(address); - } - - static byte getByte(byte[] data, int index) { - return UNSAFE.getByte(data, BYTE_ARRAY_BASE_OFFSET + index); - } - - static short getShort(byte[] data, int index) { - return UNSAFE.getShort(data, BYTE_ARRAY_BASE_OFFSET + index); - } - - static int getInt(byte[] data, int index) { - return UNSAFE.getInt(data, BYTE_ARRAY_BASE_OFFSET + index); - } - - static long getLong(byte[] data, int index) { - return UNSAFE.getLong(data, BYTE_ARRAY_BASE_OFFSET + index); - } - - static void putOrderedObject(Object object, long address, Object value) { - UNSAFE.putOrderedObject(object, address, value); - } - - static void putByte(long address, byte value) { - UNSAFE.putByte(address, value); - } - - static void putShort(long address, short value) { - UNSAFE.putShort(address, value); - } - - static void putInt(long address, int value) { - UNSAFE.putInt(address, value); - } - - static void putLong(long address, long value) { - UNSAFE.putLong(address, value); - } - - static void putByte(byte[] data, int index, byte value) { - UNSAFE.putByte(data, BYTE_ARRAY_BASE_OFFSET + index, value); - } - - static void putShort(byte[] data, int index, short value) { - UNSAFE.putShort(data, BYTE_ARRAY_BASE_OFFSET + index, value); - } - - static void putInt(byte[] data, int index, int value) { - UNSAFE.putInt(data, BYTE_ARRAY_BASE_OFFSET + index, value); - } - - static void putLong(byte[] data, int index, long value) { - UNSAFE.putLong(data, BYTE_ARRAY_BASE_OFFSET + index, value); - } - - static void copyMemory(long srcAddr, long dstAddr, long length) { - //UNSAFE.copyMemory(srcAddr, dstAddr, length); - while (length > 0) { - long size = Math.min(length, UNSAFE_COPY_THRESHOLD); - UNSAFE.copyMemory(srcAddr, dstAddr, size); - length -= size; - srcAddr += size; - dstAddr += size; - } - } - - static void copyMemory(Object src, long srcOffset, Object dst, long dstOffset, long length) { - //UNSAFE.copyMemory(src, srcOffset, dst, dstOffset, length); - while (length > 0) { - long size = Math.min(length, UNSAFE_COPY_THRESHOLD); - UNSAFE.copyMemory(src, srcOffset, dst, dstOffset, size); - length -= size; - srcOffset += size; - dstOffset += size; - } - } - - static AtomicReferenceFieldUpdater newAtomicReferenceFieldUpdater( - Class tclass, String fieldName) throws Exception { - return new UnsafeAtomicReferenceFieldUpdater(UNSAFE, tclass, fieldName); - } - - static AtomicIntegerFieldUpdater newAtomicIntegerFieldUpdater( - Class tclass, String fieldName) throws Exception { - return new UnsafeAtomicIntegerFieldUpdater(UNSAFE, tclass, fieldName); - } - - static AtomicLongFieldUpdater newAtomicLongFieldUpdater( - Class tclass, String fieldName) throws Exception { - return new UnsafeAtomicLongFieldUpdater(UNSAFE, tclass, fieldName); - } - - static ClassLoader getClassLoader(final Class clazz) { - if (System.getSecurityManager() == null) { - return clazz.getClassLoader(); - } else { - return AccessController.doPrivileged(new PrivilegedAction() { - @Override - public ClassLoader run() { - return clazz.getClassLoader(); - } - }); - } - } - - static ClassLoader getContextClassLoader() { - if (System.getSecurityManager() == null) { - return Thread.currentThread().getContextClassLoader(); - } else { - return AccessController.doPrivileged(new PrivilegedAction() { - @Override - public ClassLoader run() { - return Thread.currentThread().getContextClassLoader(); - } - }); - } - } - - static ClassLoader getSystemClassLoader() { - if (System.getSecurityManager() == null) { - return ClassLoader.getSystemClassLoader(); - } else { - return AccessController.doPrivileged(new PrivilegedAction() { - @Override - public ClassLoader run() { - return ClassLoader.getSystemClassLoader(); - } - }); - } - } - - static int addressSize() { - return UNSAFE.addressSize(); - } - - static long allocateMemory(long size) { - return UNSAFE.allocateMemory(size); - } - - static void freeMemory(long address) { - UNSAFE.freeMemory(address); - } - - private PlatformDependent0() { - } - -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/ReadOnlyIterator.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/ReadOnlyIterator.java deleted file mode 100755 index 99b94c0d43..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/ReadOnlyIterator.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.util.internal; - -import java.util.Iterator; - -public final class ReadOnlyIterator implements Iterator { - private final Iterator iterator; - - public ReadOnlyIterator(Iterator iterator) { - if (iterator == null) { - throw new NullPointerException("iterator"); - } - this.iterator = iterator; - } - - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - public T next() { - return iterator.next(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException("read-only"); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/RecyclableArrayList.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/RecyclableArrayList.java deleted file mode 100755 index 8d0f0257b7..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/RecyclableArrayList.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.util.internal; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.RandomAccess; - -import com.ai.cloud.io.netty.util.Recycler; -import com.ai.cloud.io.netty.util.Recycler.Handle; - -/** - * A simple list which is recyclable. This implementation does not allow {@code null} elements to be added. - */ -public final class RecyclableArrayList extends ArrayList { - - private static final long serialVersionUID = -8605125654176467947L; - - private static final int DEFAULT_INITIAL_CAPACITY = 8; - - private static final Recycler RECYCLER = new Recycler() { - @Override - protected RecyclableArrayList newObject(Handle handle) { - return new RecyclableArrayList(handle); - } - }; - - private boolean insertSinceRecycled; - - /** - * Create a new empty {@link RecyclableArrayList} instance - */ - public static RecyclableArrayList newInstance() { - return newInstance(DEFAULT_INITIAL_CAPACITY); - } - - /** - * Create a new empty {@link RecyclableArrayList} instance with the given capacity. - */ - public static RecyclableArrayList newInstance(int minCapacity) { - RecyclableArrayList ret = RECYCLER.get(); - ret.ensureCapacity(minCapacity); - return ret; - } - - private final Handle handle; - - private RecyclableArrayList(Handle handle) { - this(handle, DEFAULT_INITIAL_CAPACITY); - } - - private RecyclableArrayList(Handle handle, int initialCapacity) { - super(initialCapacity); - this.handle = handle; - } - - @Override - public boolean addAll(Collection c) { - checkNullElements(c); - if (super.addAll(c)) { - insertSinceRecycled = true; - return true; - } - return false; - } - - @Override - public boolean addAll(int index, Collection c) { - checkNullElements(c); - if (super.addAll(index, c)) { - insertSinceRecycled = true; - return true; - } - return false; - } - - private static void checkNullElements(Collection c) { - if (c instanceof RandomAccess && c instanceof List) { - // produce less garbage - List list = (List) c; - int size = list.size(); - for (int i = 0; i < size; i++) { - if (list.get(i) == null) { - throw new IllegalArgumentException("c contains null values"); - } - } - } else { - for (Object element: c) { - if (element == null) { - throw new IllegalArgumentException("c contains null values"); - } - } - } - } - - @Override - public boolean add(Object element) { - if (element == null) { - throw new NullPointerException("element"); - } - if (super.add(element)) { - insertSinceRecycled = true; - return true; - } - return false; - } - - @Override - public void add(int index, Object element) { - if (element == null) { - throw new NullPointerException("element"); - } - super.add(index, element); - insertSinceRecycled = true; - } - - @Override - public Object set(int index, Object element) { - if (element == null) { - throw new NullPointerException("element"); - } - Object old = super.set(index, element); - insertSinceRecycled = true; - return old; - } - - /** - * Returns {@code true} if any elements where added or set. This will be reset once {@link #recycle()} was called. - */ - public boolean insertSinceRecycled() { - return insertSinceRecycled; - } - - /** - * Clear and recycle this instance. - */ - public boolean recycle() { - clear(); - insertSinceRecycled = false; - return RECYCLER.recycle(this, handle); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/RecyclableMpscLinkedQueueNode.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/RecyclableMpscLinkedQueueNode.java deleted file mode 100755 index 8d7e643b48..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/RecyclableMpscLinkedQueueNode.java +++ /dev/null @@ -1,45 +0,0 @@ -/* -* Copyright 2014 The Netty Project -* -* The Netty Project licenses this file to you under the Apache License, -* version 2.0 (the "License"); you may not use this file except in compliance -* with the License. You may obtain a copy of the License at: -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -* License for the specific language governing permissions and limitations -* under the License. -*/ - -package com.ai.cloud.io.netty.util.internal; - -import com.ai.cloud.io.netty.util.Recycler; - -/** - * {@link MpscLinkedQueueNode} that will automatically call {@link #recycle(Recycler.Handle)} when the node was - * unlinked. - */ -public abstract class RecyclableMpscLinkedQueueNode extends MpscLinkedQueueNode { - private final Recycler.Handle handle; - - protected RecyclableMpscLinkedQueueNode(Recycler.Handle handle) { - if (handle == null) { - throw new NullPointerException("handle"); - } - this.handle = handle; - } - - @Override - final void unlink() { - super.unlink(); - recycle(handle); - } - - /** - * Called once unliked and so ready to recycled. - */ - protected abstract void recycle(Recycler.Handle handle); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/StringUtil.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/StringUtil.java deleted file mode 100755 index d239bc66a1..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/StringUtil.java +++ /dev/null @@ -1,397 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.internal; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Formatter; -import java.util.List; - -import static com.ai.cloud.io.netty.util.internal.ObjectUtil.checkNotNull; - -/** - * String utility class. - */ -public final class StringUtil { - - public static final String NEWLINE; - public static final char DOUBLE_QUOTE = '\"'; - public static final char COMMA = ','; - public static final char LINE_FEED = '\n'; - public static final char CARRIAGE_RETURN = '\r'; - public static final String EMPTY_STRING = ""; - private static final String[] BYTE2HEX_PAD = new String[256]; - private static final String[] BYTE2HEX_NOPAD = new String[256]; - - /** - * 2 - Quote character at beginning and end. - * 5 - Extra allowance for anticipated escape characters that may be added. - */ - private static final int CSV_NUMBER_ESCAPE_CHARACTERS = 2 + 5; - private static final char PACKAGE_SEPARATOR_CHAR = '.'; - - static { - // Determine the newline character of the current platform. - String newLine; - - Formatter formatter = new Formatter(); - try { - newLine = formatter.format("%n").toString(); - } catch (Exception e) { - // Should not reach here, but just in case. - newLine = "\n"; - } finally { - formatter.close(); - } - - NEWLINE = newLine; - - // Generate the lookup table that converts a byte into a 2-digit hexadecimal integer. - int i; - for (i = 0; i < 10; i ++) { - StringBuilder buf = new StringBuilder(2); - buf.append('0'); - buf.append(i); - BYTE2HEX_PAD[i] = buf.toString(); - BYTE2HEX_NOPAD[i] = String.valueOf(i); - } - for (; i < 16; i ++) { - StringBuilder buf = new StringBuilder(2); - char c = (char) ('a' + i - 10); - buf.append('0'); - buf.append(c); - BYTE2HEX_PAD[i] = buf.toString(); - BYTE2HEX_NOPAD[i] = String.valueOf(c); - } - for (; i < BYTE2HEX_PAD.length; i ++) { - StringBuilder buf = new StringBuilder(2); - buf.append(Integer.toHexString(i)); - String str = buf.toString(); - BYTE2HEX_PAD[i] = str; - BYTE2HEX_NOPAD[i] = str; - } - } - - /** - * Splits the specified {@link String} with the specified delimiter. This operation is a simplified and optimized - * version of {@link String#split(String)}. - */ - public static String[] split(String value, char delim) { - final int end = value.length(); - final List res = new ArrayList(); - - int start = 0; - for (int i = 0; i < end; i ++) { - if (value.charAt(i) == delim) { - if (start == i) { - res.add(EMPTY_STRING); - } else { - res.add(value.substring(start, i)); - } - start = i + 1; - } - } - - if (start == 0) { // If no delimiter was found in the value - res.add(value); - } else { - if (start != end) { - // Add the last element if it's not empty. - res.add(value.substring(start, end)); - } else { - // Truncate trailing empty elements. - for (int i = res.size() - 1; i >= 0; i --) { - if (res.get(i).isEmpty()) { - res.remove(i); - } else { - break; - } - } - } - } - - return res.toArray(new String[res.size()]); - } - - /** - * Splits the specified {@link String} with the specified delimiter in maxParts maximum parts. - * This operation is a simplified and optimized - * version of {@link String#split(String, int)}. - */ - public static String[] split(String value, char delim, int maxParts) { - final int end = value.length(); - final List res = new ArrayList(); - - int start = 0; - int cpt = 1; - for (int i = 0; i < end && cpt < maxParts; i ++) { - if (value.charAt(i) == delim) { - if (start == i) { - res.add(EMPTY_STRING); - } else { - res.add(value.substring(start, i)); - } - start = i + 1; - cpt++; - } - } - - if (start == 0) { // If no delimiter was found in the value - res.add(value); - } else { - if (start != end) { - // Add the last element if it's not empty. - res.add(value.substring(start, end)); - } else { - // Truncate trailing empty elements. - for (int i = res.size() - 1; i >= 0; i --) { - if (res.get(i).isEmpty()) { - res.remove(i); - } else { - break; - } - } - } - } - - return res.toArray(new String[res.size()]); - } - - /** - * Get the item after one char delim if the delim is found (else null). - * This operation is a simplified and optimized - * version of {@link String#split(String, int)}. - */ - public static String substringAfter(String value, char delim) { - int pos = value.indexOf(delim); - if (pos >= 0) { - return value.substring(pos + 1); - } - return null; - } - - /** - * Converts the specified byte value into a 2-digit hexadecimal integer. - */ - public static String byteToHexStringPadded(int value) { - return BYTE2HEX_PAD[value & 0xff]; - } - - /** - * Converts the specified byte value into a 2-digit hexadecimal integer and appends it to the specified buffer. - */ - public static T byteToHexStringPadded(T buf, int value) { - try { - buf.append(byteToHexStringPadded(value)); - } catch (IOException e) { - PlatformDependent.throwException(e); - } - return buf; - } - - /** - * Converts the specified byte array into a hexadecimal value. - */ - public static String toHexStringPadded(byte[] src) { - return toHexStringPadded(src, 0, src.length); - } - - /** - * Converts the specified byte array into a hexadecimal value. - */ - public static String toHexStringPadded(byte[] src, int offset, int length) { - return toHexStringPadded(new StringBuilder(length << 1), src, offset, length).toString(); - } - - /** - * Converts the specified byte array into a hexadecimal value and appends it to the specified buffer. - */ - public static T toHexStringPadded(T dst, byte[] src) { - return toHexStringPadded(dst, src, 0, src.length); - } - - /** - * Converts the specified byte array into a hexadecimal value and appends it to the specified buffer. - */ - public static T toHexStringPadded(T dst, byte[] src, int offset, int length) { - final int end = offset + length; - for (int i = offset; i < end; i ++) { - byteToHexStringPadded(dst, src[i]); - } - return dst; - } - - /** - * Converts the specified byte value into a hexadecimal integer. - */ - public static String byteToHexString(int value) { - return BYTE2HEX_NOPAD[value & 0xff]; - } - - /** - * Converts the specified byte value into a hexadecimal integer and appends it to the specified buffer. - */ - public static T byteToHexString(T buf, int value) { - try { - buf.append(byteToHexString(value)); - } catch (IOException e) { - PlatformDependent.throwException(e); - } - return buf; - } - - /** - * Converts the specified byte array into a hexadecimal value. - */ - public static String toHexString(byte[] src) { - return toHexString(src, 0, src.length); - } - - /** - * Converts the specified byte array into a hexadecimal value. - */ - public static String toHexString(byte[] src, int offset, int length) { - return toHexString(new StringBuilder(length << 1), src, offset, length).toString(); - } - - /** - * Converts the specified byte array into a hexadecimal value and appends it to the specified buffer. - */ - public static T toHexString(T dst, byte[] src) { - return toHexString(dst, src, 0, src.length); - } - - /** - * Converts the specified byte array into a hexadecimal value and appends it to the specified buffer. - */ - public static T toHexString(T dst, byte[] src, int offset, int length) { - assert length >= 0; - if (length == 0) { - return dst; - } - - final int end = offset + length; - final int endMinusOne = end - 1; - int i; - - // Skip preceding zeroes. - for (i = offset; i < endMinusOne; i ++) { - if (src[i] != 0) { - break; - } - } - - byteToHexString(dst, src[i ++]); - int remaining = end - i; - toHexStringPadded(dst, src, i, remaining); - - return dst; - } - - /** - * The shortcut to {@link #simpleClassName(Class) simpleClassName(o.getClass())}. - */ - public static String simpleClassName(Object o) { - if (o == null) { - return "null_object"; - } else { - return simpleClassName(o.getClass()); - } - } - - /** - * Generates a simplified name from a {@link Class}. Similar to {@link Class#getSimpleName()}, but it works fine - * with anonymous classes. - */ - public static String simpleClassName(Class clazz) { - String className = ObjectUtil.checkNotNull(clazz, "clazz").getName(); - final int lastDotIdx = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR); - if (lastDotIdx > -1) { - return className.substring(lastDotIdx + 1); - } - return className; - } - - /** - * Escapes the specified value, if necessary according to - * RFC-4180. - * - * @param value The value which will be escaped according to - * RFC-4180 - * @return {@link CharSequence} the escaped value if necessary, or the value unchanged - */ - public static CharSequence escapeCsv(CharSequence value) { - int length = checkNotNull(value, "value").length(); - if (length == 0) { - return value; - } - int last = length - 1; - boolean quoted = isDoubleQuote(value.charAt(0)) && isDoubleQuote(value.charAt(last)) && length != 1; - boolean foundSpecialCharacter = false; - boolean escapedDoubleQuote = false; - StringBuilder escaped = new StringBuilder(length + CSV_NUMBER_ESCAPE_CHARACTERS).append(DOUBLE_QUOTE); - for (int i = 0; i < length; i++) { - char current = value.charAt(i); - switch (current) { - case DOUBLE_QUOTE: - if (i == 0 || i == last) { - if (!quoted) { - escaped.append(DOUBLE_QUOTE); - } else { - continue; - } - } else { - boolean isNextCharDoubleQuote = isDoubleQuote(value.charAt(i + 1)); - if (!isDoubleQuote(value.charAt(i - 1)) && - (!isNextCharDoubleQuote || i + 1 == last)) { - escaped.append(DOUBLE_QUOTE); - escapedDoubleQuote = true; - } - break; - } - case LINE_FEED: - case CARRIAGE_RETURN: - case COMMA: - foundSpecialCharacter = true; - } - escaped.append(current); - } - return escapedDoubleQuote || foundSpecialCharacter && !quoted ? - escaped.append(DOUBLE_QUOTE) : value; - } - - /** - * Get the length of a string, {@code null} input is considered {@code 0} length. - */ - public static int length(String s) { - return s == null ? 0 : s.length(); - } - - /** - * Determine if a string is {@code null} or {@link String#isEmpty()} returns {@code true}. - */ - public static boolean isNullOrEmpty(String s) { - return s == null || s.isEmpty(); - } - - private static boolean isDoubleQuote(char c) { - return c == DOUBLE_QUOTE; - } - - private StringUtil() { - // Unused. - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/SystemPropertyUtil.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/SystemPropertyUtil.java deleted file mode 100755 index d5aa795394..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/SystemPropertyUtil.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.internal; - -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.regex.Pattern; - -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * A collection of utility methods to retrieve and parse the values of the Java system properties. - */ -public final class SystemPropertyUtil { - - private static boolean initializedLogger; - private static final InternalLogger logger; - private static boolean loggedException; - - static { - initializedLogger = false; - logger = InternalLoggerFactory.getInstance(SystemPropertyUtil.class); - initializedLogger = true; - } - - /** - * Returns {@code true} if and only if the system property with the specified {@code key} - * exists. - */ - public static boolean contains(String key) { - return get(key) != null; - } - - /** - * Returns the value of the Java system property with the specified - * {@code key}, while falling back to {@code null} if the property access fails. - * - * @return the property value or {@code null} - */ - public static String get(String key) { - return get(key, null); - } - - /** - * Returns the value of the Java system property with the specified - * {@code key}, while falling back to the specified default value if - * the property access fails. - * - * @return the property value. - * {@code def} if there's no such property or if an access to the - * specified property is not allowed. - */ - public static String get(final String key, String def) { - if (key == null) { - throw new NullPointerException("key"); - } - if (key.isEmpty()) { - throw new IllegalArgumentException("key must not be empty."); - } - - String value = null; - try { - if (System.getSecurityManager() == null) { - value = System.getProperty(key); - } else { - value = AccessController.doPrivileged(new PrivilegedAction() { - @Override - public String run() { - return System.getProperty(key); - } - }); - } - } catch (Exception e) { - if (!loggedException) { - log("Unable to retrieve a system property '" + key + "'; default values will be used.", e); - loggedException = true; - } - } - - if (value == null) { - return def; - } - - return value; - } - - /** - * Returns the value of the Java system property with the specified - * {@code key}, while falling back to the specified default value if - * the property access fails. - * - * @return the property value. - * {@code def} if there's no such property or if an access to the - * specified property is not allowed. - */ - public static boolean getBoolean(String key, boolean def) { - String value = get(key); - if (value == null) { - return def; - } - - value = value.trim().toLowerCase(); - if (value.isEmpty()) { - return true; - } - - if ("true".equals(value) || "yes".equals(value) || "1".equals(value)) { - return true; - } - - if ("false".equals(value) || "no".equals(value) || "0".equals(value)) { - return false; - } - - log( - "Unable to parse the boolean system property '" + key + "':" + value + " - " + - "using the default value: " + def); - - return def; - } - - private static final Pattern INTEGER_PATTERN = Pattern.compile("-?[0-9]+"); - - /** - * Returns the value of the Java system property with the specified - * {@code key}, while falling back to the specified default value if - * the property access fails. - * - * @return the property value. - * {@code def} if there's no such property or if an access to the - * specified property is not allowed. - */ - public static int getInt(String key, int def) { - String value = get(key); - if (value == null) { - return def; - } - - value = value.trim().toLowerCase(); - if (INTEGER_PATTERN.matcher(value).matches()) { - try { - return Integer.parseInt(value); - } catch (Exception e) { - // Ignore - } - } - - log( - "Unable to parse the integer system property '" + key + "':" + value + " - " + - "using the default value: " + def); - - return def; - } - - /** - * Returns the value of the Java system property with the specified - * {@code key}, while falling back to the specified default value if - * the property access fails. - * - * @return the property value. - * {@code def} if there's no such property or if an access to the - * specified property is not allowed. - */ - public static long getLong(String key, long def) { - String value = get(key); - if (value == null) { - return def; - } - - value = value.trim().toLowerCase(); - if (INTEGER_PATTERN.matcher(value).matches()) { - try { - return Long.parseLong(value); - } catch (Exception e) { - // Ignore - } - } - - log( - "Unable to parse the long integer system property '" + key + "':" + value + " - " + - "using the default value: " + def); - - return def; - } - - private static void log(String msg) { - if (initializedLogger) { - logger.warn(msg); - } else { - // Use JDK logging if logger was not initialized yet. - Logger.getLogger(SystemPropertyUtil.class.getName()).log(Level.WARNING, msg); - } - } - - private static void log(String msg, Exception e) { - if (initializedLogger) { - logger.warn(msg, e); - } else { - // Use JDK logging if logger was not initialized yet. - Logger.getLogger(SystemPropertyUtil.class.getName()).log(Level.WARNING, msg, e); - } - } - - private SystemPropertyUtil() { - // Unused - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/ThreadLocalRandom.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/ThreadLocalRandom.java deleted file mode 100755 index 9885a50bf1..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/ThreadLocalRandom.java +++ /dev/null @@ -1,336 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/* - * Written by Doug Lea with assistance from members of JCP JSR-166 - * Expert Group and released to the public domain, as explained at - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -package com.ai.cloud.io.netty.util.internal; - -import java.lang.Thread.UncaughtExceptionHandler; -import java.security.SecureRandom; -import java.util.Random; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; - -import com.ai.cloud.io.netty.util.internal.logging.InternalLogger; -import com.ai.cloud.io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * A random number generator isolated to the current thread. Like the - * global {@link java.util.Random} generator used by the {@link - * java.lang.Math} class, a {@code ThreadLocalRandom} is initialized - * with an internally generated seed that may not otherwise be - * modified. When applicable, use of {@code ThreadLocalRandom} rather - * than shared {@code Random} objects in concurrent programs will - * typically encounter much less overhead and contention. Use of - * {@code ThreadLocalRandom} is particularly appropriate when multiple - * tasks (for example, each a {@link com.ai.cloud.io.netty.util.internal.chmv8.ForkJoinTask}) use random numbers - * in parallel in thread pools. - * - *

Usages of this class should typically be of the form: - * {@code ThreadLocalRandom.current().nextX(...)} (where - * {@code X} is {@code Int}, {@code Long}, etc). - * When all usages are of this form, it is never possible to - * accidently share a {@code ThreadLocalRandom} across multiple threads. - * - *

This class also provides additional commonly used bounded random - * generation methods. - * - * //since 1.7 - * //author Doug Lea - */ -@SuppressWarnings("all") -public final class ThreadLocalRandom extends Random { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(ThreadLocalRandom.class); - - private static final AtomicLong seedUniquifier = new AtomicLong(); - - private static volatile long initialSeedUniquifier; - - public static void setInitialSeedUniquifier(long initialSeedUniquifier) { - ThreadLocalRandom.initialSeedUniquifier = initialSeedUniquifier; - } - - public static synchronized long getInitialSeedUniquifier() { - // Use the value set via the setter. - long initialSeedUniquifier = ThreadLocalRandom.initialSeedUniquifier; - if (initialSeedUniquifier == 0) { - // Use the system property value. - ThreadLocalRandom.initialSeedUniquifier = initialSeedUniquifier = - SystemPropertyUtil.getLong("io.netty.initialSeedUniquifier", 0); - } - - // Otherwise, generate one. - if (initialSeedUniquifier == 0) { - // Try to generate a real random number from /dev/random. - // Get from a different thread to avoid blocking indefinitely on a machine without much entropy. - final BlockingQueue queue = new LinkedBlockingQueue(); - Thread generatorThread = new Thread("initialSeedUniquifierGenerator") { - @Override - public void run() { - SecureRandom random = new SecureRandom(); // Get the real random seed from /dev/random - queue.add(random.generateSeed(8)); - } - }; - generatorThread.setDaemon(true); - generatorThread.start(); - generatorThread.setUncaughtExceptionHandler(new UncaughtExceptionHandler() { - @Override - public void uncaughtException(Thread t, Throwable e) { - logger.debug("An exception has been raised by {}", t.getName(), e); - } - }); - - // Get the random seed from the thread with timeout. - final long timeoutSeconds = 3; - final long deadLine = System.nanoTime() + TimeUnit.SECONDS.toNanos(timeoutSeconds); - boolean interrupted = false; - for (;;) { - long waitTime = deadLine - System.nanoTime(); - if (waitTime <= 0) { - generatorThread.interrupt(); - logger.warn( - "Failed to generate a seed from SecureRandom within {} seconds. " + - "Not enough entrophy?", timeoutSeconds - ); - break; - } - - try { - byte[] seed = queue.poll(waitTime, TimeUnit.NANOSECONDS); - if (seed != null) { - initialSeedUniquifier = - ((long) seed[0] & 0xff) << 56 | - ((long) seed[1] & 0xff) << 48 | - ((long) seed[2] & 0xff) << 40 | - ((long) seed[3] & 0xff) << 32 | - ((long) seed[4] & 0xff) << 24 | - ((long) seed[5] & 0xff) << 16 | - ((long) seed[6] & 0xff) << 8 | - (long) seed[7] & 0xff; - break; - } - } catch (InterruptedException e) { - interrupted = true; - logger.warn("Failed to generate a seed from SecureRandom due to an InterruptedException."); - break; - } - } - - // Just in case the initialSeedUniquifier is zero or some other constant - initialSeedUniquifier ^= 0x3255ecdc33bae119L; // just a meaningless random number - initialSeedUniquifier ^= Long.reverse(System.nanoTime()); - - ThreadLocalRandom.initialSeedUniquifier = initialSeedUniquifier; - - if (interrupted) { - // Restore the interrupt status because we don't know how to/don't need to handle it here. - Thread.currentThread().interrupt(); - - // Interrupt the generator thread if it's still running, - // in the hope that the SecureRandom provider raises an exception on interruption. - generatorThread.interrupt(); - } - } - - return initialSeedUniquifier; - } - - private static long newSeed() { - final long startTime = System.nanoTime(); - for (;;) { - final long current = seedUniquifier.get(); - final long actualCurrent = current != 0? current : getInitialSeedUniquifier(); - - // L'Ecuyer, "Tables of Linear Congruential Generators of Different Sizes and Good Lattice Structure", 1999 - final long next = actualCurrent * 181783497276652981L; - - if (seedUniquifier.compareAndSet(current, next)) { - if (current == 0 && logger.isDebugEnabled()) { - logger.debug(String.format( - "-Dio.netty.initialSeedUniquifier: 0x%016x (took %d ms)", - actualCurrent, TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime))); - } - return next ^ System.nanoTime(); - } - } - } - - // same constants as Random, but must be redeclared because private - private static final long multiplier = 0x5DEECE66DL; - private static final long addend = 0xBL; - private static final long mask = (1L << 48) - 1; - - /** - * The random seed. We can't use super.seed. - */ - private long rnd; - - /** - * Initialization flag to permit calls to setSeed to succeed only - * while executing the Random constructor. We can't allow others - * since it would cause setting seed in one part of a program to - * unintentionally impact other usages by the thread. - */ - boolean initialized; - - // Padding to help avoid memory contention among seed updates in - // different TLRs in the common case that they are located near - // each other. - private long pad0, pad1, pad2, pad3, pad4, pad5, pad6, pad7; - - /** - * Constructor called only by localRandom.initialValue. - */ - ThreadLocalRandom() { - super(newSeed()); - initialized = true; - } - - /** - * Returns the current thread's {@code ThreadLocalRandom}. - * - * @return the current thread's {@code ThreadLocalRandom} - */ - public static ThreadLocalRandom current() { - return InternalThreadLocalMap.get().random(); - } - - /** - * Throws {@code UnsupportedOperationException}. Setting seeds in - * this generator is not supported. - * - * @throws UnsupportedOperationException always - */ - public void setSeed(long seed) { - if (initialized) { - throw new UnsupportedOperationException(); - } - rnd = (seed ^ multiplier) & mask; - } - - protected int next(int bits) { - rnd = (rnd * multiplier + addend) & mask; - return (int) (rnd >>> (48 - bits)); - } - - /** - * Returns a pseudorandom, uniformly distributed value between the - * given least value (inclusive) and bound (exclusive). - * - * @param least the least value returned - * @param bound the upper bound (exclusive) - * @throws IllegalArgumentException if least greater than or equal - * to bound - * @return the next value - */ - public int nextInt(int least, int bound) { - if (least >= bound) { - throw new IllegalArgumentException(); - } - return nextInt(bound - least) + least; - } - - /** - * Returns a pseudorandom, uniformly distributed value - * between 0 (inclusive) and the specified value (exclusive). - * - * @param n the bound on the random number to be returned. Must be - * positive. - * @return the next value - * @throws IllegalArgumentException if n is not positive - */ - public long nextLong(long n) { - if (n <= 0) { - throw new IllegalArgumentException("n must be positive"); - } - - // Divide n by two until small enough for nextInt. On each - // iteration (at most 31 of them but usually much less), - // randomly choose both whether to include high bit in result - // (offset) and whether to continue with the lower vs upper - // half (which makes a difference only if odd). - long offset = 0; - while (n >= Integer.MAX_VALUE) { - int bits = next(2); - long half = n >>> 1; - long nextn = ((bits & 2) == 0) ? half : n - half; - if ((bits & 1) == 0) { - offset += n - nextn; - } - n = nextn; - } - return offset + nextInt((int) n); - } - - /** - * Returns a pseudorandom, uniformly distributed value between the - * given least value (inclusive) and bound (exclusive). - * - * @param least the least value returned - * @param bound the upper bound (exclusive) - * @return the next value - * @throws IllegalArgumentException if least greater than or equal - * to bound - */ - public long nextLong(long least, long bound) { - if (least >= bound) { - throw new IllegalArgumentException(); - } - return nextLong(bound - least) + least; - } - - /** - * Returns a pseudorandom, uniformly distributed {@code double} value - * between 0 (inclusive) and the specified value (exclusive). - * - * @param n the bound on the random number to be returned. Must be - * positive. - * @return the next value - * @throws IllegalArgumentException if n is not positive - */ - public double nextDouble(double n) { - if (n <= 0) { - throw new IllegalArgumentException("n must be positive"); - } - return nextDouble() * n; - } - - /** - * Returns a pseudorandom, uniformly distributed value between the - * given least value (inclusive) and bound (exclusive). - * - * @param least the least value returned - * @param bound the upper bound (exclusive) - * @return the next value - * @throws IllegalArgumentException if least greater than or equal - * to bound - */ - public double nextDouble(double least, double bound) { - if (least >= bound) { - throw new IllegalArgumentException(); - } - return nextDouble() * (bound - least) + least; - } - - private static final long serialVersionUID = -5851777807851030925L; -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/TypeParameterMatcher.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/TypeParameterMatcher.java deleted file mode 100755 index 7593af55b4..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/TypeParameterMatcher.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.util.internal; - -import java.lang.reflect.Array; -import java.lang.reflect.GenericArrayType; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.util.HashMap; -import java.util.Map; - -public abstract class TypeParameterMatcher { - - private static final TypeParameterMatcher NOOP = new NoOpTypeParameterMatcher(); - private static final Object TEST_OBJECT = new Object(); - - public static TypeParameterMatcher get(final Class parameterType) { - final Map, TypeParameterMatcher> getCache = - InternalThreadLocalMap.get().typeParameterMatcherGetCache(); - - TypeParameterMatcher matcher = getCache.get(parameterType); - if (matcher == null) { - if (parameterType == Object.class) { - matcher = NOOP; - } else if (PlatformDependent.hasJavassist()) { - try { - matcher = JavassistTypeParameterMatcherGenerator.generate(parameterType); - matcher.match(TEST_OBJECT); - } catch (IllegalAccessError e) { - // Happens if parameterType is not public. - matcher = null; - } catch (Exception e) { - // Will not usually happen, but just in case. - matcher = null; - } - } - - if (matcher == null) { - matcher = new ReflectiveMatcher(parameterType); - } - - getCache.put(parameterType, matcher); - } - - return matcher; - } - - public static TypeParameterMatcher find( - final Object object, final Class parameterizedSuperclass, final String typeParamName) { - - final Map, Map> findCache = - InternalThreadLocalMap.get().typeParameterMatcherFindCache(); - final Class thisClass = object.getClass(); - - Map map = findCache.get(thisClass); - if (map == null) { - map = new HashMap(); - findCache.put(thisClass, map); - } - - TypeParameterMatcher matcher = map.get(typeParamName); - if (matcher == null) { - matcher = get(find0(object, parameterizedSuperclass, typeParamName)); - map.put(typeParamName, matcher); - } - - return matcher; - } - - private static Class find0( - final Object object, Class parameterizedSuperclass, String typeParamName) { - - final Class thisClass = object.getClass(); - Class currentClass = thisClass; - for (;;) { - if (currentClass.getSuperclass() == parameterizedSuperclass) { - int typeParamIndex = -1; - TypeVariable[] typeParams = currentClass.getSuperclass().getTypeParameters(); - for (int i = 0; i < typeParams.length; i ++) { - if (typeParamName.equals(typeParams[i].getName())) { - typeParamIndex = i; - break; - } - } - - if (typeParamIndex < 0) { - throw new IllegalStateException( - "unknown type parameter '" + typeParamName + "': " + parameterizedSuperclass); - } - - Type genericSuperType = currentClass.getGenericSuperclass(); - if (!(genericSuperType instanceof ParameterizedType)) { - return Object.class; - } - - Type[] actualTypeParams = ((ParameterizedType) genericSuperType).getActualTypeArguments(); - - Type actualTypeParam = actualTypeParams[typeParamIndex]; - if (actualTypeParam instanceof ParameterizedType) { - actualTypeParam = ((ParameterizedType) actualTypeParam).getRawType(); - } - if (actualTypeParam instanceof Class) { - return (Class) actualTypeParam; - } - if (actualTypeParam instanceof GenericArrayType) { - Type componentType = ((GenericArrayType) actualTypeParam).getGenericComponentType(); - if (componentType instanceof ParameterizedType) { - componentType = ((ParameterizedType) componentType).getRawType(); - } - if (componentType instanceof Class) { - return Array.newInstance((Class) componentType, 0).getClass(); - } - } - if (actualTypeParam instanceof TypeVariable) { - // Resolved type parameter points to another type parameter. - TypeVariable v = (TypeVariable) actualTypeParam; - currentClass = thisClass; - if (!(v.getGenericDeclaration() instanceof Class)) { - return Object.class; - } - - parameterizedSuperclass = (Class) v.getGenericDeclaration(); - typeParamName = v.getName(); - if (parameterizedSuperclass.isAssignableFrom(thisClass)) { - continue; - } else { - return Object.class; - } - } - - return fail(thisClass, typeParamName); - } - currentClass = currentClass.getSuperclass(); - if (currentClass == null) { - return fail(thisClass, typeParamName); - } - } - } - - private static Class fail(Class type, String typeParamName) { - throw new IllegalStateException( - "cannot determine the type of the type parameter '" + typeParamName + "': " + type); - } - - public abstract boolean match(Object msg); - - private static final class ReflectiveMatcher extends TypeParameterMatcher { - private final Class type; - - ReflectiveMatcher(Class type) { - this.type = type; - } - - @Override - public boolean match(Object msg) { - return type.isInstance(msg); - } - } - - protected TypeParameterMatcher() { } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/UnpaddedInternalThreadLocalMap.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/UnpaddedInternalThreadLocalMap.java deleted file mode 100755 index 51f0b55458..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/UnpaddedInternalThreadLocalMap.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package com.ai.cloud.io.netty.util.internal; - -import java.nio.charset.Charset; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CharsetEncoder; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; - -import com.ai.cloud.io.netty.util.concurrent.FastThreadLocal; - -/** - * The internal data structure that stores the thread-local variables for Netty and all {@link FastThreadLocal}s. - * Note that this class is for internal use only and is subject to change at any time. Use {@link FastThreadLocal} - * unless you know what you are doing. - */ -class UnpaddedInternalThreadLocalMap { - - static ThreadLocal slowThreadLocalMap; - static final AtomicInteger nextIndex = new AtomicInteger(); - - /** Used by {@link FastThreadLocal} */ - Object[] indexedVariables; - - // Core thread-locals - int futureListenerStackDepth; - int localChannelReaderStackDepth; - Map, Boolean> handlerSharableCache; - IntegerHolder counterHashCode; - ThreadLocalRandom random; - Map, TypeParameterMatcher> typeParameterMatcherGetCache; - Map, Map> typeParameterMatcherFindCache; - - // String-related thread-locals - StringBuilder stringBuilder; - Map charsetEncoderCache; - Map charsetDecoderCache; - - UnpaddedInternalThreadLocalMap(Object[] indexedVariables) { - this.indexedVariables = indexedVariables; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/UnsafeAtomicIntegerFieldUpdater.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/UnsafeAtomicIntegerFieldUpdater.java deleted file mode 100755 index f99c63cd55..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/UnsafeAtomicIntegerFieldUpdater.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.internal; - -import sun.misc.Unsafe; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; - -final class UnsafeAtomicIntegerFieldUpdater extends AtomicIntegerFieldUpdater { - private final long offset; - private final Unsafe unsafe; - - UnsafeAtomicIntegerFieldUpdater(Unsafe unsafe, Class tClass, String fieldName) throws NoSuchFieldException { - Field field = tClass.getDeclaredField(fieldName); - if (!Modifier.isVolatile(field.getModifiers())) { - throw new IllegalArgumentException("Must be volatile"); - } - this.unsafe = unsafe; - offset = unsafe.objectFieldOffset(field); - } - - @Override - public boolean compareAndSet(T obj, int expect, int update) { - return unsafe.compareAndSwapInt(obj, offset, expect, update); - } - - @Override - public boolean weakCompareAndSet(T obj, int expect, int update) { - return unsafe.compareAndSwapInt(obj, offset, expect, update); - } - - @Override - public void set(T obj, int newValue) { - unsafe.putIntVolatile(obj, offset, newValue); - } - - @Override - public void lazySet(T obj, int newValue) { - unsafe.putOrderedInt(obj, offset, newValue); - } - - @Override - public int get(T obj) { - return unsafe.getIntVolatile(obj, offset); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/UnsafeAtomicLongFieldUpdater.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/UnsafeAtomicLongFieldUpdater.java deleted file mode 100755 index ebef25b7ab..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/UnsafeAtomicLongFieldUpdater.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.internal; - -import sun.misc.Unsafe; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.concurrent.atomic.AtomicLongFieldUpdater; - -final class UnsafeAtomicLongFieldUpdater extends AtomicLongFieldUpdater { - private final long offset; - private final Unsafe unsafe; - - UnsafeAtomicLongFieldUpdater(Unsafe unsafe, Class tClass, String fieldName) throws NoSuchFieldException { - Field field = tClass.getDeclaredField(fieldName); - if (!Modifier.isVolatile(field.getModifiers())) { - throw new IllegalArgumentException("Must be volatile"); - } - this.unsafe = unsafe; - offset = unsafe.objectFieldOffset(field); - } - - @Override - public boolean compareAndSet(T obj, long expect, long update) { - return unsafe.compareAndSwapLong(obj, offset, expect, update); - } - - @Override - public boolean weakCompareAndSet(T obj, long expect, long update) { - return unsafe.compareAndSwapLong(obj, offset, expect, update); - } - - @Override - public void set(T obj, long newValue) { - unsafe.putLongVolatile(obj, offset, newValue); - } - - @Override - public void lazySet(T obj, long newValue) { - unsafe.putOrderedLong(obj, offset, newValue); - } - - @Override - public long get(T obj) { - return unsafe.getLongVolatile(obj, offset); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/UnsafeAtomicReferenceFieldUpdater.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/UnsafeAtomicReferenceFieldUpdater.java deleted file mode 100755 index 456f64e6e3..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/UnsafeAtomicReferenceFieldUpdater.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.internal; - -import sun.misc.Unsafe; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; - -final class UnsafeAtomicReferenceFieldUpdater extends AtomicReferenceFieldUpdater { - private final long offset; - private final Unsafe unsafe; - - UnsafeAtomicReferenceFieldUpdater(Unsafe unsafe, Class tClass, String fieldName) throws NoSuchFieldException { - Field field = tClass.getDeclaredField(fieldName); - if (!Modifier.isVolatile(field.getModifiers())) { - throw new IllegalArgumentException("Must be volatile"); - } - this.unsafe = unsafe; - offset = unsafe.objectFieldOffset(field); - } - - @Override - public boolean compareAndSet(U obj, M expect, M update) { - return unsafe.compareAndSwapObject(obj, offset, expect, update); - } - - @Override - public boolean weakCompareAndSet(U obj, M expect, M update) { - return unsafe.compareAndSwapObject(obj, offset, expect, update); - } - - @Override - public void set(U obj, M newValue) { - unsafe.putObjectVolatile(obj, offset, newValue); - } - - @Override - public void lazySet(U obj, M newValue) { - unsafe.putOrderedObject(obj, offset, newValue); - } - - @SuppressWarnings("unchecked") - @Override - public M get(U obj) { - return (M) unsafe.getObjectVolatile(obj, offset); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/chmv8/ConcurrentHashMapV8.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/chmv8/ConcurrentHashMapV8.java deleted file mode 100755 index af7262aad7..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/chmv8/ConcurrentHashMapV8.java +++ /dev/null @@ -1,6205 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/* - * Written by Doug Lea with assistance from members of JCP JSR-166 - * Expert Group and released to the public domain, as explained at - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -package com.ai.cloud.io.netty.util.internal.chmv8; - -import java.io.ObjectStreamField; -import java.io.Serializable; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.Arrays; -import java.util.Collection; -import java.util.ConcurrentModificationException; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Hashtable; -import java.util.Iterator; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Set; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; -import java.util.concurrent.locks.LockSupport; -import java.util.concurrent.locks.ReentrantLock; - -import com.ai.cloud.io.netty.util.internal.IntegerHolder; -import com.ai.cloud.io.netty.util.internal.InternalThreadLocalMap; - -/** - * A hash table supporting full concurrency of retrievals and - * high expected concurrency for updates. This class obeys the - * same functional specification as {@link java.util.Hashtable}, and - * includes versions of methods corresponding to each method of - * {@code Hashtable}. However, even though all operations are - * thread-safe, retrieval operations do not entail locking, - * and there is not any support for locking the entire table - * in a way that prevents all access. This class is fully - * interoperable with {@code Hashtable} in programs that rely on its - * thread safety but not on its synchronization details. - * - *

Retrieval operations (including {@code get}) generally do not - * block, so may overlap with update operations (including {@code put} - * and {@code remove}). Retrievals reflect the results of the most - * recently completed update operations holding upon their - * onset. (More formally, an update operation for a given key bears a - * happens-before relation with any (non-null) retrieval for - * that key reporting the updated value.) For aggregate operations - * such as {@code putAll} and {@code clear}, concurrent retrievals may - * reflect insertion or removal of only some entries. Similarly, - * Iterators and Enumerations return elements reflecting the state of - * the hash table at some point at or since the creation of the - * iterator/enumeration. They do not throw {@link - * ConcurrentModificationException}. However, iterators are designed - * to be used by only one thread at a time. Bear in mind that the - * results of aggregate status methods including {@code size}, {@code - * isEmpty}, and {@code containsValue} are typically useful only when - * a map is not undergoing concurrent updates in other threads. - * Otherwise the results of these methods reflect transient states - * that may be adequate for monitoring or estimation purposes, but not - * for program control. - * - *

The table is dynamically expanded when there are too many - * collisions (i.e., keys that have distinct hash codes but fall into - * the same slot modulo the table size), with the expected average - * effect of maintaining roughly two bins per mapping (corresponding - * to a 0.75 load factor threshold for resizing). There may be much - * variance around this average as mappings are added and removed, but - * overall, this maintains a commonly accepted time/space tradeoff for - * hash tables. However, resizing this or any other kind of hash - * table may be a relatively slow operation. When possible, it is a - * good idea to provide a size estimate as an optional {@code - * initialCapacity} constructor argument. An additional optional - * {@code loadFactor} constructor argument provides a further means of - * customizing initial table capacity by specifying the table density - * to be used in calculating the amount of space to allocate for the - * given number of elements. Also, for compatibility with previous - * versions of this class, constructors may optionally specify an - * expected {@code concurrencyLevel} as an additional hint for - * internal sizing. Note that using many keys with exactly the same - * {@code hashCode()} is a sure way to slow down performance of any - * hash table. To ameliorate impact, when keys are {@link Comparable}, - * this class may use comparison order among keys to help break ties. - * - *

A {@link Set} projection of a ConcurrentHashMapV8 may be created - * (using {@link #newKeySet()} or {@link #newKeySet(int)}), or viewed - * (using {@link #keySet(Object)} when only keys are of interest, and the - * mapped values are (perhaps transiently) not used or all take the - * same mapping value. - * - *

This class and its views and iterators implement all of the - * optional methods of the {@link Map} and {@link Iterator} - * interfaces. - * - *

Like {@link Hashtable} but unlike {@link HashMap}, this class - * does not allow {@code null} to be used as a key or value. - * - *

ConcurrentHashMapV8s support a set of sequential and parallel bulk - * operations that are designed - * to be safely, and often sensibly, applied even with maps that are - * being concurrently updated by other threads; for example, when - * computing a snapshot summary of the values in a shared registry. - * There are three kinds of operation, each with four forms, accepting - * functions with Keys, Values, Entries, and (Key, Value) arguments - * and/or return values. Because the elements of a ConcurrentHashMapV8 - * are not ordered in any particular way, and may be processed in - * different orders in different parallel executions, the correctness - * of supplied functions should not depend on any ordering, or on any - * other objects or values that may transiently change while - * computation is in progress; and except for forEach actions, should - * ideally be side-effect-free. Bulk operations on {@link java.util.Map.Entry} - * objects do not support method {@code setValue}. - * - *

    - *
  • forEach: Perform a given action on each element. - * A variant form applies a given transformation on each element - * before performing the action.
  • - * - *
  • search: Return the first available non-null result of - * applying a given function on each element; skipping further - * search when a result is found.
  • - * - *
  • reduce: Accumulate each element. The supplied reduction - * function cannot rely on ordering (more formally, it should be - * both associative and commutative). There are five variants: - * - *
      - * - *
    • Plain reductions. (There is not a form of this method for - * (key, value) function arguments since there is no corresponding - * return type.)
    • - * - *
    • Mapped reductions that accumulate the results of a given - * function applied to each element.
    • - * - *
    • Reductions to scalar doubles, longs, and ints, using a - * given basis value.
    • - * - *
    - *
  • - *
- * - *

These bulk operations accept a {@code parallelismThreshold} - * argument. Methods proceed sequentially if the current map size is - * estimated to be less than the given threshold. Using a value of - * {@code Long.MAX_VALUE} suppresses all parallelism. Using a value - * of {@code 1} results in maximal parallelism by partitioning into - * enough subtasks to fully utilize the {@link - * ForkJoinPool#commonPool()} that is used for all parallel - * computations. Normally, you would initially choose one of these - * extreme values, and then measure performance of using in-between - * values that trade off overhead versus throughput. - * - *

The concurrency properties of bulk operations follow - * from those of ConcurrentHashMapV8: Any non-null result returned - * from {@code get(key)} and related access methods bears a - * happens-before relation with the associated insertion or - * update. The result of any bulk operation reflects the - * composition of these per-element relations (but is not - * necessarily atomic with respect to the map as a whole unless it - * is somehow known to be quiescent). Conversely, because keys - * and values in the map are never null, null serves as a reliable - * atomic indicator of the current lack of any result. To - * maintain this property, null serves as an implicit basis for - * all non-scalar reduction operations. For the double, long, and - * int versions, the basis should be one that, when combined with - * any other value, returns that other value (more formally, it - * should be the identity element for the reduction). Most common - * reductions have these properties; for example, computing a sum - * with basis 0 or a minimum with basis MAX_VALUE. - * - *

Search and transformation functions provided as arguments - * should similarly return null to indicate the lack of any result - * (in which case it is not used). In the case of mapped - * reductions, this also enables transformations to serve as - * filters, returning null (or, in the case of primitive - * specializations, the identity basis) if the element should not - * be combined. You can create compound transformations and - * filterings by composing them yourself under this "null means - * there is nothing there now" rule before using them in search or - * reduce operations. - * - *

Methods accepting and/or returning Entry arguments maintain - * key-value associations. They may be useful for example when - * finding the key for the greatest value. Note that "plain" Entry - * arguments can be supplied using {@code new - * AbstractMap.SimpleEntry(k,v)}. - * - *

Bulk operations may complete abruptly, throwing an - * exception encountered in the application of a supplied - * function. Bear in mind when handling such exceptions that other - * concurrently executing functions could also have thrown - * exceptions, or would have done so if the first exception had - * not occurred. - * - *

Speedups for parallel compared to sequential forms are common - * but not guaranteed. Parallel operations involving brief functions - * on small maps may execute more slowly than sequential forms if the - * underlying work to parallelize the computation is more expensive - * than the computation itself. Similarly, parallelization may not - * lead to much actual parallelism if all processors are busy - * performing unrelated tasks. - * - *

All arguments to all task methods must be non-null. - * - *

jsr166e note: During transition, this class - * uses nested functional interfaces with different names but the - * same forms as those expected for JDK8. - * - *

This class is a member of the - * - * Java Collections Framework. - * - * @since 1.5 - * @author Doug Lea - * @param the type of keys maintained by this map - * @param the type of mapped values - */ -@SuppressWarnings("all") -public class ConcurrentHashMapV8 - implements ConcurrentMap, Serializable { - private static final long serialVersionUID = 7249069246763182397L; - - /** - * An object for traversing and partitioning elements of a source. - * This interface provides a subset of the functionality of JDK8 - * java.util.Spliterator. - */ - public static interface ConcurrentHashMapSpliterator { - /** - * If possible, returns a new spliterator covering - * approximately one half of the elements, which will not be - * covered by this spliterator. Returns null if cannot be - * split. - */ - ConcurrentHashMapSpliterator trySplit(); - /** - * Returns an estimate of the number of elements covered by - * this Spliterator. - */ - long estimateSize(); - - /** Applies the action to each untraversed element */ - void forEachRemaining(Action action); - /** If an element remains, applies the action and returns true. */ - boolean tryAdvance(Action action); - } - - // Sams - /** Interface describing a void action of one argument */ - public interface Action { void apply(A a); } - /** Interface describing a void action of two arguments */ - public interface BiAction { void apply(A a, B b); } - /** Interface describing a function of one argument */ - public interface Fun { T apply(A a); } - /** Interface describing a function of two arguments */ - public interface BiFun { T apply(A a, B b); } - /** Interface describing a function mapping its argument to a double */ - public interface ObjectToDouble { double apply(A a); } - /** Interface describing a function mapping its argument to a long */ - public interface ObjectToLong { long apply(A a); } - /** Interface describing a function mapping its argument to an int */ - public interface ObjectToInt {int apply(A a); } - /** Interface describing a function mapping two arguments to a double */ - public interface ObjectByObjectToDouble { double apply(A a, B b); } - /** Interface describing a function mapping two arguments to a long */ - public interface ObjectByObjectToLong { long apply(A a, B b); } - /** Interface describing a function mapping two arguments to an int */ - public interface ObjectByObjectToInt {int apply(A a, B b); } - /** Interface describing a function mapping two doubles to a double */ - public interface DoubleByDoubleToDouble { double apply(double a, double b); } - /** Interface describing a function mapping two longs to a long */ - public interface LongByLongToLong { long apply(long a, long b); } - /** Interface describing a function mapping two ints to an int */ - public interface IntByIntToInt { int apply(int a, int b); } - - /* - * Overview: - * - * The primary design goal of this hash table is to maintain - * concurrent readability (typically method get(), but also - * iterators and related methods) while minimizing update - * contention. Secondary goals are to keep space consumption about - * the same or better than java.util.HashMap, and to support high - * initial insertion rates on an empty table by many threads. - * - * This map usually acts as a binned (bucketed) hash table. Each - * key-value mapping is held in a Node. Most nodes are instances - * of the basic Node class with hash, key, value, and next - * fields. However, various subclasses exist: TreeNodes are - * arranged in balanced trees, not lists. TreeBins hold the roots - * of sets of TreeNodes. ForwardingNodes are placed at the heads - * of bins during resizing. ReservationNodes are used as - * placeholders while establishing values in computeIfAbsent and - * related methods. The types TreeBin, ForwardingNode, and - * ReservationNode do not hold normal user keys, values, or - * hashes, and are readily distinguishable during search etc - * because they have negative hash fields and null key and value - * fields. (These special nodes are either uncommon or transient, - * so the impact of carrying around some unused fields is - * insignificant.) - * - * The table is lazily initialized to a power-of-two size upon the - * first insertion. Each bin in the table normally contains a - * list of Nodes (most often, the list has only zero or one Node). - * Table accesses require volatile/atomic reads, writes, and - * CASes. Because there is no other way to arrange this without - * adding further indirections, we use intrinsics - * (sun.misc.Unsafe) operations. - * - * We use the top (sign) bit of Node hash fields for control - * purposes -- it is available anyway because of addressing - * constraints. Nodes with negative hash fields are specially - * handled or ignored in map methods. - * - * Insertion (via put or its variants) of the first node in an - * empty bin is performed by just CASing it to the bin. This is - * by far the most common case for put operations under most - * key/hash distributions. Other update operations (insert, - * delete, and replace) require locks. We do not want to waste - * the space required to associate a distinct lock object with - * each bin, so instead use the first node of a bin list itself as - * a lock. Locking support for these locks relies on builtin - * "synchronized" monitors. - * - * Using the first node of a list as a lock does not by itself - * suffice though: When a node is locked, any update must first - * validate that it is still the first node after locking it, and - * retry if not. Because new nodes are always appended to lists, - * once a node is first in a bin, it remains first until deleted - * or the bin becomes invalidated (upon resizing). - * - * The main disadvantage of per-bin locks is that other update - * operations on other nodes in a bin list protected by the same - * lock can stall, for example when user equals() or mapping - * functions take a long time. However, statistically, under - * random hash codes, this is not a common problem. Ideally, the - * frequency of nodes in bins follows a Poisson distribution - * (http://en.wikipedia.org/wiki/Poisson_distribution) with a - * parameter of about 0.5 on average, given the resizing threshold - * of 0.75, although with a large variance because of resizing - * granularity. Ignoring variance, the expected occurrences of - * list size k are (exp(-0.5) * pow(0.5, k) / factorial(k)). The - * first values are: - * - * 0: 0.60653066 - * 1: 0.30326533 - * 2: 0.07581633 - * 3: 0.01263606 - * 4: 0.00157952 - * 5: 0.00015795 - * 6: 0.00001316 - * 7: 0.00000094 - * 8: 0.00000006 - * more: less than 1 in ten million - * - * Lock contention probability for two threads accessing distinct - * elements is roughly 1 / (8 * #elements) under random hashes. - * - * Actual hash code distributions encountered in practice - * sometimes deviate significantly from uniform randomness. This - * includes the case when N > (1<<30), so some keys MUST collide. - * Similarly for dumb or hostile usages in which multiple keys are - * designed to have identical hash codes or ones that differs only - * in masked-out high bits. So we use a secondary strategy that - * applies when the number of nodes in a bin exceeds a - * threshold. These TreeBins use a balanced tree to hold nodes (a - * specialized form of red-black trees), bounding search time to - * O(log N). Each search step in a TreeBin is at least twice as - * slow as in a regular list, but given that N cannot exceed - * (1<<64) (before running out of addresses) this bounds search - * steps, lock hold times, etc, to reasonable constants (roughly - * 100 nodes inspected per operation worst case) so long as keys - * are Comparable (which is very common -- String, Long, etc). - * TreeBin nodes (TreeNodes) also maintain the same "next" - * traversal pointers as regular nodes, so can be traversed in - * iterators in the same way. - * - * The table is resized when occupancy exceeds a percentage - * threshold (nominally, 0.75, but see below). Any thread - * noticing an overfull bin may assist in resizing after the - * initiating thread allocates and sets up the replacement - * array. However, rather than stalling, these other threads may - * proceed with insertions etc. The use of TreeBins shields us - * from the worst case effects of overfilling while resizes are in - * progress. Resizing proceeds by transferring bins, one by one, - * from the table to the next table. To enable concurrency, the - * next table must be (incrementally) prefilled with place-holders - * serving as reverse forwarders to the old table. Because we are - * using power-of-two expansion, the elements from each bin must - * either stay at same index, or move with a power of two - * offset. We eliminate unnecessary node creation by catching - * cases where old nodes can be reused because their next fields - * won't change. On average, only about one-sixth of them need - * cloning when a table doubles. The nodes they replace will be - * garbage collectable as soon as they are no longer referenced by - * any reader thread that may be in the midst of concurrently - * traversing table. Upon transfer, the old table bin contains - * only a special forwarding node (with hash field "MOVED") that - * contains the next table as its key. On encountering a - * forwarding node, access and update operations restart, using - * the new table. - * - * Each bin transfer requires its bin lock, which can stall - * waiting for locks while resizing. However, because other - * threads can join in and help resize rather than contend for - * locks, average aggregate waits become shorter as resizing - * progresses. The transfer operation must also ensure that all - * accessible bins in both the old and new table are usable by any - * traversal. This is arranged by proceeding from the last bin - * (table.length - 1) up towards the first. Upon seeing a - * forwarding node, traversals (see class Traverser) arrange to - * move to the new table without revisiting nodes. However, to - * ensure that no intervening nodes are skipped, bin splitting can - * only begin after the associated reverse-forwarders are in - * place. - * - * The traversal scheme also applies to partial traversals of - * ranges of bins (via an alternate Traverser constructor) - * to support partitioned aggregate operations. Also, read-only - * operations give up if ever forwarded to a null table, which - * provides support for shutdown-style clearing, which is also not - * currently implemented. - * - * Lazy table initialization minimizes footprint until first use, - * and also avoids resizings when the first operation is from a - * putAll, constructor with map argument, or deserialization. - * These cases attempt to override the initial capacity settings, - * but harmlessly fail to take effect in cases of races. - * - * The element count is maintained using a specialization of - * LongAdder. We need to incorporate a specialization rather than - * just use a LongAdder in order to access implicit - * contention-sensing that leads to creation of multiple - * CounterCells. The counter mechanics avoid contention on - * updates but can encounter cache thrashing if read too - * frequently during concurrent access. To avoid reading so often, - * resizing under contention is attempted only upon adding to a - * bin already holding two or more nodes. Under uniform hash - * distributions, the probability of this occurring at threshold - * is around 13%, meaning that only about 1 in 8 puts check - * threshold (and after resizing, many fewer do so). - * - * TreeBins use a special form of comparison for search and - * related operations (which is the main reason we cannot use - * existing collections such as TreeMaps). TreeBins contain - * Comparable elements, but may contain others, as well as - * elements that are Comparable but not necessarily Comparable - * for the same T, so we cannot invoke compareTo among them. To - * handle this, the tree is ordered primarily by hash value, then - * by Comparable.compareTo order if applicable. On lookup at a - * node, if elements are not comparable or compare as 0 then both - * left and right children may need to be searched in the case of - * tied hash values. (This corresponds to the full list search - * that would be necessary if all elements were non-Comparable and - * had tied hashes.) The red-black balancing code is updated from - * pre-jdk-collections - * (http://gee.cs.oswego.edu/dl/classes/collections/RBCell.java) - * based in turn on Cormen, Leiserson, and Rivest "Introduction to - * Algorithms" (CLR). - * - * TreeBins also require an additional locking mechanism. While - * list traversal is always possible by readers even during - * updates, tree traversal is not, mainly because of tree-rotations - * that may change the root node and/or its linkages. TreeBins - * include a simple read-write lock mechanism parasitic on the - * main bin-synchronization strategy: Structural adjustments - * associated with an insertion or removal are already bin-locked - * (and so cannot conflict with other writers) but must wait for - * ongoing readers to finish. Since there can be only one such - * waiter, we use a simple scheme using a single "waiter" field to - * block writers. However, readers need never block. If the root - * lock is held, they proceed along the slow traversal path (via - * next-pointers) until the lock becomes available or the list is - * exhausted, whichever comes first. These cases are not fast, but - * maximize aggregate expected throughput. - * - * Maintaining API and serialization compatibility with previous - * versions of this class introduces several oddities. Mainly: We - * leave untouched but unused constructor arguments refering to - * concurrencyLevel. We accept a loadFactor constructor argument, - * but apply it only to initial table capacity (which is the only - * time that we can guarantee to honor it.) We also declare an - * unused "Segment" class that is instantiated in minimal form - * only when serializing. - * - * This file is organized to make things a little easier to follow - * while reading than they might otherwise: First the main static - * declarations and utilities, then fields, then main public - * methods (with a few factorings of multiple public methods into - * internal ones), then sizing methods, trees, traversers, and - * bulk operations. - */ - - /* ---------------- Constants -------------- */ - - /** - * The largest possible table capacity. This value must be - * exactly 1<<30 to stay within Java array allocation and indexing - * bounds for power of two table sizes, and is further required - * because the top two bits of 32bit hash fields are used for - * control purposes. - */ - private static final int MAXIMUM_CAPACITY = 1 << 30; - - /** - * The default initial table capacity. Must be a power of 2 - * (i.e., at least 1) and at most MAXIMUM_CAPACITY. - */ - private static final int DEFAULT_CAPACITY = 16; - - /** - * The largest possible (non-power of two) array size. - * Needed by toArray and related methods. - */ - static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; - - /** - * The default concurrency level for this table. Unused but - * defined for compatibility with previous versions of this class. - */ - private static final int DEFAULT_CONCURRENCY_LEVEL = 16; - - /** - * The load factor for this table. Overrides of this value in - * constructors affect only the initial table capacity. The - * actual floating point value isn't normally used -- it is - * simpler to use expressions such as {@code n - (n >>> 2)} for - * the associated resizing threshold. - */ - private static final float LOAD_FACTOR = 0.75f; - - /** - * The bin count threshold for using a tree rather than list for a - * bin. Bins are converted to trees when adding an element to a - * bin with at least this many nodes. The value must be greater - * than 2, and should be at least 8 to mesh with assumptions in - * tree removal about conversion back to plain bins upon - * shrinkage. - */ - static final int TREEIFY_THRESHOLD = 8; - - /** - * The bin count threshold for untreeifying a (split) bin during a - * resize operation. Should be less than TREEIFY_THRESHOLD, and at - * most 6 to mesh with shrinkage detection under removal. - */ - static final int UNTREEIFY_THRESHOLD = 6; - - /** - * The smallest table capacity for which bins may be treeified. - * (Otherwise the table is resized if too many nodes in a bin.) - * The value should be at least 4 * TREEIFY_THRESHOLD to avoid - * conflicts between resizing and treeification thresholds. - */ - static final int MIN_TREEIFY_CAPACITY = 64; - - /** - * Minimum number of rebinnings per transfer step. Ranges are - * subdivided to allow multiple resizer threads. This value - * serves as a lower bound to avoid resizers encountering - * excessive memory contention. The value should be at least - * DEFAULT_CAPACITY. - */ - private static final int MIN_TRANSFER_STRIDE = 16; - - /* - * Encodings for Node hash fields. See above for explanation. - */ - static final int MOVED = -1; // hash for forwarding nodes - static final int TREEBIN = -2; // hash for roots of trees - static final int RESERVED = -3; // hash for transient reservations - static final int HASH_BITS = 0x7fffffff; // usable bits of normal node hash - - /** Number of CPUS, to place bounds on some sizings */ - static final int NCPU = Runtime.getRuntime().availableProcessors(); - - /** For serialization compatibility. */ - private static final ObjectStreamField[] serialPersistentFields = { - new ObjectStreamField("segments", Segment[].class), - new ObjectStreamField("segmentMask", Integer.TYPE), - new ObjectStreamField("segmentShift", Integer.TYPE) - }; - - /* ---------------- Nodes -------------- */ - - /** - * Key-value entry. This class is never exported out as a - * user-mutable Map.Entry (i.e., one supporting setValue; see - * MapEntry below), but can be used for read-only traversals used - * in bulk tasks. Subclasses of Node with a negative hash field - * are special, and contain null keys and values (but are never - * exported). Otherwise, keys and vals are never null. - */ - static class Node implements Map.Entry { - final int hash; - final K key; - volatile V val; - volatile Node next; - - Node(int hash, K key, V val, Node next) { - this.hash = hash; - this.key = key; - this.val = val; - this.next = next; - } - - public final K getKey() { return key; } - public final V getValue() { return val; } - public final int hashCode() { return key.hashCode() ^ val.hashCode(); } - public final String toString(){ return key + "=" + val; } - public final V setValue(V value) { - throw new UnsupportedOperationException(); - } - - public final boolean equals(Object o) { - Object k, v, u; Map.Entry e; - return ((o instanceof Map.Entry) && - (k = (e = (Map.Entry)o).getKey()) != null && - (v = e.getValue()) != null && - (k == key || k.equals(key)) && - (v == (u = val) || v.equals(u))); - } - - /** - * Virtualized support for map.get(); overridden in subclasses. - */ - Node find(int h, Object k) { - Node e = this; - if (k != null) { - do { - K ek; - if (e.hash == h && - ((ek = e.key) == k || (ek != null && k.equals(ek)))) - return e; - } while ((e = e.next) != null); - } - return null; - } - } - - /* ---------------- Static utilities -------------- */ - - /** - * Spreads (XORs) higher bits of hash to lower and also forces top - * bit to 0. Because the table uses power-of-two masking, sets of - * hashes that vary only in bits above the current mask will - * always collide. (Among known examples are sets of Float keys - * holding consecutive whole numbers in small tables.) So we - * apply a transform that spreads the impact of higher bits - * downward. There is a tradeoff between speed, utility, and - * quality of bit-spreading. Because many common sets of hashes - * are already reasonably distributed (so don't benefit from - * spreading), and because we use trees to handle large sets of - * collisions in bins, we just XOR some shifted bits in the - * cheapest possible way to reduce systematic lossage, as well as - * to incorporate impact of the highest bits that would otherwise - * never be used in index calculations because of table bounds. - */ - static final int spread(int h) { - return (h ^ (h >>> 16)) & HASH_BITS; - } - - /** - * Returns a power of two table size for the given desired capacity. - * See Hackers Delight, sec 3.2 - */ - private static final int tableSizeFor(int c) { - int n = c - 1; - n |= n >>> 1; - n |= n >>> 2; - n |= n >>> 4; - n |= n >>> 8; - n |= n >>> 16; - return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1; - } - - /** - * Returns x's Class if it is of the form "class C implements - * Comparable", else null. - */ - static Class comparableClassFor(Object x) { - if (x instanceof Comparable) { - Class c; Type[] ts, as; Type t; ParameterizedType p; - if ((c = x.getClass()) == String.class) // bypass checks - return c; - if ((ts = c.getGenericInterfaces()) != null) { - for (int i = 0; i < ts.length; ++i) { - if (((t = ts[i]) instanceof ParameterizedType) && - ((p = (ParameterizedType)t).getRawType() == - Comparable.class) && - (as = p.getActualTypeArguments()) != null && - as.length == 1 && as[0] == c) // type arg is c - return c; - } - } - } - return null; - } - - /** - * Returns k.compareTo(x) if x matches kc (k's screened comparable - * class), else 0. - */ - @SuppressWarnings({"rawtypes","unchecked"}) // for cast to Comparable - static int compareComparables(Class kc, Object k, Object x) { - return (x == null || x.getClass() != kc ? 0 : - ((Comparable)k).compareTo(x)); - } - - /* ---------------- Table element access -------------- */ - - /* - * Volatile access methods are used for table elements as well as - * elements of in-progress next table while resizing. All uses of - * the tab arguments must be null checked by callers. All callers - * also paranoically precheck that tab's length is not zero (or an - * equivalent check), thus ensuring that any index argument taking - * the form of a hash value anded with (length - 1) is a valid - * index. Note that, to be correct wrt arbitrary concurrency - * errors by users, these checks must operate on local variables, - * which accounts for some odd-looking inline assignments below. - * Note that calls to setTabAt always occur within locked regions, - * and so in principle require only release ordering, not need - * full volatile semantics, but are currently coded as volatile - * writes to be conservative. - */ - - @SuppressWarnings("unchecked") - static final Node tabAt(Node[] tab, int i) { - return (Node)U.getObjectVolatile(tab, ((long)i << ASHIFT) + ABASE); - } - - static final boolean casTabAt(Node[] tab, int i, - Node c, Node v) { - return U.compareAndSwapObject(tab, ((long)i << ASHIFT) + ABASE, c, v); - } - - static final void setTabAt(Node[] tab, int i, Node v) { - U.putObjectVolatile(tab, ((long)i << ASHIFT) + ABASE, v); - } - - /* ---------------- Fields -------------- */ - - /** - * The array of bins. Lazily initialized upon first insertion. - * Size is always a power of two. Accessed directly by iterators. - */ - transient volatile Node[] table; - - /** - * The next table to use; non-null only while resizing. - */ - private transient volatile Node[] nextTable; - - /** - * Base counter value, used mainly when there is no contention, - * but also as a fallback during table initialization - * races. Updated via CAS. - */ - private transient volatile long baseCount; - - /** - * Table initialization and resizing control. When negative, the - * table is being initialized or resized: -1 for initialization, - * else -(1 + the number of active resizing threads). Otherwise, - * when table is null, holds the initial table size to use upon - * creation, or 0 for default. After initialization, holds the - * next element count value upon which to resize the table. - */ - private transient volatile int sizeCtl; - - /** - * The next table index (plus one) to split while resizing. - */ - private transient volatile int transferIndex; - - /** - * The least available table index to split while resizing. - */ - private transient volatile int transferOrigin; - - /** - * Spinlock (locked via CAS) used when resizing and/or creating CounterCells. - */ - private transient volatile int cellsBusy; - - /** - * Table of counter cells. When non-null, size is a power of 2. - */ - private transient volatile CounterCell[] counterCells; - - // views - private transient KeySetView keySet; - private transient ValuesView values; - private transient EntrySetView entrySet; - - - /* ---------------- Public operations -------------- */ - - /** - * Creates a new, empty map with the default initial table size (16). - */ - public ConcurrentHashMapV8() { - } - - /** - * Creates a new, empty map with an initial table size - * accommodating the specified number of elements without the need - * to dynamically resize. - * - * @param initialCapacity The implementation performs internal - * sizing to accommodate this many elements. - * @throws IllegalArgumentException if the initial capacity of - * elements is negative - */ - public ConcurrentHashMapV8(int initialCapacity) { - if (initialCapacity < 0) - throw new IllegalArgumentException(); - int cap = ((initialCapacity >= (MAXIMUM_CAPACITY >>> 1)) ? - MAXIMUM_CAPACITY : - tableSizeFor(initialCapacity + (initialCapacity >>> 1) + 1)); - this.sizeCtl = cap; - } - - /** - * Creates a new map with the same mappings as the given map. - * - * @param m the map - */ - public ConcurrentHashMapV8(Map m) { - this.sizeCtl = DEFAULT_CAPACITY; - putAll(m); - } - - /** - * Creates a new, empty map with an initial table size based on - * the given number of elements ({@code initialCapacity}) and - * initial table density ({@code loadFactor}). - * - * @param initialCapacity the initial capacity. The implementation - * performs internal sizing to accommodate this many elements, - * given the specified load factor. - * @param loadFactor the load factor (table density) for - * establishing the initial table size - * @throws IllegalArgumentException if the initial capacity of - * elements is negative or the load factor is nonpositive - * - * @since 1.6 - */ - public ConcurrentHashMapV8(int initialCapacity, float loadFactor) { - this(initialCapacity, loadFactor, 1); - } - - /** - * Creates a new, empty map with an initial table size based on - * the given number of elements ({@code initialCapacity}), table - * density ({@code loadFactor}), and number of concurrently - * updating threads ({@code concurrencyLevel}). - * - * @param initialCapacity the initial capacity. The implementation - * performs internal sizing to accommodate this many elements, - * given the specified load factor. - * @param loadFactor the load factor (table density) for - * establishing the initial table size - * @param concurrencyLevel the estimated number of concurrently - * updating threads. The implementation may use this value as - * a sizing hint. - * @throws IllegalArgumentException if the initial capacity is - * negative or the load factor or concurrencyLevel are - * nonpositive - */ - public ConcurrentHashMapV8(int initialCapacity, - float loadFactor, int concurrencyLevel) { - if (!(loadFactor > 0.0f) || initialCapacity < 0 || concurrencyLevel <= 0) - throw new IllegalArgumentException(); - if (initialCapacity < concurrencyLevel) // Use at least as many bins - initialCapacity = concurrencyLevel; // as estimated threads - long size = (long)(1.0 + (long)initialCapacity / loadFactor); - int cap = (size >= (long)MAXIMUM_CAPACITY) ? - MAXIMUM_CAPACITY : tableSizeFor((int)size); - this.sizeCtl = cap; - } - - // Original (since JDK1.2) Map methods - - /** - * {@inheritDoc} - */ - public int size() { - long n = sumCount(); - return ((n < 0L) ? 0 : - (n > (long)Integer.MAX_VALUE) ? Integer.MAX_VALUE : - (int)n); - } - - /** - * {@inheritDoc} - */ - public boolean isEmpty() { - return sumCount() <= 0L; // ignore transient negative values - } - - /** - * Returns the value to which the specified key is mapped, - * or {@code null} if this map contains no mapping for the key. - * - *

More formally, if this map contains a mapping from a key - * {@code k} to a value {@code v} such that {@code key.equals(k)}, - * then this method returns {@code v}; otherwise it returns - * {@code null}. (There can be at most one such mapping.) - * - * @throws NullPointerException if the specified key is null - */ - public V get(Object key) { - Node[] tab; Node e, p; int n, eh; K ek; - int h = spread(key.hashCode()); - if ((tab = table) != null && (n = tab.length) > 0 && - (e = tabAt(tab, (n - 1) & h)) != null) { - if ((eh = e.hash) == h) { - if ((ek = e.key) == key || (ek != null && key.equals(ek))) - return e.val; - } - else if (eh < 0) - return (p = e.find(h, key)) != null ? p.val : null; - while ((e = e.next) != null) { - if (e.hash == h && - ((ek = e.key) == key || (ek != null && key.equals(ek)))) - return e.val; - } - } - return null; - } - - /** - * Tests if the specified object is a key in this table. - * - * @param key possible key - * @return {@code true} if and only if the specified object - * is a key in this table, as determined by the - * {@code equals} method; {@code false} otherwise - * @throws NullPointerException if the specified key is null - */ - public boolean containsKey(Object key) { - return get(key) != null; - } - - /** - * Returns {@code true} if this map maps one or more keys to the - * specified value. Note: This method may require a full traversal - * of the map, and is much slower than method {@code containsKey}. - * - * @param value value whose presence in this map is to be tested - * @return {@code true} if this map maps one or more keys to the - * specified value - * @throws NullPointerException if the specified value is null - */ - public boolean containsValue(Object value) { - if (value == null) - throw new NullPointerException(); - Node[] t; - if ((t = table) != null) { - Traverser it = new Traverser(t, t.length, 0, t.length); - for (Node p; (p = it.advance()) != null; ) { - V v; - if ((v = p.val) == value || (v != null && value.equals(v))) - return true; - } - } - return false; - } - - /** - * Maps the specified key to the specified value in this table. - * Neither the key nor the value can be null. - * - *

The value can be retrieved by calling the {@code get} method - * with a key that is equal to the original key. - * - * @param key key with which the specified value is to be associated - * @param value value to be associated with the specified key - * @return the previous value associated with {@code key}, or - * {@code null} if there was no mapping for {@code key} - * @throws NullPointerException if the specified key or value is null - */ - public V put(K key, V value) { - return putVal(key, value, false); - } - - /** Implementation for put and putIfAbsent */ - final V putVal(K key, V value, boolean onlyIfAbsent) { - if (key == null || value == null) throw new NullPointerException(); - int hash = spread(key.hashCode()); - int binCount = 0; - for (Node[] tab = table;;) { - Node f; int n, i, fh; - if (tab == null || (n = tab.length) == 0) - tab = initTable(); - else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) { - if (casTabAt(tab, i, null, - new Node(hash, key, value, null))) - break; // no lock when adding to empty bin - } - else if ((fh = f.hash) == MOVED) - tab = helpTransfer(tab, f); - else { - V oldVal = null; - synchronized (f) { - if (tabAt(tab, i) == f) { - if (fh >= 0) { - binCount = 1; - for (Node e = f;; ++binCount) { - K ek; - if (e.hash == hash && - ((ek = e.key) == key || - (ek != null && key.equals(ek)))) { - oldVal = e.val; - if (!onlyIfAbsent) - e.val = value; - break; - } - Node pred = e; - if ((e = e.next) == null) { - pred.next = new Node(hash, key, - value, null); - break; - } - } - } - else if (f instanceof TreeBin) { - Node p; - binCount = 2; - if ((p = ((TreeBin)f).putTreeVal(hash, key, - value)) != null) { - oldVal = p.val; - if (!onlyIfAbsent) - p.val = value; - } - } - } - } - if (binCount != 0) { - if (binCount >= TREEIFY_THRESHOLD) - treeifyBin(tab, i); - if (oldVal != null) - return oldVal; - break; - } - } - } - addCount(1L, binCount); - return null; - } - - /** - * Copies all of the mappings from the specified map to this one. - * These mappings replace any mappings that this map had for any of the - * keys currently in the specified map. - * - * @param m mappings to be stored in this map - */ - public void putAll(Map m) { - tryPresize(m.size()); - for (Map.Entry e : m.entrySet()) - putVal(e.getKey(), e.getValue(), false); - } - - /** - * Removes the key (and its corresponding value) from this map. - * This method does nothing if the key is not in the map. - * - * @param key the key that needs to be removed - * @return the previous value associated with {@code key}, or - * {@code null} if there was no mapping for {@code key} - * @throws NullPointerException if the specified key is null - */ - public V remove(Object key) { - return replaceNode(key, null, null); - } - - /** - * Implementation for the four public remove/replace methods: - * Replaces node value with v, conditional upon match of cv if - * non-null. If resulting value is null, delete. - */ - final V replaceNode(Object key, V value, Object cv) { - int hash = spread(key.hashCode()); - for (Node[] tab = table;;) { - Node f; int n, i, fh; - if (tab == null || (n = tab.length) == 0 || - (f = tabAt(tab, i = (n - 1) & hash)) == null) - break; - else if ((fh = f.hash) == MOVED) - tab = helpTransfer(tab, f); - else { - V oldVal = null; - boolean validated = false; - synchronized (f) { - if (tabAt(tab, i) == f) { - if (fh >= 0) { - validated = true; - for (Node e = f, pred = null;;) { - K ek; - if (e.hash == hash && - ((ek = e.key) == key || - (ek != null && key.equals(ek)))) { - V ev = e.val; - if (cv == null || cv == ev || - (ev != null && cv.equals(ev))) { - oldVal = ev; - if (value != null) - e.val = value; - else if (pred != null) - pred.next = e.next; - else - setTabAt(tab, i, e.next); - } - break; - } - pred = e; - if ((e = e.next) == null) - break; - } - } - else if (f instanceof TreeBin) { - validated = true; - TreeBin t = (TreeBin)f; - TreeNode r, p; - if ((r = t.root) != null && - (p = r.findTreeNode(hash, key, null)) != null) { - V pv = p.val; - if (cv == null || cv == pv || - (pv != null && cv.equals(pv))) { - oldVal = pv; - if (value != null) - p.val = value; - else if (t.removeTreeNode(p)) - setTabAt(tab, i, untreeify(t.first)); - } - } - } - } - } - if (validated) { - if (oldVal != null) { - if (value == null) - addCount(-1L, -1); - return oldVal; - } - break; - } - } - } - return null; - } - - /** - * Removes all of the mappings from this map. - */ - public void clear() { - long delta = 0L; // negative number of deletions - int i = 0; - Node[] tab = table; - while (tab != null && i < tab.length) { - int fh; - Node f = tabAt(tab, i); - if (f == null) - ++i; - else if ((fh = f.hash) == MOVED) { - tab = helpTransfer(tab, f); - i = 0; // restart - } - else { - synchronized (f) { - if (tabAt(tab, i) == f) { - Node p = (fh >= 0 ? f : - (f instanceof TreeBin) ? - ((TreeBin)f).first : null); - while (p != null) { - --delta; - p = p.next; - } - setTabAt(tab, i++, null); - } - } - } - } - if (delta != 0L) - addCount(delta, -1); - } - - /** - * Returns a {@link Set} view of the keys contained in this map. - * The set is backed by the map, so changes to the map are - * reflected in the set, and vice-versa. The set supports element - * removal, which removes the corresponding mapping from this map, - * via the {@code Iterator.remove}, {@code Set.remove}, - * {@code removeAll}, {@code retainAll}, and {@code clear} - * operations. It does not support the {@code add} or - * {@code addAll} operations. - * - *

The view's {@code iterator} is a "weakly consistent" iterator - * that will never throw {@link ConcurrentModificationException}, - * and guarantees to traverse elements as they existed upon - * construction of the iterator, and may (but is not guaranteed to) - * reflect any modifications subsequent to construction. - * - * @return the set view - */ - public KeySetView keySet() { - KeySetView ks; - return (ks = keySet) != null ? ks : (keySet = new KeySetView(this, null)); - } - - /** - * Returns a {@link Collection} view of the values contained in this map. - * The collection is backed by the map, so changes to the map are - * reflected in the collection, and vice-versa. The collection - * supports element removal, which removes the corresponding - * mapping from this map, via the {@code Iterator.remove}, - * {@code Collection.remove}, {@code removeAll}, - * {@code retainAll}, and {@code clear} operations. It does not - * support the {@code add} or {@code addAll} operations. - * - *

The view's {@code iterator} is a "weakly consistent" iterator - * that will never throw {@link ConcurrentModificationException}, - * and guarantees to traverse elements as they existed upon - * construction of the iterator, and may (but is not guaranteed to) - * reflect any modifications subsequent to construction. - * - * @return the collection view - */ - public Collection values() { - ValuesView vs; - return (vs = values) != null ? vs : (values = new ValuesView(this)); - } - - /** - * Returns a {@link Set} view of the mappings contained in this map. - * The set is backed by the map, so changes to the map are - * reflected in the set, and vice-versa. The set supports element - * removal, which removes the corresponding mapping from the map, - * via the {@code Iterator.remove}, {@code Set.remove}, - * {@code removeAll}, {@code retainAll}, and {@code clear} - * operations. - * - *

The view's {@code iterator} is a "weakly consistent" iterator - * that will never throw {@link ConcurrentModificationException}, - * and guarantees to traverse elements as they existed upon - * construction of the iterator, and may (but is not guaranteed to) - * reflect any modifications subsequent to construction. - * - * @return the set view - */ - public Set> entrySet() { - EntrySetView es; - return (es = entrySet) != null ? es : (entrySet = new EntrySetView(this)); - } - - /** - * Returns the hash code value for this {@link Map}, i.e., - * the sum of, for each key-value pair in the map, - * {@code key.hashCode() ^ value.hashCode()}. - * - * @return the hash code value for this map - */ - public int hashCode() { - int h = 0; - Node[] t; - if ((t = table) != null) { - Traverser it = new Traverser(t, t.length, 0, t.length); - for (Node p; (p = it.advance()) != null; ) - h += p.key.hashCode() ^ p.val.hashCode(); - } - return h; - } - - /** - * Returns a string representation of this map. The string - * representation consists of a list of key-value mappings (in no - * particular order) enclosed in braces ("{@code {}}"). Adjacent - * mappings are separated by the characters {@code ", "} (comma - * and space). Each key-value mapping is rendered as the key - * followed by an equals sign ("{@code =}") followed by the - * associated value. - * - * @return a string representation of this map - */ - public String toString() { - Node[] t; - int f = (t = table) == null ? 0 : t.length; - Traverser it = new Traverser(t, f, 0, f); - StringBuilder sb = new StringBuilder(); - sb.append('{'); - Node p; - if ((p = it.advance()) != null) { - for (;;) { - K k = p.key; - V v = p.val; - sb.append(k == this ? "(this Map)" : k); - sb.append('='); - sb.append(v == this ? "(this Map)" : v); - if ((p = it.advance()) == null) - break; - sb.append(',').append(' '); - } - } - return sb.append('}').toString(); - } - - /** - * Compares the specified object with this map for equality. - * Returns {@code true} if the given object is a map with the same - * mappings as this map. This operation may return misleading - * results if either map is concurrently modified during execution - * of this method. - * - * @param o object to be compared for equality with this map - * @return {@code true} if the specified object is equal to this map - */ - public boolean equals(Object o) { - if (o != this) { - if (!(o instanceof Map)) - return false; - Map m = (Map) o; - Node[] t; - int f = (t = table) == null ? 0 : t.length; - Traverser it = new Traverser(t, f, 0, f); - for (Node p; (p = it.advance()) != null; ) { - V val = p.val; - Object v = m.get(p.key); - if (v == null || (v != val && !v.equals(val))) - return false; - } - for (Map.Entry e : m.entrySet()) { - Object mk, mv, v; - if ((mk = e.getKey()) == null || - (mv = e.getValue()) == null || - (v = get(mk)) == null || - (mv != v && !mv.equals(v))) - return false; - } - } - return true; - } - - /** - * Stripped-down version of helper class used in previous version, - * declared for the sake of serialization compatibility - */ - static class Segment extends ReentrantLock implements Serializable { - private static final long serialVersionUID = 2249069246763182397L; - final float loadFactor; - Segment(float lf) { this.loadFactor = lf; } - } - - /** - * Saves the state of the {@code ConcurrentHashMapV8} instance to a - * stream (i.e., serializes it). - * @param s the stream - * @serialData - * the key (Object) and value (Object) - * for each key-value mapping, followed by a null pair. - * The key-value mappings are emitted in no particular order. - */ - private void writeObject(java.io.ObjectOutputStream s) - throws java.io.IOException { - // For serialization compatibility - // Emulate segment calculation from previous version of this class - int sshift = 0; - int ssize = 1; - while (ssize < DEFAULT_CONCURRENCY_LEVEL) { - ++sshift; - ssize <<= 1; - } - int segmentShift = 32 - sshift; - int segmentMask = ssize - 1; - @SuppressWarnings("unchecked") Segment[] segments = (Segment[]) - new Segment[DEFAULT_CONCURRENCY_LEVEL]; - for (int i = 0; i < segments.length; ++i) - segments[i] = new Segment(LOAD_FACTOR); - s.putFields().put("segments", segments); - s.putFields().put("segmentShift", segmentShift); - s.putFields().put("segmentMask", segmentMask); - s.writeFields(); - - Node[] t; - if ((t = table) != null) { - Traverser it = new Traverser(t, t.length, 0, t.length); - for (Node p; (p = it.advance()) != null; ) { - s.writeObject(p.key); - s.writeObject(p.val); - } - } - s.writeObject(null); - s.writeObject(null); - segments = null; // throw away - } - - /** - * Reconstitutes the instance from a stream (that is, deserializes it). - * @param s the stream - */ - private void readObject(java.io.ObjectInputStream s) - throws java.io.IOException, ClassNotFoundException { - /* - * To improve performance in typical cases, we create nodes - * while reading, then place in table once size is known. - * However, we must also validate uniqueness and deal with - * overpopulated bins while doing so, which requires - * specialized versions of putVal mechanics. - */ - sizeCtl = -1; // force exclusion for table construction - s.defaultReadObject(); - long size = 0L; - Node p = null; - for (;;) { - @SuppressWarnings("unchecked") K k = (K) s.readObject(); - @SuppressWarnings("unchecked") V v = (V) s.readObject(); - if (k != null && v != null) { - p = new Node(spread(k.hashCode()), k, v, p); - ++size; - } - else - break; - } - if (size == 0L) - sizeCtl = 0; - else { - int n; - if (size >= (long)(MAXIMUM_CAPACITY >>> 1)) - n = MAXIMUM_CAPACITY; - else { - int sz = (int)size; - n = tableSizeFor(sz + (sz >>> 1) + 1); - } - @SuppressWarnings({"rawtypes","unchecked"}) - Node[] tab = (Node[])new Node[n]; - int mask = n - 1; - long added = 0L; - while (p != null) { - boolean insertAtFront; - Node next = p.next, first; - int h = p.hash, j = h & mask; - if ((first = tabAt(tab, j)) == null) - insertAtFront = true; - else { - K k = p.key; - if (first.hash < 0) { - TreeBin t = (TreeBin)first; - if (t.putTreeVal(h, k, p.val) == null) - ++added; - insertAtFront = false; - } - else { - int binCount = 0; - insertAtFront = true; - Node q; K qk; - for (q = first; q != null; q = q.next) { - if (q.hash == h && - ((qk = q.key) == k || - (qk != null && k.equals(qk)))) { - insertAtFront = false; - break; - } - ++binCount; - } - if (insertAtFront && binCount >= TREEIFY_THRESHOLD) { - insertAtFront = false; - ++added; - p.next = first; - TreeNode hd = null, tl = null; - for (q = p; q != null; q = q.next) { - TreeNode t = new TreeNode - (q.hash, q.key, q.val, null, null); - if ((t.prev = tl) == null) - hd = t; - else - tl.next = t; - tl = t; - } - setTabAt(tab, j, new TreeBin(hd)); - } - } - } - if (insertAtFront) { - ++added; - p.next = first; - setTabAt(tab, j, p); - } - p = next; - } - table = tab; - sizeCtl = n - (n >>> 2); - baseCount = added; - } - } - - // ConcurrentMap methods - - /** - * {@inheritDoc} - * - * @return the previous value associated with the specified key, - * or {@code null} if there was no mapping for the key - * @throws NullPointerException if the specified key or value is null - */ - public V putIfAbsent(K key, V value) { - return putVal(key, value, true); - } - - /** - * {@inheritDoc} - * - * @throws NullPointerException if the specified key is null - */ - public boolean remove(Object key, Object value) { - if (key == null) - throw new NullPointerException(); - return value != null && replaceNode(key, null, value) != null; - } - - /** - * {@inheritDoc} - * - * @throws NullPointerException if any of the arguments are null - */ - public boolean replace(K key, V oldValue, V newValue) { - if (key == null || oldValue == null || newValue == null) - throw new NullPointerException(); - return replaceNode(key, newValue, oldValue) != null; - } - - /** - * {@inheritDoc} - * - * @return the previous value associated with the specified key, - * or {@code null} if there was no mapping for the key - * @throws NullPointerException if the specified key or value is null - */ - public V replace(K key, V value) { - if (key == null || value == null) - throw new NullPointerException(); - return replaceNode(key, value, null); - } - - // Overrides of JDK8+ Map extension method defaults - - /** - * Returns the value to which the specified key is mapped, or the - * given default value if this map contains no mapping for the - * key. - * - * @param key the key whose associated value is to be returned - * @param defaultValue the value to return if this map contains - * no mapping for the given key - * @return the mapping for the key, if present; else the default value - * @throws NullPointerException if the specified key is null - */ - public V getOrDefault(Object key, V defaultValue) { - V v; - return (v = get(key)) == null ? defaultValue : v; - } - - public void forEach(BiAction action) { - if (action == null) throw new NullPointerException(); - Node[] t; - if ((t = table) != null) { - Traverser it = new Traverser(t, t.length, 0, t.length); - for (Node p; (p = it.advance()) != null; ) { - action.apply(p.key, p.val); - } - } - } - - public void replaceAll(BiFun function) { - if (function == null) throw new NullPointerException(); - Node[] t; - if ((t = table) != null) { - Traverser it = new Traverser(t, t.length, 0, t.length); - for (Node p; (p = it.advance()) != null; ) { - V oldValue = p.val; - for (K key = p.key;;) { - V newValue = function.apply(key, oldValue); - if (newValue == null) - throw new NullPointerException(); - if (replaceNode(key, newValue, oldValue) != null || - (oldValue = get(key)) == null) - break; - } - } - } - } - - /** - * If the specified key is not already associated with a value, - * attempts to compute its value using the given mapping function - * and enters it into this map unless {@code null}. The entire - * method invocation is performed atomically, so the function is - * applied at most once per key. Some attempted update operations - * on this map by other threads may be blocked while computation - * is in progress, so the computation should be short and simple, - * and must not attempt to update any other mappings of this map. - * - * @param key key with which the specified value is to be associated - * @param mappingFunction the function to compute a value - * @return the current (existing or computed) value associated with - * the specified key, or null if the computed value is null - * @throws NullPointerException if the specified key or mappingFunction - * is null - * @throws IllegalStateException if the computation detectably - * attempts a recursive update to this map that would - * otherwise never complete - * @throws RuntimeException or Error if the mappingFunction does so, - * in which case the mapping is left unestablished - */ - public V computeIfAbsent(K key, Fun mappingFunction) { - if (key == null || mappingFunction == null) - throw new NullPointerException(); - int h = spread(key.hashCode()); - V val = null; - int binCount = 0; - for (Node[] tab = table;;) { - Node f; int n, i, fh; - if (tab == null || (n = tab.length) == 0) - tab = initTable(); - else if ((f = tabAt(tab, i = (n - 1) & h)) == null) { - Node r = new ReservationNode(); - synchronized (r) { - if (casTabAt(tab, i, null, r)) { - binCount = 1; - Node node = null; - try { - if ((val = mappingFunction.apply(key)) != null) - node = new Node(h, key, val, null); - } finally { - setTabAt(tab, i, node); - } - } - } - if (binCount != 0) - break; - } - else if ((fh = f.hash) == MOVED) - tab = helpTransfer(tab, f); - else { - boolean added = false; - synchronized (f) { - if (tabAt(tab, i) == f) { - if (fh >= 0) { - binCount = 1; - for (Node e = f;; ++binCount) { - K ek; V ev; - if (e.hash == h && - ((ek = e.key) == key || - (ek != null && key.equals(ek)))) { - val = e.val; - break; - } - Node pred = e; - if ((e = e.next) == null) { - if ((val = mappingFunction.apply(key)) != null) { - added = true; - pred.next = new Node(h, key, val, null); - } - break; - } - } - } - else if (f instanceof TreeBin) { - binCount = 2; - TreeBin t = (TreeBin)f; - TreeNode r, p; - if ((r = t.root) != null && - (p = r.findTreeNode(h, key, null)) != null) - val = p.val; - else if ((val = mappingFunction.apply(key)) != null) { - added = true; - t.putTreeVal(h, key, val); - } - } - } - } - if (binCount != 0) { - if (binCount >= TREEIFY_THRESHOLD) - treeifyBin(tab, i); - if (!added) - return val; - break; - } - } - } - if (val != null) - addCount(1L, binCount); - return val; - } - - /** - * If the value for the specified key is present, attempts to - * compute a new mapping given the key and its current mapped - * value. The entire method invocation is performed atomically. - * Some attempted update operations on this map by other threads - * may be blocked while computation is in progress, so the - * computation should be short and simple, and must not attempt to - * update any other mappings of this map. - * - * @param key key with which a value may be associated - * @param remappingFunction the function to compute a value - * @return the new value associated with the specified key, or null if none - * @throws NullPointerException if the specified key or remappingFunction - * is null - * @throws IllegalStateException if the computation detectably - * attempts a recursive update to this map that would - * otherwise never complete - * @throws RuntimeException or Error if the remappingFunction does so, - * in which case the mapping is unchanged - */ - public V computeIfPresent(K key, BiFun remappingFunction) { - if (key == null || remappingFunction == null) - throw new NullPointerException(); - int h = spread(key.hashCode()); - V val = null; - int delta = 0; - int binCount = 0; - for (Node[] tab = table;;) { - Node f; int n, i, fh; - if (tab == null || (n = tab.length) == 0) - tab = initTable(); - else if ((f = tabAt(tab, i = (n - 1) & h)) == null) - break; - else if ((fh = f.hash) == MOVED) - tab = helpTransfer(tab, f); - else { - synchronized (f) { - if (tabAt(tab, i) == f) { - if (fh >= 0) { - binCount = 1; - for (Node e = f, pred = null;; ++binCount) { - K ek; - if (e.hash == h && - ((ek = e.key) == key || - (ek != null && key.equals(ek)))) { - val = remappingFunction.apply(key, e.val); - if (val != null) - e.val = val; - else { - delta = -1; - Node en = e.next; - if (pred != null) - pred.next = en; - else - setTabAt(tab, i, en); - } - break; - } - pred = e; - if ((e = e.next) == null) - break; - } - } - else if (f instanceof TreeBin) { - binCount = 2; - TreeBin t = (TreeBin)f; - TreeNode r, p; - if ((r = t.root) != null && - (p = r.findTreeNode(h, key, null)) != null) { - val = remappingFunction.apply(key, p.val); - if (val != null) - p.val = val; - else { - delta = -1; - if (t.removeTreeNode(p)) - setTabAt(tab, i, untreeify(t.first)); - } - } - } - } - } - if (binCount != 0) - break; - } - } - if (delta != 0) - addCount((long)delta, binCount); - return val; - } - - /** - * Attempts to compute a mapping for the specified key and its - * current mapped value (or {@code null} if there is no current - * mapping). The entire method invocation is performed atomically. - * Some attempted update operations on this map by other threads - * may be blocked while computation is in progress, so the - * computation should be short and simple, and must not attempt to - * update any other mappings of this Map. - * - * @param key key with which the specified value is to be associated - * @param remappingFunction the function to compute a value - * @return the new value associated with the specified key, or null if none - * @throws NullPointerException if the specified key or remappingFunction - * is null - * @throws IllegalStateException if the computation detectably - * attempts a recursive update to this map that would - * otherwise never complete - * @throws RuntimeException or Error if the remappingFunction does so, - * in which case the mapping is unchanged - */ - public V compute(K key, - BiFun remappingFunction) { - if (key == null || remappingFunction == null) - throw new NullPointerException(); - int h = spread(key.hashCode()); - V val = null; - int delta = 0; - int binCount = 0; - for (Node[] tab = table;;) { - Node f; int n, i, fh; - if (tab == null || (n = tab.length) == 0) - tab = initTable(); - else if ((f = tabAt(tab, i = (n - 1) & h)) == null) { - Node r = new ReservationNode(); - synchronized (r) { - if (casTabAt(tab, i, null, r)) { - binCount = 1; - Node node = null; - try { - if ((val = remappingFunction.apply(key, null)) != null) { - delta = 1; - node = new Node(h, key, val, null); - } - } finally { - setTabAt(tab, i, node); - } - } - } - if (binCount != 0) - break; - } - else if ((fh = f.hash) == MOVED) - tab = helpTransfer(tab, f); - else { - synchronized (f) { - if (tabAt(tab, i) == f) { - if (fh >= 0) { - binCount = 1; - for (Node e = f, pred = null;; ++binCount) { - K ek; - if (e.hash == h && - ((ek = e.key) == key || - (ek != null && key.equals(ek)))) { - val = remappingFunction.apply(key, e.val); - if (val != null) - e.val = val; - else { - delta = -1; - Node en = e.next; - if (pred != null) - pred.next = en; - else - setTabAt(tab, i, en); - } - break; - } - pred = e; - if ((e = e.next) == null) { - val = remappingFunction.apply(key, null); - if (val != null) { - delta = 1; - pred.next = - new Node(h, key, val, null); - } - break; - } - } - } - else if (f instanceof TreeBin) { - binCount = 1; - TreeBin t = (TreeBin)f; - TreeNode r, p; - if ((r = t.root) != null) - p = r.findTreeNode(h, key, null); - else - p = null; - V pv = (p == null) ? null : p.val; - val = remappingFunction.apply(key, pv); - if (val != null) { - if (p != null) - p.val = val; - else { - delta = 1; - t.putTreeVal(h, key, val); - } - } - else if (p != null) { - delta = -1; - if (t.removeTreeNode(p)) - setTabAt(tab, i, untreeify(t.first)); - } - } - } - } - if (binCount != 0) { - if (binCount >= TREEIFY_THRESHOLD) - treeifyBin(tab, i); - break; - } - } - } - if (delta != 0) - addCount((long)delta, binCount); - return val; - } - - /** - * If the specified key is not already associated with a - * (non-null) value, associates it with the given value. - * Otherwise, replaces the value with the results of the given - * remapping function, or removes if {@code null}. The entire - * method invocation is performed atomically. Some attempted - * update operations on this map by other threads may be blocked - * while computation is in progress, so the computation should be - * short and simple, and must not attempt to update any other - * mappings of this Map. - * - * @param key key with which the specified value is to be associated - * @param value the value to use if absent - * @param remappingFunction the function to recompute a value if present - * @return the new value associated with the specified key, or null if none - * @throws NullPointerException if the specified key or the - * remappingFunction is null - * @throws RuntimeException or Error if the remappingFunction does so, - * in which case the mapping is unchanged - */ - public V merge(K key, V value, BiFun remappingFunction) { - if (key == null || value == null || remappingFunction == null) - throw new NullPointerException(); - int h = spread(key.hashCode()); - V val = null; - int delta = 0; - int binCount = 0; - for (Node[] tab = table;;) { - Node f; int n, i, fh; - if (tab == null || (n = tab.length) == 0) - tab = initTable(); - else if ((f = tabAt(tab, i = (n - 1) & h)) == null) { - if (casTabAt(tab, i, null, new Node(h, key, value, null))) { - delta = 1; - val = value; - break; - } - } - else if ((fh = f.hash) == MOVED) - tab = helpTransfer(tab, f); - else { - synchronized (f) { - if (tabAt(tab, i) == f) { - if (fh >= 0) { - binCount = 1; - for (Node e = f, pred = null;; ++binCount) { - K ek; - if (e.hash == h && - ((ek = e.key) == key || - (ek != null && key.equals(ek)))) { - val = remappingFunction.apply(e.val, value); - if (val != null) - e.val = val; - else { - delta = -1; - Node en = e.next; - if (pred != null) - pred.next = en; - else - setTabAt(tab, i, en); - } - break; - } - pred = e; - if ((e = e.next) == null) { - delta = 1; - val = value; - pred.next = - new Node(h, key, val, null); - break; - } - } - } - else if (f instanceof TreeBin) { - binCount = 2; - TreeBin t = (TreeBin)f; - TreeNode r = t.root; - TreeNode p = (r == null) ? null : - r.findTreeNode(h, key, null); - val = (p == null) ? value : - remappingFunction.apply(p.val, value); - if (val != null) { - if (p != null) - p.val = val; - else { - delta = 1; - t.putTreeVal(h, key, val); - } - } - else if (p != null) { - delta = -1; - if (t.removeTreeNode(p)) - setTabAt(tab, i, untreeify(t.first)); - } - } - } - } - if (binCount != 0) { - if (binCount >= TREEIFY_THRESHOLD) - treeifyBin(tab, i); - break; - } - } - } - if (delta != 0) - addCount((long)delta, binCount); - return val; - } - - // Hashtable legacy methods - - /** - * Legacy method testing if some key maps into the specified value - * in this table. This method is identical in functionality to - * {@link #containsValue(Object)}, and exists solely to ensure - * full compatibility with class {@link java.util.Hashtable}, - * which supported this method prior to introduction of the - * Java Collections framework. - * - * @param value a value to search for - * @return {@code true} if and only if some key maps to the - * {@code value} argument in this table as - * determined by the {@code equals} method; - * {@code false} otherwise - * @throws NullPointerException if the specified value is null - */ - @Deprecated public boolean contains(Object value) { - return containsValue(value); - } - - /** - * Returns an enumeration of the keys in this table. - * - * @return an enumeration of the keys in this table - * @see #keySet() - */ - public Enumeration keys() { - Node[] t; - int f = (t = table) == null ? 0 : t.length; - return new KeyIterator(t, f, 0, f, this); - } - - /** - * Returns an enumeration of the values in this table. - * - * @return an enumeration of the values in this table - * @see #values() - */ - public Enumeration elements() { - Node[] t; - int f = (t = table) == null ? 0 : t.length; - return new ValueIterator(t, f, 0, f, this); - } - - // ConcurrentHashMapV8-only methods - - /** - * Returns the number of mappings. This method should be used - * instead of {@link #size} because a ConcurrentHashMapV8 may - * contain more mappings than can be represented as an int. The - * value returned is an estimate; the actual count may differ if - * there are concurrent insertions or removals. - * - * @return the number of mappings - * @since 1.8 - */ - public long mappingCount() { - long n = sumCount(); - return (n < 0L) ? 0L : n; // ignore transient negative values - } - - /** - * Creates a new {@link Set} backed by a ConcurrentHashMapV8 - * from the given type to {@code Boolean.TRUE}. - * - * @return the new set - * @since 1.8 - */ - public static KeySetView newKeySet() { - return new KeySetView - (new ConcurrentHashMapV8(), Boolean.TRUE); - } - - /** - * Creates a new {@link Set} backed by a ConcurrentHashMapV8 - * from the given type to {@code Boolean.TRUE}. - * - * @param initialCapacity The implementation performs internal - * sizing to accommodate this many elements. - * @throws IllegalArgumentException if the initial capacity of - * elements is negative - * @return the new set - * @since 1.8 - */ - public static KeySetView newKeySet(int initialCapacity) { - return new KeySetView - (new ConcurrentHashMapV8(initialCapacity), Boolean.TRUE); - } - - /** - * Returns a {@link Set} view of the keys in this map, using the - * given common mapped value for any additions (i.e., {@link - * Collection#add} and {@link Collection#addAll(Collection)}). - * This is of course only appropriate if it is acceptable to use - * the same value for all additions from this view. - * - * @param mappedValue the mapped value to use for any additions - * @return the set view - * @throws NullPointerException if the mappedValue is null - */ - public KeySetView keySet(V mappedValue) { - if (mappedValue == null) - throw new NullPointerException(); - return new KeySetView(this, mappedValue); - } - - /* ---------------- Special Nodes -------------- */ - - /** - * A node inserted at head of bins during transfer operations. - */ - static final class ForwardingNode extends Node { - final Node[] nextTable; - ForwardingNode(Node[] tab) { - super(MOVED, null, null, null); - this.nextTable = tab; - } - - Node find(int h, Object k) { - // loop to avoid arbitrarily deep recursion on forwarding nodes - outer: for (Node[] tab = nextTable;;) { - Node e; int n; - if (k == null || tab == null || (n = tab.length) == 0 || - (e = tabAt(tab, (n - 1) & h)) == null) - return null; - for (;;) { - int eh; K ek; - if ((eh = e.hash) == h && - ((ek = e.key) == k || (ek != null && k.equals(ek)))) - return e; - if (eh < 0) { - if (e instanceof ForwardingNode) { - tab = ((ForwardingNode)e).nextTable; - continue outer; - } - else - return e.find(h, k); - } - if ((e = e.next) == null) - return null; - } - } - } - } - - /** - * A place-holder node used in computeIfAbsent and compute - */ - static final class ReservationNode extends Node { - ReservationNode() { - super(RESERVED, null, null, null); - } - - Node find(int h, Object k) { - return null; - } - } - - /* ---------------- Table Initialization and Resizing -------------- */ - - /** - * Initializes table, using the size recorded in sizeCtl. - */ - private final Node[] initTable() { - Node[] tab; int sc; - while ((tab = table) == null || tab.length == 0) { - if ((sc = sizeCtl) < 0) - Thread.yield(); // lost initialization race; just spin - else if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) { - try { - if ((tab = table) == null || tab.length == 0) { - int n = (sc > 0) ? sc : DEFAULT_CAPACITY; - @SuppressWarnings({"rawtypes","unchecked"}) - Node[] nt = (Node[])new Node[n]; - table = tab = nt; - sc = n - (n >>> 2); - } - } finally { - sizeCtl = sc; - } - break; - } - } - return tab; - } - - /** - * Adds to count, and if table is too small and not already - * resizing, initiates transfer. If already resizing, helps - * perform transfer if work is available. Rechecks occupancy - * after a transfer to see if another resize is already needed - * because resizings are lagging additions. - * - * @param x the count to add - * @param check if <0, don't check resize, if <= 1 only check if uncontended - */ - private final void addCount(long x, int check) { - CounterCell[] as; long b, s; - if ((as = counterCells) != null || - !U.compareAndSwapLong(this, BASECOUNT, b = baseCount, s = b + x)) { - IntegerHolder hc; CounterCell a; long v; int m; - boolean uncontended = true; - InternalThreadLocalMap threadLocals = InternalThreadLocalMap.get(); - if ((hc = threadLocals.counterHashCode()) == null || - as == null || (m = as.length - 1) < 0 || - (a = as[m & hc.value]) == null || - !(uncontended = - U.compareAndSwapLong(a, CELLVALUE, v = a.value, v + x))) { - fullAddCount(threadLocals, x, hc, uncontended); - return; - } - if (check <= 1) - return; - s = sumCount(); - } - if (check >= 0) { - Node[] tab, nt; int sc; - while (s >= (long)(sc = sizeCtl) && (tab = table) != null && - tab.length < MAXIMUM_CAPACITY) { - if (sc < 0) { - if (sc == -1 || transferIndex <= transferOrigin || - (nt = nextTable) == null) - break; - if (U.compareAndSwapInt(this, SIZECTL, sc, sc - 1)) - transfer(tab, nt); - } - else if (U.compareAndSwapInt(this, SIZECTL, sc, -2)) - transfer(tab, null); - s = sumCount(); - } - } - } - - /** - * Helps transfer if a resize is in progress. - */ - final Node[] helpTransfer(Node[] tab, Node f) { - Node[] nextTab; int sc; - if ((f instanceof ForwardingNode) && - (nextTab = ((ForwardingNode)f).nextTable) != null) { - if (nextTab == nextTable && tab == table && - transferIndex > transferOrigin && (sc = sizeCtl) < -1 && - U.compareAndSwapInt(this, SIZECTL, sc, sc - 1)) - transfer(tab, nextTab); - return nextTab; - } - return table; - } - - /** - * Tries to presize table to accommodate the given number of elements. - * - * @param size number of elements (doesn't need to be perfectly accurate) - */ - private final void tryPresize(int size) { - int c = (size >= (MAXIMUM_CAPACITY >>> 1)) ? MAXIMUM_CAPACITY : - tableSizeFor(size + (size >>> 1) + 1); - int sc; - while ((sc = sizeCtl) >= 0) { - Node[] tab = table; int n; - if (tab == null || (n = tab.length) == 0) { - n = (sc > c) ? sc : c; - if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) { - try { - if (table == tab) { - @SuppressWarnings({"rawtypes","unchecked"}) - Node[] nt = (Node[])new Node[n]; - table = nt; - sc = n - (n >>> 2); - } - } finally { - sizeCtl = sc; - } - } - } - else if (c <= sc || n >= MAXIMUM_CAPACITY) - break; - else if (tab == table && - U.compareAndSwapInt(this, SIZECTL, sc, -2)) - transfer(tab, null); - } - } - - /** - * Moves and/or copies the nodes in each bin to new table. See - * above for explanation. - */ - private final void transfer(Node[] tab, Node[] nextTab) { - int n = tab.length, stride; - if ((stride = (NCPU > 1) ? (n >>> 3) / NCPU : n) < MIN_TRANSFER_STRIDE) - stride = MIN_TRANSFER_STRIDE; // subdivide range - if (nextTab == null) { // initiating - try { - @SuppressWarnings({"rawtypes","unchecked"}) - Node[] nt = (Node[])new Node[n << 1]; - nextTab = nt; - } catch (Throwable ex) { // try to cope with OOME - sizeCtl = Integer.MAX_VALUE; - return; - } - nextTable = nextTab; - transferOrigin = n; - transferIndex = n; - ForwardingNode rev = new ForwardingNode(tab); - for (int k = n; k > 0;) { // progressively reveal ready slots - int nextk = (k > stride) ? k - stride : 0; - for (int m = nextk; m < k; ++m) - nextTab[m] = rev; - for (int m = n + nextk; m < n + k; ++m) - nextTab[m] = rev; - U.putOrderedInt(this, TRANSFERORIGIN, k = nextk); - } - } - int nextn = nextTab.length; - ForwardingNode fwd = new ForwardingNode(nextTab); - boolean advance = true; - boolean finishing = false; // to ensure sweep before committing nextTab - for (int i = 0, bound = 0;;) { - int nextIndex, nextBound, fh; Node f; - while (advance) { - if (--i >= bound || finishing) - advance = false; - else if ((nextIndex = transferIndex) <= transferOrigin) { - i = -1; - advance = false; - } - else if (U.compareAndSwapInt - (this, TRANSFERINDEX, nextIndex, - nextBound = (nextIndex > stride ? - nextIndex - stride : 0))) { - bound = nextBound; - i = nextIndex - 1; - advance = false; - } - } - if (i < 0 || i >= n || i + n >= nextn) { - if (finishing) { - nextTable = null; - table = nextTab; - sizeCtl = (n << 1) - (n >>> 1); - return; - } - for (int sc;;) { - if (U.compareAndSwapInt(this, SIZECTL, sc = sizeCtl, ++sc)) { - if (sc != -1) - return; - finishing = advance = true; - i = n; // recheck before commit - break; - } - } - } - else if ((f = tabAt(tab, i)) == null) { - if (casTabAt(tab, i, null, fwd)) { - setTabAt(nextTab, i, null); - setTabAt(nextTab, i + n, null); - advance = true; - } - } - else if ((fh = f.hash) == MOVED) - advance = true; // already processed - else { - synchronized (f) { - if (tabAt(tab, i) == f) { - Node ln, hn; - if (fh >= 0) { - int runBit = fh & n; - Node lastRun = f; - for (Node p = f.next; p != null; p = p.next) { - int b = p.hash & n; - if (b != runBit) { - runBit = b; - lastRun = p; - } - } - if (runBit == 0) { - ln = lastRun; - hn = null; - } - else { - hn = lastRun; - ln = null; - } - for (Node p = f; p != lastRun; p = p.next) { - int ph = p.hash; K pk = p.key; V pv = p.val; - if ((ph & n) == 0) - ln = new Node(ph, pk, pv, ln); - else - hn = new Node(ph, pk, pv, hn); - } - setTabAt(nextTab, i, ln); - setTabAt(nextTab, i + n, hn); - setTabAt(tab, i, fwd); - advance = true; - } - else if (f instanceof TreeBin) { - TreeBin t = (TreeBin)f; - TreeNode lo = null, loTail = null; - TreeNode hi = null, hiTail = null; - int lc = 0, hc = 0; - for (Node e = t.first; e != null; e = e.next) { - int h = e.hash; - TreeNode p = new TreeNode - (h, e.key, e.val, null, null); - if ((h & n) == 0) { - if ((p.prev = loTail) == null) - lo = p; - else - loTail.next = p; - loTail = p; - ++lc; - } - else { - if ((p.prev = hiTail) == null) - hi = p; - else - hiTail.next = p; - hiTail = p; - ++hc; - } - } - ln = (lc <= UNTREEIFY_THRESHOLD) ? untreeify(lo) : - (hc != 0) ? new TreeBin(lo) : t; - hn = (hc <= UNTREEIFY_THRESHOLD) ? untreeify(hi) : - (lc != 0) ? new TreeBin(hi) : t; - setTabAt(nextTab, i, ln); - setTabAt(nextTab, i + n, hn); - setTabAt(tab, i, fwd); - advance = true; - } - } - } - } - } - } - - /* ---------------- Conversion from/to TreeBins -------------- */ - - /** - * Replaces all linked nodes in bin at given index unless table is - * too small, in which case resizes instead. - */ - private final void treeifyBin(Node[] tab, int index) { - Node b; int n, sc; - if (tab != null) { - if ((n = tab.length) < MIN_TREEIFY_CAPACITY) { - if (tab == table && (sc = sizeCtl) >= 0 && - U.compareAndSwapInt(this, SIZECTL, sc, -2)) - transfer(tab, null); - } - else if ((b = tabAt(tab, index)) != null && b.hash >= 0) { - synchronized (b) { - if (tabAt(tab, index) == b) { - TreeNode hd = null, tl = null; - for (Node e = b; e != null; e = e.next) { - TreeNode p = - new TreeNode(e.hash, e.key, e.val, - null, null); - if ((p.prev = tl) == null) - hd = p; - else - tl.next = p; - tl = p; - } - setTabAt(tab, index, new TreeBin(hd)); - } - } - } - } - } - - /** - * Returns a list on non-TreeNodes replacing those in given list. - */ - static Node untreeify(Node b) { - Node hd = null, tl = null; - for (Node q = b; q != null; q = q.next) { - Node p = new Node(q.hash, q.key, q.val, null); - if (tl == null) - hd = p; - else - tl.next = p; - tl = p; - } - return hd; - } - - /* ---------------- TreeNodes -------------- */ - - /** - * Nodes for use in TreeBins - */ - static final class TreeNode extends Node { - TreeNode parent; // red-black tree links - TreeNode left; - TreeNode right; - TreeNode prev; // needed to unlink next upon deletion - boolean red; - - TreeNode(int hash, K key, V val, Node next, - TreeNode parent) { - super(hash, key, val, next); - this.parent = parent; - } - - Node find(int h, Object k) { - return findTreeNode(h, k, null); - } - - /** - * Returns the TreeNode (or null if not found) for the given key - * starting at given root. - */ - final TreeNode findTreeNode(int h, Object k, Class kc) { - if (k != null) { - TreeNode p = this; - do { - int ph, dir; K pk; TreeNode q; - TreeNode pl = p.left, pr = p.right; - if ((ph = p.hash) > h) - p = pl; - else if (ph < h) - p = pr; - else if ((pk = p.key) == k || (pk != null && k.equals(pk))) - return p; - else if (pl == null && pr == null) - break; - else if ((kc != null || - (kc = comparableClassFor(k)) != null) && - (dir = compareComparables(kc, k, pk)) != 0) - p = (dir < 0) ? pl : pr; - else if (pl == null) - p = pr; - else if (pr == null || - (q = pr.findTreeNode(h, k, kc)) == null) - p = pl; - else - return q; - } while (p != null); - } - return null; - } - } - - /* ---------------- TreeBins -------------- */ - - /** - * TreeNodes used at the heads of bins. TreeBins do not hold user - * keys or values, but instead point to list of TreeNodes and - * their root. They also maintain a parasitic read-write lock - * forcing writers (who hold bin lock) to wait for readers (who do - * not) to complete before tree restructuring operations. - */ - static final class TreeBin extends Node { - TreeNode root; - volatile TreeNode first; - volatile Thread waiter; - volatile int lockState; - // values for lockState - static final int WRITER = 1; // set while holding write lock - static final int WAITER = 2; // set when waiting for write lock - static final int READER = 4; // increment value for setting read lock - - /** - * Creates bin with initial set of nodes headed by b. - */ - TreeBin(TreeNode b) { - super(TREEBIN, null, null, null); - this.first = b; - TreeNode r = null; - for (TreeNode x = b, next; x != null; x = next) { - next = (TreeNode)x.next; - x.left = x.right = null; - if (r == null) { - x.parent = null; - x.red = false; - r = x; - } - else { - Object key = x.key; - int hash = x.hash; - Class kc = null; - for (TreeNode p = r;;) { - int dir, ph; - if ((ph = p.hash) > hash) - dir = -1; - else if (ph < hash) - dir = 1; - else if ((kc != null || - (kc = comparableClassFor(key)) != null)) - dir = compareComparables(kc, key, p.key); - else - dir = 0; - TreeNode xp = p; - if ((p = (dir <= 0) ? p.left : p.right) == null) { - x.parent = xp; - if (dir <= 0) - xp.left = x; - else - xp.right = x; - r = balanceInsertion(r, x); - break; - } - } - } - } - this.root = r; - } - - /** - * Acquires write lock for tree restructuring. - */ - private final void lockRoot() { - if (!U.compareAndSwapInt(this, LOCKSTATE, 0, WRITER)) - contendedLock(); // offload to separate method - } - - /** - * Releases write lock for tree restructuring. - */ - private final void unlockRoot() { - lockState = 0; - } - - /** - * Possibly blocks awaiting root lock. - */ - private final void contendedLock() { - boolean waiting = false; - for (int s;;) { - if (((s = lockState) & WRITER) == 0) { - if (U.compareAndSwapInt(this, LOCKSTATE, s, WRITER)) { - if (waiting) - waiter = null; - return; - } - } - else if ((s & WAITER) == 0) { - if (U.compareAndSwapInt(this, LOCKSTATE, s, s | WAITER)) { - waiting = true; - waiter = Thread.currentThread(); - } - } - else if (waiting) - LockSupport.park(this); - } - } - - /** - * Returns matching node or null if none. Tries to search - * using tree comparisons from root, but continues linear - * search when lock not available. - */ - final Node find(int h, Object k) { - if (k != null) { - for (Node e = first; e != null; e = e.next) { - int s; K ek; - if (((s = lockState) & (WAITER|WRITER)) != 0) { - if (e.hash == h && - ((ek = e.key) == k || (ek != null && k.equals(ek)))) - return e; - } - else if (U.compareAndSwapInt(this, LOCKSTATE, s, - s + READER)) { - TreeNode r, p; - try { - p = ((r = root) == null ? null : - r.findTreeNode(h, k, null)); - } finally { - Thread w; - int ls; - do {} while (!U.compareAndSwapInt - (this, LOCKSTATE, - ls = lockState, ls - READER)); - if (ls == (READER|WAITER) && (w = waiter) != null) - LockSupport.unpark(w); - } - return p; - } - } - } - return null; - } - - /** - * Finds or adds a node. - * @return null if added - */ - final TreeNode putTreeVal(int h, K k, V v) { - Class kc = null; - for (TreeNode p = root;;) { - int dir, ph; K pk; TreeNode q, pr; - if (p == null) { - first = root = new TreeNode(h, k, v, null, null); - break; - } - else if ((ph = p.hash) > h) - dir = -1; - else if (ph < h) - dir = 1; - else if ((pk = p.key) == k || (pk != null && k.equals(pk))) - return p; - else if ((kc == null && - (kc = comparableClassFor(k)) == null) || - (dir = compareComparables(kc, k, pk)) == 0) { - if (p.left == null) - dir = 1; - else if ((pr = p.right) == null || - (q = pr.findTreeNode(h, k, kc)) == null) - dir = -1; - else - return q; - } - TreeNode xp = p; - if ((p = (dir < 0) ? p.left : p.right) == null) { - TreeNode x, f = first; - first = x = new TreeNode(h, k, v, f, xp); - if (f != null) - f.prev = x; - if (dir < 0) - xp.left = x; - else - xp.right = x; - if (!xp.red) - x.red = true; - else { - lockRoot(); - try { - root = balanceInsertion(root, x); - } finally { - unlockRoot(); - } - } - break; - } - } - assert checkInvariants(root); - return null; - } - - /** - * Removes the given node, that must be present before this - * call. This is messier than typical red-black deletion code - * because we cannot swap the contents of an interior node - * with a leaf successor that is pinned by "next" pointers - * that are accessible independently of lock. So instead we - * swap the tree linkages. - * - * @return true if now too small, so should be untreeified - */ - final boolean removeTreeNode(TreeNode p) { - TreeNode next = (TreeNode)p.next; - TreeNode pred = p.prev; // unlink traversal pointers - TreeNode r, rl; - if (pred == null) - first = next; - else - pred.next = next; - if (next != null) - next.prev = pred; - if (first == null) { - root = null; - return true; - } - if ((r = root) == null || r.right == null || // too small - (rl = r.left) == null || rl.left == null) - return true; - lockRoot(); - try { - TreeNode replacement; - TreeNode pl = p.left; - TreeNode pr = p.right; - if (pl != null && pr != null) { - TreeNode s = pr, sl; - while ((sl = s.left) != null) // find successor - s = sl; - boolean c = s.red; s.red = p.red; p.red = c; // swap colors - TreeNode sr = s.right; - TreeNode pp = p.parent; - if (s == pr) { // p was s's direct parent - p.parent = s; - s.right = p; - } - else { - TreeNode sp = s.parent; - if ((p.parent = sp) != null) { - if (s == sp.left) - sp.left = p; - else - sp.right = p; - } - s.right = pr; - pr.parent = s; - } - p.left = null; - s.left = pl; - pl.parent = s; - if ((p.right = sr) != null) - sr.parent = p; - if ((s.parent = pp) == null) - r = s; - else if (p == pp.left) - pp.left = s; - else - pp.right = s; - if (sr != null) - replacement = sr; - else - replacement = p; - } - else if (pl != null) - replacement = pl; - else if (pr != null) - replacement = pr; - else - replacement = p; - if (replacement != p) { - TreeNode pp = replacement.parent = p.parent; - if (pp == null) - r = replacement; - else if (p == pp.left) - pp.left = replacement; - else - pp.right = replacement; - p.left = p.right = p.parent = null; - } - - root = (p.red) ? r : balanceDeletion(r, replacement); - - if (p == replacement) { // detach pointers - TreeNode pp; - if ((pp = p.parent) != null) { - if (p == pp.left) - pp.left = null; - else if (p == pp.right) - pp.right = null; - p.parent = null; - } - } - } finally { - unlockRoot(); - } - assert checkInvariants(root); - return false; - } - - /* ------------------------------------------------------------ */ - // Red-black tree methods, all adapted from CLR - - static TreeNode rotateLeft(TreeNode root, - TreeNode p) { - TreeNode r, pp, rl; - if (p != null && (r = p.right) != null) { - if ((rl = p.right = r.left) != null) - rl.parent = p; - if ((pp = r.parent = p.parent) == null) - (root = r).red = false; - else if (pp.left == p) - pp.left = r; - else - pp.right = r; - r.left = p; - p.parent = r; - } - return root; - } - - static TreeNode rotateRight(TreeNode root, - TreeNode p) { - TreeNode l, pp, lr; - if (p != null && (l = p.left) != null) { - if ((lr = p.left = l.right) != null) - lr.parent = p; - if ((pp = l.parent = p.parent) == null) - (root = l).red = false; - else if (pp.right == p) - pp.right = l; - else - pp.left = l; - l.right = p; - p.parent = l; - } - return root; - } - - static TreeNode balanceInsertion(TreeNode root, - TreeNode x) { - x.red = true; - for (TreeNode xp, xpp, xppl, xppr;;) { - if ((xp = x.parent) == null) { - x.red = false; - return x; - } - else if (!xp.red || (xpp = xp.parent) == null) - return root; - if (xp == (xppl = xpp.left)) { - if ((xppr = xpp.right) != null && xppr.red) { - xppr.red = false; - xp.red = false; - xpp.red = true; - x = xpp; - } - else { - if (x == xp.right) { - root = rotateLeft(root, x = xp); - xpp = (xp = x.parent) == null ? null : xp.parent; - } - if (xp != null) { - xp.red = false; - if (xpp != null) { - xpp.red = true; - root = rotateRight(root, xpp); - } - } - } - } - else { - if (xppl != null && xppl.red) { - xppl.red = false; - xp.red = false; - xpp.red = true; - x = xpp; - } - else { - if (x == xp.left) { - root = rotateRight(root, x = xp); - xpp = (xp = x.parent) == null ? null : xp.parent; - } - if (xp != null) { - xp.red = false; - if (xpp != null) { - xpp.red = true; - root = rotateLeft(root, xpp); - } - } - } - } - } - } - - static TreeNode balanceDeletion(TreeNode root, - TreeNode x) { - for (TreeNode xp, xpl, xpr;;) { - if (x == null || x == root) - return root; - else if ((xp = x.parent) == null) { - x.red = false; - return x; - } - else if (x.red) { - x.red = false; - return root; - } - else if ((xpl = xp.left) == x) { - if ((xpr = xp.right) != null && xpr.red) { - xpr.red = false; - xp.red = true; - root = rotateLeft(root, xp); - xpr = (xp = x.parent) == null ? null : xp.right; - } - if (xpr == null) - x = xp; - else { - TreeNode sl = xpr.left, sr = xpr.right; - if ((sr == null || !sr.red) && - (sl == null || !sl.red)) { - xpr.red = true; - x = xp; - } - else { - if (sr == null || !sr.red) { - if (sl != null) - sl.red = false; - xpr.red = true; - root = rotateRight(root, xpr); - xpr = (xp = x.parent) == null ? - null : xp.right; - } - if (xpr != null) { - xpr.red = (xp == null) ? false : xp.red; - if ((sr = xpr.right) != null) - sr.red = false; - } - if (xp != null) { - xp.red = false; - root = rotateLeft(root, xp); - } - x = root; - } - } - } - else { // symmetric - if (xpl != null && xpl.red) { - xpl.red = false; - xp.red = true; - root = rotateRight(root, xp); - xpl = (xp = x.parent) == null ? null : xp.left; - } - if (xpl == null) - x = xp; - else { - TreeNode sl = xpl.left, sr = xpl.right; - if ((sl == null || !sl.red) && - (sr == null || !sr.red)) { - xpl.red = true; - x = xp; - } - else { - if (sl == null || !sl.red) { - if (sr != null) - sr.red = false; - xpl.red = true; - root = rotateLeft(root, xpl); - xpl = (xp = x.parent) == null ? - null : xp.left; - } - if (xpl != null) { - xpl.red = (xp == null) ? false : xp.red; - if ((sl = xpl.left) != null) - sl.red = false; - } - if (xp != null) { - xp.red = false; - root = rotateRight(root, xp); - } - x = root; - } - } - } - } - } - - /** - * Recursive invariant check - */ - static boolean checkInvariants(TreeNode t) { - TreeNode tp = t.parent, tl = t.left, tr = t.right, - tb = t.prev, tn = (TreeNode)t.next; - if (tb != null && tb.next != t) - return false; - if (tn != null && tn.prev != t) - return false; - if (tp != null && t != tp.left && t != tp.right) - return false; - if (tl != null && (tl.parent != t || tl.hash > t.hash)) - return false; - if (tr != null && (tr.parent != t || tr.hash < t.hash)) - return false; - if (t.red && tl != null && tl.red && tr != null && tr.red) - return false; - if (tl != null && !checkInvariants(tl)) - return false; - if (tr != null && !checkInvariants(tr)) - return false; - return true; - } - - private static final sun.misc.Unsafe U; - private static final long LOCKSTATE; - static { - try { - U = getUnsafe(); - Class k = TreeBin.class; - LOCKSTATE = U.objectFieldOffset - (k.getDeclaredField("lockState")); - } catch (Exception e) { - throw new Error(e); - } - } - } - - /* ----------------Table Traversal -------------- */ - - /** - * Encapsulates traversal for methods such as containsValue; also - * serves as a base class for other iterators and spliterators. - * - * Method advance visits once each still-valid node that was - * reachable upon iterator construction. It might miss some that - * were added to a bin after the bin was visited, which is OK wrt - * consistency guarantees. Maintaining this property in the face - * of possible ongoing resizes requires a fair amount of - * bookkeeping state that is difficult to optimize away amidst - * volatile accesses. Even so, traversal maintains reasonable - * throughput. - * - * Normally, iteration proceeds bin-by-bin traversing lists. - * However, if the table has been resized, then all future steps - * must traverse both the bin at the current index as well as at - * (index + baseSize); and so on for further resizings. To - * paranoically cope with potential sharing by users of iterators - * across threads, iteration terminates if a bounds checks fails - * for a table read. - */ - static class Traverser { - Node[] tab; // current table; updated if resized - Node next; // the next entry to use - int index; // index of bin to use next - int baseIndex; // current index of initial table - int baseLimit; // index bound for initial table - final int baseSize; // initial table size - - Traverser(Node[] tab, int size, int index, int limit) { - this.tab = tab; - this.baseSize = size; - this.baseIndex = this.index = index; - this.baseLimit = limit; - this.next = null; - } - - /** - * Advances if possible, returning next valid node, or null if none. - */ - final Node advance() { - Node e; - if ((e = next) != null) - e = e.next; - for (;;) { - Node[] t; int i, n; K ek; // must use locals in checks - if (e != null) - return next = e; - if (baseIndex >= baseLimit || (t = tab) == null || - (n = t.length) <= (i = index) || i < 0) - return next = null; - if ((e = tabAt(t, index)) != null && e.hash < 0) { - if (e instanceof ForwardingNode) { - tab = ((ForwardingNode)e).nextTable; - e = null; - continue; - } - else if (e instanceof TreeBin) - e = ((TreeBin)e).first; - else - e = null; - } - if ((index += baseSize) >= n) - index = ++baseIndex; // visit upper slots if present - } - } - } - - /** - * Base of key, value, and entry Iterators. Adds fields to - * Traverser to support iterator.remove. - */ - static class BaseIterator extends Traverser { - final ConcurrentHashMapV8 map; - Node lastReturned; - BaseIterator(Node[] tab, int size, int index, int limit, - ConcurrentHashMapV8 map) { - super(tab, size, index, limit); - this.map = map; - advance(); - } - - public final boolean hasNext() { return next != null; } - public final boolean hasMoreElements() { return next != null; } - - public final void remove() { - Node p; - if ((p = lastReturned) == null) - throw new IllegalStateException(); - lastReturned = null; - map.replaceNode(p.key, null, null); - } - } - - static final class KeyIterator extends BaseIterator - implements Iterator, Enumeration { - KeyIterator(Node[] tab, int index, int size, int limit, - ConcurrentHashMapV8 map) { - super(tab, index, size, limit, map); - } - - public final K next() { - Node p; - if ((p = next) == null) - throw new NoSuchElementException(); - K k = p.key; - lastReturned = p; - advance(); - return k; - } - - public final K nextElement() { return next(); } - } - - static final class ValueIterator extends BaseIterator - implements Iterator, Enumeration { - ValueIterator(Node[] tab, int index, int size, int limit, - ConcurrentHashMapV8 map) { - super(tab, index, size, limit, map); - } - - public final V next() { - Node p; - if ((p = next) == null) - throw new NoSuchElementException(); - V v = p.val; - lastReturned = p; - advance(); - return v; - } - - public final V nextElement() { return next(); } - } - - static final class EntryIterator extends BaseIterator - implements Iterator> { - EntryIterator(Node[] tab, int index, int size, int limit, - ConcurrentHashMapV8 map) { - super(tab, index, size, limit, map); - } - - public final Map.Entry next() { - Node p; - if ((p = next) == null) - throw new NoSuchElementException(); - K k = p.key; - V v = p.val; - lastReturned = p; - advance(); - return new MapEntry(k, v, map); - } - } - - /** - * Exported Entry for EntryIterator - */ - static final class MapEntry implements Map.Entry { - final K key; // non-null - V val; // non-null - final ConcurrentHashMapV8 map; - MapEntry(K key, V val, ConcurrentHashMapV8 map) { - this.key = key; - this.val = val; - this.map = map; - } - public K getKey() { return key; } - public V getValue() { return val; } - public int hashCode() { return key.hashCode() ^ val.hashCode(); } - public String toString() { return key + "=" + val; } - - public boolean equals(Object o) { - Object k, v; Map.Entry e; - return ((o instanceof Map.Entry) && - (k = (e = (Map.Entry)o).getKey()) != null && - (v = e.getValue()) != null && - (k == key || k.equals(key)) && - (v == val || v.equals(val))); - } - - /** - * Sets our entry's value and writes through to the map. The - * value to return is somewhat arbitrary here. Since we do not - * necessarily track asynchronous changes, the most recent - * "previous" value could be different from what we return (or - * could even have been removed, in which case the put will - * re-establish). We do not and cannot guarantee more. - */ - public V setValue(V value) { - if (value == null) throw new NullPointerException(); - V v = val; - val = value; - map.put(key, value); - return v; - } - } - - static final class KeySpliterator extends Traverser - implements ConcurrentHashMapSpliterator { - long est; // size estimate - KeySpliterator(Node[] tab, int size, int index, int limit, - long est) { - super(tab, size, index, limit); - this.est = est; - } - - public ConcurrentHashMapSpliterator trySplit() { - int i, f, h; - return (h = ((i = baseIndex) + (f = baseLimit)) >>> 1) <= i ? null : - new KeySpliterator(tab, baseSize, baseLimit = h, - f, est >>>= 1); - } - - public void forEachRemaining(Action action) { - if (action == null) throw new NullPointerException(); - for (Node p; (p = advance()) != null;) - action.apply(p.key); - } - - public boolean tryAdvance(Action action) { - if (action == null) throw new NullPointerException(); - Node p; - if ((p = advance()) == null) - return false; - action.apply(p.key); - return true; - } - - public long estimateSize() { return est; } - - } - - static final class ValueSpliterator extends Traverser - implements ConcurrentHashMapSpliterator { - long est; // size estimate - ValueSpliterator(Node[] tab, int size, int index, int limit, - long est) { - super(tab, size, index, limit); - this.est = est; - } - - public ConcurrentHashMapSpliterator trySplit() { - int i, f, h; - return (h = ((i = baseIndex) + (f = baseLimit)) >>> 1) <= i ? null : - new ValueSpliterator(tab, baseSize, baseLimit = h, - f, est >>>= 1); - } - - public void forEachRemaining(Action action) { - if (action == null) throw new NullPointerException(); - for (Node p; (p = advance()) != null;) - action.apply(p.val); - } - - public boolean tryAdvance(Action action) { - if (action == null) throw new NullPointerException(); - Node p; - if ((p = advance()) == null) - return false; - action.apply(p.val); - return true; - } - - public long estimateSize() { return est; } - - } - - static final class EntrySpliterator extends Traverser - implements ConcurrentHashMapSpliterator> { - final ConcurrentHashMapV8 map; // To export MapEntry - long est; // size estimate - EntrySpliterator(Node[] tab, int size, int index, int limit, - long est, ConcurrentHashMapV8 map) { - super(tab, size, index, limit); - this.map = map; - this.est = est; - } - - public ConcurrentHashMapSpliterator> trySplit() { - int i, f, h; - return (h = ((i = baseIndex) + (f = baseLimit)) >>> 1) <= i ? null : - new EntrySpliterator(tab, baseSize, baseLimit = h, - f, est >>>= 1, map); - } - - public void forEachRemaining(Action> action) { - if (action == null) throw new NullPointerException(); - for (Node p; (p = advance()) != null; ) - action.apply(new MapEntry(p.key, p.val, map)); - } - - public boolean tryAdvance(Action> action) { - if (action == null) throw new NullPointerException(); - Node p; - if ((p = advance()) == null) - return false; - action.apply(new MapEntry(p.key, p.val, map)); - return true; - } - - public long estimateSize() { return est; } - - } - - // Parallel bulk operations - - /** - * Computes initial batch value for bulk tasks. The returned value - * is approximately exp2 of the number of times (minus one) to - * split task by two before executing leaf action. This value is - * faster to compute and more convenient to use as a guide to - * splitting than is the depth, since it is used while dividing by - * two anyway. - */ - final int batchFor(long b) { - long n; - if (b == Long.MAX_VALUE || (n = sumCount()) <= 1L || n < b) - return 0; - int sp = ForkJoinPool.getCommonPoolParallelism() << 2; // slack of 4 - return (b <= 0L || (n /= b) >= sp) ? sp : (int)n; - } - - /** - * Performs the given action for each (key, value). - * - * @param parallelismThreshold the (estimated) number of elements - * needed for this operation to be executed in parallel - * @param action the action - * @since 1.8 - */ - public void forEach(long parallelismThreshold, - BiAction action) { - if (action == null) throw new NullPointerException(); - new ForEachMappingTask - (null, batchFor(parallelismThreshold), 0, 0, table, - action).invoke(); - } - - /** - * Performs the given action for each non-null transformation - * of each (key, value). - * - * @param parallelismThreshold the (estimated) number of elements - * needed for this operation to be executed in parallel - * @param transformer a function returning the transformation - * for an element, or null if there is no transformation (in - * which case the action is not applied) - * @param action the action - * @since 1.8 - */ - public void forEach(long parallelismThreshold, - BiFun transformer, - Action action) { - if (transformer == null || action == null) - throw new NullPointerException(); - new ForEachTransformedMappingTask - (null, batchFor(parallelismThreshold), 0, 0, table, - transformer, action).invoke(); - } - - /** - * Returns a non-null result from applying the given search - * function on each (key, value), or null if none. Upon - * success, further element processing is suppressed and the - * results of any other parallel invocations of the search - * function are ignored. - * - * @param parallelismThreshold the (estimated) number of elements - * needed for this operation to be executed in parallel - * @param searchFunction a function returning a non-null - * result on success, else null - * @return a non-null result from applying the given search - * function on each (key, value), or null if none - * @since 1.8 - */ - public U search(long parallelismThreshold, - BiFun searchFunction) { - if (searchFunction == null) throw new NullPointerException(); - return new SearchMappingsTask - (null, batchFor(parallelismThreshold), 0, 0, table, - searchFunction, new AtomicReference()).invoke(); - } - - /** - * Returns the result of accumulating the given transformation - * of all (key, value) pairs using the given reducer to - * combine values, or null if none. - * - * @param parallelismThreshold the (estimated) number of elements - * needed for this operation to be executed in parallel - * @param transformer a function returning the transformation - * for an element, or null if there is no transformation (in - * which case it is not combined) - * @param reducer a commutative associative combining function - * @return the result of accumulating the given transformation - * of all (key, value) pairs - * @since 1.8 - */ - public U reduce(long parallelismThreshold, - BiFun transformer, - BiFun reducer) { - if (transformer == null || reducer == null) - throw new NullPointerException(); - return new MapReduceMappingsTask - (null, batchFor(parallelismThreshold), 0, 0, table, - null, transformer, reducer).invoke(); - } - - /** - * Returns the result of accumulating the given transformation - * of all (key, value) pairs using the given reducer to - * combine values, and the given basis as an identity value. - * - * @param parallelismThreshold the (estimated) number of elements - * needed for this operation to be executed in parallel - * @param transformer a function returning the transformation - * for an element - * @param basis the identity (initial default value) for the reduction - * @param reducer a commutative associative combining function - * @return the result of accumulating the given transformation - * of all (key, value) pairs - * @since 1.8 - */ - public double reduceToDouble(long parallelismThreshold, - ObjectByObjectToDouble transformer, - double basis, - DoubleByDoubleToDouble reducer) { - if (transformer == null || reducer == null) - throw new NullPointerException(); - return new MapReduceMappingsToDoubleTask - (null, batchFor(parallelismThreshold), 0, 0, table, - null, transformer, basis, reducer).invoke(); - } - - /** - * Returns the result of accumulating the given transformation - * of all (key, value) pairs using the given reducer to - * combine values, and the given basis as an identity value. - * - * @param parallelismThreshold the (estimated) number of elements - * needed for this operation to be executed in parallel - * @param transformer a function returning the transformation - * for an element - * @param basis the identity (initial default value) for the reduction - * @param reducer a commutative associative combining function - * @return the result of accumulating the given transformation - * of all (key, value) pairs - * @since 1.8 - */ - public long reduceToLong(long parallelismThreshold, - ObjectByObjectToLong transformer, - long basis, - LongByLongToLong reducer) { - if (transformer == null || reducer == null) - throw new NullPointerException(); - return new MapReduceMappingsToLongTask - (null, batchFor(parallelismThreshold), 0, 0, table, - null, transformer, basis, reducer).invoke(); - } - - /** - * Returns the result of accumulating the given transformation - * of all (key, value) pairs using the given reducer to - * combine values, and the given basis as an identity value. - * - * @param parallelismThreshold the (estimated) number of elements - * needed for this operation to be executed in parallel - * @param transformer a function returning the transformation - * for an element - * @param basis the identity (initial default value) for the reduction - * @param reducer a commutative associative combining function - * @return the result of accumulating the given transformation - * of all (key, value) pairs - * @since 1.8 - */ - public int reduceToInt(long parallelismThreshold, - ObjectByObjectToInt transformer, - int basis, - IntByIntToInt reducer) { - if (transformer == null || reducer == null) - throw new NullPointerException(); - return new MapReduceMappingsToIntTask - (null, batchFor(parallelismThreshold), 0, 0, table, - null, transformer, basis, reducer).invoke(); - } - - /** - * Performs the given action for each key. - * - * @param parallelismThreshold the (estimated) number of elements - * needed for this operation to be executed in parallel - * @param action the action - * @since 1.8 - */ - public void forEachKey(long parallelismThreshold, - Action action) { - if (action == null) throw new NullPointerException(); - new ForEachKeyTask - (null, batchFor(parallelismThreshold), 0, 0, table, - action).invoke(); - } - - /** - * Performs the given action for each non-null transformation - * of each key. - * - * @param parallelismThreshold the (estimated) number of elements - * needed for this operation to be executed in parallel - * @param transformer a function returning the transformation - * for an element, or null if there is no transformation (in - * which case the action is not applied) - * @param action the action - * @since 1.8 - */ - public void forEachKey(long parallelismThreshold, - Fun transformer, - Action action) { - if (transformer == null || action == null) - throw new NullPointerException(); - new ForEachTransformedKeyTask - (null, batchFor(parallelismThreshold), 0, 0, table, - transformer, action).invoke(); - } - - /** - * Returns a non-null result from applying the given search - * function on each key, or null if none. Upon success, - * further element processing is suppressed and the results of - * any other parallel invocations of the search function are - * ignored. - * - * @param parallelismThreshold the (estimated) number of elements - * needed for this operation to be executed in parallel - * @param searchFunction a function returning a non-null - * result on success, else null - * @return a non-null result from applying the given search - * function on each key, or null if none - * @since 1.8 - */ - public U searchKeys(long parallelismThreshold, - Fun searchFunction) { - if (searchFunction == null) throw new NullPointerException(); - return new SearchKeysTask - (null, batchFor(parallelismThreshold), 0, 0, table, - searchFunction, new AtomicReference()).invoke(); - } - - /** - * Returns the result of accumulating all keys using the given - * reducer to combine values, or null if none. - * - * @param parallelismThreshold the (estimated) number of elements - * needed for this operation to be executed in parallel - * @param reducer a commutative associative combining function - * @return the result of accumulating all keys using the given - * reducer to combine values, or null if none - * @since 1.8 - */ - public K reduceKeys(long parallelismThreshold, - BiFun reducer) { - if (reducer == null) throw new NullPointerException(); - return new ReduceKeysTask - (null, batchFor(parallelismThreshold), 0, 0, table, - null, reducer).invoke(); - } - - /** - * Returns the result of accumulating the given transformation - * of all keys using the given reducer to combine values, or - * null if none. - * - * @param parallelismThreshold the (estimated) number of elements - * needed for this operation to be executed in parallel - * @param transformer a function returning the transformation - * for an element, or null if there is no transformation (in - * which case it is not combined) - * @param reducer a commutative associative combining function - * @return the result of accumulating the given transformation - * of all keys - * @since 1.8 - */ - public U reduceKeys(long parallelismThreshold, - Fun transformer, - BiFun reducer) { - if (transformer == null || reducer == null) - throw new NullPointerException(); - return new MapReduceKeysTask - (null, batchFor(parallelismThreshold), 0, 0, table, - null, transformer, reducer).invoke(); - } - - /** - * Returns the result of accumulating the given transformation - * of all keys using the given reducer to combine values, and - * the given basis as an identity value. - * - * @param parallelismThreshold the (estimated) number of elements - * needed for this operation to be executed in parallel - * @param transformer a function returning the transformation - * for an element - * @param basis the identity (initial default value) for the reduction - * @param reducer a commutative associative combining function - * @return the result of accumulating the given transformation - * of all keys - * @since 1.8 - */ - public double reduceKeysToDouble(long parallelismThreshold, - ObjectToDouble transformer, - double basis, - DoubleByDoubleToDouble reducer) { - if (transformer == null || reducer == null) - throw new NullPointerException(); - return new MapReduceKeysToDoubleTask - (null, batchFor(parallelismThreshold), 0, 0, table, - null, transformer, basis, reducer).invoke(); - } - - /** - * Returns the result of accumulating the given transformation - * of all keys using the given reducer to combine values, and - * the given basis as an identity value. - * - * @param parallelismThreshold the (estimated) number of elements - * needed for this operation to be executed in parallel - * @param transformer a function returning the transformation - * for an element - * @param basis the identity (initial default value) for the reduction - * @param reducer a commutative associative combining function - * @return the result of accumulating the given transformation - * of all keys - * @since 1.8 - */ - public long reduceKeysToLong(long parallelismThreshold, - ObjectToLong transformer, - long basis, - LongByLongToLong reducer) { - if (transformer == null || reducer == null) - throw new NullPointerException(); - return new MapReduceKeysToLongTask - (null, batchFor(parallelismThreshold), 0, 0, table, - null, transformer, basis, reducer).invoke(); - } - - /** - * Returns the result of accumulating the given transformation - * of all keys using the given reducer to combine values, and - * the given basis as an identity value. - * - * @param parallelismThreshold the (estimated) number of elements - * needed for this operation to be executed in parallel - * @param transformer a function returning the transformation - * for an element - * @param basis the identity (initial default value) for the reduction - * @param reducer a commutative associative combining function - * @return the result of accumulating the given transformation - * of all keys - * @since 1.8 - */ - public int reduceKeysToInt(long parallelismThreshold, - ObjectToInt transformer, - int basis, - IntByIntToInt reducer) { - if (transformer == null || reducer == null) - throw new NullPointerException(); - return new MapReduceKeysToIntTask - (null, batchFor(parallelismThreshold), 0, 0, table, - null, transformer, basis, reducer).invoke(); - } - - /** - * Performs the given action for each value. - * - * @param parallelismThreshold the (estimated) number of elements - * needed for this operation to be executed in parallel - * @param action the action - * @since 1.8 - */ - public void forEachValue(long parallelismThreshold, - Action action) { - if (action == null) - throw new NullPointerException(); - new ForEachValueTask - (null, batchFor(parallelismThreshold), 0, 0, table, - action).invoke(); - } - - /** - * Performs the given action for each non-null transformation - * of each value. - * - * @param parallelismThreshold the (estimated) number of elements - * needed for this operation to be executed in parallel - * @param transformer a function returning the transformation - * for an element, or null if there is no transformation (in - * which case the action is not applied) - * @param action the action - * @since 1.8 - */ - public void forEachValue(long parallelismThreshold, - Fun transformer, - Action action) { - if (transformer == null || action == null) - throw new NullPointerException(); - new ForEachTransformedValueTask - (null, batchFor(parallelismThreshold), 0, 0, table, - transformer, action).invoke(); - } - - /** - * Returns a non-null result from applying the given search - * function on each value, or null if none. Upon success, - * further element processing is suppressed and the results of - * any other parallel invocations of the search function are - * ignored. - * - * @param parallelismThreshold the (estimated) number of elements - * needed for this operation to be executed in parallel - * @param searchFunction a function returning a non-null - * result on success, else null - * @return a non-null result from applying the given search - * function on each value, or null if none - * @since 1.8 - */ - public U searchValues(long parallelismThreshold, - Fun searchFunction) { - if (searchFunction == null) throw new NullPointerException(); - return new SearchValuesTask - (null, batchFor(parallelismThreshold), 0, 0, table, - searchFunction, new AtomicReference()).invoke(); - } - - /** - * Returns the result of accumulating all values using the - * given reducer to combine values, or null if none. - * - * @param parallelismThreshold the (estimated) number of elements - * needed for this operation to be executed in parallel - * @param reducer a commutative associative combining function - * @return the result of accumulating all values - * @since 1.8 - */ - public V reduceValues(long parallelismThreshold, - BiFun reducer) { - if (reducer == null) throw new NullPointerException(); - return new ReduceValuesTask - (null, batchFor(parallelismThreshold), 0, 0, table, - null, reducer).invoke(); - } - - /** - * Returns the result of accumulating the given transformation - * of all values using the given reducer to combine values, or - * null if none. - * - * @param parallelismThreshold the (estimated) number of elements - * needed for this operation to be executed in parallel - * @param transformer a function returning the transformation - * for an element, or null if there is no transformation (in - * which case it is not combined) - * @param reducer a commutative associative combining function - * @return the result of accumulating the given transformation - * of all values - * @since 1.8 - */ - public U reduceValues(long parallelismThreshold, - Fun transformer, - BiFun reducer) { - if (transformer == null || reducer == null) - throw new NullPointerException(); - return new MapReduceValuesTask - (null, batchFor(parallelismThreshold), 0, 0, table, - null, transformer, reducer).invoke(); - } - - /** - * Returns the result of accumulating the given transformation - * of all values using the given reducer to combine values, - * and the given basis as an identity value. - * - * @param parallelismThreshold the (estimated) number of elements - * needed for this operation to be executed in parallel - * @param transformer a function returning the transformation - * for an element - * @param basis the identity (initial default value) for the reduction - * @param reducer a commutative associative combining function - * @return the result of accumulating the given transformation - * of all values - * @since 1.8 - */ - public double reduceValuesToDouble(long parallelismThreshold, - ObjectToDouble transformer, - double basis, - DoubleByDoubleToDouble reducer) { - if (transformer == null || reducer == null) - throw new NullPointerException(); - return new MapReduceValuesToDoubleTask - (null, batchFor(parallelismThreshold), 0, 0, table, - null, transformer, basis, reducer).invoke(); - } - - /** - * Returns the result of accumulating the given transformation - * of all values using the given reducer to combine values, - * and the given basis as an identity value. - * - * @param parallelismThreshold the (estimated) number of elements - * needed for this operation to be executed in parallel - * @param transformer a function returning the transformation - * for an element - * @param basis the identity (initial default value) for the reduction - * @param reducer a commutative associative combining function - * @return the result of accumulating the given transformation - * of all values - * @since 1.8 - */ - public long reduceValuesToLong(long parallelismThreshold, - ObjectToLong transformer, - long basis, - LongByLongToLong reducer) { - if (transformer == null || reducer == null) - throw new NullPointerException(); - return new MapReduceValuesToLongTask - (null, batchFor(parallelismThreshold), 0, 0, table, - null, transformer, basis, reducer).invoke(); - } - - /** - * Returns the result of accumulating the given transformation - * of all values using the given reducer to combine values, - * and the given basis as an identity value. - * - * @param parallelismThreshold the (estimated) number of elements - * needed for this operation to be executed in parallel - * @param transformer a function returning the transformation - * for an element - * @param basis the identity (initial default value) for the reduction - * @param reducer a commutative associative combining function - * @return the result of accumulating the given transformation - * of all values - * @since 1.8 - */ - public int reduceValuesToInt(long parallelismThreshold, - ObjectToInt transformer, - int basis, - IntByIntToInt reducer) { - if (transformer == null || reducer == null) - throw new NullPointerException(); - return new MapReduceValuesToIntTask - (null, batchFor(parallelismThreshold), 0, 0, table, - null, transformer, basis, reducer).invoke(); - } - - /** - * Performs the given action for each entry. - * - * @param parallelismThreshold the (estimated) number of elements - * needed for this operation to be executed in parallel - * @param action the action - * @since 1.8 - */ - public void forEachEntry(long parallelismThreshold, - Action> action) { - if (action == null) throw new NullPointerException(); - new ForEachEntryTask(null, batchFor(parallelismThreshold), 0, 0, table, - action).invoke(); - } - - /** - * Performs the given action for each non-null transformation - * of each entry. - * - * @param parallelismThreshold the (estimated) number of elements - * needed for this operation to be executed in parallel - * @param transformer a function returning the transformation - * for an element, or null if there is no transformation (in - * which case the action is not applied) - * @param action the action - * @since 1.8 - */ - public void forEachEntry(long parallelismThreshold, - Fun, ? extends U> transformer, - Action action) { - if (transformer == null || action == null) - throw new NullPointerException(); - new ForEachTransformedEntryTask - (null, batchFor(parallelismThreshold), 0, 0, table, - transformer, action).invoke(); - } - - /** - * Returns a non-null result from applying the given search - * function on each entry, or null if none. Upon success, - * further element processing is suppressed and the results of - * any other parallel invocations of the search function are - * ignored. - * - * @param parallelismThreshold the (estimated) number of elements - * needed for this operation to be executed in parallel - * @param searchFunction a function returning a non-null - * result on success, else null - * @return a non-null result from applying the given search - * function on each entry, or null if none - * @since 1.8 - */ - public U searchEntries(long parallelismThreshold, - Fun, ? extends U> searchFunction) { - if (searchFunction == null) throw new NullPointerException(); - return new SearchEntriesTask - (null, batchFor(parallelismThreshold), 0, 0, table, - searchFunction, new AtomicReference()).invoke(); - } - - /** - * Returns the result of accumulating all entries using the - * given reducer to combine values, or null if none. - * - * @param parallelismThreshold the (estimated) number of elements - * needed for this operation to be executed in parallel - * @param reducer a commutative associative combining function - * @return the result of accumulating all entries - * @since 1.8 - */ - public Map.Entry reduceEntries(long parallelismThreshold, - BiFun, Map.Entry, ? extends Map.Entry> reducer) { - if (reducer == null) throw new NullPointerException(); - return new ReduceEntriesTask - (null, batchFor(parallelismThreshold), 0, 0, table, - null, reducer).invoke(); - } - - /** - * Returns the result of accumulating the given transformation - * of all entries using the given reducer to combine values, - * or null if none. - * - * @param parallelismThreshold the (estimated) number of elements - * needed for this operation to be executed in parallel - * @param transformer a function returning the transformation - * for an element, or null if there is no transformation (in - * which case it is not combined) - * @param reducer a commutative associative combining function - * @return the result of accumulating the given transformation - * of all entries - * @since 1.8 - */ - public U reduceEntries(long parallelismThreshold, - Fun, ? extends U> transformer, - BiFun reducer) { - if (transformer == null || reducer == null) - throw new NullPointerException(); - return new MapReduceEntriesTask - (null, batchFor(parallelismThreshold), 0, 0, table, - null, transformer, reducer).invoke(); - } - - /** - * Returns the result of accumulating the given transformation - * of all entries using the given reducer to combine values, - * and the given basis as an identity value. - * - * @param parallelismThreshold the (estimated) number of elements - * needed for this operation to be executed in parallel - * @param transformer a function returning the transformation - * for an element - * @param basis the identity (initial default value) for the reduction - * @param reducer a commutative associative combining function - * @return the result of accumulating the given transformation - * of all entries - * @since 1.8 - */ - public double reduceEntriesToDouble(long parallelismThreshold, - ObjectToDouble> transformer, - double basis, - DoubleByDoubleToDouble reducer) { - if (transformer == null || reducer == null) - throw new NullPointerException(); - return new MapReduceEntriesToDoubleTask - (null, batchFor(parallelismThreshold), 0, 0, table, - null, transformer, basis, reducer).invoke(); - } - - /** - * Returns the result of accumulating the given transformation - * of all entries using the given reducer to combine values, - * and the given basis as an identity value. - * - * @param parallelismThreshold the (estimated) number of elements - * needed for this operation to be executed in parallel - * @param transformer a function returning the transformation - * for an element - * @param basis the identity (initial default value) for the reduction - * @param reducer a commutative associative combining function - * @return the result of accumulating the given transformation - * of all entries - * @since 1.8 - */ - public long reduceEntriesToLong(long parallelismThreshold, - ObjectToLong> transformer, - long basis, - LongByLongToLong reducer) { - if (transformer == null || reducer == null) - throw new NullPointerException(); - return new MapReduceEntriesToLongTask - (null, batchFor(parallelismThreshold), 0, 0, table, - null, transformer, basis, reducer).invoke(); - } - - /** - * Returns the result of accumulating the given transformation - * of all entries using the given reducer to combine values, - * and the given basis as an identity value. - * - * @param parallelismThreshold the (estimated) number of elements - * needed for this operation to be executed in parallel - * @param transformer a function returning the transformation - * for an element - * @param basis the identity (initial default value) for the reduction - * @param reducer a commutative associative combining function - * @return the result of accumulating the given transformation - * of all entries - * @since 1.8 - */ - public int reduceEntriesToInt(long parallelismThreshold, - ObjectToInt> transformer, - int basis, - IntByIntToInt reducer) { - if (transformer == null || reducer == null) - throw new NullPointerException(); - return new MapReduceEntriesToIntTask - (null, batchFor(parallelismThreshold), 0, 0, table, - null, transformer, basis, reducer).invoke(); - } - - - /* ----------------Views -------------- */ - - /** - * Base class for views. - */ - abstract static class CollectionView - implements Collection, java.io.Serializable { - private static final long serialVersionUID = 7249069246763182397L; - final ConcurrentHashMapV8 map; - CollectionView(ConcurrentHashMapV8 map) { this.map = map; } - - /** - * Returns the map backing this view. - * - * @return the map backing this view - */ - public ConcurrentHashMapV8 getMap() { return map; } - - /** - * Removes all of the elements from this view, by removing all - * the mappings from the map backing this view. - */ - public final void clear() { map.clear(); } - public final int size() { return map.size(); } - public final boolean isEmpty() { return map.isEmpty(); } - - // implementations below rely on concrete classes supplying these - // abstract methods - /** - * Returns a "weakly consistent" iterator that will never - * throw {@link ConcurrentModificationException}, and - * guarantees to traverse elements as they existed upon - * construction of the iterator, and may (but is not - * guaranteed to) reflect any modifications subsequent to - * construction. - */ - public abstract Iterator iterator(); - public abstract boolean contains(Object o); - public abstract boolean remove(Object o); - - private static final String oomeMsg = "Required array size too large"; - - public final Object[] toArray() { - long sz = map.mappingCount(); - if (sz > MAX_ARRAY_SIZE) - throw new OutOfMemoryError(oomeMsg); - int n = (int)sz; - Object[] r = new Object[n]; - int i = 0; - for (E e : this) { - if (i == n) { - if (n >= MAX_ARRAY_SIZE) - throw new OutOfMemoryError(oomeMsg); - if (n >= MAX_ARRAY_SIZE - (MAX_ARRAY_SIZE >>> 1) - 1) - n = MAX_ARRAY_SIZE; - else - n += (n >>> 1) + 1; - r = Arrays.copyOf(r, n); - } - r[i++] = e; - } - return (i == n) ? r : Arrays.copyOf(r, i); - } - - @SuppressWarnings("unchecked") - public final T[] toArray(T[] a) { - long sz = map.mappingCount(); - if (sz > MAX_ARRAY_SIZE) - throw new OutOfMemoryError(oomeMsg); - int m = (int)sz; - T[] r = (a.length >= m) ? a : - (T[])java.lang.reflect.Array - .newInstance(a.getClass().getComponentType(), m); - int n = r.length; - int i = 0; - for (E e : this) { - if (i == n) { - if (n >= MAX_ARRAY_SIZE) - throw new OutOfMemoryError(oomeMsg); - if (n >= MAX_ARRAY_SIZE - (MAX_ARRAY_SIZE >>> 1) - 1) - n = MAX_ARRAY_SIZE; - else - n += (n >>> 1) + 1; - r = Arrays.copyOf(r, n); - } - r[i++] = (T)e; - } - if (a == r && i < n) { - r[i] = null; // null-terminate - return r; - } - return (i == n) ? r : Arrays.copyOf(r, i); - } - - /** - * Returns a string representation of this collection. - * The string representation consists of the string representations - * of the collection's elements in the order they are returned by - * its iterator, enclosed in square brackets ({@code "[]"}). - * Adjacent elements are separated by the characters {@code ", "} - * (comma and space). Elements are converted to strings as by - * {@link String#valueOf(Object)}. - * - * @return a string representation of this collection - */ - public final String toString() { - StringBuilder sb = new StringBuilder(); - sb.append('['); - Iterator it = iterator(); - if (it.hasNext()) { - for (;;) { - Object e = it.next(); - sb.append(e == this ? "(this Collection)" : e); - if (!it.hasNext()) - break; - sb.append(',').append(' '); - } - } - return sb.append(']').toString(); - } - - public final boolean containsAll(Collection c) { - if (c != this) { - for (Object e : c) { - if (e == null || !contains(e)) - return false; - } - } - return true; - } - - public final boolean removeAll(Collection c) { - boolean modified = false; - for (Iterator it = iterator(); it.hasNext();) { - if (c.contains(it.next())) { - it.remove(); - modified = true; - } - } - return modified; - } - - public final boolean retainAll(Collection c) { - boolean modified = false; - for (Iterator it = iterator(); it.hasNext();) { - if (!c.contains(it.next())) { - it.remove(); - modified = true; - } - } - return modified; - } - - } - - /** - * A view of a ConcurrentHashMapV8 as a {@link Set} of keys, in - * which additions may optionally be enabled by mapping to a - * common value. This class cannot be directly instantiated. - * See {@link #keySet() keySet()}, - * {@link #keySet(Object) keySet(V)}, - * {@link #newKeySet() newKeySet()}, - * {@link #newKeySet(int) newKeySet(int)}. - * - * @since 1.8 - */ - public static class KeySetView extends CollectionView - implements Set, java.io.Serializable { - private static final long serialVersionUID = 7249069246763182397L; - private final V value; - KeySetView(ConcurrentHashMapV8 map, V value) { // non-public - super(map); - this.value = value; - } - - /** - * Returns the default mapped value for additions, - * or {@code null} if additions are not supported. - * - * @return the default mapped value for additions, or {@code null} - * if not supported - */ - public V getMappedValue() { return value; } - - /** - * {@inheritDoc} - * @throws NullPointerException if the specified key is null - */ - public boolean contains(Object o) { return map.containsKey(o); } - - /** - * Removes the key from this map view, by removing the key (and its - * corresponding value) from the backing map. This method does - * nothing if the key is not in the map. - * - * @param o the key to be removed from the backing map - * @return {@code true} if the backing map contained the specified key - * @throws NullPointerException if the specified key is null - */ - public boolean remove(Object o) { return map.remove(o) != null; } - - /** - * @return an iterator over the keys of the backing map - */ - public Iterator iterator() { - Node[] t; - ConcurrentHashMapV8 m = map; - int f = (t = m.table) == null ? 0 : t.length; - return new KeyIterator(t, f, 0, f, m); - } - - /** - * Adds the specified key to this set view by mapping the key to - * the default mapped value in the backing map, if defined. - * - * @param e key to be added - * @return {@code true} if this set changed as a result of the call - * @throws NullPointerException if the specified key is null - * @throws UnsupportedOperationException if no default mapped value - * for additions was provided - */ - public boolean add(K e) { - V v; - if ((v = value) == null) - throw new UnsupportedOperationException(); - return map.putVal(e, v, true) == null; - } - - /** - * Adds all of the elements in the specified collection to this set, - * as if by calling {@link #add} on each one. - * - * @param c the elements to be inserted into this set - * @return {@code true} if this set changed as a result of the call - * @throws NullPointerException if the collection or any of its - * elements are {@code null} - * @throws UnsupportedOperationException if no default mapped value - * for additions was provided - */ - public boolean addAll(Collection c) { - boolean added = false; - V v; - if ((v = value) == null) - throw new UnsupportedOperationException(); - for (K e : c) { - if (map.putVal(e, v, true) == null) - added = true; - } - return added; - } - - public int hashCode() { - int h = 0; - for (K e : this) - h += e.hashCode(); - return h; - } - - public boolean equals(Object o) { - Set c; - return ((o instanceof Set) && - ((c = (Set)o) == this || - (containsAll(c) && c.containsAll(this)))); - } - - public ConcurrentHashMapSpliterator spliterator166() { - Node[] t; - ConcurrentHashMapV8 m = map; - long n = m.sumCount(); - int f = (t = m.table) == null ? 0 : t.length; - return new KeySpliterator(t, f, 0, f, n < 0L ? 0L : n); - } - - public void forEach(Action action) { - if (action == null) throw new NullPointerException(); - Node[] t; - if ((t = map.table) != null) { - Traverser it = new Traverser(t, t.length, 0, t.length); - for (Node p; (p = it.advance()) != null; ) - action.apply(p.key); - } - } - } - - /** - * A view of a ConcurrentHashMapV8 as a {@link Collection} of - * values, in which additions are disabled. This class cannot be - * directly instantiated. See {@link #values()}. - */ - static final class ValuesView extends CollectionView - implements Collection, java.io.Serializable { - private static final long serialVersionUID = 2249069246763182397L; - ValuesView(ConcurrentHashMapV8 map) { super(map); } - public final boolean contains(Object o) { - return map.containsValue(o); - } - - public final boolean remove(Object o) { - if (o != null) { - for (Iterator it = iterator(); it.hasNext();) { - if (o.equals(it.next())) { - it.remove(); - return true; - } - } - } - return false; - } - - public final Iterator iterator() { - ConcurrentHashMapV8 m = map; - Node[] t; - int f = (t = m.table) == null ? 0 : t.length; - return new ValueIterator(t, f, 0, f, m); - } - - public final boolean add(V e) { - throw new UnsupportedOperationException(); - } - public final boolean addAll(Collection c) { - throw new UnsupportedOperationException(); - } - - public ConcurrentHashMapSpliterator spliterator166() { - Node[] t; - ConcurrentHashMapV8 m = map; - long n = m.sumCount(); - int f = (t = m.table) == null ? 0 : t.length; - return new ValueSpliterator(t, f, 0, f, n < 0L ? 0L : n); - } - - public void forEach(Action action) { - if (action == null) throw new NullPointerException(); - Node[] t; - if ((t = map.table) != null) { - Traverser it = new Traverser(t, t.length, 0, t.length); - for (Node p; (p = it.advance()) != null; ) - action.apply(p.val); - } - } - } - - /** - * A view of a ConcurrentHashMapV8 as a {@link Set} of (key, value) - * entries. This class cannot be directly instantiated. See - * {@link #entrySet()}. - */ - static final class EntrySetView extends CollectionView> - implements Set>, java.io.Serializable { - private static final long serialVersionUID = 2249069246763182397L; - EntrySetView(ConcurrentHashMapV8 map) { super(map); } - - public boolean contains(Object o) { - Object k, v, r; Map.Entry e; - return ((o instanceof Map.Entry) && - (k = (e = (Map.Entry)o).getKey()) != null && - (r = map.get(k)) != null && - (v = e.getValue()) != null && - (v == r || v.equals(r))); - } - - public boolean remove(Object o) { - Object k, v; Map.Entry e; - return ((o instanceof Map.Entry) && - (k = (e = (Map.Entry)o).getKey()) != null && - (v = e.getValue()) != null && - map.remove(k, v)); - } - - /** - * @return an iterator over the entries of the backing map - */ - public Iterator> iterator() { - ConcurrentHashMapV8 m = map; - Node[] t; - int f = (t = m.table) == null ? 0 : t.length; - return new EntryIterator(t, f, 0, f, m); - } - - public boolean add(Entry e) { - return map.putVal(e.getKey(), e.getValue(), false) == null; - } - - public boolean addAll(Collection> c) { - boolean added = false; - for (Entry e : c) { - if (add(e)) - added = true; - } - return added; - } - - public final int hashCode() { - int h = 0; - Node[] t; - if ((t = map.table) != null) { - Traverser it = new Traverser(t, t.length, 0, t.length); - for (Node p; (p = it.advance()) != null; ) { - h += p.hashCode(); - } - } - return h; - } - - public final boolean equals(Object o) { - Set c; - return ((o instanceof Set) && - ((c = (Set)o) == this || - (containsAll(c) && c.containsAll(this)))); - } - - public ConcurrentHashMapSpliterator> spliterator166() { - Node[] t; - ConcurrentHashMapV8 m = map; - long n = m.sumCount(); - int f = (t = m.table) == null ? 0 : t.length; - return new EntrySpliterator(t, f, 0, f, n < 0L ? 0L : n, m); - } - - public void forEach(Action> action) { - if (action == null) throw new NullPointerException(); - Node[] t; - if ((t = map.table) != null) { - Traverser it = new Traverser(t, t.length, 0, t.length); - for (Node p; (p = it.advance()) != null; ) - action.apply(new MapEntry(p.key, p.val, map)); - } - } - - } - - // ------------------------------------------------------- - - /** - * Base class for bulk tasks. Repeats some fields and code from - * class Traverser, because we need to subclass CountedCompleter. - */ - abstract static class BulkTask extends CountedCompleter { - Node[] tab; // same as Traverser - Node next; - int index; - int baseIndex; - int baseLimit; - final int baseSize; - int batch; // split control - - BulkTask(BulkTask par, int b, int i, int f, Node[] t) { - super(par); - this.batch = b; - this.index = this.baseIndex = i; - if ((this.tab = t) == null) - this.baseSize = this.baseLimit = 0; - else if (par == null) - this.baseSize = this.baseLimit = t.length; - else { - this.baseLimit = f; - this.baseSize = par.baseSize; - } - } - - /** - * Same as Traverser version - */ - final Node advance() { - Node e; - if ((e = next) != null) - e = e.next; - for (;;) { - Node[] t; int i, n; K ek; // must use locals in checks - if (e != null) - return next = e; - if (baseIndex >= baseLimit || (t = tab) == null || - (n = t.length) <= (i = index) || i < 0) - return next = null; - if ((e = tabAt(t, index)) != null && e.hash < 0) { - if (e instanceof ForwardingNode) { - tab = ((ForwardingNode)e).nextTable; - e = null; - continue; - } - else if (e instanceof TreeBin) - e = ((TreeBin)e).first; - else - e = null; - } - if ((index += baseSize) >= n) - index = ++baseIndex; // visit upper slots if present - } - } - } - - /* - * Task classes. Coded in a regular but ugly format/style to - * simplify checks that each variant differs in the right way from - * others. The null screenings exist because compilers cannot tell - * that we've already null-checked task arguments, so we force - * simplest hoisted bypass to help avoid convoluted traps. - */ - @SuppressWarnings("serial") - static final class ForEachKeyTask - extends BulkTask { - final Action action; - ForEachKeyTask - (BulkTask p, int b, int i, int f, Node[] t, - Action action) { - super(p, b, i, f, t); - this.action = action; - } - public final void compute() { - final Action action; - if ((action = this.action) != null) { - for (int i = baseIndex, f, h; batch > 0 && - (h = ((f = baseLimit) + i) >>> 1) > i;) { - addToPendingCount(1); - new ForEachKeyTask - (this, batch >>>= 1, baseLimit = h, f, tab, - action).fork(); - } - for (Node p; (p = advance()) != null;) - action.apply(p.key); - propagateCompletion(); - } - } - } - - @SuppressWarnings("serial") - static final class ForEachValueTask - extends BulkTask { - final Action action; - ForEachValueTask - (BulkTask p, int b, int i, int f, Node[] t, - Action action) { - super(p, b, i, f, t); - this.action = action; - } - public final void compute() { - final Action action; - if ((action = this.action) != null) { - for (int i = baseIndex, f, h; batch > 0 && - (h = ((f = baseLimit) + i) >>> 1) > i;) { - addToPendingCount(1); - new ForEachValueTask - (this, batch >>>= 1, baseLimit = h, f, tab, - action).fork(); - } - for (Node p; (p = advance()) != null;) - action.apply(p.val); - propagateCompletion(); - } - } - } - - @SuppressWarnings("serial") - static final class ForEachEntryTask - extends BulkTask { - final Action> action; - ForEachEntryTask - (BulkTask p, int b, int i, int f, Node[] t, - Action> action) { - super(p, b, i, f, t); - this.action = action; - } - public final void compute() { - final Action> action; - if ((action = this.action) != null) { - for (int i = baseIndex, f, h; batch > 0 && - (h = ((f = baseLimit) + i) >>> 1) > i;) { - addToPendingCount(1); - new ForEachEntryTask - (this, batch >>>= 1, baseLimit = h, f, tab, - action).fork(); - } - for (Node p; (p = advance()) != null; ) - action.apply(p); - propagateCompletion(); - } - } - } - - @SuppressWarnings("serial") - static final class ForEachMappingTask - extends BulkTask { - final BiAction action; - ForEachMappingTask - (BulkTask p, int b, int i, int f, Node[] t, - BiAction action) { - super(p, b, i, f, t); - this.action = action; - } - public final void compute() { - final BiAction action; - if ((action = this.action) != null) { - for (int i = baseIndex, f, h; batch > 0 && - (h = ((f = baseLimit) + i) >>> 1) > i;) { - addToPendingCount(1); - new ForEachMappingTask - (this, batch >>>= 1, baseLimit = h, f, tab, - action).fork(); - } - for (Node p; (p = advance()) != null; ) - action.apply(p.key, p.val); - propagateCompletion(); - } - } - } - - @SuppressWarnings("serial") - static final class ForEachTransformedKeyTask - extends BulkTask { - final Fun transformer; - final Action action; - ForEachTransformedKeyTask - (BulkTask p, int b, int i, int f, Node[] t, - Fun transformer, Action action) { - super(p, b, i, f, t); - this.transformer = transformer; this.action = action; - } - public final void compute() { - final Fun transformer; - final Action action; - if ((transformer = this.transformer) != null && - (action = this.action) != null) { - for (int i = baseIndex, f, h; batch > 0 && - (h = ((f = baseLimit) + i) >>> 1) > i;) { - addToPendingCount(1); - new ForEachTransformedKeyTask - (this, batch >>>= 1, baseLimit = h, f, tab, - transformer, action).fork(); - } - for (Node p; (p = advance()) != null; ) { - U u; - if ((u = transformer.apply(p.key)) != null) - action.apply(u); - } - propagateCompletion(); - } - } - } - - @SuppressWarnings("serial") - static final class ForEachTransformedValueTask - extends BulkTask { - final Fun transformer; - final Action action; - ForEachTransformedValueTask - (BulkTask p, int b, int i, int f, Node[] t, - Fun transformer, Action action) { - super(p, b, i, f, t); - this.transformer = transformer; this.action = action; - } - public final void compute() { - final Fun transformer; - final Action action; - if ((transformer = this.transformer) != null && - (action = this.action) != null) { - for (int i = baseIndex, f, h; batch > 0 && - (h = ((f = baseLimit) + i) >>> 1) > i;) { - addToPendingCount(1); - new ForEachTransformedValueTask - (this, batch >>>= 1, baseLimit = h, f, tab, - transformer, action).fork(); - } - for (Node p; (p = advance()) != null; ) { - U u; - if ((u = transformer.apply(p.val)) != null) - action.apply(u); - } - propagateCompletion(); - } - } - } - - @SuppressWarnings("serial") - static final class ForEachTransformedEntryTask - extends BulkTask { - final Fun, ? extends U> transformer; - final Action action; - ForEachTransformedEntryTask - (BulkTask p, int b, int i, int f, Node[] t, - Fun, ? extends U> transformer, Action action) { - super(p, b, i, f, t); - this.transformer = transformer; this.action = action; - } - public final void compute() { - final Fun, ? extends U> transformer; - final Action action; - if ((transformer = this.transformer) != null && - (action = this.action) != null) { - for (int i = baseIndex, f, h; batch > 0 && - (h = ((f = baseLimit) + i) >>> 1) > i;) { - addToPendingCount(1); - new ForEachTransformedEntryTask - (this, batch >>>= 1, baseLimit = h, f, tab, - transformer, action).fork(); - } - for (Node p; (p = advance()) != null; ) { - U u; - if ((u = transformer.apply(p)) != null) - action.apply(u); - } - propagateCompletion(); - } - } - } - - @SuppressWarnings("serial") - static final class ForEachTransformedMappingTask - extends BulkTask { - final BiFun transformer; - final Action action; - ForEachTransformedMappingTask - (BulkTask p, int b, int i, int f, Node[] t, - BiFun transformer, - Action action) { - super(p, b, i, f, t); - this.transformer = transformer; this.action = action; - } - public final void compute() { - final BiFun transformer; - final Action action; - if ((transformer = this.transformer) != null && - (action = this.action) != null) { - for (int i = baseIndex, f, h; batch > 0 && - (h = ((f = baseLimit) + i) >>> 1) > i;) { - addToPendingCount(1); - new ForEachTransformedMappingTask - (this, batch >>>= 1, baseLimit = h, f, tab, - transformer, action).fork(); - } - for (Node p; (p = advance()) != null; ) { - U u; - if ((u = transformer.apply(p.key, p.val)) != null) - action.apply(u); - } - propagateCompletion(); - } - } - } - - @SuppressWarnings("serial") - static final class SearchKeysTask - extends BulkTask { - final Fun searchFunction; - final AtomicReference result; - SearchKeysTask - (BulkTask p, int b, int i, int f, Node[] t, - Fun searchFunction, - AtomicReference result) { - super(p, b, i, f, t); - this.searchFunction = searchFunction; this.result = result; - } - public final U getRawResult() { return result.get(); } - public final void compute() { - final Fun searchFunction; - final AtomicReference result; - if ((searchFunction = this.searchFunction) != null && - (result = this.result) != null) { - for (int i = baseIndex, f, h; batch > 0 && - (h = ((f = baseLimit) + i) >>> 1) > i;) { - if (result.get() != null) - return; - addToPendingCount(1); - new SearchKeysTask - (this, batch >>>= 1, baseLimit = h, f, tab, - searchFunction, result).fork(); - } - while (result.get() == null) { - U u; - Node p; - if ((p = advance()) == null) { - propagateCompletion(); - break; - } - if ((u = searchFunction.apply(p.key)) != null) { - if (result.compareAndSet(null, u)) - quietlyCompleteRoot(); - break; - } - } - } - } - } - - @SuppressWarnings("serial") - static final class SearchValuesTask - extends BulkTask { - final Fun searchFunction; - final AtomicReference result; - SearchValuesTask - (BulkTask p, int b, int i, int f, Node[] t, - Fun searchFunction, - AtomicReference result) { - super(p, b, i, f, t); - this.searchFunction = searchFunction; this.result = result; - } - public final U getRawResult() { return result.get(); } - public final void compute() { - final Fun searchFunction; - final AtomicReference result; - if ((searchFunction = this.searchFunction) != null && - (result = this.result) != null) { - for (int i = baseIndex, f, h; batch > 0 && - (h = ((f = baseLimit) + i) >>> 1) > i;) { - if (result.get() != null) - return; - addToPendingCount(1); - new SearchValuesTask - (this, batch >>>= 1, baseLimit = h, f, tab, - searchFunction, result).fork(); - } - while (result.get() == null) { - U u; - Node p; - if ((p = advance()) == null) { - propagateCompletion(); - break; - } - if ((u = searchFunction.apply(p.val)) != null) { - if (result.compareAndSet(null, u)) - quietlyCompleteRoot(); - break; - } - } - } - } - } - - @SuppressWarnings("serial") - static final class SearchEntriesTask - extends BulkTask { - final Fun, ? extends U> searchFunction; - final AtomicReference result; - SearchEntriesTask - (BulkTask p, int b, int i, int f, Node[] t, - Fun, ? extends U> searchFunction, - AtomicReference result) { - super(p, b, i, f, t); - this.searchFunction = searchFunction; this.result = result; - } - public final U getRawResult() { return result.get(); } - public final void compute() { - final Fun, ? extends U> searchFunction; - final AtomicReference result; - if ((searchFunction = this.searchFunction) != null && - (result = this.result) != null) { - for (int i = baseIndex, f, h; batch > 0 && - (h = ((f = baseLimit) + i) >>> 1) > i;) { - if (result.get() != null) - return; - addToPendingCount(1); - new SearchEntriesTask - (this, batch >>>= 1, baseLimit = h, f, tab, - searchFunction, result).fork(); - } - while (result.get() == null) { - U u; - Node p; - if ((p = advance()) == null) { - propagateCompletion(); - break; - } - if ((u = searchFunction.apply(p)) != null) { - if (result.compareAndSet(null, u)) - quietlyCompleteRoot(); - return; - } - } - } - } - } - - @SuppressWarnings("serial") - static final class SearchMappingsTask - extends BulkTask { - final BiFun searchFunction; - final AtomicReference result; - SearchMappingsTask - (BulkTask p, int b, int i, int f, Node[] t, - BiFun searchFunction, - AtomicReference result) { - super(p, b, i, f, t); - this.searchFunction = searchFunction; this.result = result; - } - public final U getRawResult() { return result.get(); } - public final void compute() { - final BiFun searchFunction; - final AtomicReference result; - if ((searchFunction = this.searchFunction) != null && - (result = this.result) != null) { - for (int i = baseIndex, f, h; batch > 0 && - (h = ((f = baseLimit) + i) >>> 1) > i;) { - if (result.get() != null) - return; - addToPendingCount(1); - new SearchMappingsTask - (this, batch >>>= 1, baseLimit = h, f, tab, - searchFunction, result).fork(); - } - while (result.get() == null) { - U u; - Node p; - if ((p = advance()) == null) { - propagateCompletion(); - break; - } - if ((u = searchFunction.apply(p.key, p.val)) != null) { - if (result.compareAndSet(null, u)) - quietlyCompleteRoot(); - break; - } - } - } - } - } - - @SuppressWarnings("serial") - static final class ReduceKeysTask - extends BulkTask { - final BiFun reducer; - K result; - ReduceKeysTask rights, nextRight; - ReduceKeysTask - (BulkTask p, int b, int i, int f, Node[] t, - ReduceKeysTask nextRight, - BiFun reducer) { - super(p, b, i, f, t); this.nextRight = nextRight; - this.reducer = reducer; - } - public final K getRawResult() { return result; } - public final void compute() { - final BiFun reducer; - if ((reducer = this.reducer) != null) { - for (int i = baseIndex, f, h; batch > 0 && - (h = ((f = baseLimit) + i) >>> 1) > i;) { - addToPendingCount(1); - (rights = new ReduceKeysTask - (this, batch >>>= 1, baseLimit = h, f, tab, - rights, reducer)).fork(); - } - K r = null; - for (Node p; (p = advance()) != null; ) { - K u = p.key; - r = (r == null) ? u : u == null ? r : reducer.apply(r, u); - } - result = r; - CountedCompleter c; - for (c = firstComplete(); c != null; c = c.nextComplete()) { - @SuppressWarnings("unchecked") ReduceKeysTask - t = (ReduceKeysTask)c, - s = t.rights; - while (s != null) { - K tr, sr; - if ((sr = s.result) != null) - t.result = (((tr = t.result) == null) ? sr : - reducer.apply(tr, sr)); - s = t.rights = s.nextRight; - } - } - } - } - } - - @SuppressWarnings("serial") - static final class ReduceValuesTask - extends BulkTask { - final BiFun reducer; - V result; - ReduceValuesTask rights, nextRight; - ReduceValuesTask - (BulkTask p, int b, int i, int f, Node[] t, - ReduceValuesTask nextRight, - BiFun reducer) { - super(p, b, i, f, t); this.nextRight = nextRight; - this.reducer = reducer; - } - public final V getRawResult() { return result; } - public final void compute() { - final BiFun reducer; - if ((reducer = this.reducer) != null) { - for (int i = baseIndex, f, h; batch > 0 && - (h = ((f = baseLimit) + i) >>> 1) > i;) { - addToPendingCount(1); - (rights = new ReduceValuesTask - (this, batch >>>= 1, baseLimit = h, f, tab, - rights, reducer)).fork(); - } - V r = null; - for (Node p; (p = advance()) != null; ) { - V v = p.val; - r = (r == null) ? v : reducer.apply(r, v); - } - result = r; - CountedCompleter c; - for (c = firstComplete(); c != null; c = c.nextComplete()) { - @SuppressWarnings("unchecked") ReduceValuesTask - t = (ReduceValuesTask)c, - s = t.rights; - while (s != null) { - V tr, sr; - if ((sr = s.result) != null) - t.result = (((tr = t.result) == null) ? sr : - reducer.apply(tr, sr)); - s = t.rights = s.nextRight; - } - } - } - } - } - - @SuppressWarnings("serial") - static final class ReduceEntriesTask - extends BulkTask> { - final BiFun, Map.Entry, ? extends Map.Entry> reducer; - Map.Entry result; - ReduceEntriesTask rights, nextRight; - ReduceEntriesTask - (BulkTask p, int b, int i, int f, Node[] t, - ReduceEntriesTask nextRight, - BiFun, Map.Entry, ? extends Map.Entry> reducer) { - super(p, b, i, f, t); this.nextRight = nextRight; - this.reducer = reducer; - } - public final Map.Entry getRawResult() { return result; } - public final void compute() { - final BiFun, Map.Entry, ? extends Map.Entry> reducer; - if ((reducer = this.reducer) != null) { - for (int i = baseIndex, f, h; batch > 0 && - (h = ((f = baseLimit) + i) >>> 1) > i;) { - addToPendingCount(1); - (rights = new ReduceEntriesTask - (this, batch >>>= 1, baseLimit = h, f, tab, - rights, reducer)).fork(); - } - Map.Entry r = null; - for (Node p; (p = advance()) != null; ) - r = (r == null) ? p : reducer.apply(r, p); - result = r; - CountedCompleter c; - for (c = firstComplete(); c != null; c = c.nextComplete()) { - @SuppressWarnings("unchecked") ReduceEntriesTask - t = (ReduceEntriesTask)c, - s = t.rights; - while (s != null) { - Map.Entry tr, sr; - if ((sr = s.result) != null) - t.result = (((tr = t.result) == null) ? sr : - reducer.apply(tr, sr)); - s = t.rights = s.nextRight; - } - } - } - } - } - - @SuppressWarnings("serial") - static final class MapReduceKeysTask - extends BulkTask { - final Fun transformer; - final BiFun reducer; - U result; - MapReduceKeysTask rights, nextRight; - MapReduceKeysTask - (BulkTask p, int b, int i, int f, Node[] t, - MapReduceKeysTask nextRight, - Fun transformer, - BiFun reducer) { - super(p, b, i, f, t); this.nextRight = nextRight; - this.transformer = transformer; - this.reducer = reducer; - } - public final U getRawResult() { return result; } - public final void compute() { - final Fun transformer; - final BiFun reducer; - if ((transformer = this.transformer) != null && - (reducer = this.reducer) != null) { - for (int i = baseIndex, f, h; batch > 0 && - (h = ((f = baseLimit) + i) >>> 1) > i;) { - addToPendingCount(1); - (rights = new MapReduceKeysTask - (this, batch >>>= 1, baseLimit = h, f, tab, - rights, transformer, reducer)).fork(); - } - U r = null; - for (Node p; (p = advance()) != null; ) { - U u; - if ((u = transformer.apply(p.key)) != null) - r = (r == null) ? u : reducer.apply(r, u); - } - result = r; - CountedCompleter c; - for (c = firstComplete(); c != null; c = c.nextComplete()) { - @SuppressWarnings("unchecked") MapReduceKeysTask - t = (MapReduceKeysTask)c, - s = t.rights; - while (s != null) { - U tr, sr; - if ((sr = s.result) != null) - t.result = (((tr = t.result) == null) ? sr : - reducer.apply(tr, sr)); - s = t.rights = s.nextRight; - } - } - } - } - } - - @SuppressWarnings("serial") - static final class MapReduceValuesTask - extends BulkTask { - final Fun transformer; - final BiFun reducer; - U result; - MapReduceValuesTask rights, nextRight; - MapReduceValuesTask - (BulkTask p, int b, int i, int f, Node[] t, - MapReduceValuesTask nextRight, - Fun transformer, - BiFun reducer) { - super(p, b, i, f, t); this.nextRight = nextRight; - this.transformer = transformer; - this.reducer = reducer; - } - public final U getRawResult() { return result; } - public final void compute() { - final Fun transformer; - final BiFun reducer; - if ((transformer = this.transformer) != null && - (reducer = this.reducer) != null) { - for (int i = baseIndex, f, h; batch > 0 && - (h = ((f = baseLimit) + i) >>> 1) > i;) { - addToPendingCount(1); - (rights = new MapReduceValuesTask - (this, batch >>>= 1, baseLimit = h, f, tab, - rights, transformer, reducer)).fork(); - } - U r = null; - for (Node p; (p = advance()) != null; ) { - U u; - if ((u = transformer.apply(p.val)) != null) - r = (r == null) ? u : reducer.apply(r, u); - } - result = r; - CountedCompleter c; - for (c = firstComplete(); c != null; c = c.nextComplete()) { - @SuppressWarnings("unchecked") MapReduceValuesTask - t = (MapReduceValuesTask)c, - s = t.rights; - while (s != null) { - U tr, sr; - if ((sr = s.result) != null) - t.result = (((tr = t.result) == null) ? sr : - reducer.apply(tr, sr)); - s = t.rights = s.nextRight; - } - } - } - } - } - - @SuppressWarnings("serial") - static final class MapReduceEntriesTask - extends BulkTask { - final Fun, ? extends U> transformer; - final BiFun reducer; - U result; - MapReduceEntriesTask rights, nextRight; - MapReduceEntriesTask - (BulkTask p, int b, int i, int f, Node[] t, - MapReduceEntriesTask nextRight, - Fun, ? extends U> transformer, - BiFun reducer) { - super(p, b, i, f, t); this.nextRight = nextRight; - this.transformer = transformer; - this.reducer = reducer; - } - public final U getRawResult() { return result; } - public final void compute() { - final Fun, ? extends U> transformer; - final BiFun reducer; - if ((transformer = this.transformer) != null && - (reducer = this.reducer) != null) { - for (int i = baseIndex, f, h; batch > 0 && - (h = ((f = baseLimit) + i) >>> 1) > i;) { - addToPendingCount(1); - (rights = new MapReduceEntriesTask - (this, batch >>>= 1, baseLimit = h, f, tab, - rights, transformer, reducer)).fork(); - } - U r = null; - for (Node p; (p = advance()) != null; ) { - U u; - if ((u = transformer.apply(p)) != null) - r = (r == null) ? u : reducer.apply(r, u); - } - result = r; - CountedCompleter c; - for (c = firstComplete(); c != null; c = c.nextComplete()) { - @SuppressWarnings("unchecked") MapReduceEntriesTask - t = (MapReduceEntriesTask)c, - s = t.rights; - while (s != null) { - U tr, sr; - if ((sr = s.result) != null) - t.result = (((tr = t.result) == null) ? sr : - reducer.apply(tr, sr)); - s = t.rights = s.nextRight; - } - } - } - } - } - - @SuppressWarnings("serial") - static final class MapReduceMappingsTask - extends BulkTask { - final BiFun transformer; - final BiFun reducer; - U result; - MapReduceMappingsTask rights, nextRight; - MapReduceMappingsTask - (BulkTask p, int b, int i, int f, Node[] t, - MapReduceMappingsTask nextRight, - BiFun transformer, - BiFun reducer) { - super(p, b, i, f, t); this.nextRight = nextRight; - this.transformer = transformer; - this.reducer = reducer; - } - public final U getRawResult() { return result; } - public final void compute() { - final BiFun transformer; - final BiFun reducer; - if ((transformer = this.transformer) != null && - (reducer = this.reducer) != null) { - for (int i = baseIndex, f, h; batch > 0 && - (h = ((f = baseLimit) + i) >>> 1) > i;) { - addToPendingCount(1); - (rights = new MapReduceMappingsTask - (this, batch >>>= 1, baseLimit = h, f, tab, - rights, transformer, reducer)).fork(); - } - U r = null; - for (Node p; (p = advance()) != null; ) { - U u; - if ((u = transformer.apply(p.key, p.val)) != null) - r = (r == null) ? u : reducer.apply(r, u); - } - result = r; - CountedCompleter c; - for (c = firstComplete(); c != null; c = c.nextComplete()) { - @SuppressWarnings("unchecked") MapReduceMappingsTask - t = (MapReduceMappingsTask)c, - s = t.rights; - while (s != null) { - U tr, sr; - if ((sr = s.result) != null) - t.result = (((tr = t.result) == null) ? sr : - reducer.apply(tr, sr)); - s = t.rights = s.nextRight; - } - } - } - } - } - - @SuppressWarnings("serial") - static final class MapReduceKeysToDoubleTask - extends BulkTask { - final ObjectToDouble transformer; - final DoubleByDoubleToDouble reducer; - final double basis; - double result; - MapReduceKeysToDoubleTask rights, nextRight; - MapReduceKeysToDoubleTask - (BulkTask p, int b, int i, int f, Node[] t, - MapReduceKeysToDoubleTask nextRight, - ObjectToDouble transformer, - double basis, - DoubleByDoubleToDouble reducer) { - super(p, b, i, f, t); this.nextRight = nextRight; - this.transformer = transformer; - this.basis = basis; this.reducer = reducer; - } - public final Double getRawResult() { return result; } - public final void compute() { - final ObjectToDouble transformer; - final DoubleByDoubleToDouble reducer; - if ((transformer = this.transformer) != null && - (reducer = this.reducer) != null) { - double r = this.basis; - for (int i = baseIndex, f, h; batch > 0 && - (h = ((f = baseLimit) + i) >>> 1) > i;) { - addToPendingCount(1); - (rights = new MapReduceKeysToDoubleTask - (this, batch >>>= 1, baseLimit = h, f, tab, - rights, transformer, r, reducer)).fork(); - } - for (Node p; (p = advance()) != null; ) - r = reducer.apply(r, transformer.apply(p.key)); - result = r; - CountedCompleter c; - for (c = firstComplete(); c != null; c = c.nextComplete()) { - @SuppressWarnings("unchecked") MapReduceKeysToDoubleTask - t = (MapReduceKeysToDoubleTask)c, - s = t.rights; - while (s != null) { - t.result = reducer.apply(t.result, s.result); - s = t.rights = s.nextRight; - } - } - } - } - } - - @SuppressWarnings("serial") - static final class MapReduceValuesToDoubleTask - extends BulkTask { - final ObjectToDouble transformer; - final DoubleByDoubleToDouble reducer; - final double basis; - double result; - MapReduceValuesToDoubleTask rights, nextRight; - MapReduceValuesToDoubleTask - (BulkTask p, int b, int i, int f, Node[] t, - MapReduceValuesToDoubleTask nextRight, - ObjectToDouble transformer, - double basis, - DoubleByDoubleToDouble reducer) { - super(p, b, i, f, t); this.nextRight = nextRight; - this.transformer = transformer; - this.basis = basis; this.reducer = reducer; - } - public final Double getRawResult() { return result; } - public final void compute() { - final ObjectToDouble transformer; - final DoubleByDoubleToDouble reducer; - if ((transformer = this.transformer) != null && - (reducer = this.reducer) != null) { - double r = this.basis; - for (int i = baseIndex, f, h; batch > 0 && - (h = ((f = baseLimit) + i) >>> 1) > i;) { - addToPendingCount(1); - (rights = new MapReduceValuesToDoubleTask - (this, batch >>>= 1, baseLimit = h, f, tab, - rights, transformer, r, reducer)).fork(); - } - for (Node p; (p = advance()) != null; ) - r = reducer.apply(r, transformer.apply(p.val)); - result = r; - CountedCompleter c; - for (c = firstComplete(); c != null; c = c.nextComplete()) { - @SuppressWarnings("unchecked") MapReduceValuesToDoubleTask - t = (MapReduceValuesToDoubleTask)c, - s = t.rights; - while (s != null) { - t.result = reducer.apply(t.result, s.result); - s = t.rights = s.nextRight; - } - } - } - } - } - - @SuppressWarnings("serial") - static final class MapReduceEntriesToDoubleTask - extends BulkTask { - final ObjectToDouble> transformer; - final DoubleByDoubleToDouble reducer; - final double basis; - double result; - MapReduceEntriesToDoubleTask rights, nextRight; - MapReduceEntriesToDoubleTask - (BulkTask p, int b, int i, int f, Node[] t, - MapReduceEntriesToDoubleTask nextRight, - ObjectToDouble> transformer, - double basis, - DoubleByDoubleToDouble reducer) { - super(p, b, i, f, t); this.nextRight = nextRight; - this.transformer = transformer; - this.basis = basis; this.reducer = reducer; - } - public final Double getRawResult() { return result; } - public final void compute() { - final ObjectToDouble> transformer; - final DoubleByDoubleToDouble reducer; - if ((transformer = this.transformer) != null && - (reducer = this.reducer) != null) { - double r = this.basis; - for (int i = baseIndex, f, h; batch > 0 && - (h = ((f = baseLimit) + i) >>> 1) > i;) { - addToPendingCount(1); - (rights = new MapReduceEntriesToDoubleTask - (this, batch >>>= 1, baseLimit = h, f, tab, - rights, transformer, r, reducer)).fork(); - } - for (Node p; (p = advance()) != null; ) - r = reducer.apply(r, transformer.apply(p)); - result = r; - CountedCompleter c; - for (c = firstComplete(); c != null; c = c.nextComplete()) { - @SuppressWarnings("unchecked") MapReduceEntriesToDoubleTask - t = (MapReduceEntriesToDoubleTask)c, - s = t.rights; - while (s != null) { - t.result = reducer.apply(t.result, s.result); - s = t.rights = s.nextRight; - } - } - } - } - } - - @SuppressWarnings("serial") - static final class MapReduceMappingsToDoubleTask - extends BulkTask { - final ObjectByObjectToDouble transformer; - final DoubleByDoubleToDouble reducer; - final double basis; - double result; - MapReduceMappingsToDoubleTask rights, nextRight; - MapReduceMappingsToDoubleTask - (BulkTask p, int b, int i, int f, Node[] t, - MapReduceMappingsToDoubleTask nextRight, - ObjectByObjectToDouble transformer, - double basis, - DoubleByDoubleToDouble reducer) { - super(p, b, i, f, t); this.nextRight = nextRight; - this.transformer = transformer; - this.basis = basis; this.reducer = reducer; - } - public final Double getRawResult() { return result; } - public final void compute() { - final ObjectByObjectToDouble transformer; - final DoubleByDoubleToDouble reducer; - if ((transformer = this.transformer) != null && - (reducer = this.reducer) != null) { - double r = this.basis; - for (int i = baseIndex, f, h; batch > 0 && - (h = ((f = baseLimit) + i) >>> 1) > i;) { - addToPendingCount(1); - (rights = new MapReduceMappingsToDoubleTask - (this, batch >>>= 1, baseLimit = h, f, tab, - rights, transformer, r, reducer)).fork(); - } - for (Node p; (p = advance()) != null; ) - r = reducer.apply(r, transformer.apply(p.key, p.val)); - result = r; - CountedCompleter c; - for (c = firstComplete(); c != null; c = c.nextComplete()) { - @SuppressWarnings("unchecked") MapReduceMappingsToDoubleTask - t = (MapReduceMappingsToDoubleTask)c, - s = t.rights; - while (s != null) { - t.result = reducer.apply(t.result, s.result); - s = t.rights = s.nextRight; - } - } - } - } - } - - @SuppressWarnings("serial") - static final class MapReduceKeysToLongTask - extends BulkTask { - final ObjectToLong transformer; - final LongByLongToLong reducer; - final long basis; - long result; - MapReduceKeysToLongTask rights, nextRight; - MapReduceKeysToLongTask - (BulkTask p, int b, int i, int f, Node[] t, - MapReduceKeysToLongTask nextRight, - ObjectToLong transformer, - long basis, - LongByLongToLong reducer) { - super(p, b, i, f, t); this.nextRight = nextRight; - this.transformer = transformer; - this.basis = basis; this.reducer = reducer; - } - public final Long getRawResult() { return result; } - public final void compute() { - final ObjectToLong transformer; - final LongByLongToLong reducer; - if ((transformer = this.transformer) != null && - (reducer = this.reducer) != null) { - long r = this.basis; - for (int i = baseIndex, f, h; batch > 0 && - (h = ((f = baseLimit) + i) >>> 1) > i;) { - addToPendingCount(1); - (rights = new MapReduceKeysToLongTask - (this, batch >>>= 1, baseLimit = h, f, tab, - rights, transformer, r, reducer)).fork(); - } - for (Node p; (p = advance()) != null; ) - r = reducer.apply(r, transformer.apply(p.key)); - result = r; - CountedCompleter c; - for (c = firstComplete(); c != null; c = c.nextComplete()) { - @SuppressWarnings("unchecked") MapReduceKeysToLongTask - t = (MapReduceKeysToLongTask)c, - s = t.rights; - while (s != null) { - t.result = reducer.apply(t.result, s.result); - s = t.rights = s.nextRight; - } - } - } - } - } - - @SuppressWarnings("serial") - static final class MapReduceValuesToLongTask - extends BulkTask { - final ObjectToLong transformer; - final LongByLongToLong reducer; - final long basis; - long result; - MapReduceValuesToLongTask rights, nextRight; - MapReduceValuesToLongTask - (BulkTask p, int b, int i, int f, Node[] t, - MapReduceValuesToLongTask nextRight, - ObjectToLong transformer, - long basis, - LongByLongToLong reducer) { - super(p, b, i, f, t); this.nextRight = nextRight; - this.transformer = transformer; - this.basis = basis; this.reducer = reducer; - } - public final Long getRawResult() { return result; } - public final void compute() { - final ObjectToLong transformer; - final LongByLongToLong reducer; - if ((transformer = this.transformer) != null && - (reducer = this.reducer) != null) { - long r = this.basis; - for (int i = baseIndex, f, h; batch > 0 && - (h = ((f = baseLimit) + i) >>> 1) > i;) { - addToPendingCount(1); - (rights = new MapReduceValuesToLongTask - (this, batch >>>= 1, baseLimit = h, f, tab, - rights, transformer, r, reducer)).fork(); - } - for (Node p; (p = advance()) != null; ) - r = reducer.apply(r, transformer.apply(p.val)); - result = r; - CountedCompleter c; - for (c = firstComplete(); c != null; c = c.nextComplete()) { - @SuppressWarnings("unchecked") MapReduceValuesToLongTask - t = (MapReduceValuesToLongTask)c, - s = t.rights; - while (s != null) { - t.result = reducer.apply(t.result, s.result); - s = t.rights = s.nextRight; - } - } - } - } - } - - @SuppressWarnings("serial") - static final class MapReduceEntriesToLongTask - extends BulkTask { - final ObjectToLong> transformer; - final LongByLongToLong reducer; - final long basis; - long result; - MapReduceEntriesToLongTask rights, nextRight; - MapReduceEntriesToLongTask - (BulkTask p, int b, int i, int f, Node[] t, - MapReduceEntriesToLongTask nextRight, - ObjectToLong> transformer, - long basis, - LongByLongToLong reducer) { - super(p, b, i, f, t); this.nextRight = nextRight; - this.transformer = transformer; - this.basis = basis; this.reducer = reducer; - } - public final Long getRawResult() { return result; } - public final void compute() { - final ObjectToLong> transformer; - final LongByLongToLong reducer; - if ((transformer = this.transformer) != null && - (reducer = this.reducer) != null) { - long r = this.basis; - for (int i = baseIndex, f, h; batch > 0 && - (h = ((f = baseLimit) + i) >>> 1) > i;) { - addToPendingCount(1); - (rights = new MapReduceEntriesToLongTask - (this, batch >>>= 1, baseLimit = h, f, tab, - rights, transformer, r, reducer)).fork(); - } - for (Node p; (p = advance()) != null; ) - r = reducer.apply(r, transformer.apply(p)); - result = r; - CountedCompleter c; - for (c = firstComplete(); c != null; c = c.nextComplete()) { - @SuppressWarnings("unchecked") MapReduceEntriesToLongTask - t = (MapReduceEntriesToLongTask)c, - s = t.rights; - while (s != null) { - t.result = reducer.apply(t.result, s.result); - s = t.rights = s.nextRight; - } - } - } - } - } - - @SuppressWarnings("serial") - static final class MapReduceMappingsToLongTask - extends BulkTask { - final ObjectByObjectToLong transformer; - final LongByLongToLong reducer; - final long basis; - long result; - MapReduceMappingsToLongTask rights, nextRight; - MapReduceMappingsToLongTask - (BulkTask p, int b, int i, int f, Node[] t, - MapReduceMappingsToLongTask nextRight, - ObjectByObjectToLong transformer, - long basis, - LongByLongToLong reducer) { - super(p, b, i, f, t); this.nextRight = nextRight; - this.transformer = transformer; - this.basis = basis; this.reducer = reducer; - } - public final Long getRawResult() { return result; } - public final void compute() { - final ObjectByObjectToLong transformer; - final LongByLongToLong reducer; - if ((transformer = this.transformer) != null && - (reducer = this.reducer) != null) { - long r = this.basis; - for (int i = baseIndex, f, h; batch > 0 && - (h = ((f = baseLimit) + i) >>> 1) > i;) { - addToPendingCount(1); - (rights = new MapReduceMappingsToLongTask - (this, batch >>>= 1, baseLimit = h, f, tab, - rights, transformer, r, reducer)).fork(); - } - for (Node p; (p = advance()) != null; ) - r = reducer.apply(r, transformer.apply(p.key, p.val)); - result = r; - CountedCompleter c; - for (c = firstComplete(); c != null; c = c.nextComplete()) { - @SuppressWarnings("unchecked") MapReduceMappingsToLongTask - t = (MapReduceMappingsToLongTask)c, - s = t.rights; - while (s != null) { - t.result = reducer.apply(t.result, s.result); - s = t.rights = s.nextRight; - } - } - } - } - } - - @SuppressWarnings("serial") - static final class MapReduceKeysToIntTask - extends BulkTask { - final ObjectToInt transformer; - final IntByIntToInt reducer; - final int basis; - int result; - MapReduceKeysToIntTask rights, nextRight; - MapReduceKeysToIntTask - (BulkTask p, int b, int i, int f, Node[] t, - MapReduceKeysToIntTask nextRight, - ObjectToInt transformer, - int basis, - IntByIntToInt reducer) { - super(p, b, i, f, t); this.nextRight = nextRight; - this.transformer = transformer; - this.basis = basis; this.reducer = reducer; - } - public final Integer getRawResult() { return result; } - public final void compute() { - final ObjectToInt transformer; - final IntByIntToInt reducer; - if ((transformer = this.transformer) != null && - (reducer = this.reducer) != null) { - int r = this.basis; - for (int i = baseIndex, f, h; batch > 0 && - (h = ((f = baseLimit) + i) >>> 1) > i;) { - addToPendingCount(1); - (rights = new MapReduceKeysToIntTask - (this, batch >>>= 1, baseLimit = h, f, tab, - rights, transformer, r, reducer)).fork(); - } - for (Node p; (p = advance()) != null; ) - r = reducer.apply(r, transformer.apply(p.key)); - result = r; - CountedCompleter c; - for (c = firstComplete(); c != null; c = c.nextComplete()) { - @SuppressWarnings("unchecked") MapReduceKeysToIntTask - t = (MapReduceKeysToIntTask)c, - s = t.rights; - while (s != null) { - t.result = reducer.apply(t.result, s.result); - s = t.rights = s.nextRight; - } - } - } - } - } - - @SuppressWarnings("serial") - static final class MapReduceValuesToIntTask - extends BulkTask { - final ObjectToInt transformer; - final IntByIntToInt reducer; - final int basis; - int result; - MapReduceValuesToIntTask rights, nextRight; - MapReduceValuesToIntTask - (BulkTask p, int b, int i, int f, Node[] t, - MapReduceValuesToIntTask nextRight, - ObjectToInt transformer, - int basis, - IntByIntToInt reducer) { - super(p, b, i, f, t); this.nextRight = nextRight; - this.transformer = transformer; - this.basis = basis; this.reducer = reducer; - } - public final Integer getRawResult() { return result; } - public final void compute() { - final ObjectToInt transformer; - final IntByIntToInt reducer; - if ((transformer = this.transformer) != null && - (reducer = this.reducer) != null) { - int r = this.basis; - for (int i = baseIndex, f, h; batch > 0 && - (h = ((f = baseLimit) + i) >>> 1) > i;) { - addToPendingCount(1); - (rights = new MapReduceValuesToIntTask - (this, batch >>>= 1, baseLimit = h, f, tab, - rights, transformer, r, reducer)).fork(); - } - for (Node p; (p = advance()) != null; ) - r = reducer.apply(r, transformer.apply(p.val)); - result = r; - CountedCompleter c; - for (c = firstComplete(); c != null; c = c.nextComplete()) { - @SuppressWarnings("unchecked") MapReduceValuesToIntTask - t = (MapReduceValuesToIntTask)c, - s = t.rights; - while (s != null) { - t.result = reducer.apply(t.result, s.result); - s = t.rights = s.nextRight; - } - } - } - } - } - - @SuppressWarnings("serial") - static final class MapReduceEntriesToIntTask - extends BulkTask { - final ObjectToInt> transformer; - final IntByIntToInt reducer; - final int basis; - int result; - MapReduceEntriesToIntTask rights, nextRight; - MapReduceEntriesToIntTask - (BulkTask p, int b, int i, int f, Node[] t, - MapReduceEntriesToIntTask nextRight, - ObjectToInt> transformer, - int basis, - IntByIntToInt reducer) { - super(p, b, i, f, t); this.nextRight = nextRight; - this.transformer = transformer; - this.basis = basis; this.reducer = reducer; - } - public final Integer getRawResult() { return result; } - public final void compute() { - final ObjectToInt> transformer; - final IntByIntToInt reducer; - if ((transformer = this.transformer) != null && - (reducer = this.reducer) != null) { - int r = this.basis; - for (int i = baseIndex, f, h; batch > 0 && - (h = ((f = baseLimit) + i) >>> 1) > i;) { - addToPendingCount(1); - (rights = new MapReduceEntriesToIntTask - (this, batch >>>= 1, baseLimit = h, f, tab, - rights, transformer, r, reducer)).fork(); - } - for (Node p; (p = advance()) != null; ) - r = reducer.apply(r, transformer.apply(p)); - result = r; - CountedCompleter c; - for (c = firstComplete(); c != null; c = c.nextComplete()) { - @SuppressWarnings("unchecked") MapReduceEntriesToIntTask - t = (MapReduceEntriesToIntTask)c, - s = t.rights; - while (s != null) { - t.result = reducer.apply(t.result, s.result); - s = t.rights = s.nextRight; - } - } - } - } - } - - @SuppressWarnings("serial") - static final class MapReduceMappingsToIntTask - extends BulkTask { - final ObjectByObjectToInt transformer; - final IntByIntToInt reducer; - final int basis; - int result; - MapReduceMappingsToIntTask rights, nextRight; - MapReduceMappingsToIntTask - (BulkTask p, int b, int i, int f, Node[] t, - MapReduceMappingsToIntTask nextRight, - ObjectByObjectToInt transformer, - int basis, - IntByIntToInt reducer) { - super(p, b, i, f, t); this.nextRight = nextRight; - this.transformer = transformer; - this.basis = basis; this.reducer = reducer; - } - public final Integer getRawResult() { return result; } - public final void compute() { - final ObjectByObjectToInt transformer; - final IntByIntToInt reducer; - if ((transformer = this.transformer) != null && - (reducer = this.reducer) != null) { - int r = this.basis; - for (int i = baseIndex, f, h; batch > 0 && - (h = ((f = baseLimit) + i) >>> 1) > i;) { - addToPendingCount(1); - (rights = new MapReduceMappingsToIntTask - (this, batch >>>= 1, baseLimit = h, f, tab, - rights, transformer, r, reducer)).fork(); - } - for (Node p; (p = advance()) != null; ) - r = reducer.apply(r, transformer.apply(p.key, p.val)); - result = r; - CountedCompleter c; - for (c = firstComplete(); c != null; c = c.nextComplete()) { - @SuppressWarnings("unchecked") MapReduceMappingsToIntTask - t = (MapReduceMappingsToIntTask)c, - s = t.rights; - while (s != null) { - t.result = reducer.apply(t.result, s.result); - s = t.rights = s.nextRight; - } - } - } - } - } - - /* ---------------- Counters -------------- */ - - // Adapted from LongAdder and Striped64. - // See their internal docs for explanation. - - // A padded cell for distributing counts - static final class CounterCell { - volatile long p0, p1, p2, p3, p4, p5, p6; - volatile long value; - volatile long q0, q1, q2, q3, q4, q5, q6; - CounterCell(long x) { value = x; } - } - - /** - * Holder for the thread-local hash code determining which - * CounterCell to use. The code is initialized via the - * counterHashCodeGenerator, but may be moved upon collisions. - */ - static final class CounterHashCode { - int code; - } - - /** - * Generates initial value for per-thread CounterHashCodes. - */ - static final AtomicInteger counterHashCodeGenerator = new AtomicInteger(); - - /** - * Increment for counterHashCodeGenerator. See class ThreadLocal - * for explanation. - */ - static final int SEED_INCREMENT = 0x61c88647; - - final long sumCount() { - CounterCell[] as = counterCells; CounterCell a; - long sum = baseCount; - if (as != null) { - for (int i = 0; i < as.length; ++i) { - if ((a = as[i]) != null) - sum += a.value; - } - } - return sum; - } - - // See LongAdder version for explanation - private final void fullAddCount(InternalThreadLocalMap threadLocals, - long x, IntegerHolder hc, - boolean wasUncontended) { - int h; - if (hc == null) { - hc = new IntegerHolder(); - int s = counterHashCodeGenerator.addAndGet(SEED_INCREMENT); - h = hc.value = (s == 0) ? 1 : s; // Avoid zero - threadLocals.setCounterHashCode(hc); - } - else - h = hc.value; - boolean collide = false; // True if last slot nonempty - for (;;) { - CounterCell[] as; CounterCell a; int n; long v; - if ((as = counterCells) != null && (n = as.length) > 0) { - if ((a = as[(n - 1) & h]) == null) { - if (cellsBusy == 0) { // Try to attach new Cell - CounterCell r = new CounterCell(x); // Optimistic create - if (cellsBusy == 0 && - U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) { - boolean created = false; - try { // Recheck under lock - CounterCell[] rs; int m, j; - if ((rs = counterCells) != null && - (m = rs.length) > 0 && - rs[j = (m - 1) & h] == null) { - rs[j] = r; - created = true; - } - } finally { - cellsBusy = 0; - } - if (created) - break; - continue; // Slot is now non-empty - } - } - collide = false; - } - else if (!wasUncontended) // CAS already known to fail - wasUncontended = true; // Continue after rehash - else if (U.compareAndSwapLong(a, CELLVALUE, v = a.value, v + x)) - break; - else if (counterCells != as || n >= NCPU) - collide = false; // At max size or stale - else if (!collide) - collide = true; - else if (cellsBusy == 0 && - U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) { - try { - if (counterCells == as) {// Expand table unless stale - CounterCell[] rs = new CounterCell[n << 1]; - for (int i = 0; i < n; ++i) - rs[i] = as[i]; - counterCells = rs; - } - } finally { - cellsBusy = 0; - } - collide = false; - continue; // Retry with expanded table - } - h ^= h << 13; // Rehash - h ^= h >>> 17; - h ^= h << 5; - } - else if (cellsBusy == 0 && counterCells == as && - U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) { - boolean init = false; - try { // Initialize table - if (counterCells == as) { - CounterCell[] rs = new CounterCell[2]; - rs[h & 1] = new CounterCell(x); - counterCells = rs; - init = true; - } - } finally { - cellsBusy = 0; - } - if (init) - break; - } - else if (U.compareAndSwapLong(this, BASECOUNT, v = baseCount, v + x)) - break; // Fall back on using base - } - hc.value = h; // Record index for next time - } - - // Unsafe mechanics - private static final sun.misc.Unsafe U; - private static final long SIZECTL; - private static final long TRANSFERINDEX; - private static final long TRANSFERORIGIN; - private static final long BASECOUNT; - private static final long CELLSBUSY; - private static final long CELLVALUE; - private static final long ABASE; - private static final int ASHIFT; - - static { - try { - U = getUnsafe(); - Class k = ConcurrentHashMapV8.class; - SIZECTL = U.objectFieldOffset - (k.getDeclaredField("sizeCtl")); - TRANSFERINDEX = U.objectFieldOffset - (k.getDeclaredField("transferIndex")); - TRANSFERORIGIN = U.objectFieldOffset - (k.getDeclaredField("transferOrigin")); - BASECOUNT = U.objectFieldOffset - (k.getDeclaredField("baseCount")); - CELLSBUSY = U.objectFieldOffset - (k.getDeclaredField("cellsBusy")); - Class ck = CounterCell.class; - CELLVALUE = U.objectFieldOffset - (ck.getDeclaredField("value")); - Class ak = Node[].class; - ABASE = U.arrayBaseOffset(ak); - int scale = U.arrayIndexScale(ak); - if ((scale & (scale - 1)) != 0) - throw new Error("data type scale not a power of two"); - ASHIFT = 31 - Integer.numberOfLeadingZeros(scale); - } catch (Exception e) { - throw new Error(e); - } - } - - /** - * Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package. - * Replace with a simple call to Unsafe.getUnsafe when integrating - * into a jdk. - * - * @return a sun.misc.Unsafe - */ - private static sun.misc.Unsafe getUnsafe() { - try { - return sun.misc.Unsafe.getUnsafe(); - } catch (SecurityException tryReflectionInstead) {} - try { - return java.security.AccessController.doPrivileged - (new java.security.PrivilegedExceptionAction() { - public sun.misc.Unsafe run() throws Exception { - Class k = sun.misc.Unsafe.class; - for (java.lang.reflect.Field f : k.getDeclaredFields()) { - f.setAccessible(true); - Object x = f.get(null); - if (k.isInstance(x)) - return k.cast(x); - } - throw new NoSuchFieldError("the Unsafe"); - }}); - } catch (java.security.PrivilegedActionException e) { - throw new RuntimeException("Could not initialize intrinsics", - e.getCause()); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/chmv8/CountedCompleter.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/chmv8/CountedCompleter.java deleted file mode 100755 index 6725df57c1..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/chmv8/CountedCompleter.java +++ /dev/null @@ -1,769 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/* - * Written by Doug Lea with assistance from members of JCP JSR-166 - * Expert Group and released to the public domain, as explained at - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -package com.ai.cloud.io.netty.util.internal.chmv8; - -import java.util.concurrent.RecursiveAction; - -/** - * A {@link ForkJoinTask} with a completion action performed when - * triggered and there are no remaining pending actions. - * CountedCompleters are in general more robust in the - * presence of subtask stalls and blockage than are other forms of - * ForkJoinTasks, but are less intuitive to program. Uses of - * CountedCompleter are similar to those of other completion based - * components (such as {@link java.nio.channels.CompletionHandler}) - * except that multiple pending completions may be necessary - * to trigger the completion action {@link #onCompletion(CountedCompleter)}, - * not just one. - * Unless initialized otherwise, the {@linkplain #getPendingCount pending - * count} starts at zero, but may be (atomically) changed using - * methods {@link #setPendingCount}, {@link #addToPendingCount}, and - * {@link #compareAndSetPendingCount}. Upon invocation of {@link - * #tryComplete}, if the pending action count is nonzero, it is - * decremented; otherwise, the completion action is performed, and if - * this completer itself has a completer, the process is continued - * with its completer. As is the case with related synchronization - * components such as {@link java.util.concurrent.Phaser Phaser} and - * {@link java.util.concurrent.Semaphore Semaphore}, these methods - * affect only internal counts; they do not establish any further - * internal bookkeeping. In particular, the identities of pending - * tasks are not maintained. As illustrated below, you can create - * subclasses that do record some or all pending tasks or their - * results when needed. As illustrated below, utility methods - * supporting customization of completion traversals are also - * provided. However, because CountedCompleters provide only basic - * synchronization mechanisms, it may be useful to create further - * abstract subclasses that maintain linkages, fields, and additional - * support methods appropriate for a set of related usages. - * - *

A concrete CountedCompleter class must define method {@link - * #compute}, that should in most cases (as illustrated below), invoke - * {@code tryComplete()} once before returning. The class may also - * optionally override method {@link #onCompletion(CountedCompleter)} - * to perform an action upon normal completion, and method - * {@link #onExceptionalCompletion(Throwable, CountedCompleter)} to - * perform an action upon any exception. - * - *

CountedCompleters most often do not bear results, in which case - * they are normally declared as {@code CountedCompleter}, and - * will always return {@code null} as a result value. In other cases, - * you should override method {@link #getRawResult} to provide a - * result from {@code join(), invoke()}, and related methods. In - * general, this method should return the value of a field (or a - * function of one or more fields) of the CountedCompleter object that - * holds the result upon completion. Method {@link #setRawResult} by - * default plays no role in CountedCompleters. It is possible, but - * rarely applicable, to override this method to maintain other - * objects or fields holding result data. - * - *

A CountedCompleter that does not itself have a completer (i.e., - * one for which {@link #getCompleter} returns {@code null}) can be - * used as a regular ForkJoinTask with this added functionality. - * However, any completer that in turn has another completer serves - * only as an internal helper for other computations, so its own task - * status (as reported in methods such as {@link ForkJoinTask#isDone}) - * is arbitrary; this status changes only upon explicit invocations of - * {@link #complete}, {@link ForkJoinTask#cancel}, - * {@link ForkJoinTask#completeExceptionally(Throwable)} or upon - * exceptional completion of method {@code compute}. Upon any - * exceptional completion, the exception may be relayed to a task's - * completer (and its completer, and so on), if one exists and it has - * not otherwise already completed. Similarly, cancelling an internal - * CountedCompleter has only a local effect on that completer, so is - * not often useful. - * - *

Sample Usages. - * - *

Parallel recursive decomposition. CountedCompleters may - * be arranged in trees similar to those often used with {@link - * RecursiveAction}s, although the constructions involved in setting - * them up typically vary. Here, the completer of each task is its - * parent in the computation tree. Even though they entail a bit more - * bookkeeping, CountedCompleters may be better choices when applying - * a possibly time-consuming operation (that cannot be further - * subdivided) to each element of an array or collection; especially - * when the operation takes a significantly different amount of time - * to complete for some elements than others, either because of - * intrinsic variation (for example I/O) or auxiliary effects such as - * garbage collection. Because CountedCompleters provide their own - * continuations, other threads need not block waiting to perform - * them. - * - *

For example, here is an initial version of a class that uses - * divide-by-two recursive decomposition to divide work into single - * pieces (leaf tasks). Even when work is split into individual calls, - * tree-based techniques are usually preferable to directly forking - * leaf tasks, because they reduce inter-thread communication and - * improve load balancing. In the recursive case, the second of each - * pair of subtasks to finish triggers completion of its parent - * (because no result combination is performed, the default no-op - * implementation of method {@code onCompletion} is not overridden). - * A static utility method sets up the base task and invokes it - * (here, implicitly using the {@link ForkJoinPool#commonPool()}). - * - *

 {@code
- * class MyOperation { void apply(E e) { ... }  }
- *
- * class ForEach extends CountedCompleter {
- *
- *   public static  void forEach(E[] array, MyOperation op) {
- *     new ForEach(null, array, op, 0, array.length).invoke();
- *   }
- *
- *   final E[] array; final MyOperation op; final int lo, hi;
- *   ForEach(CountedCompleter p, E[] array, MyOperation op, int lo, int hi) {
- *     super(p);
- *     this.array = array; this.op = op; this.lo = lo; this.hi = hi;
- *   }
- *
- *   public void compute() { // version 1
- *     if (hi - lo >= 2) {
- *       int mid = (lo + hi) >>> 1;
- *       setPendingCount(2); // must set pending count before fork
- *       new ForEach(this, array, op, mid, hi).fork(); // right child
- *       new ForEach(this, array, op, lo, mid).fork(); // left child
- *     }
- *     else if (hi > lo)
- *       op.apply(array[lo]);
- *     tryComplete();
- *   }
- * }}
- * - * This design can be improved by noticing that in the recursive case, - * the task has nothing to do after forking its right task, so can - * directly invoke its left task before returning. (This is an analog - * of tail recursion removal.) Also, because the task returns upon - * executing its left task (rather than falling through to invoke - * {@code tryComplete}) the pending count is set to one: - * - *
 {@code
- * class ForEach ...
- *   public void compute() { // version 2
- *     if (hi - lo >= 2) {
- *       int mid = (lo + hi) >>> 1;
- *       setPendingCount(1); // only one pending
- *       new ForEach(this, array, op, mid, hi).fork(); // right child
- *       new ForEach(this, array, op, lo, mid).compute(); // direct invoke
- *     }
- *     else {
- *       if (hi > lo)
- *         op.apply(array[lo]);
- *       tryComplete();
- *     }
- *   }
- * }
- * - * As a further improvement, notice that the left task need not even exist. - * Instead of creating a new one, we can iterate using the original task, - * and add a pending count for each fork. Additionally, because no task - * in this tree implements an {@link #onCompletion(CountedCompleter)} method, - * {@code tryComplete()} can be replaced with {@link #propagateCompletion}. - * - *
 {@code
- * class ForEach ...
- *   public void compute() { // version 3
- *     int l = lo,  h = hi;
- *     while (h - l >= 2) {
- *       int mid = (l + h) >>> 1;
- *       addToPendingCount(1);
- *       new ForEach(this, array, op, mid, h).fork(); // right child
- *       h = mid;
- *     }
- *     if (h > l)
- *       op.apply(array[l]);
- *     propagateCompletion();
- *   }
- * }
- * - * Additional improvements of such classes might entail precomputing - * pending counts so that they can be established in constructors, - * specializing classes for leaf steps, subdividing by say, four, - * instead of two per iteration, and using an adaptive threshold - * instead of always subdividing down to single elements. - * - *

Searching. A tree of CountedCompleters can search for a - * value or property in different parts of a data structure, and - * report a result in an {@link - * java.util.concurrent.atomic.AtomicReference AtomicReference} as - * soon as one is found. The others can poll the result to avoid - * unnecessary work. (You could additionally {@linkplain #cancel - * cancel} other tasks, but it is usually simpler and more efficient - * to just let them notice that the result is set and if so skip - * further processing.) Illustrating again with an array using full - * partitioning (again, in practice, leaf tasks will almost always - * process more than one element): - * - *

 {@code
- * class Searcher extends CountedCompleter {
- *   final E[] array; final AtomicReference result; final int lo, hi;
- *   Searcher(CountedCompleter p, E[] array, AtomicReference result, int lo, int hi) {
- *     super(p);
- *     this.array = array; this.result = result; this.lo = lo; this.hi = hi;
- *   }
- *   public E getRawResult() { return result.get(); }
- *   public void compute() { // similar to ForEach version 3
- *     int l = lo,  h = hi;
- *     while (result.get() == null && h >= l) {
- *       if (h - l >= 2) {
- *         int mid = (l + h) >>> 1;
- *         addToPendingCount(1);
- *         new Searcher(this, array, result, mid, h).fork();
- *         h = mid;
- *       }
- *       else {
- *         E x = array[l];
- *         if (matches(x) && result.compareAndSet(null, x))
- *           quietlyCompleteRoot(); // root task is now joinable
- *         break;
- *       }
- *     }
- *     tryComplete(); // normally complete whether or not found
- *   }
- *   boolean matches(E e) { ... } // return true if found
- *
- *   public static  E search(E[] array) {
- *       return new Searcher(null, array, new AtomicReference(), 0, array.length).invoke();
- *   }
- * }}
- * - * In this example, as well as others in which tasks have no other - * effects except to compareAndSet a common result, the trailing - * unconditional invocation of {@code tryComplete} could be made - * conditional ({@code if (result.get() == null) tryComplete();}) - * because no further bookkeeping is required to manage completions - * once the root task completes. - * - *

Recording subtasks. CountedCompleter tasks that combine - * results of multiple subtasks usually need to access these results - * in method {@link #onCompletion(CountedCompleter)}. As illustrated in the following - * class (that performs a simplified form of map-reduce where mappings - * and reductions are all of type {@code E}), one way to do this in - * divide and conquer designs is to have each subtask record its - * sibling, so that it can be accessed in method {@code onCompletion}. - * This technique applies to reductions in which the order of - * combining left and right results does not matter; ordered - * reductions require explicit left/right designations. Variants of - * other streamlinings seen in the above examples may also apply. - * - *

 {@code
- * class MyMapper { E apply(E v) {  ...  } }
- * class MyReducer { E apply(E x, E y) {  ...  } }
- * class MapReducer extends CountedCompleter {
- *   final E[] array; final MyMapper mapper;
- *   final MyReducer reducer; final int lo, hi;
- *   MapReducer sibling;
- *   E result;
- *   MapReducer(CountedCompleter p, E[] array, MyMapper mapper,
- *              MyReducer reducer, int lo, int hi) {
- *     super(p);
- *     this.array = array; this.mapper = mapper;
- *     this.reducer = reducer; this.lo = lo; this.hi = hi;
- *   }
- *   public void compute() {
- *     if (hi - lo >= 2) {
- *       int mid = (lo + hi) >>> 1;
- *       MapReducer left = new MapReducer(this, array, mapper, reducer, lo, mid);
- *       MapReducer right = new MapReducer(this, array, mapper, reducer, mid, hi);
- *       left.sibling = right;
- *       right.sibling = left;
- *       setPendingCount(1); // only right is pending
- *       right.fork();
- *       left.compute();     // directly execute left
- *     }
- *     else {
- *       if (hi > lo)
- *           result = mapper.apply(array[lo]);
- *       tryComplete();
- *     }
- *   }
- *   public void onCompletion(CountedCompleter caller) {
- *     if (caller != this) {
- *       MapReducer child = (MapReducer)caller;
- *       MapReducer sib = child.sibling;
- *       if (sib == null || sib.result == null)
- *         result = child.result;
- *       else
- *         result = reducer.apply(child.result, sib.result);
- *     }
- *   }
- *   public E getRawResult() { return result; }
- *
- *   public static  E mapReduce(E[] array, MyMapper mapper, MyReducer reducer) {
- *     return new MapReducer(null, array, mapper, reducer,
- *                              0, array.length).invoke();
- *   }
- * }}
- * - * Here, method {@code onCompletion} takes a form common to many - * completion designs that combine results. This callback-style method - * is triggered once per task, in either of the two different contexts - * in which the pending count is, or becomes, zero: (1) by a task - * itself, if its pending count is zero upon invocation of {@code - * tryComplete}, or (2) by any of its subtasks when they complete and - * decrement the pending count to zero. The {@code caller} argument - * distinguishes cases. Most often, when the caller is {@code this}, - * no action is necessary. Otherwise the caller argument can be used - * (usually via a cast) to supply a value (and/or links to other - * values) to be combined. Assuming proper use of pending counts, the - * actions inside {@code onCompletion} occur (once) upon completion of - * a task and its subtasks. No additional synchronization is required - * within this method to ensure thread safety of accesses to fields of - * this task or other completed tasks. - * - *

Completion Traversals. If using {@code onCompletion} to - * process completions is inapplicable or inconvenient, you can use - * methods {@link #firstComplete} and {@link #nextComplete} to create - * custom traversals. For example, to define a MapReducer that only - * splits out right-hand tasks in the form of the third ForEach - * example, the completions must cooperatively reduce along - * unexhausted subtask links, which can be done as follows: - * - *

 {@code
- * class MapReducer extends CountedCompleter { // version 2
- *   final E[] array; final MyMapper mapper;
- *   final MyReducer reducer; final int lo, hi;
- *   MapReducer forks, next; // record subtask forks in list
- *   E result;
- *   MapReducer(CountedCompleter p, E[] array, MyMapper mapper,
- *              MyReducer reducer, int lo, int hi, MapReducer next) {
- *     super(p);
- *     this.array = array; this.mapper = mapper;
- *     this.reducer = reducer; this.lo = lo; this.hi = hi;
- *     this.next = next;
- *   }
- *   public void compute() {
- *     int l = lo,  h = hi;
- *     while (h - l >= 2) {
- *       int mid = (l + h) >>> 1;
- *       addToPendingCount(1);
- *       (forks = new MapReducer(this, array, mapper, reducer, mid, h, forks)).fork();
- *       h = mid;
- *     }
- *     if (h > l)
- *       result = mapper.apply(array[l]);
- *     // process completions by reducing along and advancing subtask links
- *     for (CountedCompleter c = firstComplete(); c != null; c = c.nextComplete()) {
- *       for (MapReducer t = (MapReducer)c, s = t.forks;  s != null; s = t.forks = s.next)
- *         t.result = reducer.apply(t.result, s.result);
- *     }
- *   }
- *   public E getRawResult() { return result; }
- *
- *   public static  E mapReduce(E[] array, MyMapper mapper, MyReducer reducer) {
- *     return new MapReducer(null, array, mapper, reducer,
- *                              0, array.length, null).invoke();
- *   }
- * }}
- * - *

Triggers. Some CountedCompleters are themselves never - * forked, but instead serve as bits of plumbing in other designs; - * including those in which the completion of one or more async tasks - * triggers another async task. For example: - * - *

 {@code
- * class HeaderBuilder extends CountedCompleter<...> { ... }
- * class BodyBuilder extends CountedCompleter<...> { ... }
- * class PacketSender extends CountedCompleter<...> {
- *   PacketSender(...) { super(null, 1); ... } // trigger on second completion
- *   public void compute() { } // never called
- *   public void onCompletion(CountedCompleter caller) { sendPacket(); }
- * }
- * // sample use:
- * PacketSender p = new PacketSender();
- * new HeaderBuilder(p, ...).fork();
- * new BodyBuilder(p, ...).fork();
- * }
- * - * @since 1.8 - * @author Doug Lea - */ -@SuppressWarnings("all") -public abstract class CountedCompleter extends ForkJoinTask { - private static final long serialVersionUID = 5232453752276485070L; - - /** This task's completer, or null if none */ - final CountedCompleter completer; - /** The number of pending tasks until completion */ - volatile int pending; - - /** - * Creates a new CountedCompleter with the given completer - * and initial pending count. - * - * @param completer this task's completer, or {@code null} if none - * @param initialPendingCount the initial pending count - */ - protected CountedCompleter(CountedCompleter completer, - int initialPendingCount) { - this.completer = completer; - this.pending = initialPendingCount; - } - - /** - * Creates a new CountedCompleter with the given completer - * and an initial pending count of zero. - * - * @param completer this task's completer, or {@code null} if none - */ - protected CountedCompleter(CountedCompleter completer) { - this.completer = completer; - } - - /** - * Creates a new CountedCompleter with no completer - * and an initial pending count of zero. - */ - protected CountedCompleter() { - this.completer = null; - } - - /** - * The main computation performed by this task. - */ - public abstract void compute(); - - /** - * Performs an action when method {@link #tryComplete} is invoked - * and the pending count is zero, or when the unconditional - * method {@link #complete} is invoked. By default, this method - * does nothing. You can distinguish cases by checking the - * identity of the given caller argument. If not equal to {@code - * this}, then it is typically a subtask that may contain results - * (and/or links to other results) to combine. - * - * @param caller the task invoking this method (which may - * be this task itself) - */ - public void onCompletion(CountedCompleter caller) { - } - - /** - * Performs an action when method {@link - * #completeExceptionally(Throwable)} is invoked or method {@link - * #compute} throws an exception, and this task has not already - * otherwise completed normally. On entry to this method, this task - * {@link ForkJoinTask#isCompletedAbnormally}. The return value - * of this method controls further propagation: If {@code true} - * and this task has a completer that has not completed, then that - * completer is also completed exceptionally, with the same - * exception as this completer. The default implementation of - * this method does nothing except return {@code true}. - * - * @param ex the exception - * @param caller the task invoking this method (which may - * be this task itself) - * @return {@code true} if this exception should be propagated to this - * task's completer, if one exists - */ - public boolean onExceptionalCompletion(Throwable ex, CountedCompleter caller) { - return true; - } - - /** - * Returns the completer established in this task's constructor, - * or {@code null} if none. - * - * @return the completer - */ - public final CountedCompleter getCompleter() { - return completer; - } - - /** - * Returns the current pending count. - * - * @return the current pending count - */ - public final int getPendingCount() { - return pending; - } - - /** - * Sets the pending count to the given value. - * - * @param count the count - */ - public final void setPendingCount(int count) { - pending = count; - } - - /** - * Adds (atomically) the given value to the pending count. - * - * @param delta the value to add - */ - public final void addToPendingCount(int delta) { - int c; - do {} while (!U.compareAndSwapInt(this, PENDING, c = pending, c+delta)); - } - - /** - * Sets (atomically) the pending count to the given count only if - * it currently holds the given expected value. - * - * @param expected the expected value - * @param count the new value - * @return {@code true} if successful - */ - public final boolean compareAndSetPendingCount(int expected, int count) { - return U.compareAndSwapInt(this, PENDING, expected, count); - } - - /** - * If the pending count is nonzero, (atomically) decrements it. - * - * @return the initial (undecremented) pending count holding on entry - * to this method - */ - public final int decrementPendingCountUnlessZero() { - int c; - do {} while ((c = pending) != 0 && - !U.compareAndSwapInt(this, PENDING, c, c - 1)); - return c; - } - - /** - * Returns the root of the current computation; i.e., this - * task if it has no completer, else its completer's root. - * - * @return the root of the current computation - */ - public final CountedCompleter getRoot() { - CountedCompleter a = this, p; - while ((p = a.completer) != null) - a = p; - return a; - } - - /** - * If the pending count is nonzero, decrements the count; - * otherwise invokes {@link #onCompletion(CountedCompleter)} - * and then similarly tries to complete this task's completer, - * if one exists, else marks this task as complete. - */ - public final void tryComplete() { - CountedCompleter a = this, s = a; - for (int c;;) { - if ((c = a.pending) == 0) { - a.onCompletion(s); - if ((a = (s = a).completer) == null) { - s.quietlyComplete(); - return; - } - } - else if (U.compareAndSwapInt(a, PENDING, c, c - 1)) - return; - } - } - - /** - * Equivalent to {@link #tryComplete} but does not invoke {@link - * #onCompletion(CountedCompleter)} along the completion path: - * If the pending count is nonzero, decrements the count; - * otherwise, similarly tries to complete this task's completer, if - * one exists, else marks this task as complete. This method may be - * useful in cases where {@code onCompletion} should not, or need - * not, be invoked for each completer in a computation. - */ - public final void propagateCompletion() { - CountedCompleter a = this, s = a; - for (int c;;) { - if ((c = a.pending) == 0) { - if ((a = (s = a).completer) == null) { - s.quietlyComplete(); - return; - } - } - else if (U.compareAndSwapInt(a, PENDING, c, c - 1)) - return; - } - } - - /** - * Regardless of pending count, invokes - * {@link #onCompletion(CountedCompleter)}, marks this task as - * complete and further triggers {@link #tryComplete} on this - * task's completer, if one exists. The given rawResult is - * used as an argument to {@link #setRawResult} before invoking - * {@link #onCompletion(CountedCompleter)} or marking this task - * as complete; its value is meaningful only for classes - * overriding {@code setRawResult}. This method does not modify - * the pending count. - * - *

This method may be useful when forcing completion as soon as - * any one (versus all) of several subtask results are obtained. - * However, in the common (and recommended) case in which {@code - * setRawResult} is not overridden, this effect can be obtained - * more simply using {@code quietlyCompleteRoot();}. - * - * @param rawResult the raw result - */ - public void complete(T rawResult) { - CountedCompleter p; - setRawResult(rawResult); - onCompletion(this); - quietlyComplete(); - if ((p = completer) != null) - p.tryComplete(); - } - - - /** - * If this task's pending count is zero, returns this task; - * otherwise decrements its pending count and returns {@code - * null}. This method is designed to be used with {@link - * #nextComplete} in completion traversal loops. - * - * @return this task, if pending count was zero, else {@code null} - */ - public final CountedCompleter firstComplete() { - for (int c;;) { - if ((c = pending) == 0) - return this; - else if (U.compareAndSwapInt(this, PENDING, c, c - 1)) - return null; - } - } - - /** - * If this task does not have a completer, invokes {@link - * ForkJoinTask#quietlyComplete} and returns {@code null}. Or, if - * the completer's pending count is non-zero, decrements that - * pending count and returns {@code null}. Otherwise, returns the - * completer. This method can be used as part of a completion - * traversal loop for homogeneous task hierarchies: - * - *

 {@code
-     * for (CountedCompleter c = firstComplete();
-     *      c != null;
-     *      c = c.nextComplete()) {
-     *   // ... process c ...
-     * }}
- * - * @return the completer, or {@code null} if none - */ - public final CountedCompleter nextComplete() { - CountedCompleter p; - if ((p = completer) != null) - return p.firstComplete(); - else { - quietlyComplete(); - return null; - } - } - - /** - * Equivalent to {@code getRoot().quietlyComplete()}. - */ - public final void quietlyCompleteRoot() { - for (CountedCompleter a = this, p;;) { - if ((p = a.completer) == null) { - a.quietlyComplete(); - return; - } - a = p; - } - } - - /** - * Supports ForkJoinTask exception propagation. - */ - void internalPropagateException(Throwable ex) { - CountedCompleter a = this, s = a; - while (a.onExceptionalCompletion(ex, s) && - (a = (s = a).completer) != null && a.status >= 0 && - a.recordExceptionalCompletion(ex) == EXCEPTIONAL) - ; - } - - /** - * Implements execution conventions for CountedCompleters. - */ - protected final boolean exec() { - compute(); - return false; - } - - /** - * Returns the result of the computation. By default - * returns {@code null}, which is appropriate for {@code Void} - * actions, but in other cases should be overridden, almost - * always to return a field or function of a field that - * holds the result upon completion. - * - * @return the result of the computation - */ - public T getRawResult() { return null; } - - /** - * A method that result-bearing CountedCompleters may optionally - * use to help maintain result data. By default, does nothing. - * Overrides are not recommended. However, if this method is - * overridden to update existing objects or fields, then it must - * in general be defined to be thread-safe. - */ - protected void setRawResult(T t) { } - - // Unsafe mechanics - private static final sun.misc.Unsafe U; - private static final long PENDING; - static { - try { - U = getUnsafe(); - PENDING = U.objectFieldOffset - (CountedCompleter.class.getDeclaredField("pending")); - } catch (Exception e) { - throw new Error(e); - } - } - - /** - * Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package. - * Replace with a simple call to Unsafe.getUnsafe when integrating - * into a jdk. - * - * @return a sun.misc.Unsafe - */ - private static sun.misc.Unsafe getUnsafe() { - try { - return sun.misc.Unsafe.getUnsafe(); - } catch (SecurityException tryReflectionInstead) {} - try { - return java.security.AccessController.doPrivileged - (new java.security.PrivilegedExceptionAction() { - public sun.misc.Unsafe run() throws Exception { - Class k = sun.misc.Unsafe.class; - for (java.lang.reflect.Field f : k.getDeclaredFields()) { - f.setAccessible(true); - Object x = f.get(null); - if (k.isInstance(x)) - return k.cast(x); - } - throw new NoSuchFieldError("the Unsafe"); - }}); - } catch (java.security.PrivilegedActionException e) { - throw new RuntimeException("Could not initialize intrinsics", - e.getCause()); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/chmv8/ForkJoinPool.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/chmv8/ForkJoinPool.java deleted file mode 100755 index e37668142b..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/chmv8/ForkJoinPool.java +++ /dev/null @@ -1,3359 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/* - * Written by Doug Lea with assistance from members of JCP JSR-166 - * Expert Group and released to the public domain, as explained at - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -package com.ai.cloud.io.netty.util.internal.chmv8; - -import java.lang.Thread.UncaughtExceptionHandler; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.AbstractExecutorService; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; -import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.RunnableFuture; -import java.util.concurrent.TimeUnit; - -import com.ai.cloud.io.netty.util.internal.ThreadLocalRandom; - -/** - * An {@link ExecutorService} for running {@link ForkJoinTask}s. - * A {@code ForkJoinPool} provides the entry point for submissions - * from non-{@code ForkJoinTask} clients, as well as management and - * monitoring operations. - * - *

A {@code ForkJoinPool} differs from other kinds of {@link - * ExecutorService} mainly by virtue of employing - * work-stealing: all threads in the pool attempt to find and - * execute tasks submitted to the pool and/or created by other active - * tasks (eventually blocking waiting for work if none exist). This - * enables efficient processing when most tasks spawn other subtasks - * (as do most {@code ForkJoinTask}s), as well as when many small - * tasks are submitted to the pool from external clients. Especially - * when setting asyncMode to true in constructors, {@code - * ForkJoinPool}s may also be appropriate for use with event-style - * tasks that are never joined. - * - *

A static {@link #commonPool()} is available and appropriate for - * most applications. The common pool is used by any ForkJoinTask that - * is not explicitly submitted to a specified pool. Using the common - * pool normally reduces resource usage (its threads are slowly - * reclaimed during periods of non-use, and reinstated upon subsequent - * use). - * - *

For applications that require separate or custom pools, a {@code - * ForkJoinPool} may be constructed with a given target parallelism - * level; by default, equal to the number of available processors. The - * pool attempts to maintain enough active (or available) threads by - * dynamically adding, suspending, or resuming internal worker - * threads, even if some tasks are stalled waiting to join others. - * However, no such adjustments are guaranteed in the face of blocked - * I/O or other unmanaged synchronization. The nested {@link - * ManagedBlocker} interface enables extension of the kinds of - * synchronization accommodated. - * - *

In addition to execution and lifecycle control methods, this - * class provides status check methods (for example - * {@link #getStealCount}) that are intended to aid in developing, - * tuning, and monitoring fork/join applications. Also, method - * {@link #toString} returns indications of pool state in a - * convenient form for informal monitoring. - * - *

As is the case with other ExecutorServices, there are three - * main task execution methods summarized in the following table. - * These are designed to be used primarily by clients not already - * engaged in fork/join computations in the current pool. The main - * forms of these methods accept instances of {@code ForkJoinTask}, - * but overloaded forms also allow mixed execution of plain {@code - * Runnable}- or {@code Callable}- based activities as well. However, - * tasks that are already executing in a pool should normally instead - * use the within-computation forms listed in the table unless using - * async event-style tasks that are not usually joined, in which case - * there is little difference among choice of methods. - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
Summary of task execution methods
Call from non-fork/join clients Call from within fork/join computations
Arrange async execution {@link #execute(ForkJoinTask)} {@link ForkJoinTask#fork}
Await and obtain result {@link #invoke(ForkJoinTask)} {@link ForkJoinTask#invoke}
Arrange exec and obtain Future {@link #submit(ForkJoinTask)} {@link ForkJoinTask#fork} (ForkJoinTasks are Futures)
- * - *

The common pool is by default constructed with default - * parameters, but these may be controlled by setting three - * {@linkplain System#getProperty system properties}: - *

    - *
  • {@code java.util.concurrent.ForkJoinPool.common.parallelism} - * - the parallelism level, a non-negative integer - *
  • {@code java.util.concurrent.ForkJoinPool.common.threadFactory} - * - the class name of a {@link ForkJoinWorkerThreadFactory} - *
  • {@code java.util.concurrent.ForkJoinPool.common.exceptionHandler} - * - the class name of a {@link UncaughtExceptionHandler} - *
- * The system class loader is used to load these classes. - * Upon any error in establishing these settings, default parameters - * are used. It is possible to disable or limit the use of threads in - * the common pool by setting the parallelism property to zero, and/or - * using a factory that may return {@code null}. - * - *

Implementation notes: This implementation restricts the - * maximum number of running threads to 32767. Attempts to create - * pools with greater than the maximum number result in - * {@code IllegalArgumentException}. - * - *

This implementation rejects submitted tasks (that is, by throwing - * {@link RejectedExecutionException}) only when the pool is shut down - * or internal resources have been exhausted. - * - * @since 1.7 - * @author Doug Lea - */ -@SuppressWarnings("all") -public class ForkJoinPool extends AbstractExecutorService { - - /* - * Implementation Overview - * - * This class and its nested classes provide the main - * functionality and control for a set of worker threads: - * Submissions from non-FJ threads enter into submission queues. - * Workers take these tasks and typically split them into subtasks - * that may be stolen by other workers. Preference rules give - * first priority to processing tasks from their own queues (LIFO - * or FIFO, depending on mode), then to randomized FIFO steals of - * tasks in other queues. - * - * WorkQueues - * ========== - * - * Most operations occur within work-stealing queues (in nested - * class WorkQueue). These are special forms of Deques that - * support only three of the four possible end-operations -- push, - * pop, and poll (aka steal), under the further constraints that - * push and pop are called only from the owning thread (or, as - * extended here, under a lock), while poll may be called from - * other threads. (If you are unfamiliar with them, you probably - * want to read Herlihy and Shavit's book "The Art of - * Multiprocessor programming", chapter 16 describing these in - * more detail before proceeding.) The main work-stealing queue - * design is roughly similar to those in the papers "Dynamic - * Circular Work-Stealing Deque" by Chase and Lev, SPAA 2005 - * (http://research.sun.com/scalable/pubs/index.html) and - * "Idempotent work stealing" by Michael, Saraswat, and Vechev, - * PPoPP 2009 (http://portal.acm.org/citation.cfm?id=1504186). - * See also "Correct and Efficient Work-Stealing for Weak Memory - * Models" by Le, Pop, Cohen, and Nardelli, PPoPP 2013 - * (http://www.di.ens.fr/~zappa/readings/ppopp13.pdf) for an - * analysis of memory ordering (atomic, volatile etc) issues. The - * main differences ultimately stem from GC requirements that we - * null out taken slots as soon as we can, to maintain as small a - * footprint as possible even in programs generating huge numbers - * of tasks. To accomplish this, we shift the CAS arbitrating pop - * vs poll (steal) from being on the indices ("base" and "top") to - * the slots themselves. So, both a successful pop and poll - * mainly entail a CAS of a slot from non-null to null. Because - * we rely on CASes of references, we do not need tag bits on base - * or top. They are simple ints as used in any circular - * array-based queue (see for example ArrayDeque). Updates to the - * indices must still be ordered in a way that guarantees that top - * == base means the queue is empty, but otherwise may err on the - * side of possibly making the queue appear nonempty when a push, - * pop, or poll have not fully committed. Note that this means - * that the poll operation, considered individually, is not - * wait-free. One thief cannot successfully continue until another - * in-progress one (or, if previously empty, a push) completes. - * However, in the aggregate, we ensure at least probabilistic - * non-blockingness. If an attempted steal fails, a thief always - * chooses a different random victim target to try next. So, in - * order for one thief to progress, it suffices for any - * in-progress poll or new push on any empty queue to - * complete. (This is why we normally use method pollAt and its - * variants that try once at the apparent base index, else - * consider alternative actions, rather than method poll.) - * - * This approach also enables support of a user mode in which local - * task processing is in FIFO, not LIFO order, simply by using - * poll rather than pop. This can be useful in message-passing - * frameworks in which tasks are never joined. However neither - * mode considers affinities, loads, cache localities, etc, so - * rarely provide the best possible performance on a given - * machine, but portably provide good throughput by averaging over - * these factors. (Further, even if we did try to use such - * information, we do not usually have a basis for exploiting it. - * For example, some sets of tasks profit from cache affinities, - * but others are harmed by cache pollution effects.) - * - * WorkQueues are also used in a similar way for tasks submitted - * to the pool. We cannot mix these tasks in the same queues used - * for work-stealing (this would contaminate lifo/fifo - * processing). Instead, we randomly associate submission queues - * with submitting threads, using a form of hashing. The - * Submitter probe value serves as a hash code for - * choosing existing queues, and may be randomly repositioned upon - * contention with other submitters. In essence, submitters act - * like workers except that they are restricted to executing local - * tasks that they submitted (or in the case of CountedCompleters, - * others with the same root task). However, because most - * shared/external queue operations are more expensive than - * internal, and because, at steady state, external submitters - * will compete for CPU with workers, ForkJoinTask.join and - * related methods disable them from repeatedly helping to process - * tasks if all workers are active. Insertion of tasks in shared - * mode requires a lock (mainly to protect in the case of - * resizing) but we use only a simple spinlock (using bits in - * field qlock), because submitters encountering a busy queue move - * on to try or create other queues -- they block only when - * creating and registering new queues. - * - * Management - * ========== - * - * The main throughput advantages of work-stealing stem from - * decentralized control -- workers mostly take tasks from - * themselves or each other. We cannot negate this in the - * implementation of other management responsibilities. The main - * tactic for avoiding bottlenecks is packing nearly all - * essentially atomic control state into two volatile variables - * that are by far most often read (not written) as status and - * consistency checks. - * - * Field "ctl" contains 64 bits holding all the information needed - * to atomically decide to add, inactivate, enqueue (on an event - * queue), dequeue, and/or re-activate workers. To enable this - * packing, we restrict maximum parallelism to (1<<15)-1 (which is - * far in excess of normal operating range) to allow ids, counts, - * and their negations (used for thresholding) to fit into 16bit - * fields. - * - * Field "plock" is a form of sequence lock with a saturating - * shutdown bit (similarly for per-queue "qlocks"), mainly - * protecting updates to the workQueues array, as well as to - * enable shutdown. When used as a lock, it is normally only very - * briefly held, so is nearly always available after at most a - * brief spin, but we use a monitor-based backup strategy to - * block when needed. - * - * Recording WorkQueues. WorkQueues are recorded in the - * "workQueues" array that is created upon first use and expanded - * if necessary. Updates to the array while recording new workers - * and unrecording terminated ones are protected from each other - * by a lock but the array is otherwise concurrently readable, and - * accessed directly. To simplify index-based operations, the - * array size is always a power of two, and all readers must - * tolerate null slots. Worker queues are at odd indices. Shared - * (submission) queues are at even indices, up to a maximum of 64 - * slots, to limit growth even if array needs to expand to add - * more workers. Grouping them together in this way simplifies and - * speeds up task scanning. - * - * All worker thread creation is on-demand, triggered by task - * submissions, replacement of terminated workers, and/or - * compensation for blocked workers. However, all other support - * code is set up to work with other policies. To ensure that we - * do not hold on to worker references that would prevent GC, ALL - * accesses to workQueues are via indices into the workQueues - * array (which is one source of some of the messy code - * constructions here). In essence, the workQueues array serves as - * a weak reference mechanism. Thus for example the wait queue - * field of ctl stores indices, not references. Access to the - * workQueues in associated methods (for example signalWork) must - * both index-check and null-check the IDs. All such accesses - * ignore bad IDs by returning out early from what they are doing, - * since this can only be associated with termination, in which - * case it is OK to give up. All uses of the workQueues array - * also check that it is non-null (even if previously - * non-null). This allows nulling during termination, which is - * currently not necessary, but remains an option for - * resource-revocation-based shutdown schemes. It also helps - * reduce JIT issuance of uncommon-trap code, which tends to - * unnecessarily complicate control flow in some methods. - * - * Event Queuing. Unlike HPC work-stealing frameworks, we cannot - * let workers spin indefinitely scanning for tasks when none can - * be found immediately, and we cannot start/resume workers unless - * there appear to be tasks available. On the other hand, we must - * quickly prod them into action when new tasks are submitted or - * generated. In many usages, ramp-up time to activate workers is - * the main limiting factor in overall performance (this is - * compounded at program start-up by JIT compilation and - * allocation). So we try to streamline this as much as possible. - * We park/unpark workers after placing in an event wait queue - * when they cannot find work. This "queue" is actually a simple - * Treiber stack, headed by the "id" field of ctl, plus a 15bit - * counter value (that reflects the number of times a worker has - * been inactivated) to avoid ABA effects (we need only as many - * version numbers as worker threads). Successors are held in - * field WorkQueue.nextWait. Queuing deals with several intrinsic - * races, mainly that a task-producing thread can miss seeing (and - * signalling) another thread that gave up looking for work but - * has not yet entered the wait queue. We solve this by requiring - * a full sweep of all workers (via repeated calls to method - * scan()) both before and after a newly waiting worker is added - * to the wait queue. Because enqueued workers may actually be - * rescanning rather than waiting, we set and clear the "parker" - * field of WorkQueues to reduce unnecessary calls to unpark. - * (This requires a secondary recheck to avoid missed signals.) - * Note the unusual conventions about Thread.interrupts - * surrounding parking and other blocking: Because interrupts are - * used solely to alert threads to check termination, which is - * checked anyway upon blocking, we clear status (using - * Thread.interrupted) before any call to park, so that park does - * not immediately return due to status being set via some other - * unrelated call to interrupt in user code. - * - * Signalling. We create or wake up workers only when there - * appears to be at least one task they might be able to find and - * execute. When a submission is added or another worker adds a - * task to a queue that has fewer than two tasks, they signal - * waiting workers (or trigger creation of new ones if fewer than - * the given parallelism level -- signalWork). These primary - * signals are buttressed by others whenever other threads remove - * a task from a queue and notice that there are other tasks there - * as well. So in general, pools will be over-signalled. On most - * platforms, signalling (unpark) overhead time is noticeably - * long, and the time between signalling a thread and it actually - * making progress can be very noticeably long, so it is worth - * offloading these delays from critical paths as much as - * possible. Additionally, workers spin-down gradually, by staying - * alive so long as they see the ctl state changing. Similar - * stability-sensing techniques are also used before blocking in - * awaitJoin and helpComplete. - * - * Trimming workers. To release resources after periods of lack of - * use, a worker starting to wait when the pool is quiescent will - * time out and terminate if the pool has remained quiescent for a - * given period -- a short period if there are more threads than - * parallelism, longer as the number of threads decreases. This - * will slowly propagate, eventually terminating all workers after - * periods of non-use. - * - * Shutdown and Termination. A call to shutdownNow atomically sets - * a plock bit and then (non-atomically) sets each worker's - * qlock status, cancels all unprocessed tasks, and wakes up - * all waiting workers. Detecting whether termination should - * commence after a non-abrupt shutdown() call requires more work - * and bookkeeping. We need consensus about quiescence (i.e., that - * there is no more work). The active count provides a primary - * indication but non-abrupt shutdown still requires a rechecking - * scan for any workers that are inactive but not queued. - * - * Joining Tasks - * ============= - * - * Any of several actions may be taken when one worker is waiting - * to join a task stolen (or always held) by another. Because we - * are multiplexing many tasks on to a pool of workers, we can't - * just let them block (as in Thread.join). We also cannot just - * reassign the joiner's run-time stack with another and replace - * it later, which would be a form of "continuation", that even if - * possible is not necessarily a good idea since we sometimes need - * both an unblocked task and its continuation to progress. - * Instead we combine two tactics: - * - * Helping: Arranging for the joiner to execute some task that it - * would be running if the steal had not occurred. - * - * Compensating: Unless there are already enough live threads, - * method tryCompensate() may create or re-activate a spare - * thread to compensate for blocked joiners until they unblock. - * - * A third form (implemented in tryRemoveAndExec) amounts to - * helping a hypothetical compensator: If we can readily tell that - * a possible action of a compensator is to steal and execute the - * task being joined, the joining thread can do so directly, - * without the need for a compensation thread (although at the - * expense of larger run-time stacks, but the tradeoff is - * typically worthwhile). - * - * The ManagedBlocker extension API can't use helping so relies - * only on compensation in method awaitBlocker. - * - * The algorithm in tryHelpStealer entails a form of "linear" - * helping: Each worker records (in field currentSteal) the most - * recent task it stole from some other worker. Plus, it records - * (in field currentJoin) the task it is currently actively - * joining. Method tryHelpStealer uses these markers to try to - * find a worker to help (i.e., steal back a task from and execute - * it) that could hasten completion of the actively joined task. - * In essence, the joiner executes a task that would be on its own - * local deque had the to-be-joined task not been stolen. This may - * be seen as a conservative variant of the approach in Wagner & - * Calder "Leapfrogging: a portable technique for implementing - * efficient futures" SIGPLAN Notices, 1993 - * (http://portal.acm.org/citation.cfm?id=155354). It differs in - * that: (1) We only maintain dependency links across workers upon - * steals, rather than use per-task bookkeeping. This sometimes - * requires a linear scan of workQueues array to locate stealers, - * but often doesn't because stealers leave hints (that may become - * stale/wrong) of where to locate them. It is only a hint - * because a worker might have had multiple steals and the hint - * records only one of them (usually the most current). Hinting - * isolates cost to when it is needed, rather than adding to - * per-task overhead. (2) It is "shallow", ignoring nesting and - * potentially cyclic mutual steals. (3) It is intentionally - * racy: field currentJoin is updated only while actively joining, - * which means that we miss links in the chain during long-lived - * tasks, GC stalls etc (which is OK since blocking in such cases - * is usually a good idea). (4) We bound the number of attempts - * to find work (see MAX_HELP) and fall back to suspending the - * worker and if necessary replacing it with another. - * - * Helping actions for CountedCompleters are much simpler: Method - * helpComplete can take and execute any task with the same root - * as the task being waited on. However, this still entails some - * traversal of completer chains, so is less efficient than using - * CountedCompleters without explicit joins. - * - * It is impossible to keep exactly the target parallelism number - * of threads running at any given time. Determining the - * existence of conservatively safe helping targets, the - * availability of already-created spares, and the apparent need - * to create new spares are all racy, so we rely on multiple - * retries of each. Compensation in the apparent absence of - * helping opportunities is challenging to control on JVMs, where - * GC and other activities can stall progress of tasks that in - * turn stall out many other dependent tasks, without us being - * able to determine whether they will ever require compensation. - * Even though work-stealing otherwise encounters little - * degradation in the presence of more threads than cores, - * aggressively adding new threads in such cases entails risk of - * unwanted positive feedback control loops in which more threads - * cause more dependent stalls (as well as delayed progress of - * unblocked threads to the point that we know they are available) - * leading to more situations requiring more threads, and so - * on. This aspect of control can be seen as an (analytically - * intractable) game with an opponent that may choose the worst - * (for us) active thread to stall at any time. We take several - * precautions to bound losses (and thus bound gains), mainly in - * methods tryCompensate and awaitJoin. - * - * Common Pool - * =========== - * - * The static common pool always exists after static - * initialization. Since it (or any other created pool) need - * never be used, we minimize initial construction overhead and - * footprint to the setup of about a dozen fields, with no nested - * allocation. Most bootstrapping occurs within method - * fullExternalPush during the first submission to the pool. - * - * When external threads submit to the common pool, they can - * perform subtask processing (see externalHelpJoin and related - * methods). This caller-helps policy makes it sensible to set - * common pool parallelism level to one (or more) less than the - * total number of available cores, or even zero for pure - * caller-runs. We do not need to record whether external - * submissions are to the common pool -- if not, externalHelpJoin - * returns quickly (at the most helping to signal some common pool - * workers). These submitters would otherwise be blocked waiting - * for completion, so the extra effort (with liberally sprinkled - * task status checks) in inapplicable cases amounts to an odd - * form of limited spin-wait before blocking in ForkJoinTask.join. - * - * Style notes - * =========== - * - * There is a lot of representation-level coupling among classes - * ForkJoinPool, ForkJoinWorkerThread, and ForkJoinTask. The - * fields of WorkQueue maintain data structures managed by - * ForkJoinPool, so are directly accessed. There is little point - * trying to reduce this, since any associated future changes in - * representations will need to be accompanied by algorithmic - * changes anyway. Several methods intrinsically sprawl because - * they must accumulate sets of consistent reads of volatiles held - * in local variables. Methods signalWork() and scan() are the - * main bottlenecks, so are especially heavily - * micro-optimized/mangled. There are lots of inline assignments - * (of form "while ((local = field) != 0)") which are usually the - * simplest way to ensure the required read orderings (which are - * sometimes critical). This leads to a "C"-like style of listing - * declarations of these locals at the heads of methods or blocks. - * There are several occurrences of the unusual "do {} while - * (!cas...)" which is the simplest way to force an update of a - * CAS'ed variable. There are also other coding oddities (including - * several unnecessary-looking hoisted null checks) that help - * some methods perform reasonably even when interpreted (not - * compiled). - * - * The order of declarations in this file is: - * (1) Static utility functions - * (2) Nested (static) classes - * (3) Static fields - * (4) Fields, along with constants used when unpacking some of them - * (5) Internal control methods - * (6) Callbacks and other support for ForkJoinTask methods - * (7) Exported methods - * (8) Static block initializing statics in minimally dependent order - */ - - // Static utilities - - /** - * If there is a security manager, makes sure caller has - * permission to modify threads. - */ - private static void checkPermission() { - SecurityManager security = System.getSecurityManager(); - if (security != null) - security.checkPermission(modifyThreadPermission); - } - - // Nested classes - - /** - * Factory for creating new {@link ForkJoinWorkerThread}s. - * A {@code ForkJoinWorkerThreadFactory} must be defined and used - * for {@code ForkJoinWorkerThread} subclasses that extend base - * functionality or initialize threads with different contexts. - */ - public static interface ForkJoinWorkerThreadFactory { - /** - * Returns a new worker thread operating in the given pool. - * - * @param pool the pool this thread works in - * @throws NullPointerException if the pool is null - * @return the new worker thread - */ - public ForkJoinWorkerThread newThread(ForkJoinPool pool); - } - - /** - * Default ForkJoinWorkerThreadFactory implementation; creates a - * new ForkJoinWorkerThread. - */ - static final class DefaultForkJoinWorkerThreadFactory - implements ForkJoinWorkerThreadFactory { - public final ForkJoinWorkerThread newThread(ForkJoinPool pool) { - return new ForkJoinWorkerThread(pool); - } - } - - /** - * Class for artificial tasks that are used to replace the target - * of local joins if they are removed from an interior queue slot - * in WorkQueue.tryRemoveAndExec. We don't need the proxy to - * actually do anything beyond having a unique identity. - */ - static final class EmptyTask extends ForkJoinTask { - private static final long serialVersionUID = -7721805057305804111L; - EmptyTask() { status = ForkJoinTask.NORMAL; } // force done - public final Void getRawResult() { return null; } - public final void setRawResult(Void x) {} - public final boolean exec() { return true; } - } - - /** - * Queues supporting work-stealing as well as external task - * submission. See above for main rationale and algorithms. - * Implementation relies heavily on "Unsafe" intrinsics - * and selective use of "volatile": - * - * Field "base" is the index (mod array.length) of the least valid - * queue slot, which is always the next position to steal (poll) - * from if nonempty. Reads and writes require volatile orderings - * but not CAS, because updates are only performed after slot - * CASes. - * - * Field "top" is the index (mod array.length) of the next queue - * slot to push to or pop from. It is written only by owner thread - * for push, or under lock for external/shared push, and accessed - * by other threads only after reading (volatile) base. Both top - * and base are allowed to wrap around on overflow, but (top - - * base) (or more commonly -(base - top) to force volatile read of - * base before top) still estimates size. The lock ("qlock") is - * forced to -1 on termination, causing all further lock attempts - * to fail. (Note: we don't need CAS for termination state because - * upon pool shutdown, all shared-queues will stop being used - * anyway.) Nearly all lock bodies are set up so that exceptions - * within lock bodies are "impossible" (modulo JVM errors that - * would cause failure anyway.) - * - * The array slots are read and written using the emulation of - * volatiles/atomics provided by Unsafe. Insertions must in - * general use putOrderedObject as a form of releasing store to - * ensure that all writes to the task object are ordered before - * its publication in the queue. All removals entail a CAS to - * null. The array is always a power of two. To ensure safety of - * Unsafe array operations, all accesses perform explicit null - * checks and implicit bounds checks via power-of-two masking. - * - * In addition to basic queuing support, this class contains - * fields described elsewhere to control execution. It turns out - * to work better memory-layout-wise to include them in this class - * rather than a separate class. - * - * Performance on most platforms is very sensitive to placement of - * instances of both WorkQueues and their arrays -- we absolutely - * do not want multiple WorkQueue instances or multiple queue - * arrays sharing cache lines. (It would be best for queue objects - * and their arrays to share, but there is nothing available to - * help arrange that). The @Contended annotation alerts JVMs to - * try to keep instances apart. - */ - static final class WorkQueue { - /** - * Capacity of work-stealing queue array upon initialization. - * Must be a power of two; at least 4, but should be larger to - * reduce or eliminate cacheline sharing among queues. - * Currently, it is much larger, as a partial workaround for - * the fact that JVMs often place arrays in locations that - * share GC bookkeeping (especially cardmarks) such that - * per-write accesses encounter serious memory contention. - */ - static final int INITIAL_QUEUE_CAPACITY = 1 << 13; - - /** - * Maximum size for queue arrays. Must be a power of two less - * than or equal to 1 << (31 - width of array entry) to ensure - * lack of wraparound of index calculations, but defined to a - * value a bit less than this to help users trap runaway - * programs before saturating systems. - */ - static final int MAXIMUM_QUEUE_CAPACITY = 1 << 26; // 64M - - // Heuristic padding to ameliorate unfortunate memory placements - volatile long pad00, pad01, pad02, pad03, pad04, pad05, pad06; - - volatile int eventCount; // encoded inactivation count; < 0 if inactive - int nextWait; // encoded record of next event waiter - int nsteals; // number of steals - int hint; // steal index hint - short poolIndex; // index of this queue in pool - final short mode; // 0: lifo, > 0: fifo, < 0: shared - volatile int qlock; // 1: locked, -1: terminate; else 0 - volatile int base; // index of next slot for poll - int top; // index of next slot for push - ForkJoinTask[] array; // the elements (initially unallocated) - final ForkJoinPool pool; // the containing pool (may be null) - final ForkJoinWorkerThread owner; // owning thread or null if shared - volatile Thread parker; // == owner during call to park; else null - volatile ForkJoinTask currentJoin; // task being joined in awaitJoin - ForkJoinTask currentSteal; // current non-local task being executed - - volatile Object pad10, pad11, pad12, pad13, pad14, pad15, pad16, pad17; - volatile Object pad18, pad19, pad1a, pad1b, pad1c, pad1d; - - WorkQueue(ForkJoinPool pool, ForkJoinWorkerThread owner, int mode, - int seed) { - this.pool = pool; - this.owner = owner; - this.mode = (short)mode; - this.hint = seed; // store initial seed for runWorker - // Place indices in the center of array (that is not yet allocated) - base = top = INITIAL_QUEUE_CAPACITY >>> 1; - } - - /** - * Returns the approximate number of tasks in the queue. - */ - final int queueSize() { - int n = base - top; // non-owner callers must read base first - return (n >= 0) ? 0 : -n; // ignore transient negative - } - - /** - * Provides a more accurate estimate of whether this queue has - * any tasks than does queueSize, by checking whether a - * near-empty queue has at least one unclaimed task. - */ - final boolean isEmpty() { - ForkJoinTask[] a; int m, s; - int n = base - (s = top); - return (n >= 0 || - (n == -1 && - ((a = array) == null || - (m = a.length - 1) < 0 || - U.getObject - (a, (long)((m & (s - 1)) << ASHIFT) + ABASE) == null))); - } - - /** - * Pushes a task. Call only by owner in unshared queues. (The - * shared-queue version is embedded in method externalPush.) - * - * @param task the task. Caller must ensure non-null. - * @throws RejectedExecutionException if array cannot be resized - */ - final void push(ForkJoinTask task) { - ForkJoinTask[] a; ForkJoinPool p; - int s = top, n; - if ((a = array) != null) { // ignore if queue removed - int m = a.length - 1; - U.putOrderedObject(a, ((m & s) << ASHIFT) + ABASE, task); - if ((n = (top = s + 1) - base) <= 2) - (p = pool).signalWork(p.workQueues, this); - else if (n >= m) - growArray(); - } - } - - /** - * Initializes or doubles the capacity of array. Call either - * by owner or with lock held -- it is OK for base, but not - * top, to move while resizings are in progress. - */ - final ForkJoinTask[] growArray() { - ForkJoinTask[] oldA = array; - int size = oldA != null ? oldA.length << 1 : INITIAL_QUEUE_CAPACITY; - if (size > MAXIMUM_QUEUE_CAPACITY) - throw new RejectedExecutionException("Queue capacity exceeded"); - int oldMask, t, b; - ForkJoinTask[] a = array = new ForkJoinTask[size]; - if (oldA != null && (oldMask = oldA.length - 1) >= 0 && - (t = top) - (b = base) > 0) { - int mask = size - 1; - do { - ForkJoinTask x; - int oldj = ((b & oldMask) << ASHIFT) + ABASE; - int j = ((b & mask) << ASHIFT) + ABASE; - x = (ForkJoinTask)U.getObjectVolatile(oldA, oldj); - if (x != null && - U.compareAndSwapObject(oldA, oldj, x, null)) - U.putObjectVolatile(a, j, x); - } while (++b != t); - } - return a; - } - - /** - * Takes next task, if one exists, in LIFO order. Call only - * by owner in unshared queues. - */ - final ForkJoinTask pop() { - ForkJoinTask[] a; ForkJoinTask t; int m; - if ((a = array) != null && (m = a.length - 1) >= 0) { - for (int s; (s = top - 1) - base >= 0;) { - long j = ((m & s) << ASHIFT) + ABASE; - if ((t = (ForkJoinTask)U.getObject(a, j)) == null) - break; - if (U.compareAndSwapObject(a, j, t, null)) { - top = s; - return t; - } - } - } - return null; - } - - /** - * Takes a task in FIFO order if b is base of queue and a task - * can be claimed without contention. Specialized versions - * appear in ForkJoinPool methods scan and tryHelpStealer. - */ - final ForkJoinTask pollAt(int b) { - ForkJoinTask t; ForkJoinTask[] a; - if ((a = array) != null) { - int j = (((a.length - 1) & b) << ASHIFT) + ABASE; - if ((t = (ForkJoinTask)U.getObjectVolatile(a, j)) != null && - base == b && U.compareAndSwapObject(a, j, t, null)) { - U.putOrderedInt(this, QBASE, b + 1); - return t; - } - } - return null; - } - - /** - * Takes next task, if one exists, in FIFO order. - */ - final ForkJoinTask poll() { - ForkJoinTask[] a; int b; ForkJoinTask t; - while ((b = base) - top < 0 && (a = array) != null) { - int j = (((a.length - 1) & b) << ASHIFT) + ABASE; - t = (ForkJoinTask)U.getObjectVolatile(a, j); - if (t != null) { - if (U.compareAndSwapObject(a, j, t, null)) { - U.putOrderedInt(this, QBASE, b + 1); - return t; - } - } - else if (base == b) { - if (b + 1 == top) - break; - Thread.yield(); // wait for lagging update (very rare) - } - } - return null; - } - - /** - * Takes next task, if one exists, in order specified by mode. - */ - final ForkJoinTask nextLocalTask() { - return mode == 0 ? pop() : poll(); - } - - /** - * Returns next task, if one exists, in order specified by mode. - */ - final ForkJoinTask peek() { - ForkJoinTask[] a = array; int m; - if (a == null || (m = a.length - 1) < 0) - return null; - int i = mode == 0 ? top - 1 : base; - int j = ((i & m) << ASHIFT) + ABASE; - return (ForkJoinTask)U.getObjectVolatile(a, j); - } - - /** - * Pops the given task only if it is at the current top. - * (A shared version is available only via FJP.tryExternalUnpush) - */ - final boolean tryUnpush(ForkJoinTask t) { - ForkJoinTask[] a; int s; - if ((a = array) != null && (s = top) != base && - U.compareAndSwapObject - (a, (((a.length - 1) & --s) << ASHIFT) + ABASE, t, null)) { - top = s; - return true; - } - return false; - } - - /** - * Removes and cancels all known tasks, ignoring any exceptions. - */ - final void cancelAll() { - ForkJoinTask.cancelIgnoringExceptions(currentJoin); - ForkJoinTask.cancelIgnoringExceptions(currentSteal); - for (ForkJoinTask t; (t = poll()) != null; ) - ForkJoinTask.cancelIgnoringExceptions(t); - } - - // Specialized execution methods - - /** - * Polls and runs tasks until empty. - */ - final void pollAndExecAll() { - for (ForkJoinTask t; (t = poll()) != null;) - t.doExec(); - } - - /** - * Executes a top-level task and any local tasks remaining - * after execution. - */ - final void runTask(ForkJoinTask task) { - if ((currentSteal = task) != null) { - task.doExec(); - ForkJoinTask[] a = array; - int md = mode; - ++nsteals; - currentSteal = null; - if (md != 0) - pollAndExecAll(); - else if (a != null) { - int s, m = a.length - 1; - while ((s = top - 1) - base >= 0) { - long i = ((m & s) << ASHIFT) + ABASE; - ForkJoinTask t = (ForkJoinTask)U.getObject(a, i); - if (t == null) - break; - if (U.compareAndSwapObject(a, i, t, null)) { - top = s; - t.doExec(); - } - } - } - } - } - - /** - * If present, removes from queue and executes the given task, - * or any other cancelled task. Returns (true) on any CAS - * or consistency check failure so caller can retry. - * - * @return false if no progress can be made, else true - */ - final boolean tryRemoveAndExec(ForkJoinTask task) { - boolean stat; - ForkJoinTask[] a; int m, s, b, n; - if (task != null && (a = array) != null && (m = a.length - 1) >= 0 && - (n = (s = top) - (b = base)) > 0) { - boolean removed = false, empty = true; - stat = true; - for (ForkJoinTask t;;) { // traverse from s to b - long j = ((--s & m) << ASHIFT) + ABASE; - t = (ForkJoinTask)U.getObject(a, j); - if (t == null) // inconsistent length - break; - else if (t == task) { - if (s + 1 == top) { // pop - if (!U.compareAndSwapObject(a, j, task, null)) - break; - top = s; - removed = true; - } - else if (base == b) // replace with proxy - removed = U.compareAndSwapObject(a, j, task, - new EmptyTask()); - break; - } - else if (t.status >= 0) - empty = false; - else if (s + 1 == top) { // pop and throw away - if (U.compareAndSwapObject(a, j, t, null)) - top = s; - break; - } - if (--n == 0) { - if (!empty && base == b) - stat = false; - break; - } - } - if (removed) - task.doExec(); - } - else - stat = false; - return stat; - } - - /** - * Tries to poll for and execute the given task or any other - * task in its CountedCompleter computation. - */ - final boolean pollAndExecCC(CountedCompleter root) { - ForkJoinTask[] a; int b; Object o; CountedCompleter t, r; - if ((b = base) - top < 0 && (a = array) != null) { - long j = (((a.length - 1) & b) << ASHIFT) + ABASE; - if ((o = U.getObjectVolatile(a, j)) == null) - return true; // retry - if (o instanceof CountedCompleter) { - for (t = (CountedCompleter)o, r = t;;) { - if (r == root) { - if (base == b && - U.compareAndSwapObject(a, j, t, null)) { - U.putOrderedInt(this, QBASE, b + 1); - t.doExec(); - } - return true; - } - else if ((r = r.completer) == null) - break; // not part of root computation - } - } - } - return false; - } - - /** - * Tries to pop and execute the given task or any other task - * in its CountedCompleter computation. - */ - final boolean externalPopAndExecCC(CountedCompleter root) { - ForkJoinTask[] a; int s; Object o; CountedCompleter t, r; - if (base - (s = top) < 0 && (a = array) != null) { - long j = (((a.length - 1) & (s - 1)) << ASHIFT) + ABASE; - if ((o = U.getObject(a, j)) instanceof CountedCompleter) { - for (t = (CountedCompleter)o, r = t;;) { - if (r == root) { - if (U.compareAndSwapInt(this, QLOCK, 0, 1)) { - if (top == s && array == a && - U.compareAndSwapObject(a, j, t, null)) { - top = s - 1; - qlock = 0; - t.doExec(); - } - else - qlock = 0; - } - return true; - } - else if ((r = r.completer) == null) - break; - } - } - } - return false; - } - - /** - * Internal version - */ - final boolean internalPopAndExecCC(CountedCompleter root) { - ForkJoinTask[] a; int s; Object o; CountedCompleter t, r; - if (base - (s = top) < 0 && (a = array) != null) { - long j = (((a.length - 1) & (s - 1)) << ASHIFT) + ABASE; - if ((o = U.getObject(a, j)) instanceof CountedCompleter) { - for (t = (CountedCompleter)o, r = t;;) { - if (r == root) { - if (U.compareAndSwapObject(a, j, t, null)) { - top = s - 1; - t.doExec(); - } - return true; - } - else if ((r = r.completer) == null) - break; - } - } - } - return false; - } - - /** - * Returns true if owned and not known to be blocked. - */ - final boolean isApparentlyUnblocked() { - Thread wt; Thread.State s; - return (eventCount >= 0 && - (wt = owner) != null && - (s = wt.getState()) != Thread.State.BLOCKED && - s != Thread.State.WAITING && - s != Thread.State.TIMED_WAITING); - } - - // Unsafe mechanics - private static final sun.misc.Unsafe U; - private static final long QBASE; - private static final long QLOCK; - private static final int ABASE; - private static final int ASHIFT; - static { - try { - U = getUnsafe(); - Class k = WorkQueue.class; - Class ak = ForkJoinTask[].class; - QBASE = U.objectFieldOffset - (k.getDeclaredField("base")); - QLOCK = U.objectFieldOffset - (k.getDeclaredField("qlock")); - ABASE = U.arrayBaseOffset(ak); - int scale = U.arrayIndexScale(ak); - if ((scale & (scale - 1)) != 0) - throw new Error("data type scale not a power of two"); - ASHIFT = 31 - Integer.numberOfLeadingZeros(scale); - } catch (Exception e) { - throw new Error(e); - } - } - } - - // static fields (initialized in static initializer below) - - /** - * Per-thread submission bookkeeping. Shared across all pools - * to reduce ThreadLocal pollution and because random motion - * to avoid contention in one pool is likely to hold for others. - * Lazily initialized on first submission (but null-checked - * in other contexts to avoid unnecessary initialization). - */ - static final ThreadLocal submitters; - - /** - * Creates a new ForkJoinWorkerThread. This factory is used unless - * overridden in ForkJoinPool constructors. - */ - public static final ForkJoinWorkerThreadFactory - defaultForkJoinWorkerThreadFactory; - - /** - * Permission required for callers of methods that may start or - * kill threads. - */ - private static final RuntimePermission modifyThreadPermission; - - /** - * Common (static) pool. Non-null for public use unless a static - * construction exception, but internal usages null-check on use - * to paranoically avoid potential initialization circularities - * as well as to simplify generated code. - */ - static final ForkJoinPool common; - - /** - * Common pool parallelism. To allow simpler use and management - * when common pool threads are disabled, we allow the underlying - * common.parallelism field to be zero, but in that case still report - * parallelism as 1 to reflect resulting caller-runs mechanics. - */ - static final int commonParallelism; - - /** - * Sequence number for creating workerNamePrefix. - */ - private static int poolNumberSequence; - - /** - * Returns the next sequence number. We don't expect this to - * ever contend, so use simple builtin sync. - */ - private static final synchronized int nextPoolId() { - return ++poolNumberSequence; - } - - // static constants - - /** - * Initial timeout value (in nanoseconds) for the thread - * triggering quiescence to park waiting for new work. On timeout, - * the thread will instead try to shrink the number of - * workers. The value should be large enough to avoid overly - * aggressive shrinkage during most transient stalls (long GCs - * etc). - */ - private static final long IDLE_TIMEOUT = 2000L * 1000L * 1000L; // 2sec - - /** - * Timeout value when there are more threads than parallelism level - */ - private static final long FAST_IDLE_TIMEOUT = 200L * 1000L * 1000L; - - /** - * Tolerance for idle timeouts, to cope with timer undershoots - */ - private static final long TIMEOUT_SLOP = 2000000L; - - /** - * The maximum stolen->joining link depth allowed in method - * tryHelpStealer. Must be a power of two. Depths for legitimate - * chains are unbounded, but we use a fixed constant to avoid - * (otherwise unchecked) cycles and to bound staleness of - * traversal parameters at the expense of sometimes blocking when - * we could be helping. - */ - private static final int MAX_HELP = 64; - - /** - * Increment for seed generators. See class ThreadLocal for - * explanation. - */ - private static final int SEED_INCREMENT = 0x61c88647; - - /* - * Bits and masks for control variables - * - * Field ctl is a long packed with: - * AC: Number of active running workers minus target parallelism (16 bits) - * TC: Number of total workers minus target parallelism (16 bits) - * ST: true if pool is terminating (1 bit) - * EC: the wait count of top waiting thread (15 bits) - * ID: poolIndex of top of Treiber stack of waiters (16 bits) - * - * When convenient, we can extract the upper 32 bits of counts and - * the lower 32 bits of queue state, u = (int)(ctl >>> 32) and e = - * (int)ctl. The ec field is never accessed alone, but always - * together with id and st. The offsets of counts by the target - * parallelism and the positionings of fields makes it possible to - * perform the most common checks via sign tests of fields: When - * ac is negative, there are not enough active workers, when tc is - * negative, there are not enough total workers, and when e is - * negative, the pool is terminating. To deal with these possibly - * negative fields, we use casts in and out of "short" and/or - * signed shifts to maintain signedness. - * - * When a thread is queued (inactivated), its eventCount field is - * set negative, which is the only way to tell if a worker is - * prevented from executing tasks, even though it must continue to - * scan for them to avoid queuing races. Note however that - * eventCount updates lag releases so usage requires care. - * - * Field plock is an int packed with: - * SHUTDOWN: true if shutdown is enabled (1 bit) - * SEQ: a sequence lock, with PL_LOCK bit set if locked (30 bits) - * SIGNAL: set when threads may be waiting on the lock (1 bit) - * - * The sequence number enables simple consistency checks: - * Staleness of read-only operations on the workQueues array can - * be checked by comparing plock before vs after the reads. - */ - - // bit positions/shifts for fields - private static final int AC_SHIFT = 48; - private static final int TC_SHIFT = 32; - private static final int ST_SHIFT = 31; - private static final int EC_SHIFT = 16; - - // bounds - private static final int SMASK = 0xffff; // short bits - private static final int MAX_CAP = 0x7fff; // max #workers - 1 - private static final int EVENMASK = 0xfffe; // even short bits - private static final int SQMASK = 0x007e; // max 64 (even) slots - private static final int SHORT_SIGN = 1 << 15; - private static final int INT_SIGN = 1 << 31; - - // masks - private static final long STOP_BIT = 0x0001L << ST_SHIFT; - private static final long AC_MASK = ((long)SMASK) << AC_SHIFT; - private static final long TC_MASK = ((long)SMASK) << TC_SHIFT; - - // units for incrementing and decrementing - private static final long TC_UNIT = 1L << TC_SHIFT; - private static final long AC_UNIT = 1L << AC_SHIFT; - - // masks and units for dealing with u = (int)(ctl >>> 32) - private static final int UAC_SHIFT = AC_SHIFT - 32; - private static final int UTC_SHIFT = TC_SHIFT - 32; - private static final int UAC_MASK = SMASK << UAC_SHIFT; - private static final int UTC_MASK = SMASK << UTC_SHIFT; - private static final int UAC_UNIT = 1 << UAC_SHIFT; - private static final int UTC_UNIT = 1 << UTC_SHIFT; - - // masks and units for dealing with e = (int)ctl - private static final int E_MASK = 0x7fffffff; // no STOP_BIT - private static final int E_SEQ = 1 << EC_SHIFT; - - // plock bits - private static final int SHUTDOWN = 1 << 31; - private static final int PL_LOCK = 2; - private static final int PL_SIGNAL = 1; - private static final int PL_SPINS = 1 << 8; - - // access mode for WorkQueue - static final int LIFO_QUEUE = 0; - static final int FIFO_QUEUE = 1; - static final int SHARED_QUEUE = -1; - - // Heuristic padding to ameliorate unfortunate memory placements - volatile long pad00, pad01, pad02, pad03, pad04, pad05, pad06; - - // Instance fields - volatile long stealCount; // collects worker counts - volatile long ctl; // main pool control - volatile int plock; // shutdown status and seqLock - volatile int indexSeed; // worker/submitter index seed - final short parallelism; // parallelism level - final short mode; // LIFO/FIFO - WorkQueue[] workQueues; // main registry - final ForkJoinWorkerThreadFactory factory; - final UncaughtExceptionHandler ueh; // per-worker UEH - final String workerNamePrefix; // to create worker name string - - volatile Object pad10, pad11, pad12, pad13, pad14, pad15, pad16, pad17; - volatile Object pad18, pad19, pad1a, pad1b; - - /** - * Acquires the plock lock to protect worker array and related - * updates. This method is called only if an initial CAS on plock - * fails. This acts as a spinlock for normal cases, but falls back - * to builtin monitor to block when (rarely) needed. This would be - * a terrible idea for a highly contended lock, but works fine as - * a more conservative alternative to a pure spinlock. - */ - private int acquirePlock() { - int spins = PL_SPINS, ps, nps; - for (;;) { - if (((ps = plock) & PL_LOCK) == 0 && - U.compareAndSwapInt(this, PLOCK, ps, nps = ps + PL_LOCK)) - return nps; - else if (spins >= 0) { - if (ThreadLocalRandom.current().nextInt() >= 0) - --spins; - } - else if (U.compareAndSwapInt(this, PLOCK, ps, ps | PL_SIGNAL)) { - synchronized (this) { - if ((plock & PL_SIGNAL) != 0) { - try { - wait(); - } catch (InterruptedException ie) { - try { - Thread.currentThread().interrupt(); - } catch (SecurityException ignore) { - } - } - } - else - notifyAll(); - } - } - } - } - - /** - * Unlocks and signals any thread waiting for plock. Called only - * when CAS of seq value for unlock fails. - */ - private void releasePlock(int ps) { - plock = ps; - synchronized (this) { notifyAll(); } - } - - /** - * Tries to create and start one worker if fewer than target - * parallelism level exist. Adjusts counts etc on failure. - */ - private void tryAddWorker() { - long c; int u, e; - while ((u = (int)((c = ctl) >>> 32)) < 0 && - (u & SHORT_SIGN) != 0 && (e = (int)c) >= 0) { - long nc = ((long)(((u + UTC_UNIT) & UTC_MASK) | - ((u + UAC_UNIT) & UAC_MASK)) << 32) | (long)e; - if (U.compareAndSwapLong(this, CTL, c, nc)) { - ForkJoinWorkerThreadFactory fac; - Throwable ex = null; - ForkJoinWorkerThread wt = null; - try { - if ((fac = factory) != null && - (wt = fac.newThread(this)) != null) { - wt.start(); - break; - } - } catch (Throwable rex) { - ex = rex; - } - deregisterWorker(wt, ex); - break; - } - } - } - - // Registering and deregistering workers - - /** - * Callback from ForkJoinWorkerThread to establish and record its - * WorkQueue. To avoid scanning bias due to packing entries in - * front of the workQueues array, we treat the array as a simple - * power-of-two hash table using per-thread seed as hash, - * expanding as needed. - * - * @param wt the worker thread - * @return the worker's queue - */ - final WorkQueue registerWorker(ForkJoinWorkerThread wt) { - UncaughtExceptionHandler handler; WorkQueue[] ws; int s, ps; - wt.setDaemon(true); - if ((handler = ueh) != null) - wt.setUncaughtExceptionHandler(handler); - do {} while (!U.compareAndSwapInt(this, INDEXSEED, s = indexSeed, - s += SEED_INCREMENT) || - s == 0); // skip 0 - WorkQueue w = new WorkQueue(this, wt, mode, s); - if (((ps = plock) & PL_LOCK) != 0 || - !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK)) - ps = acquirePlock(); - int nps = (ps & SHUTDOWN) | ((ps + PL_LOCK) & ~SHUTDOWN); - try { - if ((ws = workQueues) != null) { // skip if shutting down - int n = ws.length, m = n - 1; - int r = (s << 1) | 1; // use odd-numbered indices - if (ws[r &= m] != null) { // collision - int probes = 0; // step by approx half size - int step = (n <= 4) ? 2 : ((n >>> 1) & EVENMASK) + 2; - while (ws[r = (r + step) & m] != null) { - if (++probes >= n) { - workQueues = ws = Arrays.copyOf(ws, n <<= 1); - m = n - 1; - probes = 0; - } - } - } - w.poolIndex = (short)r; - w.eventCount = r; // volatile write orders - ws[r] = w; - } - } finally { - if (!U.compareAndSwapInt(this, PLOCK, ps, nps)) - releasePlock(nps); - } - wt.setName(workerNamePrefix.concat(Integer.toString(w.poolIndex >>> 1))); - return w; - } - - /** - * Final callback from terminating worker, as well as upon failure - * to construct or start a worker. Removes record of worker from - * array, and adjusts counts. If pool is shutting down, tries to - * complete termination. - * - * @param wt the worker thread, or null if construction failed - * @param ex the exception causing failure, or null if none - */ - final void deregisterWorker(ForkJoinWorkerThread wt, Throwable ex) { - WorkQueue w = null; - if (wt != null && (w = wt.workQueue) != null) { - int ps; long sc; - w.qlock = -1; // ensure set - do {} while (!U.compareAndSwapLong(this, STEALCOUNT, - sc = stealCount, - sc + w.nsteals)); - if (((ps = plock) & PL_LOCK) != 0 || - !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK)) - ps = acquirePlock(); - int nps = (ps & SHUTDOWN) | ((ps + PL_LOCK) & ~SHUTDOWN); - try { - int idx = w.poolIndex; - WorkQueue[] ws = workQueues; - if (ws != null && idx >= 0 && idx < ws.length && ws[idx] == w) - ws[idx] = null; - } finally { - if (!U.compareAndSwapInt(this, PLOCK, ps, nps)) - releasePlock(nps); - } - } - - long c; // adjust ctl counts - do {} while (!U.compareAndSwapLong - (this, CTL, c = ctl, (((c - AC_UNIT) & AC_MASK) | - ((c - TC_UNIT) & TC_MASK) | - (c & ~(AC_MASK|TC_MASK))))); - - if (!tryTerminate(false, false) && w != null && w.array != null) { - w.cancelAll(); // cancel remaining tasks - WorkQueue[] ws; WorkQueue v; Thread p; int u, i, e; - while ((u = (int)((c = ctl) >>> 32)) < 0 && (e = (int)c) >= 0) { - if (e > 0) { // activate or create replacement - if ((ws = workQueues) == null || - (i = e & SMASK) >= ws.length || - (v = ws[i]) == null) - break; - long nc = (((long)(v.nextWait & E_MASK)) | - ((long)(u + UAC_UNIT) << 32)); - if (v.eventCount != (e | INT_SIGN)) - break; - if (U.compareAndSwapLong(this, CTL, c, nc)) { - v.eventCount = (e + E_SEQ) & E_MASK; - if ((p = v.parker) != null) - U.unpark(p); - break; - } - } - else { - if ((short)u < 0) - tryAddWorker(); - break; - } - } - } - if (ex == null) // help clean refs on way out - ForkJoinTask.helpExpungeStaleExceptions(); - else // rethrow - ForkJoinTask.rethrow(ex); - } - - // Submissions - - /** - * Per-thread records for threads that submit to pools. Currently - * holds only pseudo-random seed / index that is used to choose - * submission queues in method externalPush. In the future, this may - * also incorporate a means to implement different task rejection - * and resubmission policies. - * - * Seeds for submitters and workers/workQueues work in basically - * the same way but are initialized and updated using slightly - * different mechanics. Both are initialized using the same - * approach as in class ThreadLocal, where successive values are - * unlikely to collide with previous values. Seeds are then - * randomly modified upon collisions using xorshifts, which - * requires a non-zero seed. - */ - static final class Submitter { - int seed; - Submitter(int s) { seed = s; } - } - - /** - * Unless shutting down, adds the given task to a submission queue - * at submitter's current queue index (modulo submission - * range). Only the most common path is directly handled in this - * method. All others are relayed to fullExternalPush. - * - * @param task the task. Caller must ensure non-null. - */ - final void externalPush(ForkJoinTask task) { - Submitter z = submitters.get(); - WorkQueue q; int r, m, s, n, am; ForkJoinTask[] a; - int ps = plock; - WorkQueue[] ws = workQueues; - if (z != null && ps > 0 && ws != null && (m = (ws.length - 1)) >= 0 && - (q = ws[m & (r = z.seed) & SQMASK]) != null && r != 0 && - U.compareAndSwapInt(q, QLOCK, 0, 1)) { // lock - if ((a = q.array) != null && - (am = a.length - 1) > (n = (s = q.top) - q.base)) { - int j = ((am & s) << ASHIFT) + ABASE; - U.putOrderedObject(a, j, task); - q.top = s + 1; // push on to deque - q.qlock = 0; - if (n <= 1) - signalWork(ws, q); - return; - } - q.qlock = 0; - } - fullExternalPush(task); - } - - /** - * Full version of externalPush. This method is called, among - * other times, upon the first submission of the first task to the - * pool, so must perform secondary initialization. It also - * detects first submission by an external thread by looking up - * its ThreadLocal, and creates a new shared queue if the one at - * index if empty or contended. The plock lock body must be - * exception-free (so no try/finally) so we optimistically - * allocate new queues outside the lock and throw them away if - * (very rarely) not needed. - * - * Secondary initialization occurs when plock is zero, to create - * workQueue array and set plock to a valid value. This lock body - * must also be exception-free. Because the plock seq value can - * eventually wrap around zero, this method harmlessly fails to - * reinitialize if workQueues exists, while still advancing plock. - */ - private void fullExternalPush(ForkJoinTask task) { - int r = 0; // random index seed - for (Submitter z = submitters.get();;) { - WorkQueue[] ws; WorkQueue q; int ps, m, k; - if (z == null) { - if (U.compareAndSwapInt(this, INDEXSEED, r = indexSeed, - r += SEED_INCREMENT) && r != 0) - submitters.set(z = new Submitter(r)); - } - else if (r == 0) { // move to a different index - r = z.seed; - r ^= r << 13; // same xorshift as WorkQueues - r ^= r >>> 17; - z.seed = r ^= (r << 5); - } - if ((ps = plock) < 0) - throw new RejectedExecutionException(); - else if (ps == 0 || (ws = workQueues) == null || - (m = ws.length - 1) < 0) { // initialize workQueues - int p = parallelism; // find power of two table size - int n = (p > 1) ? p - 1 : 1; // ensure at least 2 slots - n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; - n |= n >>> 8; n |= n >>> 16; n = (n + 1) << 1; - WorkQueue[] nws = ((ws = workQueues) == null || ws.length == 0 ? - new WorkQueue[n] : null); - if (((ps = plock) & PL_LOCK) != 0 || - !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK)) - ps = acquirePlock(); - if (((ws = workQueues) == null || ws.length == 0) && nws != null) - workQueues = nws; - int nps = (ps & SHUTDOWN) | ((ps + PL_LOCK) & ~SHUTDOWN); - if (!U.compareAndSwapInt(this, PLOCK, ps, nps)) - releasePlock(nps); - } - else if ((q = ws[k = r & m & SQMASK]) != null) { - if (q.qlock == 0 && U.compareAndSwapInt(q, QLOCK, 0, 1)) { - ForkJoinTask[] a = q.array; - int s = q.top; - boolean submitted = false; - try { // locked version of push - if ((a != null && a.length > s + 1 - q.base) || - (a = q.growArray()) != null) { // must presize - int j = (((a.length - 1) & s) << ASHIFT) + ABASE; - U.putOrderedObject(a, j, task); - q.top = s + 1; - submitted = true; - } - } finally { - q.qlock = 0; // unlock - } - if (submitted) { - signalWork(ws, q); - return; - } - } - r = 0; // move on failure - } - else if (((ps = plock) & PL_LOCK) == 0) { // create new queue - q = new WorkQueue(this, null, SHARED_QUEUE, r); - q.poolIndex = (short)k; - if (((ps = plock) & PL_LOCK) != 0 || - !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK)) - ps = acquirePlock(); - if ((ws = workQueues) != null && k < ws.length && ws[k] == null) - ws[k] = q; - int nps = (ps & SHUTDOWN) | ((ps + PL_LOCK) & ~SHUTDOWN); - if (!U.compareAndSwapInt(this, PLOCK, ps, nps)) - releasePlock(nps); - } - else - r = 0; - } - } - - // Maintaining ctl counts - - /** - * Increments active count; mainly called upon return from blocking. - */ - final void incrementActiveCount() { - long c; - do {} while (!U.compareAndSwapLong - (this, CTL, c = ctl, ((c & ~AC_MASK) | - ((c & AC_MASK) + AC_UNIT)))); - } - - /** - * Tries to create or activate a worker if too few are active. - * - * @param ws the worker array to use to find signallees - * @param q if non-null, the queue holding tasks to be processed - */ - final void signalWork(WorkQueue[] ws, WorkQueue q) { - for (;;) { - long c; int e, u, i; WorkQueue w; Thread p; - if ((u = (int)((c = ctl) >>> 32)) >= 0) - break; - if ((e = (int)c) <= 0) { - if ((short)u < 0) - tryAddWorker(); - break; - } - if (ws == null || ws.length <= (i = e & SMASK) || - (w = ws[i]) == null) - break; - long nc = (((long)(w.nextWait & E_MASK)) | - ((long)(u + UAC_UNIT)) << 32); - int ne = (e + E_SEQ) & E_MASK; - if (w.eventCount == (e | INT_SIGN) && - U.compareAndSwapLong(this, CTL, c, nc)) { - w.eventCount = ne; - if ((p = w.parker) != null) - U.unpark(p); - break; - } - if (q != null && q.base >= q.top) - break; - } - } - - // Scanning for tasks - - /** - * Top-level runloop for workers, called by ForkJoinWorkerThread.run. - */ - final void runWorker(WorkQueue w) { - w.growArray(); // allocate queue - for (int r = w.hint; scan(w, r) == 0; ) { - r ^= r << 13; r ^= r >>> 17; r ^= r << 5; // xorshift - } - } - - /** - * Scans for and, if found, runs one task, else possibly - * inactivates the worker. This method operates on single reads of - * volatile state and is designed to be re-invoked continuously, - * in part because it returns upon detecting inconsistencies, - * contention, or state changes that indicate possible success on - * re-invocation. - * - * The scan searches for tasks across queues starting at a random - * index, checking each at least twice. The scan terminates upon - * either finding a non-empty queue, or completing the sweep. If - * the worker is not inactivated, it takes and runs a task from - * this queue. Otherwise, if not activated, it tries to activate - * itself or some other worker by signalling. On failure to find a - * task, returns (for retry) if pool state may have changed during - * an empty scan, or tries to inactivate if active, else possibly - * blocks or terminates via method awaitWork. - * - * @param w the worker (via its WorkQueue) - * @param r a random seed - * @return worker qlock status if would have waited, else 0 - */ - private final int scan(WorkQueue w, int r) { - WorkQueue[] ws; int m; - long c = ctl; // for consistency check - if ((ws = workQueues) != null && (m = ws.length - 1) >= 0 && w != null) { - for (int j = m + m + 1, ec = w.eventCount;;) { - WorkQueue q; int b, e; ForkJoinTask[] a; ForkJoinTask t; - if ((q = ws[(r - j) & m]) != null && - (b = q.base) - q.top < 0 && (a = q.array) != null) { - long i = (((a.length - 1) & b) << ASHIFT) + ABASE; - if ((t = ((ForkJoinTask) - U.getObjectVolatile(a, i))) != null) { - if (ec < 0) - helpRelease(c, ws, w, q, b); - else if (q.base == b && - U.compareAndSwapObject(a, i, t, null)) { - U.putOrderedInt(q, QBASE, b + 1); - if ((b + 1) - q.top < 0) - signalWork(ws, q); - w.runTask(t); - } - } - break; - } - else if (--j < 0) { - if ((ec | (e = (int)c)) < 0) // inactive or terminating - return awaitWork(w, c, ec); - else if (ctl == c) { // try to inactivate and enqueue - long nc = (long)ec | ((c - AC_UNIT) & (AC_MASK|TC_MASK)); - w.nextWait = e; - w.eventCount = ec | INT_SIGN; - if (!U.compareAndSwapLong(this, CTL, c, nc)) - w.eventCount = ec; // back out - } - break; - } - } - } - return 0; - } - - /** - * A continuation of scan(), possibly blocking or terminating - * worker w. Returns without blocking if pool state has apparently - * changed since last invocation. Also, if inactivating w has - * caused the pool to become quiescent, checks for pool - * termination, and, so long as this is not the only worker, waits - * for event for up to a given duration. On timeout, if ctl has - * not changed, terminates the worker, which will in turn wake up - * another worker to possibly repeat this process. - * - * @param w the calling worker - * @param c the ctl value on entry to scan - * @param ec the worker's eventCount on entry to scan - */ - private final int awaitWork(WorkQueue w, long c, int ec) { - int stat, ns; long parkTime, deadline; - if ((stat = w.qlock) >= 0 && w.eventCount == ec && ctl == c && - !Thread.interrupted()) { - int e = (int)c; - int u = (int)(c >>> 32); - int d = (u >> UAC_SHIFT) + parallelism; // active count - - if (e < 0 || (d <= 0 && tryTerminate(false, false))) - stat = w.qlock = -1; // pool is terminating - else if ((ns = w.nsteals) != 0) { // collect steals and retry - long sc; - w.nsteals = 0; - do {} while (!U.compareAndSwapLong(this, STEALCOUNT, - sc = stealCount, sc + ns)); - } - else { - long pc = ((d > 0 || ec != (e | INT_SIGN)) ? 0L : - ((long)(w.nextWait & E_MASK)) | // ctl to restore - ((long)(u + UAC_UNIT)) << 32); - if (pc != 0L) { // timed wait if last waiter - int dc = -(short)(c >>> TC_SHIFT); - parkTime = (dc < 0 ? FAST_IDLE_TIMEOUT: - (dc + 1) * IDLE_TIMEOUT); - deadline = System.nanoTime() + parkTime - TIMEOUT_SLOP; - } - else - parkTime = deadline = 0L; - if (w.eventCount == ec && ctl == c) { - Thread wt = Thread.currentThread(); - U.putObject(wt, PARKBLOCKER, this); - w.parker = wt; // emulate LockSupport.park - if (w.eventCount == ec && ctl == c) - U.park(false, parkTime); // must recheck before park - w.parker = null; - U.putObject(wt, PARKBLOCKER, null); - if (parkTime != 0L && ctl == c && - deadline - System.nanoTime() <= 0L && - U.compareAndSwapLong(this, CTL, c, pc)) - stat = w.qlock = -1; // shrink pool - } - } - } - return stat; - } - - /** - * Possibly releases (signals) a worker. Called only from scan() - * when a worker with apparently inactive status finds a non-empty - * queue. This requires revalidating all of the associated state - * from caller. - */ - private final void helpRelease(long c, WorkQueue[] ws, WorkQueue w, - WorkQueue q, int b) { - WorkQueue v; int e, i; Thread p; - if (w != null && w.eventCount < 0 && (e = (int)c) > 0 && - ws != null && ws.length > (i = e & SMASK) && - (v = ws[i]) != null && ctl == c) { - long nc = (((long)(v.nextWait & E_MASK)) | - ((long)((int)(c >>> 32) + UAC_UNIT)) << 32); - int ne = (e + E_SEQ) & E_MASK; - if (q != null && q.base == b && w.eventCount < 0 && - v.eventCount == (e | INT_SIGN) && - U.compareAndSwapLong(this, CTL, c, nc)) { - v.eventCount = ne; - if ((p = v.parker) != null) - U.unpark(p); - } - } - } - - /** - * Tries to locate and execute tasks for a stealer of the given - * task, or in turn one of its stealers, Traces currentSteal -> - * currentJoin links looking for a thread working on a descendant - * of the given task and with a non-empty queue to steal back and - * execute tasks from. The first call to this method upon a - * waiting join will often entail scanning/search, (which is OK - * because the joiner has nothing better to do), but this method - * leaves hints in workers to speed up subsequent calls. The - * implementation is very branchy to cope with potential - * inconsistencies or loops encountering chains that are stale, - * unknown, or so long that they are likely cyclic. - * - * @param joiner the joining worker - * @param task the task to join - * @return 0 if no progress can be made, negative if task - * known complete, else positive - */ - private int tryHelpStealer(WorkQueue joiner, ForkJoinTask task) { - int stat = 0, steps = 0; // bound to avoid cycles - if (task != null && joiner != null && - joiner.base - joiner.top >= 0) { // hoist checks - restart: for (;;) { - ForkJoinTask subtask = task; // current target - for (WorkQueue j = joiner, v;;) { // v is stealer of subtask - WorkQueue[] ws; int m, s, h; - if ((s = task.status) < 0) { - stat = s; - break restart; - } - if ((ws = workQueues) == null || (m = ws.length - 1) <= 0) - break restart; // shutting down - if ((v = ws[h = (j.hint | 1) & m]) == null || - v.currentSteal != subtask) { - for (int origin = h;;) { // find stealer - if (((h = (h + 2) & m) & 15) == 1 && - (subtask.status < 0 || j.currentJoin != subtask)) - continue restart; // occasional staleness check - if ((v = ws[h]) != null && - v.currentSteal == subtask) { - j.hint = h; // save hint - break; - } - if (h == origin) - break restart; // cannot find stealer - } - } - for (;;) { // help stealer or descend to its stealer - ForkJoinTask[] a; int b; - if (subtask.status < 0) // surround probes with - continue restart; // consistency checks - if ((b = v.base) - v.top < 0 && (a = v.array) != null) { - int i = (((a.length - 1) & b) << ASHIFT) + ABASE; - ForkJoinTask t = - (ForkJoinTask)U.getObjectVolatile(a, i); - if (subtask.status < 0 || j.currentJoin != subtask || - v.currentSteal != subtask) - continue restart; // stale - stat = 1; // apparent progress - if (v.base == b) { - if (t == null) - break restart; - if (U.compareAndSwapObject(a, i, t, null)) { - U.putOrderedInt(v, QBASE, b + 1); - ForkJoinTask ps = joiner.currentSteal; - int jt = joiner.top; - do { - joiner.currentSteal = t; - t.doExec(); // clear local tasks too - } while (task.status >= 0 && - joiner.top != jt && - (t = joiner.pop()) != null); - joiner.currentSteal = ps; - break restart; - } - } - } - else { // empty -- try to descend - ForkJoinTask next = v.currentJoin; - if (subtask.status < 0 || j.currentJoin != subtask || - v.currentSteal != subtask) - continue restart; // stale - else if (next == null || ++steps == MAX_HELP) - break restart; // dead-end or maybe cyclic - else { - subtask = next; - j = v; - break; - } - } - } - } - } - } - return stat; - } - - /** - * Analog of tryHelpStealer for CountedCompleters. Tries to steal - * and run tasks within the target's computation. - * - * @param task the task to join - */ - private int helpComplete(WorkQueue joiner, CountedCompleter task) { - WorkQueue[] ws; int m; - int s = 0; - if ((ws = workQueues) != null && (m = ws.length - 1) >= 0 && - joiner != null && task != null) { - int j = joiner.poolIndex; - int scans = m + m + 1; - long c = 0L; // for stability check - for (int k = scans; ; j += 2) { - WorkQueue q; - if ((s = task.status) < 0) - break; - else if (joiner.internalPopAndExecCC(task)) - k = scans; - else if ((s = task.status) < 0) - break; - else if ((q = ws[j & m]) != null && q.pollAndExecCC(task)) - k = scans; - else if (--k < 0) { - if (c == (c = ctl)) - break; - k = scans; - } - } - } - return s; - } - - /** - * Tries to decrement active count (sometimes implicitly) and - * possibly release or create a compensating worker in preparation - * for blocking. Fails on contention or termination. Otherwise, - * adds a new thread if no idle workers are available and pool - * may become starved. - * - * @param c the assumed ctl value - */ - final boolean tryCompensate(long c) { - WorkQueue[] ws = workQueues; - int pc = parallelism, e = (int)c, m, tc; - if (ws != null && (m = ws.length - 1) >= 0 && e >= 0 && ctl == c) { - WorkQueue w = ws[e & m]; - if (e != 0 && w != null) { - Thread p; - long nc = ((long)(w.nextWait & E_MASK) | - (c & (AC_MASK|TC_MASK))); - int ne = (e + E_SEQ) & E_MASK; - if (w.eventCount == (e | INT_SIGN) && - U.compareAndSwapLong(this, CTL, c, nc)) { - w.eventCount = ne; - if ((p = w.parker) != null) - U.unpark(p); - return true; // replace with idle worker - } - } - else if ((tc = (short)(c >>> TC_SHIFT)) >= 0 && - (int)(c >> AC_SHIFT) + pc > 1) { - long nc = ((c - AC_UNIT) & AC_MASK) | (c & ~AC_MASK); - if (U.compareAndSwapLong(this, CTL, c, nc)) - return true; // no compensation - } - else if (tc + pc < MAX_CAP) { - long nc = ((c + TC_UNIT) & TC_MASK) | (c & ~TC_MASK); - if (U.compareAndSwapLong(this, CTL, c, nc)) { - ForkJoinWorkerThreadFactory fac; - Throwable ex = null; - ForkJoinWorkerThread wt = null; - try { - if ((fac = factory) != null && - (wt = fac.newThread(this)) != null) { - wt.start(); - return true; - } - } catch (Throwable rex) { - ex = rex; - } - deregisterWorker(wt, ex); // clean up and return false - } - } - } - return false; - } - - /** - * Helps and/or blocks until the given task is done. - * - * @param joiner the joining worker - * @param task the task - * @return task status on exit - */ - final int awaitJoin(WorkQueue joiner, ForkJoinTask task) { - int s = 0; - if (task != null && (s = task.status) >= 0 && joiner != null) { - ForkJoinTask prevJoin = joiner.currentJoin; - joiner.currentJoin = task; - do {} while (joiner.tryRemoveAndExec(task) && // process local tasks - (s = task.status) >= 0); - if (s >= 0 && (task instanceof CountedCompleter)) - s = helpComplete(joiner, (CountedCompleter)task); - long cc = 0; // for stability checks - while (s >= 0 && (s = task.status) >= 0) { - if ((s = tryHelpStealer(joiner, task)) == 0 && - (s = task.status) >= 0) { - if (!tryCompensate(cc)) - cc = ctl; - else { - if (task.trySetSignal() && (s = task.status) >= 0) { - synchronized (task) { - if (task.status >= 0) { - try { // see ForkJoinTask - task.wait(); // for explanation - } catch (InterruptedException ie) { - } - } - else - task.notifyAll(); - } - } - long c; // reactivate - do {} while (!U.compareAndSwapLong - (this, CTL, c = ctl, - ((c & ~AC_MASK) | - ((c & AC_MASK) + AC_UNIT)))); - } - } - } - joiner.currentJoin = prevJoin; - } - return s; - } - - /** - * Stripped-down variant of awaitJoin used by timed joins. Tries - * to help join only while there is continuous progress. (Caller - * will then enter a timed wait.) - * - * @param joiner the joining worker - * @param task the task - */ - final void helpJoinOnce(WorkQueue joiner, ForkJoinTask task) { - int s; - if (joiner != null && task != null && (s = task.status) >= 0) { - ForkJoinTask prevJoin = joiner.currentJoin; - joiner.currentJoin = task; - do {} while (joiner.tryRemoveAndExec(task) && // process local tasks - (s = task.status) >= 0); - if (s >= 0) { - if (task instanceof CountedCompleter) - helpComplete(joiner, (CountedCompleter)task); - do {} while (task.status >= 0 && - tryHelpStealer(joiner, task) > 0); - } - joiner.currentJoin = prevJoin; - } - } - - /** - * Returns a (probably) non-empty steal queue, if one is found - * during a scan, else null. This method must be retried by - * caller if, by the time it tries to use the queue, it is empty. - */ - private WorkQueue findNonEmptyStealQueue() { - int r = ThreadLocalRandom.current().nextInt(); - for (;;) { - int ps = plock, m; WorkQueue[] ws; WorkQueue q; - if ((ws = workQueues) != null && (m = ws.length - 1) >= 0) { - for (int j = (m + 1) << 2; j >= 0; --j) { - if ((q = ws[(((r - j) << 1) | 1) & m]) != null && - q.base - q.top < 0) - return q; - } - } - if (plock == ps) - return null; - } - } - - /** - * Runs tasks until {@code isQuiescent()}. We piggyback on - * active count ctl maintenance, but rather than blocking - * when tasks cannot be found, we rescan until all others cannot - * find tasks either. - */ - final void helpQuiescePool(WorkQueue w) { - ForkJoinTask ps = w.currentSteal; - for (boolean active = true;;) { - long c; WorkQueue q; ForkJoinTask t; int b; - while ((t = w.nextLocalTask()) != null) - t.doExec(); - if ((q = findNonEmptyStealQueue()) != null) { - if (!active) { // re-establish active count - active = true; - do {} while (!U.compareAndSwapLong - (this, CTL, c = ctl, - ((c & ~AC_MASK) | - ((c & AC_MASK) + AC_UNIT)))); - } - if ((b = q.base) - q.top < 0 && (t = q.pollAt(b)) != null) { - (w.currentSteal = t).doExec(); - w.currentSteal = ps; - } - } - else if (active) { // decrement active count without queuing - long nc = ((c = ctl) & ~AC_MASK) | ((c & AC_MASK) - AC_UNIT); - if ((int)(nc >> AC_SHIFT) + parallelism == 0) - break; // bypass decrement-then-increment - if (U.compareAndSwapLong(this, CTL, c, nc)) - active = false; - } - else if ((int)((c = ctl) >> AC_SHIFT) + parallelism <= 0 && - U.compareAndSwapLong - (this, CTL, c, ((c & ~AC_MASK) | - ((c & AC_MASK) + AC_UNIT)))) - break; - } - } - - /** - * Gets and removes a local or stolen task for the given worker. - * - * @return a task, if available - */ - final ForkJoinTask nextTaskFor(WorkQueue w) { - for (ForkJoinTask t;;) { - WorkQueue q; int b; - if ((t = w.nextLocalTask()) != null) - return t; - if ((q = findNonEmptyStealQueue()) == null) - return null; - if ((b = q.base) - q.top < 0 && (t = q.pollAt(b)) != null) - return t; - } - } - - /** - * Returns a cheap heuristic guide for task partitioning when - * programmers, frameworks, tools, or languages have little or no - * idea about task granularity. In essence by offering this - * method, we ask users only about tradeoffs in overhead vs - * expected throughput and its variance, rather than how finely to - * partition tasks. - * - * In a steady state strict (tree-structured) computation, each - * thread makes available for stealing enough tasks for other - * threads to remain active. Inductively, if all threads play by - * the same rules, each thread should make available only a - * constant number of tasks. - * - * The minimum useful constant is just 1. But using a value of 1 - * would require immediate replenishment upon each steal to - * maintain enough tasks, which is infeasible. Further, - * partitionings/granularities of offered tasks should minimize - * steal rates, which in general means that threads nearer the top - * of computation tree should generate more than those nearer the - * bottom. In perfect steady state, each thread is at - * approximately the same level of computation tree. However, - * producing extra tasks amortizes the uncertainty of progress and - * diffusion assumptions. - * - * So, users will want to use values larger (but not much larger) - * than 1 to both smooth over transient shortages and hedge - * against uneven progress; as traded off against the cost of - * extra task overhead. We leave the user to pick a threshold - * value to compare with the results of this call to guide - * decisions, but recommend values such as 3. - * - * When all threads are active, it is on average OK to estimate - * surplus strictly locally. In steady-state, if one thread is - * maintaining say 2 surplus tasks, then so are others. So we can - * just use estimated queue length. However, this strategy alone - * leads to serious mis-estimates in some non-steady-state - * conditions (ramp-up, ramp-down, other stalls). We can detect - * many of these by further considering the number of "idle" - * threads, that are known to have zero queued tasks, so - * compensate by a factor of (#idle/#active) threads. - * - * Note: The approximation of #busy workers as #active workers is - * not very good under current signalling scheme, and should be - * improved. - */ - static int getSurplusQueuedTaskCount() { - Thread t; ForkJoinWorkerThread wt; ForkJoinPool pool; WorkQueue q; - if (((t = Thread.currentThread()) instanceof ForkJoinWorkerThread)) { - int p = (pool = (wt = (ForkJoinWorkerThread)t).pool).parallelism; - int n = (q = wt.workQueue).top - q.base; - int a = (int)(pool.ctl >> AC_SHIFT) + p; - return n - (a > (p >>>= 1) ? 0 : - a > (p >>>= 1) ? 1 : - a > (p >>>= 1) ? 2 : - a > (p >>>= 1) ? 4 : - 8); - } - return 0; - } - - // Termination - - /** - * Possibly initiates and/or completes termination. The caller - * triggering termination runs three passes through workQueues: - * (0) Setting termination status, followed by wakeups of queued - * workers; (1) cancelling all tasks; (2) interrupting lagging - * threads (likely in external tasks, but possibly also blocked in - * joins). Each pass repeats previous steps because of potential - * lagging thread creation. - * - * @param now if true, unconditionally terminate, else only - * if no work and no active workers - * @param enable if true, enable shutdown when next possible - * @return true if now terminating or terminated - */ - private boolean tryTerminate(boolean now, boolean enable) { - int ps; - if (this == common) // cannot shut down - return false; - if ((ps = plock) >= 0) { // enable by setting plock - if (!enable) - return false; - if ((ps & PL_LOCK) != 0 || - !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK)) - ps = acquirePlock(); - int nps = ((ps + PL_LOCK) & ~SHUTDOWN) | SHUTDOWN; - if (!U.compareAndSwapInt(this, PLOCK, ps, nps)) - releasePlock(nps); - } - for (long c;;) { - if (((c = ctl) & STOP_BIT) != 0) { // already terminating - if ((short)(c >>> TC_SHIFT) + parallelism <= 0) { - synchronized (this) { - notifyAll(); // signal when 0 workers - } - } - return true; - } - if (!now) { // check if idle & no tasks - WorkQueue[] ws; WorkQueue w; - if ((int)(c >> AC_SHIFT) + parallelism > 0) - return false; - if ((ws = workQueues) != null) { - for (int i = 0; i < ws.length; ++i) { - if ((w = ws[i]) != null && - (!w.isEmpty() || - ((i & 1) != 0 && w.eventCount >= 0))) { - signalWork(ws, w); - return false; - } - } - } - } - if (U.compareAndSwapLong(this, CTL, c, c | STOP_BIT)) { - for (int pass = 0; pass < 3; ++pass) { - WorkQueue[] ws; WorkQueue w; Thread wt; - if ((ws = workQueues) != null) { - int n = ws.length; - for (int i = 0; i < n; ++i) { - if ((w = ws[i]) != null) { - w.qlock = -1; - if (pass > 0) { - w.cancelAll(); - if (pass > 1 && (wt = w.owner) != null) { - if (!wt.isInterrupted()) { - try { - wt.interrupt(); - } catch (Throwable ignore) { - } - } - U.unpark(wt); - } - } - } - } - // Wake up workers parked on event queue - int i, e; long cc; Thread p; - while ((e = (int)(cc = ctl) & E_MASK) != 0 && - (i = e & SMASK) < n && i >= 0 && - (w = ws[i]) != null) { - long nc = ((long)(w.nextWait & E_MASK) | - ((cc + AC_UNIT) & AC_MASK) | - (cc & (TC_MASK|STOP_BIT))); - if (w.eventCount == (e | INT_SIGN) && - U.compareAndSwapLong(this, CTL, cc, nc)) { - w.eventCount = (e + E_SEQ) & E_MASK; - w.qlock = -1; - if ((p = w.parker) != null) - U.unpark(p); - } - } - } - } - } - } - } - - // external operations on common pool - - /** - * Returns common pool queue for a thread that has submitted at - * least one task. - */ - static WorkQueue commonSubmitterQueue() { - Submitter z; ForkJoinPool p; WorkQueue[] ws; int m, r; - return ((z = submitters.get()) != null && - (p = common) != null && - (ws = p.workQueues) != null && - (m = ws.length - 1) >= 0) ? - ws[m & z.seed & SQMASK] : null; - } - - /** - * Tries to pop the given task from submitter's queue in common pool. - */ - final boolean tryExternalUnpush(ForkJoinTask task) { - WorkQueue joiner; ForkJoinTask[] a; int m, s; - Submitter z = submitters.get(); - WorkQueue[] ws = workQueues; - boolean popped = false; - if (z != null && ws != null && (m = ws.length - 1) >= 0 && - (joiner = ws[z.seed & m & SQMASK]) != null && - joiner.base != (s = joiner.top) && - (a = joiner.array) != null) { - long j = (((a.length - 1) & (s - 1)) << ASHIFT) + ABASE; - if (U.getObject(a, j) == task && - U.compareAndSwapInt(joiner, QLOCK, 0, 1)) { - if (joiner.top == s && joiner.array == a && - U.compareAndSwapObject(a, j, task, null)) { - joiner.top = s - 1; - popped = true; - } - joiner.qlock = 0; - } - } - return popped; - } - - final int externalHelpComplete(CountedCompleter task) { - WorkQueue joiner; int m, j; - Submitter z = submitters.get(); - WorkQueue[] ws = workQueues; - int s = 0; - if (z != null && ws != null && (m = ws.length - 1) >= 0 && - (joiner = ws[(j = z.seed) & m & SQMASK]) != null && task != null) { - int scans = m + m + 1; - long c = 0L; // for stability check - j |= 1; // poll odd queues - for (int k = scans; ; j += 2) { - WorkQueue q; - if ((s = task.status) < 0) - break; - else if (joiner.externalPopAndExecCC(task)) - k = scans; - else if ((s = task.status) < 0) - break; - else if ((q = ws[j & m]) != null && q.pollAndExecCC(task)) - k = scans; - else if (--k < 0) { - if (c == (c = ctl)) - break; - k = scans; - } - } - } - return s; - } - - // Exported methods - - // Constructors - - /** - * Creates a {@code ForkJoinPool} with parallelism equal to {@link - * java.lang.Runtime#availableProcessors}, using the {@linkplain - * #defaultForkJoinWorkerThreadFactory default thread factory}, - * no UncaughtExceptionHandler, and non-async LIFO processing mode. - * - * @throws SecurityException if a security manager exists and - * the caller is not permitted to modify threads - * because it does not hold {@link - * java.lang.RuntimePermission}{@code ("modifyThread")} - */ - public ForkJoinPool() { - this(Math.min(MAX_CAP, Runtime.getRuntime().availableProcessors()), - defaultForkJoinWorkerThreadFactory, null, false); - } - - /** - * Creates a {@code ForkJoinPool} with the indicated parallelism - * level, the {@linkplain - * #defaultForkJoinWorkerThreadFactory default thread factory}, - * no UncaughtExceptionHandler, and non-async LIFO processing mode. - * - * @param parallelism the parallelism level - * @throws IllegalArgumentException if parallelism less than or - * equal to zero, or greater than implementation limit - * @throws SecurityException if a security manager exists and - * the caller is not permitted to modify threads - * because it does not hold {@link - * java.lang.RuntimePermission}{@code ("modifyThread")} - */ - public ForkJoinPool(int parallelism) { - this(parallelism, defaultForkJoinWorkerThreadFactory, null, false); - } - - /** - * Creates a {@code ForkJoinPool} with the given parameters. - * - * @param parallelism the parallelism level. For default value, - * use {@link java.lang.Runtime#availableProcessors}. - * @param factory the factory for creating new threads. For default value, - * use {@link #defaultForkJoinWorkerThreadFactory}. - * @param handler the handler for internal worker threads that - * terminate due to unrecoverable errors encountered while executing - * tasks. For default value, use {@code null}. - * @param asyncMode if true, - * establishes local first-in-first-out scheduling mode for forked - * tasks that are never joined. This mode may be more appropriate - * than default locally stack-based mode in applications in which - * worker threads only process event-style asynchronous tasks. - * For default value, use {@code false}. - * @throws IllegalArgumentException if parallelism less than or - * equal to zero, or greater than implementation limit - * @throws NullPointerException if the factory is null - * @throws SecurityException if a security manager exists and - * the caller is not permitted to modify threads - * because it does not hold {@link - * java.lang.RuntimePermission}{@code ("modifyThread")} - */ - public ForkJoinPool(int parallelism, - ForkJoinWorkerThreadFactory factory, - UncaughtExceptionHandler handler, - boolean asyncMode) { - this(checkParallelism(parallelism), - checkFactory(factory), - handler, - (asyncMode ? FIFO_QUEUE : LIFO_QUEUE), - "ForkJoinPool-" + nextPoolId() + "-worker-"); - checkPermission(); - } - - private static int checkParallelism(int parallelism) { - if (parallelism <= 0 || parallelism > MAX_CAP) - throw new IllegalArgumentException(); - return parallelism; - } - - private static ForkJoinWorkerThreadFactory checkFactory - (ForkJoinWorkerThreadFactory factory) { - if (factory == null) - throw new NullPointerException(); - return factory; - } - - /** - * Creates a {@code ForkJoinPool} with the given parameters, without - * any security checks or parameter validation. Invoked directly by - * makeCommonPool. - */ - private ForkJoinPool(int parallelism, - ForkJoinWorkerThreadFactory factory, - UncaughtExceptionHandler handler, - int mode, - String workerNamePrefix) { - this.workerNamePrefix = workerNamePrefix; - this.factory = factory; - this.ueh = handler; - this.mode = (short)mode; - this.parallelism = (short)parallelism; - long np = (long)(-parallelism); // offset ctl counts - this.ctl = ((np << AC_SHIFT) & AC_MASK) | ((np << TC_SHIFT) & TC_MASK); - } - - /** - * Returns the common pool instance. This pool is statically - * constructed; its run state is unaffected by attempts to {@link - * #shutdown} or {@link #shutdownNow}. However this pool and any - * ongoing processing are automatically terminated upon program - * {@link System#exit}. Any program that relies on asynchronous - * task processing to complete before program termination should - * invoke {@code commonPool().}{@link #awaitQuiescence awaitQuiescence}, - * before exit. - * - * @return the common pool instance - * @since 1.8 - */ - public static ForkJoinPool commonPool() { - // assert common != null : "static init error"; - return common; - } - - // Execution methods - - /** - * Performs the given task, returning its result upon completion. - * If the computation encounters an unchecked Exception or Error, - * it is rethrown as the outcome of this invocation. Rethrown - * exceptions behave in the same way as regular exceptions, but, - * when possible, contain stack traces (as displayed for example - * using {@code ex.printStackTrace()}) of both the current thread - * as well as the thread actually encountering the exception; - * minimally only the latter. - * - * @param task the task - * @return the task's result - * @throws NullPointerException if the task is null - * @throws RejectedExecutionException if the task cannot be - * scheduled for execution - */ - public T invoke(ForkJoinTask task) { - if (task == null) - throw new NullPointerException(); - externalPush(task); - return task.join(); - } - - /** - * Arranges for (asynchronous) execution of the given task. - * - * @param task the task - * @throws NullPointerException if the task is null - * @throws RejectedExecutionException if the task cannot be - * scheduled for execution - */ - public void execute(ForkJoinTask task) { - if (task == null) - throw new NullPointerException(); - externalPush(task); - } - - // AbstractExecutorService methods - - /** - * @throws NullPointerException if the task is null - * @throws RejectedExecutionException if the task cannot be - * scheduled for execution - */ - public void execute(Runnable task) { - if (task == null) - throw new NullPointerException(); - ForkJoinTask job; - if (task instanceof ForkJoinTask) // avoid re-wrap - job = (ForkJoinTask) task; - else - job = new ForkJoinTask.RunnableExecuteAction(task); - externalPush(job); - } - - /** - * Submits a ForkJoinTask for execution. - * - * @param task the task to submit - * @return the task - * @throws NullPointerException if the task is null - * @throws RejectedExecutionException if the task cannot be - * scheduled for execution - */ - public ForkJoinTask submit(ForkJoinTask task) { - if (task == null) - throw new NullPointerException(); - externalPush(task); - return task; - } - - /** - * @throws NullPointerException if the task is null - * @throws RejectedExecutionException if the task cannot be - * scheduled for execution - */ - public ForkJoinTask submit(Callable task) { - ForkJoinTask job = new ForkJoinTask.AdaptedCallable(task); - externalPush(job); - return job; - } - - /** - * @throws NullPointerException if the task is null - * @throws RejectedExecutionException if the task cannot be - * scheduled for execution - */ - public ForkJoinTask submit(Runnable task, T result) { - ForkJoinTask job = new ForkJoinTask.AdaptedRunnable(task, result); - externalPush(job); - return job; - } - - /** - * @throws NullPointerException if the task is null - * @throws RejectedExecutionException if the task cannot be - * scheduled for execution - */ - public ForkJoinTask submit(Runnable task) { - if (task == null) - throw new NullPointerException(); - ForkJoinTask job; - if (task instanceof ForkJoinTask) // avoid re-wrap - job = (ForkJoinTask) task; - else - job = new ForkJoinTask.AdaptedRunnableAction(task); - externalPush(job); - return job; - } - - /** - * @throws NullPointerException {@inheritDoc} - * @throws RejectedExecutionException {@inheritDoc} - */ - public List> invokeAll(Collection> tasks) { - // In previous versions of this class, this method constructed - // a task to run ForkJoinTask.invokeAll, but now external - // invocation of multiple tasks is at least as efficient. - ArrayList> futures = new ArrayList>(tasks.size()); - - boolean done = false; - try { - for (Callable t : tasks) { - ForkJoinTask f = new ForkJoinTask.AdaptedCallable(t); - futures.add(f); - externalPush(f); - } - for (int i = 0, size = futures.size(); i < size; i++) - ((ForkJoinTask)futures.get(i)).quietlyJoin(); - done = true; - return futures; - } finally { - if (!done) - for (int i = 0, size = futures.size(); i < size; i++) - futures.get(i).cancel(false); - } - } - - /** - * Returns the factory used for constructing new workers. - * - * @return the factory used for constructing new workers - */ - public ForkJoinWorkerThreadFactory getFactory() { - return factory; - } - - /** - * Returns the handler for internal worker threads that terminate - * due to unrecoverable errors encountered while executing tasks. - * - * @return the handler, or {@code null} if none - */ - public UncaughtExceptionHandler getUncaughtExceptionHandler() { - return ueh; - } - - /** - * Returns the targeted parallelism level of this pool. - * - * @return the targeted parallelism level of this pool - */ - public int getParallelism() { - int par; - return ((par = parallelism) > 0) ? par : 1; - } - - /** - * Returns the targeted parallelism level of the common pool. - * - * @return the targeted parallelism level of the common pool - * @since 1.8 - */ - public static int getCommonPoolParallelism() { - return commonParallelism; - } - - /** - * Returns the number of worker threads that have started but not - * yet terminated. The result returned by this method may differ - * from {@link #getParallelism} when threads are created to - * maintain parallelism when others are cooperatively blocked. - * - * @return the number of worker threads - */ - public int getPoolSize() { - return parallelism + (short)(ctl >>> TC_SHIFT); - } - - /** - * Returns {@code true} if this pool uses local first-in-first-out - * scheduling mode for forked tasks that are never joined. - * - * @return {@code true} if this pool uses async mode - */ - public boolean getAsyncMode() { - return mode == FIFO_QUEUE; - } - - /** - * Returns an estimate of the number of worker threads that are - * not blocked waiting to join tasks or for other managed - * synchronization. This method may overestimate the - * number of running threads. - * - * @return the number of worker threads - */ - public int getRunningThreadCount() { - int rc = 0; - WorkQueue[] ws; WorkQueue w; - if ((ws = workQueues) != null) { - for (int i = 1; i < ws.length; i += 2) { - if ((w = ws[i]) != null && w.isApparentlyUnblocked()) - ++rc; - } - } - return rc; - } - - /** - * Returns an estimate of the number of threads that are currently - * stealing or executing tasks. This method may overestimate the - * number of active threads. - * - * @return the number of active threads - */ - public int getActiveThreadCount() { - int r = parallelism + (int)(ctl >> AC_SHIFT); - return (r <= 0) ? 0 : r; // suppress momentarily negative values - } - - /** - * Returns {@code true} if all worker threads are currently idle. - * An idle worker is one that cannot obtain a task to execute - * because none are available to steal from other threads, and - * there are no pending submissions to the pool. This method is - * conservative; it might not return {@code true} immediately upon - * idleness of all threads, but will eventually become true if - * threads remain inactive. - * - * @return {@code true} if all threads are currently idle - */ - public boolean isQuiescent() { - return parallelism + (int)(ctl >> AC_SHIFT) <= 0; - } - - /** - * Returns an estimate of the total number of tasks stolen from - * one thread's work queue by another. The reported value - * underestimates the actual total number of steals when the pool - * is not quiescent. This value may be useful for monitoring and - * tuning fork/join programs: in general, steal counts should be - * high enough to keep threads busy, but low enough to avoid - * overhead and contention across threads. - * - * @return the number of steals - */ - public long getStealCount() { - long count = stealCount; - WorkQueue[] ws; WorkQueue w; - if ((ws = workQueues) != null) { - for (int i = 1; i < ws.length; i += 2) { - if ((w = ws[i]) != null) - count += w.nsteals; - } - } - return count; - } - - /** - * Returns an estimate of the total number of tasks currently held - * in queues by worker threads (but not including tasks submitted - * to the pool that have not begun executing). This value is only - * an approximation, obtained by iterating across all threads in - * the pool. This method may be useful for tuning task - * granularities. - * - * @return the number of queued tasks - */ - public long getQueuedTaskCount() { - long count = 0; - WorkQueue[] ws; WorkQueue w; - if ((ws = workQueues) != null) { - for (int i = 1; i < ws.length; i += 2) { - if ((w = ws[i]) != null) - count += w.queueSize(); - } - } - return count; - } - - /** - * Returns an estimate of the number of tasks submitted to this - * pool that have not yet begun executing. This method may take - * time proportional to the number of submissions. - * - * @return the number of queued submissions - */ - public int getQueuedSubmissionCount() { - int count = 0; - WorkQueue[] ws; WorkQueue w; - if ((ws = workQueues) != null) { - for (int i = 0; i < ws.length; i += 2) { - if ((w = ws[i]) != null) - count += w.queueSize(); - } - } - return count; - } - - /** - * Returns {@code true} if there are any tasks submitted to this - * pool that have not yet begun executing. - * - * @return {@code true} if there are any queued submissions - */ - public boolean hasQueuedSubmissions() { - WorkQueue[] ws; WorkQueue w; - if ((ws = workQueues) != null) { - for (int i = 0; i < ws.length; i += 2) { - if ((w = ws[i]) != null && !w.isEmpty()) - return true; - } - } - return false; - } - - /** - * Removes and returns the next unexecuted submission if one is - * available. This method may be useful in extensions to this - * class that re-assign work in systems with multiple pools. - * - * @return the next submission, or {@code null} if none - */ - protected ForkJoinTask pollSubmission() { - WorkQueue[] ws; WorkQueue w; ForkJoinTask t; - if ((ws = workQueues) != null) { - for (int i = 0; i < ws.length; i += 2) { - if ((w = ws[i]) != null && (t = w.poll()) != null) - return t; - } - } - return null; - } - - /** - * Removes all available unexecuted submitted and forked tasks - * from scheduling queues and adds them to the given collection, - * without altering their execution status. These may include - * artificially generated or wrapped tasks. This method is - * designed to be invoked only when the pool is known to be - * quiescent. Invocations at other times may not remove all - * tasks. A failure encountered while attempting to add elements - * to collection {@code c} may result in elements being in - * neither, either or both collections when the associated - * exception is thrown. The behavior of this operation is - * undefined if the specified collection is modified while the - * operation is in progress. - * - * @param c the collection to transfer elements into - * @return the number of elements transferred - */ - protected int drainTasksTo(Collection> c) { - int count = 0; - WorkQueue[] ws; WorkQueue w; ForkJoinTask t; - if ((ws = workQueues) != null) { - for (int i = 0; i < ws.length; ++i) { - if ((w = ws[i]) != null) { - while ((t = w.poll()) != null) { - c.add(t); - ++count; - } - } - } - } - return count; - } - - /** - * Returns a string identifying this pool, as well as its state, - * including indications of run state, parallelism level, and - * worker and task counts. - * - * @return a string identifying this pool, as well as its state - */ - public String toString() { - // Use a single pass through workQueues to collect counts - long qt = 0L, qs = 0L; int rc = 0; - long st = stealCount; - long c = ctl; - WorkQueue[] ws; WorkQueue w; - if ((ws = workQueues) != null) { - for (int i = 0; i < ws.length; ++i) { - if ((w = ws[i]) != null) { - int size = w.queueSize(); - if ((i & 1) == 0) - qs += size; - else { - qt += size; - st += w.nsteals; - if (w.isApparentlyUnblocked()) - ++rc; - } - } - } - } - int pc = parallelism; - int tc = pc + (short)(c >>> TC_SHIFT); - int ac = pc + (int)(c >> AC_SHIFT); - if (ac < 0) // ignore transient negative - ac = 0; - String level; - if ((c & STOP_BIT) != 0) - level = (tc == 0) ? "Terminated" : "Terminating"; - else - level = plock < 0 ? "Shutting down" : "Running"; - return super.toString() + - "[" + level + - ", parallelism = " + pc + - ", size = " + tc + - ", active = " + ac + - ", running = " + rc + - ", steals = " + st + - ", tasks = " + qt + - ", submissions = " + qs + - "]"; - } - - /** - * Possibly initiates an orderly shutdown in which previously - * submitted tasks are executed, but no new tasks will be - * accepted. Invocation has no effect on execution state if this - * is the {@link #commonPool()}, and no additional effect if - * already shut down. Tasks that are in the process of being - * submitted concurrently during the course of this method may or - * may not be rejected. - * - * @throws SecurityException if a security manager exists and - * the caller is not permitted to modify threads - * because it does not hold {@link - * java.lang.RuntimePermission}{@code ("modifyThread")} - */ - public void shutdown() { - checkPermission(); - tryTerminate(false, true); - } - - /** - * Possibly attempts to cancel and/or stop all tasks, and reject - * all subsequently submitted tasks. Invocation has no effect on - * execution state if this is the {@link #commonPool()}, and no - * additional effect if already shut down. Otherwise, tasks that - * are in the process of being submitted or executed concurrently - * during the course of this method may or may not be - * rejected. This method cancels both existing and unexecuted - * tasks, in order to permit termination in the presence of task - * dependencies. So the method always returns an empty list - * (unlike the case for some other Executors). - * - * @return an empty list - * @throws SecurityException if a security manager exists and - * the caller is not permitted to modify threads - * because it does not hold {@link - * java.lang.RuntimePermission}{@code ("modifyThread")} - */ - public List shutdownNow() { - checkPermission(); - tryTerminate(true, true); - return Collections.emptyList(); - } - - /** - * Returns {@code true} if all tasks have completed following shut down. - * - * @return {@code true} if all tasks have completed following shut down - */ - public boolean isTerminated() { - long c = ctl; - return ((c & STOP_BIT) != 0L && - (short)(c >>> TC_SHIFT) + parallelism <= 0); - } - - /** - * Returns {@code true} if the process of termination has - * commenced but not yet completed. This method may be useful for - * debugging. A return of {@code true} reported a sufficient - * period after shutdown may indicate that submitted tasks have - * ignored or suppressed interruption, or are waiting for I/O, - * causing this executor not to properly terminate. (See the - * advisory notes for class {@link ForkJoinTask} stating that - * tasks should not normally entail blocking operations. But if - * they do, they must abort them on interrupt.) - * - * @return {@code true} if terminating but not yet terminated - */ - public boolean isTerminating() { - long c = ctl; - return ((c & STOP_BIT) != 0L && - (short)(c >>> TC_SHIFT) + parallelism > 0); - } - - /** - * Returns {@code true} if this pool has been shut down. - * - * @return {@code true} if this pool has been shut down - */ - public boolean isShutdown() { - return plock < 0; - } - - /** - * Blocks until all tasks have completed execution after a - * shutdown request, or the timeout occurs, or the current thread - * is interrupted, whichever happens first. Because the {@link - * #commonPool()} never terminates until program shutdown, when - * applied to the common pool, this method is equivalent to {@link - * #awaitQuiescence(long, TimeUnit)} but always returns {@code false}. - * - * @param timeout the maximum time to wait - * @param unit the time unit of the timeout argument - * @return {@code true} if this executor terminated and - * {@code false} if the timeout elapsed before termination - * @throws InterruptedException if interrupted while waiting - */ - public boolean awaitTermination(long timeout, TimeUnit unit) - throws InterruptedException { - if (Thread.interrupted()) - throw new InterruptedException(); - if (this == common) { - awaitQuiescence(timeout, unit); - return false; - } - long nanos = unit.toNanos(timeout); - if (isTerminated()) - return true; - if (nanos <= 0L) - return false; - long deadline = System.nanoTime() + nanos; - synchronized (this) { - for (;;) { - if (isTerminated()) - return true; - if (nanos <= 0L) - return false; - long millis = TimeUnit.NANOSECONDS.toMillis(nanos); - wait(millis > 0L ? millis : 1L); - nanos = deadline - System.nanoTime(); - } - } - } - - /** - * If called by a ForkJoinTask operating in this pool, equivalent - * in effect to {@link ForkJoinTask#helpQuiesce}. Otherwise, - * waits and/or attempts to assist performing tasks until this - * pool {@link #isQuiescent} or the indicated timeout elapses. - * - * @param timeout the maximum time to wait - * @param unit the time unit of the timeout argument - * @return {@code true} if quiescent; {@code false} if the - * timeout elapsed. - */ - public boolean awaitQuiescence(long timeout, TimeUnit unit) { - long nanos = unit.toNanos(timeout); - ForkJoinWorkerThread wt; - Thread thread = Thread.currentThread(); - if ((thread instanceof ForkJoinWorkerThread) && - (wt = (ForkJoinWorkerThread)thread).pool == this) { - helpQuiescePool(wt.workQueue); - return true; - } - long startTime = System.nanoTime(); - WorkQueue[] ws; - int r = 0, m; - boolean found = true; - while (!isQuiescent() && (ws = workQueues) != null && - (m = ws.length - 1) >= 0) { - if (!found) { - if ((System.nanoTime() - startTime) > nanos) - return false; - Thread.yield(); // cannot block - } - found = false; - for (int j = (m + 1) << 2; j >= 0; --j) { - ForkJoinTask t; WorkQueue q; int b; - if ((q = ws[r++ & m]) != null && (b = q.base) - q.top < 0) { - found = true; - if ((t = q.pollAt(b)) != null) - t.doExec(); - break; - } - } - } - return true; - } - - /** - * Waits and/or attempts to assist performing tasks indefinitely - * until the {@link #commonPool()} {@link #isQuiescent}. - */ - static void quiesceCommonPool() { - common.awaitQuiescence(Long.MAX_VALUE, TimeUnit.NANOSECONDS); - } - - /** - * Interface for extending managed parallelism for tasks running - * in {@link ForkJoinPool}s. - * - *

A {@code ManagedBlocker} provides two methods. Method - * {@code isReleasable} must return {@code true} if blocking is - * not necessary. Method {@code block} blocks the current thread - * if necessary (perhaps internally invoking {@code isReleasable} - * before actually blocking). These actions are performed by any - * thread invoking {@link ForkJoinPool#managedBlock(ManagedBlocker)}. - * The unusual methods in this API accommodate synchronizers that - * may, but don't usually, block for long periods. Similarly, they - * allow more efficient internal handling of cases in which - * additional workers may be, but usually are not, needed to - * ensure sufficient parallelism. Toward this end, - * implementations of method {@code isReleasable} must be amenable - * to repeated invocation. - * - *

For example, here is a ManagedBlocker based on a - * ReentrantLock: - *

 {@code
-     * class ManagedLocker implements ManagedBlocker {
-     *   final ReentrantLock lock;
-     *   boolean hasLock = false;
-     *   ManagedLocker(ReentrantLock lock) { this.lock = lock; }
-     *   public boolean block() {
-     *     if (!hasLock)
-     *       lock.lock();
-     *     return true;
-     *   }
-     *   public boolean isReleasable() {
-     *     return hasLock || (hasLock = lock.tryLock());
-     *   }
-     * }}
- * - *

Here is a class that possibly blocks waiting for an - * item on a given queue: - *

 {@code
-     * class QueueTaker implements ManagedBlocker {
-     *   final BlockingQueue queue;
-     *   volatile E item = null;
-     *   QueueTaker(BlockingQueue q) { this.queue = q; }
-     *   public boolean block() throws InterruptedException {
-     *     if (item == null)
-     *       item = queue.take();
-     *     return true;
-     *   }
-     *   public boolean isReleasable() {
-     *     return item != null || (item = queue.poll()) != null;
-     *   }
-     *   public E getItem() { // call after pool.managedBlock completes
-     *     return item;
-     *   }
-     * }}
- */ - public static interface ManagedBlocker { - /** - * Possibly blocks the current thread, for example waiting for - * a lock or condition. - * - * @return {@code true} if no additional blocking is necessary - * (i.e., if isReleasable would return true) - * @throws InterruptedException if interrupted while waiting - * (the method is not required to do so, but is allowed to) - */ - boolean block() throws InterruptedException; - - /** - * Returns {@code true} if blocking is unnecessary. - * @return {@code true} if blocking is unnecessary - */ - boolean isReleasable(); - } - - /** - * Blocks in accord with the given blocker. If the current thread - * is a {@link ForkJoinWorkerThread}, this method possibly - * arranges for a spare thread to be activated if necessary to - * ensure sufficient parallelism while the current thread is blocked. - * - *

If the caller is not a {@link ForkJoinTask}, this method is - * behaviorally equivalent to - *

 {@code
-     * while (!blocker.isReleasable())
-     *   if (blocker.block())
-     *     return;
-     * }
- * - * If the caller is a {@code ForkJoinTask}, then the pool may - * first be expanded to ensure parallelism, and later adjusted. - * - * @param blocker the blocker - * @throws InterruptedException if blocker.block did so - */ - public static void managedBlock(ManagedBlocker blocker) - throws InterruptedException { - Thread t = Thread.currentThread(); - if (t instanceof ForkJoinWorkerThread) { - ForkJoinPool p = ((ForkJoinWorkerThread)t).pool; - while (!blocker.isReleasable()) { - if (p.tryCompensate(p.ctl)) { - try { - do {} while (!blocker.isReleasable() && - !blocker.block()); - } finally { - p.incrementActiveCount(); - } - break; - } - } - } - else { - do {} while (!blocker.isReleasable() && - !blocker.block()); - } - } - - // AbstractExecutorService overrides. These rely on undocumented - // fact that ForkJoinTask.adapt returns ForkJoinTasks that also - // implement RunnableFuture. - - protected RunnableFuture newTaskFor(Runnable runnable, T value) { - return new ForkJoinTask.AdaptedRunnable(runnable, value); - } - - protected RunnableFuture newTaskFor(Callable callable) { - return new ForkJoinTask.AdaptedCallable(callable); - } - - // Unsafe mechanics - private static final sun.misc.Unsafe U; - private static final long CTL; - private static final long PARKBLOCKER; - private static final int ABASE; - private static final int ASHIFT; - private static final long STEALCOUNT; - private static final long PLOCK; - private static final long INDEXSEED; - private static final long QBASE; - private static final long QLOCK; - - static { - // initialize field offsets for CAS etc - try { - U = getUnsafe(); - Class k = ForkJoinPool.class; - CTL = U.objectFieldOffset - (k.getDeclaredField("ctl")); - STEALCOUNT = U.objectFieldOffset - (k.getDeclaredField("stealCount")); - PLOCK = U.objectFieldOffset - (k.getDeclaredField("plock")); - INDEXSEED = U.objectFieldOffset - (k.getDeclaredField("indexSeed")); - Class tk = Thread.class; - PARKBLOCKER = U.objectFieldOffset - (tk.getDeclaredField("parkBlocker")); - Class wk = WorkQueue.class; - QBASE = U.objectFieldOffset - (wk.getDeclaredField("base")); - QLOCK = U.objectFieldOffset - (wk.getDeclaredField("qlock")); - Class ak = ForkJoinTask[].class; - ABASE = U.arrayBaseOffset(ak); - int scale = U.arrayIndexScale(ak); - if ((scale & (scale - 1)) != 0) - throw new Error("data type scale not a power of two"); - ASHIFT = 31 - Integer.numberOfLeadingZeros(scale); - } catch (Exception e) { - throw new Error(e); - } - - submitters = new ThreadLocal(); - defaultForkJoinWorkerThreadFactory = - new DefaultForkJoinWorkerThreadFactory(); - modifyThreadPermission = new RuntimePermission("modifyThread"); - - common = java.security.AccessController.doPrivileged - (new java.security.PrivilegedAction() { - public ForkJoinPool run() { return makeCommonPool(); }}); - int par = common.parallelism; // report 1 even if threads disabled - commonParallelism = par > 0 ? par : 1; - } - - /** - * Creates and returns the common pool, respecting user settings - * specified via system properties. - */ - private static ForkJoinPool makeCommonPool() { - int parallelism = -1; - ForkJoinWorkerThreadFactory factory - = defaultForkJoinWorkerThreadFactory; - UncaughtExceptionHandler handler = null; - try { // ignore exceptions in accessing/parsing properties - String pp = System.getProperty - ("java.util.concurrent.ForkJoinPool.common.parallelism"); - String fp = System.getProperty - ("java.util.concurrent.ForkJoinPool.common.threadFactory"); - String hp = System.getProperty - ("java.util.concurrent.ForkJoinPool.common.exceptionHandler"); - if (pp != null) - parallelism = Integer.parseInt(pp); - if (fp != null) - factory = ((ForkJoinWorkerThreadFactory)ClassLoader. - getSystemClassLoader().loadClass(fp).newInstance()); - if (hp != null) - handler = ((UncaughtExceptionHandler)ClassLoader. - getSystemClassLoader().loadClass(hp).newInstance()); - } catch (Exception ignore) { - } - - if (parallelism < 0 && // default 1 less than #cores - (parallelism = Runtime.getRuntime().availableProcessors() - 1) < 0) - parallelism = 0; - if (parallelism > MAX_CAP) - parallelism = MAX_CAP; - return new ForkJoinPool(parallelism, factory, handler, LIFO_QUEUE, - "ForkJoinPool.commonPool-worker-"); - } - - /** - * Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package. - * Replace with a simple call to Unsafe.getUnsafe when integrating - * into a jdk. - * - * @return a sun.misc.Unsafe - */ - private static sun.misc.Unsafe getUnsafe() { - try { - return sun.misc.Unsafe.getUnsafe(); - } catch (SecurityException tryReflectionInstead) {} - try { - return java.security.AccessController.doPrivileged - (new java.security.PrivilegedExceptionAction() { - public sun.misc.Unsafe run() throws Exception { - Class k = sun.misc.Unsafe.class; - for (java.lang.reflect.Field f : k.getDeclaredFields()) { - f.setAccessible(true); - Object x = f.get(null); - if (k.isInstance(x)) - return k.cast(x); - } - throw new NoSuchFieldError("the Unsafe"); - }}); - } catch (java.security.PrivilegedActionException e) { - throw new RuntimeException("Could not initialize intrinsics", - e.getCause()); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/chmv8/ForkJoinTask.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/chmv8/ForkJoinTask.java deleted file mode 100755 index af21ddcf0d..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/chmv8/ForkJoinTask.java +++ /dev/null @@ -1,1560 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/* - * Written by Doug Lea with assistance from members of JCP JSR-166 - * Expert Group and released to the public domain, as explained at - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -package com.ai.cloud.io.netty.util.internal.chmv8; - -import java.io.Serializable; -import java.lang.ref.ReferenceQueue; -import java.lang.ref.WeakReference; -import java.lang.reflect.Constructor; -import java.util.Collection; -import java.util.List; -import java.util.RandomAccess; -import java.util.concurrent.Callable; -import java.util.concurrent.CancellationException; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.Phaser; -import java.util.concurrent.RecursiveAction; -import java.util.concurrent.RecursiveTask; -import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.RunnableFuture; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.concurrent.locks.ReentrantLock; - -/** - * Abstract base class for tasks that run within a {@link ForkJoinPool}. - * A {@code ForkJoinTask} is a thread-like entity that is much - * lighter weight than a normal thread. Huge numbers of tasks and - * subtasks may be hosted by a small number of actual threads in a - * ForkJoinPool, at the price of some usage limitations. - * - *

A "main" {@code ForkJoinTask} begins execution when it is - * explicitly submitted to a {@link ForkJoinPool}, or, if not already - * engaged in a ForkJoin computation, commenced in the {@link - * ForkJoinPool#commonPool()} via {@link #fork}, {@link #invoke}, or - * related methods. Once started, it will usually in turn start other - * subtasks. As indicated by the name of this class, many programs - * using {@code ForkJoinTask} employ only methods {@link #fork} and - * {@link #join}, or derivatives such as {@link - * #invokeAll(ForkJoinTask...) invokeAll}. However, this class also - * provides a number of other methods that can come into play in - * advanced usages, as well as extension mechanics that allow support - * of new forms of fork/join processing. - * - *

A {@code ForkJoinTask} is a lightweight form of {@link Future}. - * The efficiency of {@code ForkJoinTask}s stems from a set of - * restrictions (that are only partially statically enforceable) - * reflecting their main use as computational tasks calculating pure - * functions or operating on purely isolated objects. The primary - * coordination mechanisms are {@link #fork}, that arranges - * asynchronous execution, and {@link #join}, that doesn't proceed - * until the task's result has been computed. Computations should - * ideally avoid {@code synchronized} methods or blocks, and should - * minimize other blocking synchronization apart from joining other - * tasks or using synchronizers such as Phasers that are advertised to - * cooperate with fork/join scheduling. Subdividable tasks should also - * not perform blocking I/O, and should ideally access variables that - * are completely independent of those accessed by other running - * tasks. These guidelines are loosely enforced by not permitting - * checked exceptions such as {@code IOExceptions} to be - * thrown. However, computations may still encounter unchecked - * exceptions, that are rethrown to callers attempting to join - * them. These exceptions may additionally include {@link - * RejectedExecutionException} stemming from internal resource - * exhaustion, such as failure to allocate internal task - * queues. Rethrown exceptions behave in the same way as regular - * exceptions, but, when possible, contain stack traces (as displayed - * for example using {@code ex.printStackTrace()}) of both the thread - * that initiated the computation as well as the thread actually - * encountering the exception; minimally only the latter. - * - *

It is possible to define and use ForkJoinTasks that may block, - * but doing do requires three further considerations: (1) Completion - * of few if any other tasks should be dependent on a task - * that blocks on external synchronization or I/O. Event-style async - * tasks that are never joined (for example, those subclassing {@link - * CountedCompleter}) often fall into this category. (2) To minimize - * resource impact, tasks should be small; ideally performing only the - * (possibly) blocking action. (3) Unless the {@link - * ForkJoinPool.ManagedBlocker} API is used, or the number of possibly - * blocked tasks is known to be less than the pool's {@link - * ForkJoinPool#getParallelism} level, the pool cannot guarantee that - * enough threads will be available to ensure progress or good - * performance. - * - *

The primary method for awaiting completion and extracting - * results of a task is {@link #join}, but there are several variants: - * The {@link Future#get} methods support interruptible and/or timed - * waits for completion and report results using {@code Future} - * conventions. Method {@link #invoke} is semantically - * equivalent to {@code fork(); join()} but always attempts to begin - * execution in the current thread. The "quiet" forms of - * these methods do not extract results or report exceptions. These - * may be useful when a set of tasks are being executed, and you need - * to delay processing of results or exceptions until all complete. - * Method {@code invokeAll} (available in multiple versions) - * performs the most common form of parallel invocation: forking a set - * of tasks and joining them all. - * - *

In the most typical usages, a fork-join pair act like a call - * (fork) and return (join) from a parallel recursive function. As is - * the case with other forms of recursive calls, returns (joins) - * should be performed innermost-first. For example, {@code a.fork(); - * b.fork(); b.join(); a.join();} is likely to be substantially more - * efficient than joining {@code a} before {@code b}. - * - *

The execution status of tasks may be queried at several levels - * of detail: {@link #isDone} is true if a task completed in any way - * (including the case where a task was cancelled without executing); - * {@link #isCompletedNormally} is true if a task completed without - * cancellation or encountering an exception; {@link #isCancelled} is - * true if the task was cancelled (in which case {@link #getException} - * returns a {@link java.util.concurrent.CancellationException}); and - * {@link #isCompletedAbnormally} is true if a task was either - * cancelled or encountered an exception, in which case {@link - * #getException} will return either the encountered exception or - * {@link java.util.concurrent.CancellationException}. - * - *

The ForkJoinTask class is not usually directly subclassed. - * Instead, you subclass one of the abstract classes that support a - * particular style of fork/join processing, typically {@link - * RecursiveAction} for most computations that do not return results, - * {@link RecursiveTask} for those that do, and {@link - * CountedCompleter} for those in which completed actions trigger - * other actions. Normally, a concrete ForkJoinTask subclass declares - * fields comprising its parameters, established in a constructor, and - * then defines a {@code compute} method that somehow uses the control - * methods supplied by this base class. - * - *

Method {@link #join} and its variants are appropriate for use - * only when completion dependencies are acyclic; that is, the - * parallel computation can be described as a directed acyclic graph - * (DAG). Otherwise, executions may encounter a form of deadlock as - * tasks cyclically wait for each other. However, this framework - * supports other methods and techniques (for example the use of - * {@link Phaser}, {@link #helpQuiesce}, and {@link #complete}) that - * may be of use in constructing custom subclasses for problems that - * are not statically structured as DAGs. To support such usages, a - * ForkJoinTask may be atomically tagged with a {@code short} - * value using {@link #setForkJoinTaskTag} or {@link - * #compareAndSetForkJoinTaskTag} and checked using {@link - * #getForkJoinTaskTag}. The ForkJoinTask implementation does not use - * these {@code protected} methods or tags for any purpose, but they - * may be of use in the construction of specialized subclasses. For - * example, parallel graph traversals can use the supplied methods to - * avoid revisiting nodes/tasks that have already been processed. - * (Method names for tagging are bulky in part to encourage definition - * of methods that reflect their usage patterns.) - * - *

Most base support methods are {@code final}, to prevent - * overriding of implementations that are intrinsically tied to the - * underlying lightweight task scheduling framework. Developers - * creating new basic styles of fork/join processing should minimally - * implement {@code protected} methods {@link #exec}, {@link - * #setRawResult}, and {@link #getRawResult}, while also introducing - * an abstract computational method that can be implemented in its - * subclasses, possibly relying on other {@code protected} methods - * provided by this class. - * - *

ForkJoinTasks should perform relatively small amounts of - * computation. Large tasks should be split into smaller subtasks, - * usually via recursive decomposition. As a very rough rule of thumb, - * a task should perform more than 100 and less than 10000 basic - * computational steps, and should avoid indefinite looping. If tasks - * are too big, then parallelism cannot improve throughput. If too - * small, then memory and internal task maintenance overhead may - * overwhelm processing. - * - *

This class provides {@code adapt} methods for {@link Runnable} - * and {@link Callable}, that may be of use when mixing execution of - * {@code ForkJoinTasks} with other kinds of tasks. When all tasks are - * of this form, consider using a pool constructed in asyncMode. - * - *

ForkJoinTasks are {@code Serializable}, which enables them to be - * used in extensions such as remote execution frameworks. It is - * sensible to serialize tasks only before or after, but not during, - * execution. Serialization is not relied on during execution itself. - * - * @since 1.7 - * @author Doug Lea - */ -@SuppressWarnings("all") -public abstract class ForkJoinTask implements Future, Serializable { - - /* - * See the internal documentation of class ForkJoinPool for a - * general implementation overview. ForkJoinTasks are mainly - * responsible for maintaining their "status" field amidst relays - * to methods in ForkJoinWorkerThread and ForkJoinPool. - * - * The methods of this class are more-or-less layered into - * (1) basic status maintenance - * (2) execution and awaiting completion - * (3) user-level methods that additionally report results. - * This is sometimes hard to see because this file orders exported - * methods in a way that flows well in javadocs. - */ - - /* - * The status field holds run control status bits packed into a - * single int to minimize footprint and to ensure atomicity (via - * CAS). Status is initially zero, and takes on nonnegative - * values until completed, upon which status (anded with - * DONE_MASK) holds value NORMAL, CANCELLED, or EXCEPTIONAL. Tasks - * undergoing blocking waits by other threads have the SIGNAL bit - * set. Completion of a stolen task with SIGNAL set awakens any - * waiters via notifyAll. Even though suboptimal for some - * purposes, we use basic builtin wait/notify to take advantage of - * "monitor inflation" in JVMs that we would otherwise need to - * emulate to avoid adding further per-task bookkeeping overhead. - * We want these monitors to be "fat", i.e., not use biasing or - * thin-lock techniques, so use some odd coding idioms that tend - * to avoid them, mainly by arranging that every synchronized - * block performs a wait, notifyAll or both. - * - * These control bits occupy only (some of) the upper half (16 - * bits) of status field. The lower bits are used for user-defined - * tags. - */ - - /** The run status of this task */ - volatile int status; // accessed directly by pool and workers - static final int DONE_MASK = 0xf0000000; // mask out non-completion bits - static final int NORMAL = 0xf0000000; // must be negative - static final int CANCELLED = 0xc0000000; // must be < NORMAL - static final int EXCEPTIONAL = 0x80000000; // must be < CANCELLED - static final int SIGNAL = 0x00010000; // must be >= 1 << 16 - static final int SMASK = 0x0000ffff; // short bits for tags - - /** - * Marks completion and wakes up threads waiting to join this - * task. - * - * @param completion one of NORMAL, CANCELLED, EXCEPTIONAL - * @return completion status on exit - */ - private int setCompletion(int completion) { - for (int s;;) { - if ((s = status) < 0) - return s; - if (U.compareAndSwapInt(this, STATUS, s, s | completion)) { - if ((s >>> 16) != 0) - synchronized (this) { notifyAll(); } - return completion; - } - } - } - - /** - * Primary execution method for stolen tasks. Unless done, calls - * exec and records status if completed, but doesn't wait for - * completion otherwise. - * - * @return status on exit from this method - */ - final int doExec() { - int s; boolean completed; - if ((s = status) >= 0) { - try { - completed = exec(); - } catch (Throwable rex) { - return setExceptionalCompletion(rex); - } - if (completed) - s = setCompletion(NORMAL); - } - return s; - } - - /** - * Tries to set SIGNAL status unless already completed. Used by - * ForkJoinPool. Other variants are directly incorporated into - * externalAwaitDone etc. - * - * @return true if successful - */ - final boolean trySetSignal() { - int s = status; - return s >= 0 && U.compareAndSwapInt(this, STATUS, s, s | SIGNAL); - } - - /** - * Blocks a non-worker-thread until completion. - * @return status upon completion - */ - private int externalAwaitDone() { - int s; - ForkJoinPool cp = ForkJoinPool.common; - if ((s = status) >= 0) { - if (cp != null) { - if (this instanceof CountedCompleter) - s = cp.externalHelpComplete((CountedCompleter)this); - else if (cp.tryExternalUnpush(this)) - s = doExec(); - } - if (s >= 0 && (s = status) >= 0) { - boolean interrupted = false; - do { - if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) { - synchronized (this) { - if (status >= 0) { - try { - wait(); - } catch (InterruptedException ie) { - interrupted = true; - } - } - else - notifyAll(); - } - } - } while ((s = status) >= 0); - if (interrupted) - Thread.currentThread().interrupt(); - } - } - return s; - } - - /** - * Blocks a non-worker-thread until completion or interruption. - */ - private int externalInterruptibleAwaitDone() throws InterruptedException { - int s; - ForkJoinPool cp = ForkJoinPool.common; - if (Thread.interrupted()) - throw new InterruptedException(); - if ((s = status) >= 0 && cp != null) { - if (this instanceof CountedCompleter) - cp.externalHelpComplete((CountedCompleter)this); - else if (cp.tryExternalUnpush(this)) - doExec(); - } - while ((s = status) >= 0) { - if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) { - synchronized (this) { - if (status >= 0) - wait(); - else - notifyAll(); - } - } - } - return s; - } - - - /** - * Implementation for join, get, quietlyJoin. Directly handles - * only cases of already-completed, external wait, and - * unfork+exec. Others are relayed to ForkJoinPool.awaitJoin. - * - * @return status upon completion - */ - private int doJoin() { - int s; Thread t; ForkJoinWorkerThread wt; ForkJoinPool.WorkQueue w; - return (s = status) < 0 ? s : - ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ? - (w = (wt = (ForkJoinWorkerThread)t).workQueue). - tryUnpush(this) && (s = doExec()) < 0 ? s : - wt.pool.awaitJoin(w, this) : - externalAwaitDone(); - } - - /** - * Implementation for invoke, quietlyInvoke. - * - * @return status upon completion - */ - private int doInvoke() { - int s; Thread t; ForkJoinWorkerThread wt; - return (s = doExec()) < 0 ? s : - ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ? - (wt = (ForkJoinWorkerThread)t).pool.awaitJoin(wt.workQueue, this) : - externalAwaitDone(); - } - - // Exception table support - - /** - * Table of exceptions thrown by tasks, to enable reporting by - * callers. Because exceptions are rare, we don't directly keep - * them with task objects, but instead use a weak ref table. Note - * that cancellation exceptions don't appear in the table, but are - * instead recorded as status values. - * - * Note: These statics are initialized below in static block. - */ - private static final ExceptionNode[] exceptionTable; - private static final ReentrantLock exceptionTableLock; - private static final ReferenceQueue exceptionTableRefQueue; - - /** - * Fixed capacity for exceptionTable. - */ - private static final int EXCEPTION_MAP_CAPACITY = 32; - - /** - * Key-value nodes for exception table. The chained hash table - * uses identity comparisons, full locking, and weak references - * for keys. The table has a fixed capacity because it only - * maintains task exceptions long enough for joiners to access - * them, so should never become very large for sustained - * periods. However, since we do not know when the last joiner - * completes, we must use weak references and expunge them. We do - * so on each operation (hence full locking). Also, some thread in - * any ForkJoinPool will call helpExpungeStaleExceptions when its - * pool becomes isQuiescent. - */ - static final class ExceptionNode extends WeakReference> { - final Throwable ex; - ExceptionNode next; - final long thrower; // use id not ref to avoid weak cycles - ExceptionNode(ForkJoinTask task, Throwable ex, ExceptionNode next) { - super(task, exceptionTableRefQueue); - this.ex = ex; - this.next = next; - this.thrower = Thread.currentThread().getId(); - } - } - - /** - * Records exception and sets status. - * - * @return status on exit - */ - final int recordExceptionalCompletion(Throwable ex) { - int s; - if ((s = status) >= 0) { - int h = System.identityHashCode(this); - final ReentrantLock lock = exceptionTableLock; - lock.lock(); - try { - expungeStaleExceptions(); - ExceptionNode[] t = exceptionTable; - int i = h & (t.length - 1); - for (ExceptionNode e = t[i]; ; e = e.next) { - if (e == null) { - t[i] = new ExceptionNode(this, ex, t[i]); - break; - } - if (e.get() == this) // already present - break; - } - } finally { - lock.unlock(); - } - s = setCompletion(EXCEPTIONAL); - } - return s; - } - - /** - * Records exception and possibly propagates. - * - * @return status on exit - */ - private int setExceptionalCompletion(Throwable ex) { - int s = recordExceptionalCompletion(ex); - if ((s & DONE_MASK) == EXCEPTIONAL) - internalPropagateException(ex); - return s; - } - - /** - * Hook for exception propagation support for tasks with completers. - */ - void internalPropagateException(Throwable ex) { - } - - /** - * Cancels, ignoring any exceptions thrown by cancel. Used during - * worker and pool shutdown. Cancel is spec'ed not to throw any - * exceptions, but if it does anyway, we have no recourse during - * shutdown, so guard against this case. - */ - static final void cancelIgnoringExceptions(ForkJoinTask t) { - if (t != null && t.status >= 0) { - try { - t.cancel(false); - } catch (Throwable ignore) { - } - } - } - - /** - * Removes exception node and clears status. - */ - private void clearExceptionalCompletion() { - int h = System.identityHashCode(this); - final ReentrantLock lock = exceptionTableLock; - lock.lock(); - try { - ExceptionNode[] t = exceptionTable; - int i = h & (t.length - 1); - ExceptionNode e = t[i]; - ExceptionNode pred = null; - while (e != null) { - ExceptionNode next = e.next; - if (e.get() == this) { - if (pred == null) - t[i] = next; - else - pred.next = next; - break; - } - pred = e; - e = next; - } - expungeStaleExceptions(); - status = 0; - } finally { - lock.unlock(); - } - } - - /** - * Returns a rethrowable exception for the given task, if - * available. To provide accurate stack traces, if the exception - * was not thrown by the current thread, we try to create a new - * exception of the same type as the one thrown, but with the - * recorded exception as its cause. If there is no such - * constructor, we instead try to use a no-arg constructor, - * followed by initCause, to the same effect. If none of these - * apply, or any fail due to other exceptions, we return the - * recorded exception, which is still correct, although it may - * contain a misleading stack trace. - * - * @return the exception, or null if none - */ - private Throwable getThrowableException() { - if ((status & DONE_MASK) != EXCEPTIONAL) - return null; - int h = System.identityHashCode(this); - ExceptionNode e; - final ReentrantLock lock = exceptionTableLock; - lock.lock(); - try { - expungeStaleExceptions(); - ExceptionNode[] t = exceptionTable; - e = t[h & (t.length - 1)]; - while (e != null && e.get() != this) - e = e.next; - } finally { - lock.unlock(); - } - Throwable ex; - if (e == null || (ex = e.ex) == null) - return null; - if (false && e.thrower != Thread.currentThread().getId()) { - Class ec = ex.getClass(); - try { - Constructor noArgCtor = null; - Constructor[] cs = ec.getConstructors();// public ctors only - for (int i = 0; i < cs.length; ++i) { - Constructor c = cs[i]; - Class[] ps = c.getParameterTypes(); - if (ps.length == 0) - noArgCtor = c; - else if (ps.length == 1 && ps[0] == Throwable.class) - return (Throwable)(c.newInstance(ex)); - } - if (noArgCtor != null) { - Throwable wx = (Throwable)(noArgCtor.newInstance()); - wx.initCause(ex); - return wx; - } - } catch (Exception ignore) { - } - } - return ex; - } - - /** - * Poll stale refs and remove them. Call only while holding lock. - */ - private static void expungeStaleExceptions() { - for (Object x; (x = exceptionTableRefQueue.poll()) != null;) { - if (x instanceof ExceptionNode) { - ForkJoinTask key = ((ExceptionNode)x).get(); - ExceptionNode[] t = exceptionTable; - int i = System.identityHashCode(key) & (t.length - 1); - ExceptionNode e = t[i]; - ExceptionNode pred = null; - while (e != null) { - ExceptionNode next = e.next; - if (e == x) { - if (pred == null) - t[i] = next; - else - pred.next = next; - break; - } - pred = e; - e = next; - } - } - } - } - - /** - * If lock is available, poll stale refs and remove them. - * Called from ForkJoinPool when pools become quiescent. - */ - static final void helpExpungeStaleExceptions() { - final ReentrantLock lock = exceptionTableLock; - if (lock.tryLock()) { - try { - expungeStaleExceptions(); - } finally { - lock.unlock(); - } - } - } - - /** - * A version of "sneaky throw" to relay exceptions - */ - static void rethrow(Throwable ex) { - if (ex != null) - ForkJoinTask.uncheckedThrow(ex); - } - - /** - * The sneaky part of sneaky throw, relying on generics - * limitations to evade compiler complaints about rethrowing - * unchecked exceptions - */ - @SuppressWarnings("unchecked") static - void uncheckedThrow(Throwable t) throws T { - throw (T)t; // rely on vacuous cast - } - - /** - * Throws exception, if any, associated with the given status. - */ - private void reportException(int s) { - if (s == CANCELLED) - throw new CancellationException(); - if (s == EXCEPTIONAL) - rethrow(getThrowableException()); - } - - // public methods - - /** - * Arranges to asynchronously execute this task in the pool the - * current task is running in, if applicable, or using the {@link - * ForkJoinPool#commonPool()} if not {@link #inForkJoinPool}. While - * it is not necessarily enforced, it is a usage error to fork a - * task more than once unless it has completed and been - * reinitialized. Subsequent modifications to the state of this - * task or any data it operates on are not necessarily - * consistently observable by any thread other than the one - * executing it unless preceded by a call to {@link #join} or - * related methods, or a call to {@link #isDone} returning {@code - * true}. - * - * @return {@code this}, to simplify usage - */ - public final ForkJoinTask fork() { - Thread t; - if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) - ((ForkJoinWorkerThread)t).workQueue.push(this); - else - ForkJoinPool.common.externalPush(this); - return this; - } - - /** - * Returns the result of the computation when it {@link #isDone is - * done}. This method differs from {@link #get()} in that - * abnormal completion results in {@code RuntimeException} or - * {@code Error}, not {@code ExecutionException}, and that - * interrupts of the calling thread do not cause the - * method to abruptly return by throwing {@code - * InterruptedException}. - * - * @return the computed result - */ - public final V join() { - int s; - if ((s = doJoin() & DONE_MASK) != NORMAL) - reportException(s); - return getRawResult(); - } - - /** - * Commences performing this task, awaits its completion if - * necessary, and returns its result, or throws an (unchecked) - * {@code RuntimeException} or {@code Error} if the underlying - * computation did so. - * - * @return the computed result - */ - public final V invoke() { - int s; - if ((s = doInvoke() & DONE_MASK) != NORMAL) - reportException(s); - return getRawResult(); - } - - /** - * Forks the given tasks, returning when {@code isDone} holds for - * each task or an (unchecked) exception is encountered, in which - * case the exception is rethrown. If more than one task - * encounters an exception, then this method throws any one of - * these exceptions. If any task encounters an exception, the - * other may be cancelled. However, the execution status of - * individual tasks is not guaranteed upon exceptional return. The - * status of each task may be obtained using {@link - * #getException()} and related methods to check if they have been - * cancelled, completed normally or exceptionally, or left - * unprocessed. - * - * @param t1 the first task - * @param t2 the second task - * @throws NullPointerException if any task is null - */ - public static void invokeAll(ForkJoinTask t1, ForkJoinTask t2) { - int s1, s2; - t2.fork(); - if ((s1 = t1.doInvoke() & DONE_MASK) != NORMAL) - t1.reportException(s1); - if ((s2 = t2.doJoin() & DONE_MASK) != NORMAL) - t2.reportException(s2); - } - - /** - * Forks the given tasks, returning when {@code isDone} holds for - * each task or an (unchecked) exception is encountered, in which - * case the exception is rethrown. If more than one task - * encounters an exception, then this method throws any one of - * these exceptions. If any task encounters an exception, others - * may be cancelled. However, the execution status of individual - * tasks is not guaranteed upon exceptional return. The status of - * each task may be obtained using {@link #getException()} and - * related methods to check if they have been cancelled, completed - * normally or exceptionally, or left unprocessed. - * - * @param tasks the tasks - * @throws NullPointerException if any task is null - */ - public static void invokeAll(ForkJoinTask... tasks) { - Throwable ex = null; - int last = tasks.length - 1; - for (int i = last; i >= 0; --i) { - ForkJoinTask t = tasks[i]; - if (t == null) { - if (ex == null) - ex = new NullPointerException(); - } - else if (i != 0) - t.fork(); - else if (t.doInvoke() < NORMAL && ex == null) - ex = t.getException(); - } - for (int i = 1; i <= last; ++i) { - ForkJoinTask t = tasks[i]; - if (t != null) { - if (ex != null) - t.cancel(false); - else if (t.doJoin() < NORMAL) - ex = t.getException(); - } - } - if (ex != null) - rethrow(ex); - } - - /** - * Forks all tasks in the specified collection, returning when - * {@code isDone} holds for each task or an (unchecked) exception - * is encountered, in which case the exception is rethrown. If - * more than one task encounters an exception, then this method - * throws any one of these exceptions. If any task encounters an - * exception, others may be cancelled. However, the execution - * status of individual tasks is not guaranteed upon exceptional - * return. The status of each task may be obtained using {@link - * #getException()} and related methods to check if they have been - * cancelled, completed normally or exceptionally, or left - * unprocessed. - * - * @param tasks the collection of tasks - * @return the tasks argument, to simplify usage - * @throws NullPointerException if tasks or any element are null - */ - public static > Collection invokeAll(Collection tasks) { - if (!(tasks instanceof RandomAccess) || !(tasks instanceof List)) { - invokeAll(tasks.toArray(new ForkJoinTask[tasks.size()])); - return tasks; - } - @SuppressWarnings("unchecked") - List> ts = - (List>) tasks; - Throwable ex = null; - int last = ts.size() - 1; - for (int i = last; i >= 0; --i) { - ForkJoinTask t = ts.get(i); - if (t == null) { - if (ex == null) - ex = new NullPointerException(); - } - else if (i != 0) - t.fork(); - else if (t.doInvoke() < NORMAL && ex == null) - ex = t.getException(); - } - for (int i = 1; i <= last; ++i) { - ForkJoinTask t = ts.get(i); - if (t != null) { - if (ex != null) - t.cancel(false); - else if (t.doJoin() < NORMAL) - ex = t.getException(); - } - } - if (ex != null) - rethrow(ex); - return tasks; - } - - /** - * Attempts to cancel execution of this task. This attempt will - * fail if the task has already completed or could not be - * cancelled for some other reason. If successful, and this task - * has not started when {@code cancel} is called, execution of - * this task is suppressed. After this method returns - * successfully, unless there is an intervening call to {@link - * #reinitialize}, subsequent calls to {@link #isCancelled}, - * {@link #isDone}, and {@code cancel} will return {@code true} - * and calls to {@link #join} and related methods will result in - * {@code CancellationException}. - * - *

This method may be overridden in subclasses, but if so, must - * still ensure that these properties hold. In particular, the - * {@code cancel} method itself must not throw exceptions. - * - *

This method is designed to be invoked by other - * tasks. To terminate the current task, you can just return or - * throw an unchecked exception from its computation method, or - * invoke {@link #completeExceptionally(Throwable)}. - * - * @param mayInterruptIfRunning this value has no effect in the - * default implementation because interrupts are not used to - * control cancellation. - * - * @return {@code true} if this task is now cancelled - */ - public boolean cancel(boolean mayInterruptIfRunning) { - return (setCompletion(CANCELLED) & DONE_MASK) == CANCELLED; - } - - public final boolean isDone() { - return status < 0; - } - - public final boolean isCancelled() { - return (status & DONE_MASK) == CANCELLED; - } - - /** - * Returns {@code true} if this task threw an exception or was cancelled. - * - * @return {@code true} if this task threw an exception or was cancelled - */ - public final boolean isCompletedAbnormally() { - return status < NORMAL; - } - - /** - * Returns {@code true} if this task completed without throwing an - * exception and was not cancelled. - * - * @return {@code true} if this task completed without throwing an - * exception and was not cancelled - */ - public final boolean isCompletedNormally() { - return (status & DONE_MASK) == NORMAL; - } - - /** - * Returns the exception thrown by the base computation, or a - * {@code CancellationException} if cancelled, or {@code null} if - * none or if the method has not yet completed. - * - * @return the exception, or {@code null} if none - */ - public final Throwable getException() { - int s = status & DONE_MASK; - return ((s >= NORMAL) ? null : - (s == CANCELLED) ? new CancellationException() : - getThrowableException()); - } - - /** - * Completes this task abnormally, and if not already aborted or - * cancelled, causes it to throw the given exception upon - * {@code join} and related operations. This method may be used - * to induce exceptions in asynchronous tasks, or to force - * completion of tasks that would not otherwise complete. Its use - * in other situations is discouraged. This method is - * overridable, but overridden versions must invoke {@code super} - * implementation to maintain guarantees. - * - * @param ex the exception to throw. If this exception is not a - * {@code RuntimeException} or {@code Error}, the actual exception - * thrown will be a {@code RuntimeException} with cause {@code ex}. - */ - public void completeExceptionally(Throwable ex) { - setExceptionalCompletion((ex instanceof RuntimeException) || - (ex instanceof Error) ? ex : - new RuntimeException(ex)); - } - - /** - * Completes this task, and if not already aborted or cancelled, - * returning the given value as the result of subsequent - * invocations of {@code join} and related operations. This method - * may be used to provide results for asynchronous tasks, or to - * provide alternative handling for tasks that would not otherwise - * complete normally. Its use in other situations is - * discouraged. This method is overridable, but overridden - * versions must invoke {@code super} implementation to maintain - * guarantees. - * - * @param value the result value for this task - */ - public void complete(V value) { - try { - setRawResult(value); - } catch (Throwable rex) { - setExceptionalCompletion(rex); - return; - } - setCompletion(NORMAL); - } - - /** - * Completes this task normally without setting a value. The most - * recent value established by {@link #setRawResult} (or {@code - * null} by default) will be returned as the result of subsequent - * invocations of {@code join} and related operations. - * - * @since 1.8 - */ - public final void quietlyComplete() { - setCompletion(NORMAL); - } - - /** - * Waits if necessary for the computation to complete, and then - * retrieves its result. - * - * @return the computed result - * @throws CancellationException if the computation was cancelled - * @throws ExecutionException if the computation threw an - * exception - * @throws InterruptedException if the current thread is not a - * member of a ForkJoinPool and was interrupted while waiting - */ - public final V get() throws InterruptedException, ExecutionException { - int s = (Thread.currentThread() instanceof ForkJoinWorkerThread) ? - doJoin() : externalInterruptibleAwaitDone(); - Throwable ex; - if ((s &= DONE_MASK) == CANCELLED) - throw new CancellationException(); - if (s == EXCEPTIONAL && (ex = getThrowableException()) != null) - throw new ExecutionException(ex); - return getRawResult(); - } - - /** - * Waits if necessary for at most the given time for the computation - * to complete, and then retrieves its result, if available. - * - * @param timeout the maximum time to wait - * @param unit the time unit of the timeout argument - * @return the computed result - * @throws CancellationException if the computation was cancelled - * @throws ExecutionException if the computation threw an - * exception - * @throws InterruptedException if the current thread is not a - * member of a ForkJoinPool and was interrupted while waiting - * @throws TimeoutException if the wait timed out - */ - public final V get(long timeout, TimeUnit unit) - throws InterruptedException, ExecutionException, TimeoutException { - if (Thread.interrupted()) - throw new InterruptedException(); - // Messy in part because we measure in nanosecs, but wait in millisecs - int s; long ms; - long ns = unit.toNanos(timeout); - ForkJoinPool cp; - if ((s = status) >= 0 && ns > 0L) { - long deadline = System.nanoTime() + ns; - ForkJoinPool p = null; - ForkJoinPool.WorkQueue w = null; - Thread t = Thread.currentThread(); - if (t instanceof ForkJoinWorkerThread) { - ForkJoinWorkerThread wt = (ForkJoinWorkerThread)t; - p = wt.pool; - w = wt.workQueue; - p.helpJoinOnce(w, this); // no retries on failure - } - else if ((cp = ForkJoinPool.common) != null) { - if (this instanceof CountedCompleter) - cp.externalHelpComplete((CountedCompleter)this); - else if (cp.tryExternalUnpush(this)) - doExec(); - } - boolean canBlock = false; - boolean interrupted = false; - try { - while ((s = status) >= 0) { - if (w != null && w.qlock < 0) - cancelIgnoringExceptions(this); - else if (!canBlock) { - if (p == null || p.tryCompensate(p.ctl)) - canBlock = true; - } - else { - if ((ms = TimeUnit.NANOSECONDS.toMillis(ns)) > 0L && - U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) { - synchronized (this) { - if (status >= 0) { - try { - wait(ms); - } catch (InterruptedException ie) { - if (p == null) - interrupted = true; - } - } - else - notifyAll(); - } - } - if ((s = status) < 0 || interrupted || - (ns = deadline - System.nanoTime()) <= 0L) - break; - } - } - } finally { - if (p != null && canBlock) - p.incrementActiveCount(); - } - if (interrupted) - throw new InterruptedException(); - } - if ((s &= DONE_MASK) != NORMAL) { - Throwable ex; - if (s == CANCELLED) - throw new CancellationException(); - if (s != EXCEPTIONAL) - throw new TimeoutException(); - if ((ex = getThrowableException()) != null) - throw new ExecutionException(ex); - } - return getRawResult(); - } - - /** - * Joins this task, without returning its result or throwing its - * exception. This method may be useful when processing - * collections of tasks when some have been cancelled or otherwise - * known to have aborted. - */ - public final void quietlyJoin() { - doJoin(); - } - - /** - * Commences performing this task and awaits its completion if - * necessary, without returning its result or throwing its - * exception. - */ - public final void quietlyInvoke() { - doInvoke(); - } - - /** - * Possibly executes tasks until the pool hosting the current task - * {@link ForkJoinPool#isQuiescent is quiescent}. This method may - * be of use in designs in which many tasks are forked, but none - * are explicitly joined, instead executing them until all are - * processed. - */ - public static void helpQuiesce() { - Thread t; - if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) { - ForkJoinWorkerThread wt = (ForkJoinWorkerThread)t; - wt.pool.helpQuiescePool(wt.workQueue); - } - else - ForkJoinPool.quiesceCommonPool(); - } - - /** - * Resets the internal bookkeeping state of this task, allowing a - * subsequent {@code fork}. This method allows repeated reuse of - * this task, but only if reuse occurs when this task has either - * never been forked, or has been forked, then completed and all - * outstanding joins of this task have also completed. Effects - * under any other usage conditions are not guaranteed. - * This method may be useful when executing - * pre-constructed trees of subtasks in loops. - * - *

Upon completion of this method, {@code isDone()} reports - * {@code false}, and {@code getException()} reports {@code - * null}. However, the value returned by {@code getRawResult} is - * unaffected. To clear this value, you can invoke {@code - * setRawResult(null)}. - */ - public void reinitialize() { - if ((status & DONE_MASK) == EXCEPTIONAL) - clearExceptionalCompletion(); - else - status = 0; - } - - /** - * Returns the pool hosting the current task execution, or null - * if this task is executing outside of any ForkJoinPool. - * - * @see #inForkJoinPool - * @return the pool, or {@code null} if none - */ - public static ForkJoinPool getPool() { - Thread t = Thread.currentThread(); - return (t instanceof ForkJoinWorkerThread) ? - ((ForkJoinWorkerThread) t).pool : null; - } - - /** - * Returns {@code true} if the current thread is a {@link - * ForkJoinWorkerThread} executing as a ForkJoinPool computation. - * - * @return {@code true} if the current thread is a {@link - * ForkJoinWorkerThread} executing as a ForkJoinPool computation, - * or {@code false} otherwise - */ - public static boolean inForkJoinPool() { - return Thread.currentThread() instanceof ForkJoinWorkerThread; - } - - /** - * Tries to unschedule this task for execution. This method will - * typically (but is not guaranteed to) succeed if this task is - * the most recently forked task by the current thread, and has - * not commenced executing in another thread. This method may be - * useful when arranging alternative local processing of tasks - * that could have been, but were not, stolen. - * - * @return {@code true} if unforked - */ - public boolean tryUnfork() { - Thread t; - return (((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ? - ((ForkJoinWorkerThread)t).workQueue.tryUnpush(this) : - ForkJoinPool.common.tryExternalUnpush(this)); - } - - /** - * Returns an estimate of the number of tasks that have been - * forked by the current worker thread but not yet executed. This - * value may be useful for heuristic decisions about whether to - * fork other tasks. - * - * @return the number of tasks - */ - public static int getQueuedTaskCount() { - Thread t; ForkJoinPool.WorkQueue q; - if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) - q = ((ForkJoinWorkerThread)t).workQueue; - else - q = ForkJoinPool.commonSubmitterQueue(); - return (q == null) ? 0 : q.queueSize(); - } - - /** - * Returns an estimate of how many more locally queued tasks are - * held by the current worker thread than there are other worker - * threads that might steal them, or zero if this thread is not - * operating in a ForkJoinPool. This value may be useful for - * heuristic decisions about whether to fork other tasks. In many - * usages of ForkJoinTasks, at steady state, each worker should - * aim to maintain a small constant surplus (for example, 3) of - * tasks, and to process computations locally if this threshold is - * exceeded. - * - * @return the surplus number of tasks, which may be negative - */ - public static int getSurplusQueuedTaskCount() { - return ForkJoinPool.getSurplusQueuedTaskCount(); - } - - // Extension methods - - /** - * Returns the result that would be returned by {@link #join}, even - * if this task completed abnormally, or {@code null} if this task - * is not known to have been completed. This method is designed - * to aid debugging, as well as to support extensions. Its use in - * any other context is discouraged. - * - * @return the result, or {@code null} if not completed - */ - public abstract V getRawResult(); - - /** - * Forces the given value to be returned as a result. This method - * is designed to support extensions, and should not in general be - * called otherwise. - * - * @param value the value - */ - protected abstract void setRawResult(V value); - - /** - * Immediately performs the base action of this task and returns - * true if, upon return from this method, this task is guaranteed - * to have completed normally. This method may return false - * otherwise, to indicate that this task is not necessarily - * complete (or is not known to be complete), for example in - * asynchronous actions that require explicit invocations of - * completion methods. This method may also throw an (unchecked) - * exception to indicate abnormal exit. This method is designed to - * support extensions, and should not in general be called - * otherwise. - * - * @return {@code true} if this task is known to have completed normally - */ - protected abstract boolean exec(); - - /** - * Returns, but does not unschedule or execute, a task queued by - * the current thread but not yet executed, if one is immediately - * available. There is no guarantee that this task will actually - * be polled or executed next. Conversely, this method may return - * null even if a task exists but cannot be accessed without - * contention with other threads. This method is designed - * primarily to support extensions, and is unlikely to be useful - * otherwise. - * - * @return the next task, or {@code null} if none are available - */ - protected static ForkJoinTask peekNextLocalTask() { - Thread t; ForkJoinPool.WorkQueue q; - if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) - q = ((ForkJoinWorkerThread)t).workQueue; - else - q = ForkJoinPool.commonSubmitterQueue(); - return (q == null) ? null : q.peek(); - } - - /** - * Unschedules and returns, without executing, the next task - * queued by the current thread but not yet executed, if the - * current thread is operating in a ForkJoinPool. This method is - * designed primarily to support extensions, and is unlikely to be - * useful otherwise. - * - * @return the next task, or {@code null} if none are available - */ - protected static ForkJoinTask pollNextLocalTask() { - Thread t; - return ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ? - ((ForkJoinWorkerThread)t).workQueue.nextLocalTask() : - null; - } - - /** - * If the current thread is operating in a ForkJoinPool, - * unschedules and returns, without executing, the next task - * queued by the current thread but not yet executed, if one is - * available, or if not available, a task that was forked by some - * other thread, if available. Availability may be transient, so a - * {@code null} result does not necessarily imply quiescence of - * the pool this task is operating in. This method is designed - * primarily to support extensions, and is unlikely to be useful - * otherwise. - * - * @return a task, or {@code null} if none are available - */ - protected static ForkJoinTask pollTask() { - Thread t; ForkJoinWorkerThread wt; - return ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ? - (wt = (ForkJoinWorkerThread)t).pool.nextTaskFor(wt.workQueue) : - null; - } - - // tag operations - - /** - * Returns the tag for this task. - * - * @return the tag for this task - * @since 1.8 - */ - public final short getForkJoinTaskTag() { - return (short)status; - } - - /** - * Atomically sets the tag value for this task. - * - * @param tag the tag value - * @return the previous value of the tag - * @since 1.8 - */ - public final short setForkJoinTaskTag(short tag) { - for (int s;;) { - if (U.compareAndSwapInt(this, STATUS, s = status, - (s & ~SMASK) | (tag & SMASK))) - return (short)s; - } - } - - /** - * Atomically conditionally sets the tag value for this task. - * Among other applications, tags can be used as visit markers - * in tasks operating on graphs, as in methods that check: {@code - * if (task.compareAndSetForkJoinTaskTag((short)0, (short)1))} - * before processing, otherwise exiting because the node has - * already been visited. - * - * @param e the expected tag value - * @param tag the new tag value - * @return {@code true} if successful; i.e., the current value was - * equal to e and is now tag. - * @since 1.8 - */ - public final boolean compareAndSetForkJoinTaskTag(short e, short tag) { - for (int s;;) { - if ((short)(s = status) != e) - return false; - if (U.compareAndSwapInt(this, STATUS, s, - (s & ~SMASK) | (tag & SMASK))) - return true; - } - } - - /** - * Adaptor for Runnables. This implements RunnableFuture - * to be compliant with AbstractExecutorService constraints - * when used in ForkJoinPool. - */ - static final class AdaptedRunnable extends ForkJoinTask - implements RunnableFuture { - final Runnable runnable; - T result; - AdaptedRunnable(Runnable runnable, T result) { - if (runnable == null) throw new NullPointerException(); - this.runnable = runnable; - this.result = result; // OK to set this even before completion - } - public final T getRawResult() { return result; } - public final void setRawResult(T v) { result = v; } - public final boolean exec() { runnable.run(); return true; } - public final void run() { invoke(); } - private static final long serialVersionUID = 5232453952276885070L; - } - - /** - * Adaptor for Runnables without results - */ - static final class AdaptedRunnableAction extends ForkJoinTask - implements RunnableFuture { - final Runnable runnable; - AdaptedRunnableAction(Runnable runnable) { - if (runnable == null) throw new NullPointerException(); - this.runnable = runnable; - } - public final Void getRawResult() { return null; } - public final void setRawResult(Void v) { } - public final boolean exec() { runnable.run(); return true; } - public final void run() { invoke(); } - private static final long serialVersionUID = 5232453952276885070L; - } - - /** - * Adaptor for Runnables in which failure forces worker exception - */ - static final class RunnableExecuteAction extends ForkJoinTask { - final Runnable runnable; - RunnableExecuteAction(Runnable runnable) { - if (runnable == null) throw new NullPointerException(); - this.runnable = runnable; - } - public final Void getRawResult() { return null; } - public final void setRawResult(Void v) { } - public final boolean exec() { runnable.run(); return true; } - void internalPropagateException(Throwable ex) { - rethrow(ex); // rethrow outside exec() catches. - } - private static final long serialVersionUID = 5232453952276885070L; - } - - /** - * Adaptor for Callables - */ - static final class AdaptedCallable extends ForkJoinTask - implements RunnableFuture { - final Callable callable; - T result; - AdaptedCallable(Callable callable) { - if (callable == null) throw new NullPointerException(); - this.callable = callable; - } - public final T getRawResult() { return result; } - public final void setRawResult(T v) { result = v; } - public final boolean exec() { - try { - result = callable.call(); - return true; - } catch (Error err) { - throw err; - } catch (RuntimeException rex) { - throw rex; - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - public final void run() { invoke(); } - private static final long serialVersionUID = 2838392045355241008L; - } - - /** - * Returns a new {@code ForkJoinTask} that performs the {@code run} - * method of the given {@code Runnable} as its action, and returns - * a null result upon {@link #join}. - * - * @param runnable the runnable action - * @return the task - */ - public static ForkJoinTask adapt(Runnable runnable) { - return new AdaptedRunnableAction(runnable); - } - - /** - * Returns a new {@code ForkJoinTask} that performs the {@code run} - * method of the given {@code Runnable} as its action, and returns - * the given result upon {@link #join}. - * - * @param runnable the runnable action - * @param result the result upon completion - * @return the task - */ - public static ForkJoinTask adapt(Runnable runnable, T result) { - return new AdaptedRunnable(runnable, result); - } - - /** - * Returns a new {@code ForkJoinTask} that performs the {@code call} - * method of the given {@code Callable} as its action, and returns - * its result upon {@link #join}, translating any checked exceptions - * encountered into {@code RuntimeException}. - * - * @param callable the callable action - * @return the task - */ - public static ForkJoinTask adapt(Callable callable) { - return new AdaptedCallable(callable); - } - - // Serialization support - - private static final long serialVersionUID = -7721805057305804111L; - - /** - * Saves this task to a stream (that is, serializes it). - * - * @serialData the current run status and the exception thrown - * during execution, or {@code null} if none - */ - private void writeObject(java.io.ObjectOutputStream s) - throws java.io.IOException { - s.defaultWriteObject(); - s.writeObject(getException()); - } - - /** - * Reconstitutes this task from a stream (that is, deserializes it). - */ - private void readObject(java.io.ObjectInputStream s) - throws java.io.IOException, ClassNotFoundException { - s.defaultReadObject(); - Object ex = s.readObject(); - if (ex != null) - setExceptionalCompletion((Throwable)ex); - } - - // Unsafe mechanics - private static final sun.misc.Unsafe U; - private static final long STATUS; - - static { - exceptionTableLock = new ReentrantLock(); - exceptionTableRefQueue = new ReferenceQueue(); - exceptionTable = new ExceptionNode[EXCEPTION_MAP_CAPACITY]; - try { - U = getUnsafe(); - Class k = ForkJoinTask.class; - STATUS = U.objectFieldOffset - (k.getDeclaredField("status")); - } catch (Exception e) { - throw new Error(e); - } - } - - /** - * Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package. - * Replace with a simple call to Unsafe.getUnsafe when integrating - * into a jdk. - * - * @return a sun.misc.Unsafe - */ - private static sun.misc.Unsafe getUnsafe() { - try { - return sun.misc.Unsafe.getUnsafe(); - } catch (SecurityException tryReflectionInstead) {} - try { - return java.security.AccessController.doPrivileged - (new java.security.PrivilegedExceptionAction() { - public sun.misc.Unsafe run() throws Exception { - Class k = sun.misc.Unsafe.class; - for (java.lang.reflect.Field f : k.getDeclaredFields()) { - f.setAccessible(true); - Object x = f.get(null); - if (k.isInstance(x)) - return k.cast(x); - } - throw new NoSuchFieldError("the Unsafe"); - }}); - } catch (java.security.PrivilegedActionException e) { - throw new RuntimeException("Could not initialize intrinsics", - e.getCause()); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/chmv8/ForkJoinWorkerThread.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/chmv8/ForkJoinWorkerThread.java deleted file mode 100755 index d3467575b6..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/chmv8/ForkJoinWorkerThread.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/* - * Written by Doug Lea with assistance from members of JCP JSR-166 - * Expert Group and released to the public domain, as explained at - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -package com.ai.cloud.io.netty.util.internal.chmv8; - - -/** - * A thread managed by a {@link ForkJoinPool}, which executes - * {@link ForkJoinTask}s. - * This class is subclassable solely for the sake of adding - * functionality -- there are no overridable methods dealing with - * scheduling or execution. However, you can override initialization - * and termination methods surrounding the main task processing loop. - * If you do create such a subclass, you will also need to supply a - * custom {@link ForkJoinPool.ForkJoinWorkerThreadFactory} to - * {@linkplain ForkJoinPool#ForkJoinPool use it} in a {@code ForkJoinPool}. - * - * @since 1.7 - * @author Doug Lea - */ -@SuppressWarnings("all") -public class ForkJoinWorkerThread extends Thread { - /* - * ForkJoinWorkerThreads are managed by ForkJoinPools and perform - * ForkJoinTasks. For explanation, see the internal documentation - * of class ForkJoinPool. - * - * This class just maintains links to its pool and WorkQueue. The - * pool field is set immediately upon construction, but the - * workQueue field is not set until a call to registerWorker - * completes. This leads to a visibility race, that is tolerated - * by requiring that the workQueue field is only accessed by the - * owning thread. - */ - - final ForkJoinPool pool; // the pool this thread works in - final ForkJoinPool.WorkQueue workQueue; // work-stealing mechanics - - /** - * Creates a ForkJoinWorkerThread operating in the given pool. - * - * @param pool the pool this thread works in - * @throws NullPointerException if pool is null - */ - protected ForkJoinWorkerThread(ForkJoinPool pool) { - // Use a placeholder until a useful name can be set in registerWorker - super("aForkJoinWorkerThread"); - this.pool = pool; - this.workQueue = pool.registerWorker(this); - } - - /** - * Returns the pool hosting this thread. - * - * @return the pool - */ - public ForkJoinPool getPool() { - return pool; - } - - /** - * Returns the unique index number of this thread in its pool. - * The returned value ranges from zero to the maximum number of - * threads (minus one) that may exist in the pool, and does not - * change during the lifetime of the thread. This method may be - * useful for applications that track status or collect results - * per-worker-thread rather than per-task. - * - * @return the index number - */ - public int getPoolIndex() { - return workQueue.poolIndex >>> 1; // ignore odd/even tag bit - } - - /** - * Initializes internal state after construction but before - * processing any tasks. If you override this method, you must - * invoke {@code super.onStart()} at the beginning of the method. - * Initialization requires care: Most fields must have legal - * default values, to ensure that attempted accesses from other - * threads work correctly even before this thread starts - * processing tasks. - */ - protected void onStart() { - } - - /** - * Performs cleanup associated with termination of this worker - * thread. If you override this method, you must invoke - * {@code super.onTermination} at the end of the overridden method. - * - * @param exception the exception causing this thread to abort due - * to an unrecoverable error, or {@code null} if completed normally - */ - protected void onTermination(Throwable exception) { - } - - /** - * This method is required to be public, but should never be - * called explicitly. It performs the main run loop to execute - * {@link ForkJoinTask}s. - */ - public void run() { - Throwable exception = null; - try { - onStart(); - pool.runWorker(workQueue); - } catch (Throwable ex) { - exception = ex; - } finally { - try { - onTermination(exception); - } catch (Throwable ex) { - if (exception == null) - exception = ex; - } finally { - pool.deregisterWorker(this, exception); - } - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/chmv8/LongAdderV8.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/chmv8/LongAdderV8.java deleted file mode 100755 index 01b9369744..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/chmv8/LongAdderV8.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/* - * Written by Doug Lea with assistance from members of JCP JSR-166 - * Expert Group and released to the public domain, as explained at - * http://creativecommons.org/publicdomain/zero/1.0/ - */ -package com.ai.cloud.io.netty.util.internal.chmv8; - - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; -import java.util.concurrent.atomic.AtomicLong; - -import com.ai.cloud.io.netty.util.internal.LongCounter; - -/** - * One or more variables that together maintain an initially zero - * {@code long} sum. When updates (method {@link #add}) are contended - * across threads, the set of variables may grow dynamically to reduce - * contention. Method {@link #sum} (or, equivalently, {@link - * #longValue}) returns the current total combined across the - * variables maintaining the sum. - * - *

This class is usually preferable to {@link AtomicLong} when - * multiple threads update a common sum that is used for purposes such - * as collecting statistics, not for fine-grained synchronization - * control. Under low update contention, the two classes have similar - * characteristics. But under high contention, expected throughput of - * this class is significantly higher, at the expense of higher space - * consumption. - * - *

This class extends {@link Number}, but does not define - * methods such as {@code equals}, {@code hashCode} and {@code - * compareTo} because instances are expected to be mutated, and so are - * not useful as collection keys. - * - *

jsr166e note: This class is targeted to be placed in - * java.util.concurrent.atomic. - * - * @since 1.8 - * @author Doug Lea - */ -@SuppressWarnings("all") -public class LongAdderV8 extends Striped64 implements Serializable, LongCounter { - private static final long serialVersionUID = 7249069246863182397L; - - /** - * Version of plus for use in retryUpdate - */ - final long fn(long v, long x) { return v + x; } - - /** - * Creates a new adder with initial sum of zero. - */ - public LongAdderV8() { - } - - /** - * Adds the given value. - * - * @param x the value to add - */ - public void add(long x) { - Cell[] as; long b, v; int[] hc; Cell a; int n; - if ((as = cells) != null || !casBase(b = base, b + x)) { - boolean uncontended = true; - if ((hc = threadHashCode.get()) == null || - as == null || (n = as.length) < 1 || - (a = as[(n - 1) & hc[0]]) == null || - !(uncontended = a.cas(v = a.value, v + x))) - retryUpdate(x, hc, uncontended); - } - } - - /** - * Equivalent to {@code add(1)}. - */ - public void increment() { - add(1L); - } - - /** - * Equivalent to {@code add(-1)}. - */ - public void decrement() { - add(-1L); - } - - /** - * Returns the current sum. The returned value is NOT an - * atomic snapshot; invocation in the absence of concurrent - * updates returns an accurate result, but concurrent updates that - * occur while the sum is being calculated might not be - * incorporated. - * - * @return the sum - */ - public long sum() { - long sum = base; - Cell[] as = cells; - if (as != null) { - int n = as.length; - for (int i = 0; i < n; ++i) { - Cell a = as[i]; - if (a != null) - sum += a.value; - } - } - return sum; - } - - /** - * Resets variables maintaining the sum to zero. This method may - * be a useful alternative to creating a new adder, but is only - * effective if there are no concurrent updates. Because this - * method is intrinsically racy, it should only be used when it is - * known that no threads are concurrently updating. - */ - public void reset() { - internalReset(0L); - } - - /** - * Equivalent in effect to {@link #sum} followed by {@link - * #reset}. This method may apply for example during quiescent - * points between multithreaded computations. If there are - * updates concurrent with this method, the returned value is - * not guaranteed to be the final value occurring before - * the reset. - * - * @return the sum - */ - public long sumThenReset() { - long sum = base; - Cell[] as = cells; - base = 0L; - if (as != null) { - int n = as.length; - for (int i = 0; i < n; ++i) { - Cell a = as[i]; - if (a != null) { - sum += a.value; - a.value = 0L; - } - } - } - return sum; - } - - /** - * Returns the String representation of the {@link #sum}. - * @return the String representation of the {@link #sum} - */ - public String toString() { - return Long.toString(sum()); - } - - /** - * Equivalent to {@link #sum}. - * - * @return the sum - */ - public long longValue() { - return sum(); - } - - /** - * Returns the {@link #sum} as an {@code int} after a narrowing - * primitive conversion. - */ - public int intValue() { - return (int)sum(); - } - - /** - * Returns the {@link #sum} as a {@code float} - * after a widening primitive conversion. - */ - public float floatValue() { - return (float)sum(); - } - - /** - * Returns the {@link #sum} as a {@code double} after a widening - * primitive conversion. - */ - public double doubleValue() { - return (double)sum(); - } - - private void writeObject(ObjectOutputStream s) throws IOException { - s.defaultWriteObject(); - s.writeLong(sum()); - } - - private void readObject(ObjectInputStream s) - throws IOException, ClassNotFoundException { - s.defaultReadObject(); - busy = 0; - cells = null; - base = s.readLong(); - } - - @Override - public long value() { - return sum(); - } -} \ No newline at end of file diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/chmv8/Striped64.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/chmv8/Striped64.java deleted file mode 100755 index 46db12f426..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/chmv8/Striped64.java +++ /dev/null @@ -1,351 +0,0 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/* - * Written by Doug Lea with assistance from members of JCP JSR-166 - * Expert Group and released to the public domain, as explained at - * http://creativecommons.org/publicdomain/zero/1.0/ - */ -package com.ai.cloud.io.netty.util.internal.chmv8; - - -import java.util.Random; - -/** - * A package-local class holding common representation and mechanics - * for classes supporting dynamic striping on 64bit values. The class - * extends Number so that concrete subclasses must publicly do so. - */ -@SuppressWarnings("all") -abstract class Striped64 extends Number { - /* - * This class maintains a lazily-initialized table of atomically - * updated variables, plus an extra "base" field. The table size - * is a power of two. Indexing uses masked per-thread hash codes. - * Nearly all declarations in this class are package-private, - * accessed directly by subclasses. - * - * Table entries are of class Cell; a variant of AtomicLong padded - * to reduce cache contention on most processors. Padding is - * overkill for most Atomics because they are usually irregularly - * scattered in memory and thus don't interfere much with each - * other. But Atomic objects residing in arrays will tend to be - * placed adjacent to each other, and so will most often share - * cache lines (with a huge negative performance impact) without - * this precaution. - * - * In part because Cells are relatively large, we avoid creating - * them until they are needed. When there is no contention, all - * updates are made to the base field. Upon first contention (a - * failed CAS on base update), the table is initialized to size 2. - * The table size is doubled upon further contention until - * reaching the nearest power of two greater than or equal to the - * number of CPUS. Table slots remain empty (null) until they are - * needed. - * - * A single spinlock ("busy") is used for initializing and - * resizing the table, as well as populating slots with new Cells. - * There is no need for a blocking lock; when the lock is not - * available, threads try other slots (or the base). During these - * retries, there is increased contention and reduced locality, - * which is still better than alternatives. - * - * Per-thread hash codes are initialized to random values. - * Contention and/or table collisions are indicated by failed - * CASes when performing an update operation (see method - * retryUpdate). Upon a collision, if the table size is less than - * the capacity, it is doubled in size unless some other thread - * holds the lock. If a hashed slot is empty, and lock is - * available, a new Cell is created. Otherwise, if the slot - * exists, a CAS is tried. Retries proceed by "double hashing", - * using a secondary hash (Marsaglia XorShift) to try to find a - * free slot. - * - * The table size is capped because, when there are more threads - * than CPUs, supposing that each thread were bound to a CPU, - * there would exist a perfect hash function mapping threads to - * slots that eliminates collisions. When we reach capacity, we - * search for this mapping by randomly varying the hash codes of - * colliding threads. Because search is random, and collisions - * only become known via CAS failures, convergence can be slow, - * and because threads are typically not bound to CPUS forever, - * may not occur at all. However, despite these limitations, - * observed contention rates are typically low in these cases. - * - * It is possible for a Cell to become unused when threads that - * once hashed to it terminate, as well as in the case where - * doubling the table causes no thread to hash to it under - * expanded mask. We do not try to detect or remove such cells, - * under the assumption that for long-running instances, observed - * contention levels will recur, so the cells will eventually be - * needed again; and for short-lived ones, it does not matter. - */ - - /** - * Padded variant of AtomicLong supporting only raw accesses plus CAS. - * The value field is placed between pads, hoping that the JVM doesn't - * reorder them. - * - * JVM intrinsics note: It would be possible to use a release-only - * form of CAS here, if it were provided. - */ - static final class Cell { - volatile long p0, p1, p2, p3, p4, p5, p6; - volatile long value; - volatile long q0, q1, q2, q3, q4, q5, q6; - Cell(long x) { value = x; } - - final boolean cas(long cmp, long val) { - return UNSAFE.compareAndSwapLong(this, valueOffset, cmp, val); - } - - // Unsafe mechanics - private static final sun.misc.Unsafe UNSAFE; - private static final long valueOffset; - static { - try { - UNSAFE = getUnsafe(); - Class ak = Cell.class; - valueOffset = UNSAFE.objectFieldOffset - (ak.getDeclaredField("value")); - } catch (Exception e) { - throw new Error(e); - } - } - - } - - /** - * ThreadLocal holding a single-slot int array holding hash code. - * Unlike the JDK8 version of this class, we use a suboptimal - * int[] representation to avoid introducing a new type that can - * impede class-unloading when ThreadLocals are not removed. - */ - static final ThreadLocal threadHashCode = new ThreadLocal(); - - /** - * Generator of new random hash codes - */ - static final Random rng = new Random(); - - /** Number of CPUS, to place bound on table size */ - static final int NCPU = Runtime.getRuntime().availableProcessors(); - - /** - * Table of cells. When non-null, size is a power of 2. - */ - transient volatile Cell[] cells; - - /** - * Base value, used mainly when there is no contention, but also as - * a fallback during table initialization races. Updated via CAS. - */ - transient volatile long base; - - /** - * Spinlock (locked via CAS) used when resizing and/or creating Cells. - */ - transient volatile int busy; - - /** - * Package-private default constructor - */ - Striped64() { - } - - /** - * CASes the base field. - */ - final boolean casBase(long cmp, long val) { - return UNSAFE.compareAndSwapLong(this, baseOffset, cmp, val); - } - - /** - * CASes the busy field from 0 to 1 to acquire lock. - */ - final boolean casBusy() { - return UNSAFE.compareAndSwapInt(this, busyOffset, 0, 1); - } - - /** - * Computes the function of current and new value. Subclasses - * should open-code this update function for most uses, but the - * virtualized form is needed within retryUpdate. - * - * @param currentValue the current value (of either base or a cell) - * @param newValue the argument from a user update call - * @return result of the update function - */ - abstract long fn(long currentValue, long newValue); - - /** - * Handles cases of updates involving initialization, resizing, - * creating new Cells, and/or contention. See above for - * explanation. This method suffers the usual non-modularity - * problems of optimistic retry code, relying on rechecked sets of - * reads. - * - * @param x the value - * @param hc the hash code holder - * @param wasUncontended false if CAS failed before call - */ - final void retryUpdate(long x, int[] hc, boolean wasUncontended) { - int h; - if (hc == null) { - threadHashCode.set(hc = new int[1]); // Initialize randomly - int r = rng.nextInt(); // Avoid zero to allow xorShift rehash - h = hc[0] = (r == 0) ? 1 : r; - } - else - h = hc[0]; - boolean collide = false; // True if last slot nonempty - for (;;) { - Cell[] as; Cell a; int n; long v; - if ((as = cells) != null && (n = as.length) > 0) { - if ((a = as[(n - 1) & h]) == null) { - if (busy == 0) { // Try to attach new Cell - Cell r = new Cell(x); // Optimistically create - if (busy == 0 && casBusy()) { - boolean created = false; - try { // Recheck under lock - Cell[] rs; int m, j; - if ((rs = cells) != null && - (m = rs.length) > 0 && - rs[j = (m - 1) & h] == null) { - rs[j] = r; - created = true; - } - } finally { - busy = 0; - } - if (created) - break; - continue; // Slot is now non-empty - } - } - collide = false; - } - else if (!wasUncontended) // CAS already known to fail - wasUncontended = true; // Continue after rehash - else if (a.cas(v = a.value, fn(v, x))) - break; - else if (n >= NCPU || cells != as) - collide = false; // At max size or stale - else if (!collide) - collide = true; - else if (busy == 0 && casBusy()) { - try { - if (cells == as) { // Expand table unless stale - Cell[] rs = new Cell[n << 1]; - for (int i = 0; i < n; ++i) - rs[i] = as[i]; - cells = rs; - } - } finally { - busy = 0; - } - collide = false; - continue; // Retry with expanded table - } - h ^= h << 13; // Rehash - h ^= h >>> 17; - h ^= h << 5; - hc[0] = h; // Record index for next time - } - else if (busy == 0 && cells == as && casBusy()) { - boolean init = false; - try { // Initialize table - if (cells == as) { - Cell[] rs = new Cell[2]; - rs[h & 1] = new Cell(x); - cells = rs; - init = true; - } - } finally { - busy = 0; - } - if (init) - break; - } - else if (casBase(v = base, fn(v, x))) - break; // Fall back on using base - } - } - - - /** - * Sets base and all cells to the given value. - */ - final void internalReset(long initialValue) { - Cell[] as = cells; - base = initialValue; - if (as != null) { - int n = as.length; - for (int i = 0; i < n; ++i) { - Cell a = as[i]; - if (a != null) - a.value = initialValue; - } - } - } - - // Unsafe mechanics - private static final sun.misc.Unsafe UNSAFE; - private static final long baseOffset; - private static final long busyOffset; - static { - try { - UNSAFE = getUnsafe(); - Class sk = Striped64.class; - baseOffset = UNSAFE.objectFieldOffset - (sk.getDeclaredField("base")); - busyOffset = UNSAFE.objectFieldOffset - (sk.getDeclaredField("busy")); - } catch (Exception e) { - throw new Error(e); - } - } - - /** - * Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package. - * Replace with a simple call to Unsafe.getUnsafe when integrating - * into a jdk. - * - * @return a sun.misc.Unsafe - */ - private static sun.misc.Unsafe getUnsafe() { - try { - return sun.misc.Unsafe.getUnsafe(); - } catch (SecurityException tryReflectionInstead) {} - try { - return java.security.AccessController.doPrivileged - (new java.security.PrivilegedExceptionAction() { - public sun.misc.Unsafe run() throws Exception { - Class k = sun.misc.Unsafe.class; - for (java.lang.reflect.Field f : k.getDeclaredFields()) { - f.setAccessible(true); - Object x = f.get(null); - if (k.isInstance(x)) - return k.cast(x); - } - throw new NoSuchFieldError("the Unsafe"); - }}); - } catch (java.security.PrivilegedActionException e) { - throw new RuntimeException("Could not initialize intrinsics", - e.getCause()); - } - } -} \ No newline at end of file diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/AbstractInternalLogger.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/AbstractInternalLogger.java deleted file mode 100755 index ce39fc196c..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/AbstractInternalLogger.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.internal.logging; - -import java.io.ObjectStreamException; -import java.io.Serializable; - -import com.ai.cloud.io.netty.util.internal.StringUtil; - -/** - * A skeletal implementation of {@link InternalLogger}. This class implements - * all methods that have a {@link InternalLogLevel} parameter by default to call - * specific logger methods such as {@link #info(String)} or {@link #isInfoEnabled()}. - */ -public abstract class AbstractInternalLogger implements InternalLogger, Serializable { - - private static final long serialVersionUID = -6382972526573193470L; - - private final String name; - - /** - * Creates a new instance. - */ - protected AbstractInternalLogger(String name) { - if (name == null) { - throw new NullPointerException("name"); - } - this.name = name; - } - - @Override - public String name() { - return name; - } - - @Override - public boolean isEnabled(InternalLogLevel level) { - switch (level) { - case TRACE: - return isTraceEnabled(); - case DEBUG: - return isDebugEnabled(); - case INFO: - return isInfoEnabled(); - case WARN: - return isWarnEnabled(); - case ERROR: - return isErrorEnabled(); - default: - throw new Error(); - } - } - - @Override - public void log(InternalLogLevel level, String msg, Throwable cause) { - switch (level) { - case TRACE: - trace(msg, cause); - break; - case DEBUG: - debug(msg, cause); - break; - case INFO: - info(msg, cause); - break; - case WARN: - warn(msg, cause); - break; - case ERROR: - error(msg, cause); - break; - default: - throw new Error(); - } - } - - @Override - public void log(InternalLogLevel level, String msg) { - switch (level) { - case TRACE: - trace(msg); - break; - case DEBUG: - debug(msg); - break; - case INFO: - info(msg); - break; - case WARN: - warn(msg); - break; - case ERROR: - error(msg); - break; - default: - throw new Error(); - } - } - - @Override - public void log(InternalLogLevel level, String format, Object arg) { - switch (level) { - case TRACE: - trace(format, arg); - break; - case DEBUG: - debug(format, arg); - break; - case INFO: - info(format, arg); - break; - case WARN: - warn(format, arg); - break; - case ERROR: - error(format, arg); - break; - default: - throw new Error(); - } - } - - @Override - public void log(InternalLogLevel level, String format, Object argA, Object argB) { - switch (level) { - case TRACE: - trace(format, argA, argB); - break; - case DEBUG: - debug(format, argA, argB); - break; - case INFO: - info(format, argA, argB); - break; - case WARN: - warn(format, argA, argB); - break; - case ERROR: - error(format, argA, argB); - break; - default: - throw new Error(); - } - } - - @Override - public void log(InternalLogLevel level, String format, Object... arguments) { - switch (level) { - case TRACE: - trace(format, arguments); - break; - case DEBUG: - debug(format, arguments); - break; - case INFO: - info(format, arguments); - break; - case WARN: - warn(format, arguments); - break; - case ERROR: - error(format, arguments); - break; - default: - throw new Error(); - } - } - - protected Object readResolve() throws ObjectStreamException { - return InternalLoggerFactory.getInstance(name()); - } - - @Override - public String toString() { - return StringUtil.simpleClassName(this) + '(' + name() + ')'; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/CommonsLogger.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/CommonsLogger.java deleted file mode 100755 index a92c0218bd..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/CommonsLogger.java +++ /dev/null @@ -1,564 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -/** - * Copyright (c) 2004-2011 QOS.ch - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ -package com.ai.cloud.io.netty.util.internal.logging; - -import org.apache.commons.logging.Log; - -/** - * Apache Commons Logging - * logger. - */ -class CommonsLogger extends AbstractInternalLogger { - - private static final long serialVersionUID = 8647838678388394885L; - - private final transient Log logger; - - CommonsLogger(Log logger, String name) { - super(name); - if (logger == null) { - throw new NullPointerException("logger"); - } - this.logger = logger; - } - - /** - * Delegates to the {@link Log#isTraceEnabled} method of the underlying - * {@link Log} instance. - */ - @Override - public boolean isTraceEnabled() { - return logger.isTraceEnabled(); - } - - /** - * Delegates to the {@link Log#trace(Object)} method of the underlying - * {@link Log} instance. - * - * @param msg - the message object to be logged - */ - @Override - public void trace(String msg) { - logger.trace(msg); - } - - /** - * Delegates to the {@link Log#trace(Object)} method of the underlying - * {@link Log} instance. - * - *

- * However, this form avoids superfluous object creation when the logger is disabled - * for level TRACE. - *

- * - * @param format - * the format string - * @param arg - * the argument - */ - @Override - public void trace(String format, Object arg) { - if (logger.isTraceEnabled()) { - FormattingTuple ft = MessageFormatter.format(format, arg); - logger.trace(ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Delegates to the {@link Log#trace(Object)} method of the underlying - * {@link Log} instance. - * - *

- * However, this form avoids superfluous object creation when the logger is disabled - * for level TRACE. - *

- * - * @param format - * the format string - * @param argA - * the first argument - * @param argB - * the second argument - */ - @Override - public void trace(String format, Object argA, Object argB) { - if (logger.isTraceEnabled()) { - FormattingTuple ft = MessageFormatter.format(format, argA, argB); - logger.trace(ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Delegates to the {@link Log#trace(Object)} method of the underlying - * {@link Log} instance. - * - *

- * However, this form avoids superfluous object creation when the logger is disabled - * for level TRACE. - *

- * - * @param format the format string - * @param arguments a list of 3 or more arguments - */ - @Override - public void trace(String format, Object... arguments) { - if (logger.isTraceEnabled()) { - FormattingTuple ft = MessageFormatter.arrayFormat(format, arguments); - logger.trace(ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Delegates to the {@link Log#trace(Object, Throwable)} method of - * the underlying {@link Log} instance. - * - * @param msg - * the message accompanying the exception - * @param t - * the exception (throwable) to log - */ - @Override - public void trace(String msg, Throwable t) { - logger.trace(msg, t); - } - - /** - * Delegates to the {@link Log#isDebugEnabled} method of the underlying - * {@link Log} instance. - */ - @Override - public boolean isDebugEnabled() { - return logger.isDebugEnabled(); - } - - // - - /** - * Delegates to the {@link Log#debug(Object)} method of the underlying - * {@link Log} instance. - * - * @param msg - the message object to be logged - */ - @Override - public void debug(String msg) { - logger.debug(msg); - } - - /** - * Delegates to the {@link Log#debug(Object)} method of the underlying - * {@link Log} instance. - * - *

- * However, this form avoids superfluous object creation when the logger is disabled - * for level DEBUG. - *

- * - * @param format - * the format string - * @param arg - * the argument - */ - @Override - public void debug(String format, Object arg) { - if (logger.isDebugEnabled()) { - FormattingTuple ft = MessageFormatter.format(format, arg); - logger.debug(ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Delegates to the {@link Log#debug(Object)} method of the underlying - * {@link Log} instance. - * - *

- * However, this form avoids superfluous object creation when the logger is disabled - * for level DEBUG. - *

- * - * @param format - * the format string - * @param argA - * the first argument - * @param argB - * the second argument - */ - @Override - public void debug(String format, Object argA, Object argB) { - if (logger.isDebugEnabled()) { - FormattingTuple ft = MessageFormatter.format(format, argA, argB); - logger.debug(ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Delegates to the {@link Log#debug(Object)} method of the underlying - * {@link Log} instance. - * - *

- * However, this form avoids superfluous object creation when the logger is disabled - * for level DEBUG. - *

- * - * @param format the format string - * @param arguments a list of 3 or more arguments - */ - @Override - public void debug(String format, Object... arguments) { - if (logger.isDebugEnabled()) { - FormattingTuple ft = MessageFormatter.arrayFormat(format, arguments); - logger.debug(ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Delegates to the {@link Log#debug(Object, Throwable)} method of - * the underlying {@link Log} instance. - * - * @param msg - * the message accompanying the exception - * @param t - * the exception (throwable) to log - */ - @Override - public void debug(String msg, Throwable t) { - logger.debug(msg, t); - } - - /** - * Delegates to the {@link Log#isInfoEnabled} method of the underlying - * {@link Log} instance. - */ - @Override - public boolean isInfoEnabled() { - return logger.isInfoEnabled(); - } - - /** - * Delegates to the {@link Log#debug(Object)} method of the underlying - * {@link Log} instance. - * - * @param msg - the message object to be logged - */ - @Override - public void info(String msg) { - logger.info(msg); - } - - /** - * Delegates to the {@link Log#info(Object)} method of the underlying - * {@link Log} instance. - * - *

- * However, this form avoids superfluous object creation when the logger is disabled - * for level INFO. - *

- * - * @param format - * the format string - * @param arg - * the argument - */ - - @Override - public void info(String format, Object arg) { - if (logger.isInfoEnabled()) { - FormattingTuple ft = MessageFormatter.format(format, arg); - logger.info(ft.getMessage(), ft.getThrowable()); - } - } - /** - * Delegates to the {@link Log#info(Object)} method of the underlying - * {@link Log} instance. - * - *

- * However, this form avoids superfluous object creation when the logger is disabled - * for level INFO. - *

- * - * @param format - * the format string - * @param argA - * the first argument - * @param argB - * the second argument - */ - @Override - public void info(String format, Object argA, Object argB) { - if (logger.isInfoEnabled()) { - FormattingTuple ft = MessageFormatter.format(format, argA, argB); - logger.info(ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Delegates to the {@link Log#info(Object)} method of the underlying - * {@link Log} instance. - * - *

- * However, this form avoids superfluous object creation when the logger is disabled - * for level INFO. - *

- * - * @param format the format string - * @param arguments a list of 3 or more arguments - */ - @Override - public void info(String format, Object... arguments) { - if (logger.isInfoEnabled()) { - FormattingTuple ft = MessageFormatter.arrayFormat(format, arguments); - logger.info(ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Delegates to the {@link Log#info(Object, Throwable)} method of - * the underlying {@link Log} instance. - * - * @param msg - * the message accompanying the exception - * @param t - * the exception (throwable) to log - */ - @Override - public void info(String msg, Throwable t) { - logger.info(msg, t); - } - - /** - * Delegates to the {@link Log#isWarnEnabled} method of the underlying - * {@link Log} instance. - */ - @Override - public boolean isWarnEnabled() { - return logger.isWarnEnabled(); - } - - /** - * Delegates to the {@link Log#warn(Object)} method of the underlying - * {@link Log} instance. - * - * @param msg - the message object to be logged - */ - @Override - public void warn(String msg) { - logger.warn(msg); - } - - /** - * Delegates to the {@link Log#warn(Object)} method of the underlying - * {@link Log} instance. - * - *

- * However, this form avoids superfluous object creation when the logger is disabled - * for level WARN. - *

- * - * @param format - * the format string - * @param arg - * the argument - */ - @Override - public void warn(String format, Object arg) { - if (logger.isWarnEnabled()) { - FormattingTuple ft = MessageFormatter.format(format, arg); - logger.warn(ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Delegates to the {@link Log#warn(Object)} method of the underlying - * {@link Log} instance. - * - *

- * However, this form avoids superfluous object creation when the logger is disabled - * for level WARN. - *

- * - * @param format - * the format string - * @param argA - * the first argument - * @param argB - * the second argument - */ - @Override - public void warn(String format, Object argA, Object argB) { - if (logger.isWarnEnabled()) { - FormattingTuple ft = MessageFormatter.format(format, argA, argB); - logger.warn(ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Delegates to the {@link Log#warn(Object)} method of the underlying - * {@link Log} instance. - * - *

- * However, this form avoids superfluous object creation when the logger is disabled - * for level WARN. - *

- * - * @param format the format string - * @param arguments a list of 3 or more arguments - */ - @Override - public void warn(String format, Object... arguments) { - if (logger.isWarnEnabled()) { - FormattingTuple ft = MessageFormatter.arrayFormat(format, arguments); - logger.warn(ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Delegates to the {@link Log#warn(Object, Throwable)} method of - * the underlying {@link Log} instance. - * - * @param msg - * the message accompanying the exception - * @param t - * the exception (throwable) to log - */ - - @Override - public void warn(String msg, Throwable t) { - logger.warn(msg, t); - } - - /** - * Delegates to the {@link Log#isErrorEnabled} method of the underlying - * {@link Log} instance. - */ - @Override - public boolean isErrorEnabled() { - return logger.isErrorEnabled(); - } - - /** - * Delegates to the {@link Log#error(Object)} method of the underlying - * {@link Log} instance. - * - * @param msg - the message object to be logged - */ - @Override - public void error(String msg) { - logger.error(msg); - } - - /** - * Delegates to the {@link Log#error(Object)} method of the underlying - * {@link Log} instance. - * - *

- * However, this form avoids superfluous object creation when the logger is disabled - * for level ERROR. - *

- * - * @param format - * the format string - * @param arg - * the argument - */ - @Override - public void error(String format, Object arg) { - if (logger.isErrorEnabled()) { - FormattingTuple ft = MessageFormatter.format(format, arg); - logger.error(ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Delegates to the {@link Log#error(Object)} method of the underlying - * {@link Log} instance. - * - *

- * However, this form avoids superfluous object creation when the logger is disabled - * for level ERROR. - *

- * - * @param format - * the format string - * @param argA - * the first argument - * @param argB - * the second argument - */ - @Override - public void error(String format, Object argA, Object argB) { - if (logger.isErrorEnabled()) { - FormattingTuple ft = MessageFormatter.format(format, argA, argB); - logger.error(ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Delegates to the {@link Log#error(Object)} method of the underlying - * {@link Log} instance. - * - *

- * However, this form avoids superfluous object creation when the logger is disabled - * for level ERROR. - *

- * - * @param format the format string - * @param arguments a list of 3 or more arguments - */ - @Override - public void error(String format, Object... arguments) { - if (logger.isErrorEnabled()) { - FormattingTuple ft = MessageFormatter.arrayFormat(format, arguments); - logger.error(ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Delegates to the {@link Log#error(Object, Throwable)} method of - * the underlying {@link Log} instance. - * - * @param msg - * the message accompanying the exception - * @param t - * the exception (throwable) to log - */ - @Override - public void error(String msg, Throwable t) { - logger.error(msg, t); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/CommonsLoggerFactory.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/CommonsLoggerFactory.java deleted file mode 100755 index 1502116c7a..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/CommonsLoggerFactory.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.internal.logging; - - -import org.apache.commons.logging.LogFactory; - -import java.util.HashMap; -import java.util.Map; - -/** - * Logger factory which creates an - * Apache Commons Logging - * logger. - */ -public class CommonsLoggerFactory extends InternalLoggerFactory { - - Map loggerMap = new HashMap(); - - @Override - public InternalLogger newInstance(String name) { - return new CommonsLogger(LogFactory.getLog(name), name); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/FormattingTuple.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/FormattingTuple.java deleted file mode 100755 index 01d25c8cf0..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/FormattingTuple.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -/** - * Copyright (c) 2004-2011 QOS.ch - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ -package com.ai.cloud.io.netty.util.internal.logging; - -/** - * Holds the results of formatting done by {@link MessageFormatter}. - */ -class FormattingTuple { - - static final FormattingTuple NULL = new FormattingTuple(null); - - private final String message; - private final Throwable throwable; - private final Object[] argArray; - - FormattingTuple(String message) { - this(message, null, null); - } - - FormattingTuple(String message, Object[] argArray, Throwable throwable) { - this.message = message; - this.throwable = throwable; - if (throwable == null) { - this.argArray = argArray; - } else { - this.argArray = trimmedCopy(argArray); - } - } - - static Object[] trimmedCopy(Object[] argArray) { - if (argArray == null || argArray.length == 0) { - throw new IllegalStateException("non-sensical empty or null argument array"); - } - final int trimemdLen = argArray.length - 1; - Object[] trimmed = new Object[trimemdLen]; - System.arraycopy(argArray, 0, trimmed, 0, trimemdLen); - return trimmed; - } - - public String getMessage() { - return message; - } - - public Object[] getArgArray() { - return argArray; - } - - public Throwable getThrowable() { - return throwable; - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/InternalLogLevel.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/InternalLogLevel.java deleted file mode 100755 index 9c681eb660..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/InternalLogLevel.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.internal.logging; - -/** - * The log level that {@link InternalLogger} can log at. - */ -public enum InternalLogLevel { - /** - * 'TRACE' log level. - */ - TRACE, - /** - * 'DEBUG' log level. - */ - DEBUG, - /** - * 'INFO' log level. - */ - INFO, - /** - * 'WARN' log level. - */ - WARN, - /** - * 'ERROR' log level. - */ - ERROR -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/InternalLogger.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/InternalLogger.java deleted file mode 100755 index d81dd71a83..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/InternalLogger.java +++ /dev/null @@ -1,444 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -/** - * Copyright (c) 2004-2011 QOS.ch - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ -package com.ai.cloud.io.netty.util.internal.logging; - -/** - * Internal-use-only logger used by Netty. DO NOT - * access this class outside of Netty. - */ -public interface InternalLogger { - - /** - * Return the name of this {@link InternalLogger} instance. - * - * @return name of this logger instance - */ - String name(); - - /** - * Is the logger instance enabled for the TRACE level? - * - * @return True if this Logger is enabled for the TRACE level, - * false otherwise. - */ - boolean isTraceEnabled(); - - /** - * Log a message at the TRACE level. - * - * @param msg the message string to be logged - */ - void trace(String msg); - - /** - * Log a message at the TRACE level according to the specified format - * and argument. - *

- *

This form avoids superfluous object creation when the logger - * is disabled for the TRACE level.

- * - * @param format the format string - * @param arg the argument - */ - void trace(String format, Object arg); - - /** - * Log a message at the TRACE level according to the specified format - * and arguments. - *

- *

This form avoids superfluous object creation when the logger - * is disabled for the TRACE level.

- * - * @param format the format string - * @param argA the first argument - * @param argB the second argument - */ - void trace(String format, Object argA, Object argB); - - /** - * Log a message at the TRACE level according to the specified format - * and arguments. - *

- *

This form avoids superfluous string concatenation when the logger - * is disabled for the TRACE level. However, this variant incurs the hidden - * (and relatively small) cost of creating an {@code Object[]} before invoking the method, - * even if this logger is disabled for TRACE. The variants taking {@link #trace(String, Object) one} and - * {@link #trace(String, Object, Object) two} arguments exist solely in order to avoid this hidden cost.

- * - * @param format the format string - * @param arguments a list of 3 or more arguments - */ - void trace(String format, Object... arguments); - - /** - * Log an exception (throwable) at the TRACE level with an - * accompanying message. - * - * @param msg the message accompanying the exception - * @param t the exception (throwable) to log - */ - void trace(String msg, Throwable t); - - /** - * Is the logger instance enabled for the DEBUG level? - * - * @return True if this Logger is enabled for the DEBUG level, - * false otherwise. - */ - boolean isDebugEnabled(); - - /** - * Log a message at the DEBUG level. - * - * @param msg the message string to be logged - */ - void debug(String msg); - - /** - * Log a message at the DEBUG level according to the specified format - * and argument. - *

- *

This form avoids superfluous object creation when the logger - * is disabled for the DEBUG level.

- * - * @param format the format string - * @param arg the argument - */ - void debug(String format, Object arg); - - /** - * Log a message at the DEBUG level according to the specified format - * and arguments. - *

- *

This form avoids superfluous object creation when the logger - * is disabled for the DEBUG level.

- * - * @param format the format string - * @param argA the first argument - * @param argB the second argument - */ - void debug(String format, Object argA, Object argB); - - /** - * Log a message at the DEBUG level according to the specified format - * and arguments. - *

- *

This form avoids superfluous string concatenation when the logger - * is disabled for the DEBUG level. However, this variant incurs the hidden - * (and relatively small) cost of creating an {@code Object[]} before invoking the method, - * even if this logger is disabled for DEBUG. The variants taking - * {@link #debug(String, Object) one} and {@link #debug(String, Object, Object) two} - * arguments exist solely in order to avoid this hidden cost.

- * - * @param format the format string - * @param arguments a list of 3 or more arguments - */ - void debug(String format, Object... arguments); - - /** - * Log an exception (throwable) at the DEBUG level with an - * accompanying message. - * - * @param msg the message accompanying the exception - * @param t the exception (throwable) to log - */ - void debug(String msg, Throwable t); - - /** - * Is the logger instance enabled for the INFO level? - * - * @return True if this Logger is enabled for the INFO level, - * false otherwise. - */ - boolean isInfoEnabled(); - - /** - * Log a message at the INFO level. - * - * @param msg the message string to be logged - */ - void info(String msg); - - /** - * Log a message at the INFO level according to the specified format - * and argument. - *

- *

This form avoids superfluous object creation when the logger - * is disabled for the INFO level.

- * - * @param format the format string - * @param arg the argument - */ - void info(String format, Object arg); - - /** - * Log a message at the INFO level according to the specified format - * and arguments. - *

- *

This form avoids superfluous object creation when the logger - * is disabled for the INFO level.

- * - * @param format the format string - * @param argA the first argument - * @param argB the second argument - */ - void info(String format, Object argA, Object argB); - - /** - * Log a message at the INFO level according to the specified format - * and arguments. - *

- *

This form avoids superfluous string concatenation when the logger - * is disabled for the INFO level. However, this variant incurs the hidden - * (and relatively small) cost of creating an {@code Object[]} before invoking the method, - * even if this logger is disabled for INFO. The variants taking - * {@link #info(String, Object) one} and {@link #info(String, Object, Object) two} - * arguments exist solely in order to avoid this hidden cost.

- * - * @param format the format string - * @param arguments a list of 3 or more arguments - */ - void info(String format, Object... arguments); - - /** - * Log an exception (throwable) at the INFO level with an - * accompanying message. - * - * @param msg the message accompanying the exception - * @param t the exception (throwable) to log - */ - void info(String msg, Throwable t); - - /** - * Is the logger instance enabled for the WARN level? - * - * @return True if this Logger is enabled for the WARN level, - * false otherwise. - */ - boolean isWarnEnabled(); - - /** - * Log a message at the WARN level. - * - * @param msg the message string to be logged - */ - void warn(String msg); - - /** - * Log a message at the WARN level according to the specified format - * and argument. - *

- *

This form avoids superfluous object creation when the logger - * is disabled for the WARN level.

- * - * @param format the format string - * @param arg the argument - */ - void warn(String format, Object arg); - - /** - * Log a message at the WARN level according to the specified format - * and arguments. - *

- *

This form avoids superfluous string concatenation when the logger - * is disabled for the WARN level. However, this variant incurs the hidden - * (and relatively small) cost of creating an {@code Object[]} before invoking the method, - * even if this logger is disabled for WARN. The variants taking - * {@link #warn(String, Object) one} and {@link #warn(String, Object, Object) two} - * arguments exist solely in order to avoid this hidden cost.

- * - * @param format the format string - * @param arguments a list of 3 or more arguments - */ - void warn(String format, Object... arguments); - - /** - * Log a message at the WARN level according to the specified format - * and arguments. - *

- *

This form avoids superfluous object creation when the logger - * is disabled for the WARN level.

- * - * @param format the format string - * @param argA the first argument - * @param argB the second argument - */ - void warn(String format, Object argA, Object argB); - - /** - * Log an exception (throwable) at the WARN level with an - * accompanying message. - * - * @param msg the message accompanying the exception - * @param t the exception (throwable) to log - */ - void warn(String msg, Throwable t); - - /** - * Is the logger instance enabled for the ERROR level? - * - * @return True if this Logger is enabled for the ERROR level, - * false otherwise. - */ - boolean isErrorEnabled(); - - /** - * Log a message at the ERROR level. - * - * @param msg the message string to be logged - */ - void error(String msg); - - /** - * Log a message at the ERROR level according to the specified format - * and argument. - *

- *

This form avoids superfluous object creation when the logger - * is disabled for the ERROR level.

- * - * @param format the format string - * @param arg the argument - */ - void error(String format, Object arg); - - /** - * Log a message at the ERROR level according to the specified format - * and arguments. - *

- *

This form avoids superfluous object creation when the logger - * is disabled for the ERROR level.

- * - * @param format the format string - * @param argA the first argument - * @param argB the second argument - */ - void error(String format, Object argA, Object argB); - - /** - * Log a message at the ERROR level according to the specified format - * and arguments. - *

- *

This form avoids superfluous string concatenation when the logger - * is disabled for the ERROR level. However, this variant incurs the hidden - * (and relatively small) cost of creating an {@code Object[]} before invoking the method, - * even if this logger is disabled for ERROR. The variants taking - * {@link #error(String, Object) one} and {@link #error(String, Object, Object) two} - * arguments exist solely in order to avoid this hidden cost.

- * - * @param format the format string - * @param arguments a list of 3 or more arguments - */ - void error(String format, Object... arguments); - - /** - * Log an exception (throwable) at the ERROR level with an - * accompanying message. - * - * @param msg the message accompanying the exception - * @param t the exception (throwable) to log - */ - void error(String msg, Throwable t); - - /** - * Is the logger instance enabled for the specified {@code level}? - * - * @return True if this Logger is enabled for the specified {@code level}, - * false otherwise. - */ - boolean isEnabled(InternalLogLevel level); - - /** - * Log a message at the specified {@code level}. - * - * @param msg the message string to be logged - */ - void log(InternalLogLevel level, String msg); - - /** - * Log a message at the specified {@code level} according to the specified format - * and argument. - *

- *

This form avoids superfluous object creation when the logger - * is disabled for the specified {@code level}.

- * - * @param format the format string - * @param arg the argument - */ - void log(InternalLogLevel level, String format, Object arg); - - /** - * Log a message at the specified {@code level} according to the specified format - * and arguments. - *

- *

This form avoids superfluous object creation when the logger - * is disabled for the specified {@code level}.

- * - * @param format the format string - * @param argA the first argument - * @param argB the second argument - */ - void log(InternalLogLevel level, String format, Object argA, Object argB); - - /** - * Log a message at the specified {@code level} according to the specified format - * and arguments. - *

- *

This form avoids superfluous string concatenation when the logger - * is disabled for the specified {@code level}. However, this variant incurs the hidden - * (and relatively small) cost of creating an {@code Object[]} before invoking the method, - * even if this logger is disabled for the specified {@code level}. The variants taking - * {@link #log(InternalLogLevel, String, Object) one} and - * {@link #log(InternalLogLevel, String, Object, Object) two} arguments exist solely - * in order to avoid this hidden cost.

- * - * @param format the format string - * @param arguments a list of 3 or more arguments - */ - void log(InternalLogLevel level, String format, Object... arguments); - - /** - * Log an exception (throwable) at the specified {@code level} with an - * accompanying message. - * - * @param msg the message accompanying the exception - * @param t the exception (throwable) to log - */ - void log(InternalLogLevel level, String msg, Throwable t); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/InternalLoggerFactory.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/InternalLoggerFactory.java deleted file mode 100755 index 14cbcb502a..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/InternalLoggerFactory.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.internal.logging; - -/** - * Creates an {@link InternalLogger} or changes the default factory - * implementation. This factory allows you to choose what logging framework - * Netty should use. The default factory is {@link Slf4JLoggerFactory}. If SLF4J - * is not available, {@link Log4JLoggerFactory} is used. If Log4J is not available, - * {@link JdkLoggerFactory} is used. You can change it to your preferred - * logging framework before other Netty classes are loaded: - *
- * {@link InternalLoggerFactory}.setDefaultFactory(new {@link Log4JLoggerFactory}());
- * 
- * Please note that the new default factory is effective only for the classes - * which were loaded after the default factory is changed. Therefore, - * {@link #setDefaultFactory(InternalLoggerFactory)} should be called as early - * as possible and shouldn't be called more than once. - */ -public abstract class InternalLoggerFactory { - private static volatile InternalLoggerFactory defaultFactory = - newDefaultFactory(InternalLoggerFactory.class.getName()); - - @SuppressWarnings("UnusedCatchParameter") - private static InternalLoggerFactory newDefaultFactory(String name) { - InternalLoggerFactory f; - try { - f = new Slf4JLoggerFactory(true); - f.newInstance(name).debug("Using SLF4J as the default logging framework"); - } catch (Throwable t1) { - try { - f = new Log4JLoggerFactory(); - f.newInstance(name).debug("Using Log4J as the default logging framework"); - } catch (Throwable t2) { - f = new JdkLoggerFactory(); - f.newInstance(name).debug("Using java.util.logging as the default logging framework"); - } - } - return f; - } - - /** - * Returns the default factory. The initial default factory is - * {@link JdkLoggerFactory}. - */ - public static InternalLoggerFactory getDefaultFactory() { - return defaultFactory; - } - - /** - * Changes the default factory. - */ - public static void setDefaultFactory(InternalLoggerFactory defaultFactory) { - if (defaultFactory == null) { - throw new NullPointerException("defaultFactory"); - } - InternalLoggerFactory.defaultFactory = defaultFactory; - } - - /** - * Creates a new logger instance with the name of the specified class. - */ - public static InternalLogger getInstance(Class clazz) { - return getInstance(clazz.getName()); - } - - /** - * Creates a new logger instance with the specified name. - */ - public static InternalLogger getInstance(String name) { - return getDefaultFactory().newInstance(name); - } - - /** - * Creates a new logger instance with the specified name. - */ - protected abstract InternalLogger newInstance(String name); -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/JdkLogger.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/JdkLogger.java deleted file mode 100755 index 10d3deb969..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/JdkLogger.java +++ /dev/null @@ -1,647 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -/** - * Copyright (c) 2004-2011 QOS.ch - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ -package com.ai.cloud.io.netty.util.internal.logging; - -import java.util.logging.Level; -import java.util.logging.LogRecord; -import java.util.logging.Logger; - -/** - * java.util.logging - * logger. - */ -class JdkLogger extends AbstractInternalLogger { - - private static final long serialVersionUID = -1767272577989225979L; - - final transient Logger logger; - - JdkLogger(Logger logger) { - super(logger.getName()); - this.logger = logger; - } - - /** - * Is this logger instance enabled for the FINEST level? - * - * @return True if this Logger is enabled for level FINEST, false otherwise. - */ - @Override - public boolean isTraceEnabled() { - return logger.isLoggable(Level.FINEST); - } - - /** - * Log a message object at level FINEST. - * - * @param msg - * - the message object to be logged - */ - @Override - public void trace(String msg) { - if (logger.isLoggable(Level.FINEST)) { - log(SELF, Level.FINEST, msg, null); - } - } - - /** - * Log a message at level FINEST according to the specified format and - * argument. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for level FINEST. - *

- * - * @param format - * the format string - * @param arg - * the argument - */ - @Override - public void trace(String format, Object arg) { - if (logger.isLoggable(Level.FINEST)) { - FormattingTuple ft = MessageFormatter.format(format, arg); - log(SELF, Level.FINEST, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log a message at level FINEST according to the specified format and - * arguments. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the FINEST level. - *

- * - * @param format - * the format string - * @param argA - * the first argument - * @param argB - * the second argument - */ - @Override - public void trace(String format, Object argA, Object argB) { - if (logger.isLoggable(Level.FINEST)) { - FormattingTuple ft = MessageFormatter.format(format, argA, argB); - log(SELF, Level.FINEST, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log a message at level FINEST according to the specified format and - * arguments. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the FINEST level. - *

- * - * @param format - * the format string - * @param argArray - * an array of arguments - */ - @Override - public void trace(String format, Object... argArray) { - if (logger.isLoggable(Level.FINEST)) { - FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray); - log(SELF, Level.FINEST, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log an exception (throwable) at level FINEST with an accompanying message. - * - * @param msg - * the message accompanying the exception - * @param t - * the exception (throwable) to log - */ - @Override - public void trace(String msg, Throwable t) { - if (logger.isLoggable(Level.FINEST)) { - log(SELF, Level.FINEST, msg, t); - } - } - - /** - * Is this logger instance enabled for the FINE level? - * - * @return True if this Logger is enabled for level FINE, false otherwise. - */ - @Override - public boolean isDebugEnabled() { - return logger.isLoggable(Level.FINE); - } - - /** - * Log a message object at level FINE. - * - * @param msg - * - the message object to be logged - */ - @Override - public void debug(String msg) { - if (logger.isLoggable(Level.FINE)) { - log(SELF, Level.FINE, msg, null); - } - } - - /** - * Log a message at level FINE according to the specified format and argument. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for level FINE. - *

- * - * @param format - * the format string - * @param arg - * the argument - */ - @Override - public void debug(String format, Object arg) { - if (logger.isLoggable(Level.FINE)) { - FormattingTuple ft = MessageFormatter.format(format, arg); - log(SELF, Level.FINE, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log a message at level FINE according to the specified format and - * arguments. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the FINE level. - *

- * - * @param format - * the format string - * @param argA - * the first argument - * @param argB - * the second argument - */ - @Override - public void debug(String format, Object argA, Object argB) { - if (logger.isLoggable(Level.FINE)) { - FormattingTuple ft = MessageFormatter.format(format, argA, argB); - log(SELF, Level.FINE, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log a message at level FINE according to the specified format and - * arguments. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the FINE level. - *

- * - * @param format - * the format string - * @param argArray - * an array of arguments - */ - @Override - public void debug(String format, Object... argArray) { - if (logger.isLoggable(Level.FINE)) { - FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray); - log(SELF, Level.FINE, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log an exception (throwable) at level FINE with an accompanying message. - * - * @param msg - * the message accompanying the exception - * @param t - * the exception (throwable) to log - */ - @Override - public void debug(String msg, Throwable t) { - if (logger.isLoggable(Level.FINE)) { - log(SELF, Level.FINE, msg, t); - } - } - - /** - * Is this logger instance enabled for the INFO level? - * - * @return True if this Logger is enabled for the INFO level, false otherwise. - */ - @Override - public boolean isInfoEnabled() { - return logger.isLoggable(Level.INFO); - } - - /** - * Log a message object at the INFO level. - * - * @param msg - * - the message object to be logged - */ - @Override - public void info(String msg) { - if (logger.isLoggable(Level.INFO)) { - log(SELF, Level.INFO, msg, null); - } - } - - /** - * Log a message at level INFO according to the specified format and argument. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the INFO level. - *

- * - * @param format - * the format string - * @param arg - * the argument - */ - @Override - public void info(String format, Object arg) { - if (logger.isLoggable(Level.INFO)) { - FormattingTuple ft = MessageFormatter.format(format, arg); - log(SELF, Level.INFO, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log a message at the INFO level according to the specified format and - * arguments. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the INFO level. - *

- * - * @param format - * the format string - * @param argA - * the first argument - * @param argB - * the second argument - */ - @Override - public void info(String format, Object argA, Object argB) { - if (logger.isLoggable(Level.INFO)) { - FormattingTuple ft = MessageFormatter.format(format, argA, argB); - log(SELF, Level.INFO, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log a message at level INFO according to the specified format and - * arguments. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the INFO level. - *

- * - * @param format - * the format string - * @param argArray - * an array of arguments - */ - @Override - public void info(String format, Object... argArray) { - if (logger.isLoggable(Level.INFO)) { - FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray); - log(SELF, Level.INFO, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log an exception (throwable) at the INFO level with an accompanying - * message. - * - * @param msg - * the message accompanying the exception - * @param t - * the exception (throwable) to log - */ - @Override - public void info(String msg, Throwable t) { - if (logger.isLoggable(Level.INFO)) { - log(SELF, Level.INFO, msg, t); - } - } - - /** - * Is this logger instance enabled for the WARNING level? - * - * @return True if this Logger is enabled for the WARNING level, false - * otherwise. - */ - @Override - public boolean isWarnEnabled() { - return logger.isLoggable(Level.WARNING); - } - - /** - * Log a message object at the WARNING level. - * - * @param msg - * - the message object to be logged - */ - @Override - public void warn(String msg) { - if (logger.isLoggable(Level.WARNING)) { - log(SELF, Level.WARNING, msg, null); - } - } - - /** - * Log a message at the WARNING level according to the specified format and - * argument. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the WARNING level. - *

- * - * @param format - * the format string - * @param arg - * the argument - */ - @Override - public void warn(String format, Object arg) { - if (logger.isLoggable(Level.WARNING)) { - FormattingTuple ft = MessageFormatter.format(format, arg); - log(SELF, Level.WARNING, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log a message at the WARNING level according to the specified format and - * arguments. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the WARNING level. - *

- * - * @param format - * the format string - * @param argA - * the first argument - * @param argB - * the second argument - */ - @Override - public void warn(String format, Object argA, Object argB) { - if (logger.isLoggable(Level.WARNING)) { - FormattingTuple ft = MessageFormatter.format(format, argA, argB); - log(SELF, Level.WARNING, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log a message at level WARNING according to the specified format and - * arguments. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the WARNING level. - *

- * - * @param format - * the format string - * @param argArray - * an array of arguments - */ - @Override - public void warn(String format, Object... argArray) { - if (logger.isLoggable(Level.WARNING)) { - FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray); - log(SELF, Level.WARNING, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log an exception (throwable) at the WARNING level with an accompanying - * message. - * - * @param msg - * the message accompanying the exception - * @param t - * the exception (throwable) to log - */ - @Override - public void warn(String msg, Throwable t) { - if (logger.isLoggable(Level.WARNING)) { - log(SELF, Level.WARNING, msg, t); - } - } - - /** - * Is this logger instance enabled for level SEVERE? - * - * @return True if this Logger is enabled for level SEVERE, false otherwise. - */ - @Override - public boolean isErrorEnabled() { - return logger.isLoggable(Level.SEVERE); - } - - /** - * Log a message object at the SEVERE level. - * - * @param msg - * - the message object to be logged - */ - @Override - public void error(String msg) { - if (logger.isLoggable(Level.SEVERE)) { - log(SELF, Level.SEVERE, msg, null); - } - } - - /** - * Log a message at the SEVERE level according to the specified format and - * argument. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the SEVERE level. - *

- * - * @param format - * the format string - * @param arg - * the argument - */ - @Override - public void error(String format, Object arg) { - if (logger.isLoggable(Level.SEVERE)) { - FormattingTuple ft = MessageFormatter.format(format, arg); - log(SELF, Level.SEVERE, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log a message at the SEVERE level according to the specified format and - * arguments. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the SEVERE level. - *

- * - * @param format - * the format string - * @param argA - * the first argument - * @param argB - * the second argument - */ - @Override - public void error(String format, Object argA, Object argB) { - if (logger.isLoggable(Level.SEVERE)) { - FormattingTuple ft = MessageFormatter.format(format, argA, argB); - log(SELF, Level.SEVERE, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log a message at level SEVERE according to the specified format and - * arguments. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the SEVERE level. - *

- * - * @param format - * the format string - * @param arguments - * an array of arguments - */ - @Override - public void error(String format, Object... arguments) { - if (logger.isLoggable(Level.SEVERE)) { - FormattingTuple ft = MessageFormatter.arrayFormat(format, arguments); - log(SELF, Level.SEVERE, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log an exception (throwable) at the SEVERE level with an accompanying - * message. - * - * @param msg - * the message accompanying the exception - * @param t - * the exception (throwable) to log - */ - @Override - public void error(String msg, Throwable t) { - if (logger.isLoggable(Level.SEVERE)) { - log(SELF, Level.SEVERE, msg, t); - } - } - - /** - * Log the message at the specified level with the specified throwable if any. - * This method creates a LogRecord and fills in caller date before calling - * this instance's JDK14 logger. - * - * See bug report #13 for more details. - */ - private void log(String callerFQCN, Level level, String msg, Throwable t) { - // millis and thread are filled by the constructor - LogRecord record = new LogRecord(level, msg); - record.setLoggerName(name()); - record.setThrown(t); - fillCallerData(callerFQCN, record); - logger.log(record); - } - - static final String SELF = JdkLogger.class.getName(); - static final String SUPER = AbstractInternalLogger.class.getName(); - - /** - * Fill in caller data if possible. - * - * @param record - * The record to update - */ - private static void fillCallerData(String callerFQCN, LogRecord record) { - StackTraceElement[] steArray = new Throwable().getStackTrace(); - - int selfIndex = -1; - for (int i = 0; i < steArray.length; i++) { - final String className = steArray[i].getClassName(); - if (className.equals(callerFQCN) || className.equals(SUPER)) { - selfIndex = i; - break; - } - } - - int found = -1; - for (int i = selfIndex + 1; i < steArray.length; i++) { - final String className = steArray[i].getClassName(); - if (!(className.equals(callerFQCN) || className.equals(SUPER))) { - found = i; - break; - } - } - - if (found != -1) { - StackTraceElement ste = steArray[found]; - // setting the class name has the side effect of setting - // the needToInferCaller variable to false. - record.setSourceClassName(ste.getClassName()); - record.setSourceMethodName(ste.getMethodName()); - } - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/JdkLoggerFactory.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/JdkLoggerFactory.java deleted file mode 100755 index 60fa706dcc..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/JdkLoggerFactory.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.internal.logging; - - -import java.util.logging.Logger; - -/** - * Logger factory which creates a - * java.util.logging - * logger. - */ -public class JdkLoggerFactory extends InternalLoggerFactory { - - @Override - public InternalLogger newInstance(String name) { - return new JdkLogger(Logger.getLogger(name)); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/Log4JLogger.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/Log4JLogger.java deleted file mode 100755 index b70fd7a890..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/Log4JLogger.java +++ /dev/null @@ -1,597 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -/** - * Copyright (c) 2004-2011 QOS.ch - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ -package com.ai.cloud.io.netty.util.internal.logging; - -import org.apache.log4j.Level; -import org.apache.log4j.Logger; - -/** - * Apache Log4J - * logger. - */ -class Log4JLogger extends AbstractInternalLogger { - - private static final long serialVersionUID = 2851357342488183058L; - - final transient Logger logger; - - /** - * Following the pattern discussed in pages 162 through 168 of "The complete - * log4j manual". - */ - static final String FQCN = Log4JLogger.class.getName(); - - // Does the log4j version in use recognize the TRACE level? - // The trace level was introduced in log4j 1.2.12. - final boolean traceCapable; - - Log4JLogger(Logger logger) { - super(logger.getName()); - this.logger = logger; - traceCapable = isTraceCapable(); - } - - private boolean isTraceCapable() { - try { - logger.isTraceEnabled(); - return true; - } catch (NoSuchMethodError ignored) { - return false; - } - } - - /** - * Is this logger instance enabled for the TRACE level? - * - * @return True if this Logger is enabled for level TRACE, false otherwise. - */ - @Override - public boolean isTraceEnabled() { - if (traceCapable) { - return logger.isTraceEnabled(); - } else { - return logger.isDebugEnabled(); - } - } - - /** - * Log a message object at level TRACE. - * - * @param msg - * - the message object to be logged - */ - @Override - public void trace(String msg) { - logger.log(FQCN, traceCapable ? Level.TRACE : Level.DEBUG, msg, null); - } - - /** - * Log a message at level TRACE according to the specified format and - * argument. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for level TRACE. - *

- * - * @param format - * the format string - * @param arg - * the argument - */ - @Override - public void trace(String format, Object arg) { - if (isTraceEnabled()) { - FormattingTuple ft = MessageFormatter.format(format, arg); - logger.log(FQCN, traceCapable ? Level.TRACE : Level.DEBUG, ft - .getMessage(), ft.getThrowable()); - } - } - - /** - * Log a message at level TRACE according to the specified format and - * arguments. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the TRACE level. - *

- * - * @param format - * the format string - * @param argA - * the first argument - * @param argB - * the second argument - */ - @Override - public void trace(String format, Object argA, Object argB) { - if (isTraceEnabled()) { - FormattingTuple ft = MessageFormatter.format(format, argA, argB); - logger.log(FQCN, traceCapable ? Level.TRACE : Level.DEBUG, ft - .getMessage(), ft.getThrowable()); - } - } - - /** - * Log a message at level TRACE according to the specified format and - * arguments. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the TRACE level. - *

- * - * @param format - * the format string - * @param arguments - * an array of arguments - */ - @Override - public void trace(String format, Object... arguments) { - if (isTraceEnabled()) { - FormattingTuple ft = MessageFormatter.arrayFormat(format, arguments); - logger.log(FQCN, traceCapable ? Level.TRACE : Level.DEBUG, ft - .getMessage(), ft.getThrowable()); - } - } - - /** - * Log an exception (throwable) at level TRACE with an accompanying message. - * - * @param msg - * the message accompanying the exception - * @param t - * the exception (throwable) to log - */ - @Override - public void trace(String msg, Throwable t) { - logger.log(FQCN, traceCapable ? Level.TRACE : Level.DEBUG, msg, t); - } - - /** - * Is this logger instance enabled for the DEBUG level? - * - * @return True if this Logger is enabled for level DEBUG, false otherwise. - */ - @Override - public boolean isDebugEnabled() { - return logger.isDebugEnabled(); - } - - /** - * Log a message object at level DEBUG. - * - * @param msg - * - the message object to be logged - */ - @Override - public void debug(String msg) { - logger.log(FQCN, Level.DEBUG, msg, null); - } - - /** - * Log a message at level DEBUG according to the specified format and - * argument. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for level DEBUG. - *

- * - * @param format - * the format string - * @param arg - * the argument - */ - @Override - public void debug(String format, Object arg) { - if (logger.isDebugEnabled()) { - FormattingTuple ft = MessageFormatter.format(format, arg); - logger.log(FQCN, Level.DEBUG, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log a message at level DEBUG according to the specified format and - * arguments. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the DEBUG level. - *

- * - * @param format - * the format string - * @param argA - * the first argument - * @param argB - * the second argument - */ - @Override - public void debug(String format, Object argA, Object argB) { - if (logger.isDebugEnabled()) { - FormattingTuple ft = MessageFormatter.format(format, argA, argB); - logger.log(FQCN, Level.DEBUG, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log a message at level DEBUG according to the specified format and - * arguments. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the DEBUG level. - *

- * - * @param format - * the format string - * @param arguments an array of arguments - */ - @Override - public void debug(String format, Object... arguments) { - if (logger.isDebugEnabled()) { - FormattingTuple ft = MessageFormatter.arrayFormat(format, arguments); - logger.log(FQCN, Level.DEBUG, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log an exception (throwable) at level DEBUG with an accompanying message. - * - * @param msg - * the message accompanying the exception - * @param t - * the exception (throwable) to log - */ - @Override - public void debug(String msg, Throwable t) { - logger.log(FQCN, Level.DEBUG, msg, t); - } - - /** - * Is this logger instance enabled for the INFO level? - * - * @return True if this Logger is enabled for the INFO level, false otherwise. - */ - @Override - public boolean isInfoEnabled() { - return logger.isInfoEnabled(); - } - - /** - * Log a message object at the INFO level. - * - * @param msg - * - the message object to be logged - */ - @Override - public void info(String msg) { - logger.log(FQCN, Level.INFO, msg, null); - } - - /** - * Log a message at level INFO according to the specified format and argument. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the INFO level. - *

- * - * @param format - * the format string - * @param arg - * the argument - */ - @Override - public void info(String format, Object arg) { - if (logger.isInfoEnabled()) { - FormattingTuple ft = MessageFormatter.format(format, arg); - logger.log(FQCN, Level.INFO, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log a message at the INFO level according to the specified format and - * arguments. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the INFO level. - *

- * - * @param format - * the format string - * @param argA - * the first argument - * @param argB - * the second argument - */ - @Override - public void info(String format, Object argA, Object argB) { - if (logger.isInfoEnabled()) { - FormattingTuple ft = MessageFormatter.format(format, argA, argB); - logger.log(FQCN, Level.INFO, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log a message at level INFO according to the specified format and - * arguments. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the INFO level. - *

- * - * @param format - * the format string - * @param argArray - * an array of arguments - */ - @Override - public void info(String format, Object... argArray) { - if (logger.isInfoEnabled()) { - FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray); - logger.log(FQCN, Level.INFO, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log an exception (throwable) at the INFO level with an accompanying - * message. - * - * @param msg - * the message accompanying the exception - * @param t - * the exception (throwable) to log - */ - @Override - public void info(String msg, Throwable t) { - logger.log(FQCN, Level.INFO, msg, t); - } - - /** - * Is this logger instance enabled for the WARN level? - * - * @return True if this Logger is enabled for the WARN level, false otherwise. - */ - @Override - public boolean isWarnEnabled() { - return logger.isEnabledFor(Level.WARN); - } - - /** - * Log a message object at the WARN level. - * - * @param msg - * - the message object to be logged - */ - @Override - public void warn(String msg) { - logger.log(FQCN, Level.WARN, msg, null); - } - - /** - * Log a message at the WARN level according to the specified format and - * argument. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the WARN level. - *

- * - * @param format - * the format string - * @param arg - * the argument - */ - @Override - public void warn(String format, Object arg) { - if (logger.isEnabledFor(Level.WARN)) { - FormattingTuple ft = MessageFormatter.format(format, arg); - logger.log(FQCN, Level.WARN, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log a message at the WARN level according to the specified format and - * arguments. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the WARN level. - *

- * - * @param format - * the format string - * @param argA - * the first argument - * @param argB - * the second argument - */ - @Override - public void warn(String format, Object argA, Object argB) { - if (logger.isEnabledFor(Level.WARN)) { - FormattingTuple ft = MessageFormatter.format(format, argA, argB); - logger.log(FQCN, Level.WARN, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log a message at level WARN according to the specified format and - * arguments. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the WARN level. - *

- * - * @param format - * the format string - * @param argArray - * an array of arguments - */ - @Override - public void warn(String format, Object... argArray) { - if (logger.isEnabledFor(Level.WARN)) { - FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray); - logger.log(FQCN, Level.WARN, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log an exception (throwable) at the WARN level with an accompanying - * message. - * - * @param msg - * the message accompanying the exception - * @param t - * the exception (throwable) to log - */ - @Override - public void warn(String msg, Throwable t) { - logger.log(FQCN, Level.WARN, msg, t); - } - - /** - * Is this logger instance enabled for level ERROR? - * - * @return True if this Logger is enabled for level ERROR, false otherwise. - */ - @Override - public boolean isErrorEnabled() { - return logger.isEnabledFor(Level.ERROR); - } - - /** - * Log a message object at the ERROR level. - * - * @param msg - * - the message object to be logged - */ - @Override - public void error(String msg) { - logger.log(FQCN, Level.ERROR, msg, null); - } - - /** - * Log a message at the ERROR level according to the specified format and - * argument. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the ERROR level. - *

- * - * @param format - * the format string - * @param arg - * the argument - */ - @Override - public void error(String format, Object arg) { - if (logger.isEnabledFor(Level.ERROR)) { - FormattingTuple ft = MessageFormatter.format(format, arg); - logger.log(FQCN, Level.ERROR, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log a message at the ERROR level according to the specified format and - * arguments. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the ERROR level. - *

- * - * @param format - * the format string - * @param argA - * the first argument - * @param argB - * the second argument - */ - @Override - public void error(String format, Object argA, Object argB) { - if (logger.isEnabledFor(Level.ERROR)) { - FormattingTuple ft = MessageFormatter.format(format, argA, argB); - logger.log(FQCN, Level.ERROR, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log a message at level ERROR according to the specified format and - * arguments. - * - *

- * This form avoids superfluous object creation when the logger is disabled - * for the ERROR level. - *

- * - * @param format - * the format string - * @param argArray - * an array of arguments - */ - @Override - public void error(String format, Object... argArray) { - if (logger.isEnabledFor(Level.ERROR)) { - FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray); - logger.log(FQCN, Level.ERROR, ft.getMessage(), ft.getThrowable()); - } - } - - /** - * Log an exception (throwable) at the ERROR level with an accompanying - * message. - * - * @param msg - * the message accompanying the exception - * @param t - * the exception (throwable) to log - */ - @Override - public void error(String msg, Throwable t) { - logger.log(FQCN, Level.ERROR, msg, t); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/Log4JLoggerFactory.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/Log4JLoggerFactory.java deleted file mode 100755 index d08c89afd4..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/Log4JLoggerFactory.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.internal.logging; - -import org.apache.log4j.Logger; - -/** - * Logger factory which creates an - * Apache Log4J - * logger. - */ -public class Log4JLoggerFactory extends InternalLoggerFactory { - - @Override - public InternalLogger newInstance(String name) { - return new Log4JLogger(Logger.getLogger(name)); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/MessageFormatter.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/MessageFormatter.java deleted file mode 100755 index 23c11a4ce3..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/MessageFormatter.java +++ /dev/null @@ -1,428 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -/** - * Copyright (c) 2004-2011 QOS.ch - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ -package com.ai.cloud.io.netty.util.internal.logging; - -import java.text.MessageFormat; -import java.util.HashMap; -import java.util.Map; - -// contributors: lizongbo: proposed special treatment of array parameter values -// Joern Huxhorn: pointed out double[] omission, suggested deep array copy - -/** - * Formats messages according to very simple substitution rules. Substitutions - * can be made 1, 2 or more arguments. - *

- *

- * For example, - *

- *

- * MessageFormatter.format("Hi {}.", "there")
- * 
- *

- * will return the string "Hi there.". - *

- * The {} pair is called the formatting anchor. It serves to designate - * the location where arguments need to be substituted within the message - * pattern. - *

- * In case your message contains the '{' or the '}' character, you do not have - * to do anything special unless the '}' character immediately follows '{'. For - * example, - *

- *

- * MessageFormatter.format("Set {1,2,3} is not equal to {}.", "1,2");
- * 
- *

- * will return the string "Set {1,2,3} is not equal to 1,2.". - *

- *

- * If for whatever reason you need to place the string "{}" in the message - * without its formatting anchor meaning, then you need to escape the - * '{' character with '\', that is the backslash character. Only the '{' - * character should be escaped. There is no need to escape the '}' character. - * For example, - *

- *

- * MessageFormatter.format("Set \\{} is not equal to {}.", "1,2");
- * 
- *

- * will return the string "Set {} is not equal to 1,2.". - *

- *

- * The escaping behavior just described can be overridden by escaping the escape - * character '\'. Calling - *

- *

- * MessageFormatter.format("File name is C:\\\\{}.", "file.zip");
- * 
- *

- * will return the string "File name is C:\file.zip". - *

- *

- * The formatting conventions are different than those of {@link MessageFormat} - * which ships with the Java platform. This is justified by the fact that - * SLF4J's implementation is 10 times faster than that of {@link MessageFormat}. - * This local performance difference is both measurable and significant in the - * larger context of the complete logging processing chain. - *

- *

- * See also {@link #format(String, Object)}, - * {@link #format(String, Object, Object)} and - * {@link #arrayFormat(String, Object[])} methods for more details. - */ -final class MessageFormatter { - static final char DELIM_START = '{'; - static final char DELIM_STOP = '}'; - static final String DELIM_STR = "{}"; - private static final char ESCAPE_CHAR = '\\'; - - /** - * Performs single argument substitution for the 'messagePattern' passed as - * parameter. - *

- * For example, - *

- *

-     * MessageFormatter.format("Hi {}.", "there");
-     * 
- *

- * will return the string "Hi there.". - *

- * - * @param messagePattern The message pattern which will be parsed and formatted - * @param arg The argument to be substituted in place of the formatting anchor - * @return The formatted message - */ - static FormattingTuple format(String messagePattern, Object arg) { - return arrayFormat(messagePattern, new Object[]{arg}); - } - - /** - * Performs a two argument substitution for the 'messagePattern' passed as - * parameter. - *

- * For example, - *

- *

-     * MessageFormatter.format("Hi {}. My name is {}.", "Alice", "Bob");
-     * 
- *

- * will return the string "Hi Alice. My name is Bob.". - * - * @param messagePattern The message pattern which will be parsed and formatted - * @param argA The argument to be substituted in place of the first formatting - * anchor - * @param argB The argument to be substituted in place of the second formatting - * anchor - * @return The formatted message - */ - static FormattingTuple format(final String messagePattern, - Object argA, Object argB) { - return arrayFormat(messagePattern, new Object[]{argA, argB}); - } - - static Throwable getThrowableCandidate(Object[] argArray) { - if (argArray == null || argArray.length == 0) { - return null; - } - - final Object lastEntry = argArray[argArray.length - 1]; - if (lastEntry instanceof Throwable) { - return (Throwable) lastEntry; - } - return null; - } - - /** - * Same principle as the {@link #format(String, Object)} and - * {@link #format(String, Object, Object)} methods except that any number of - * arguments can be passed in an array. - * - * @param messagePattern The message pattern which will be parsed and formatted - * @param argArray An array of arguments to be substituted in place of formatting - * anchors - * @return The formatted message - */ - static FormattingTuple arrayFormat(final String messagePattern, - final Object[] argArray) { - - Throwable throwableCandidate = getThrowableCandidate(argArray); - - if (messagePattern == null) { - return new FormattingTuple(null, argArray, throwableCandidate); - } - - if (argArray == null) { - return new FormattingTuple(messagePattern); - } - - int i = 0; - int j; - StringBuffer sbuf = new StringBuffer(messagePattern.length() + 50); - - int L; - for (L = 0; L < argArray.length; L++) { - - j = messagePattern.indexOf(DELIM_STR, i); - - if (j == -1) { - // no more variables - if (i == 0) { // this is a simple string - return new FormattingTuple(messagePattern, argArray, - throwableCandidate); - } else { // add the tail string which contains no variables and return - // the result. - sbuf.append(messagePattern.substring(i, messagePattern.length())); - return new FormattingTuple(sbuf.toString(), argArray, - throwableCandidate); - } - } else { - if (isEscapedDelimeter(messagePattern, j)) { - if (!isDoubleEscaped(messagePattern, j)) { - L--; // DELIM_START was escaped, thus should not be incremented - sbuf.append(messagePattern.substring(i, j - 1)); - sbuf.append(DELIM_START); - i = j + 1; - } else { - // The escape character preceding the delimiter start is - // itself escaped: "abc x:\\{}" - // we have to consume one backward slash - sbuf.append(messagePattern.substring(i, j - 1)); - deeplyAppendParameter(sbuf, argArray[L], new HashMap()); - i = j + 2; - } - } else { - // normal case - sbuf.append(messagePattern.substring(i, j)); - deeplyAppendParameter(sbuf, argArray[L], new HashMap()); - i = j + 2; - } - } - } - // append the characters following the last {} pair. - sbuf.append(messagePattern.substring(i, messagePattern.length())); - if (L < argArray.length - 1) { - return new FormattingTuple(sbuf.toString(), argArray, throwableCandidate); - } else { - return new FormattingTuple(sbuf.toString(), argArray, null); - } - } - - static boolean isEscapedDelimeter(String messagePattern, - int delimeterStartIndex) { - - if (delimeterStartIndex == 0) { - return false; - } - return messagePattern.charAt(delimeterStartIndex - 1) == ESCAPE_CHAR; - } - - static boolean isDoubleEscaped(String messagePattern, - int delimeterStartIndex) { - return delimeterStartIndex >= 2 && messagePattern.charAt(delimeterStartIndex - 2) == ESCAPE_CHAR; - } - - // special treatment of array values was suggested by 'lizongbo' - private static void deeplyAppendParameter(StringBuffer sbuf, Object o, - Map seenMap) { - if (o == null) { - sbuf.append("null"); - return; - } - if (!o.getClass().isArray()) { - safeObjectAppend(sbuf, o); - } else { - // check for primitive array types because they - // unfortunately cannot be cast to Object[] - if (o instanceof boolean[]) { - booleanArrayAppend(sbuf, (boolean[]) o); - } else if (o instanceof byte[]) { - byteArrayAppend(sbuf, (byte[]) o); - } else if (o instanceof char[]) { - charArrayAppend(sbuf, (char[]) o); - } else if (o instanceof short[]) { - shortArrayAppend(sbuf, (short[]) o); - } else if (o instanceof int[]) { - intArrayAppend(sbuf, (int[]) o); - } else if (o instanceof long[]) { - longArrayAppend(sbuf, (long[]) o); - } else if (o instanceof float[]) { - floatArrayAppend(sbuf, (float[]) o); - } else if (o instanceof double[]) { - doubleArrayAppend(sbuf, (double[]) o); - } else { - objectArrayAppend(sbuf, (Object[]) o, seenMap); - } - } - } - - private static void safeObjectAppend(StringBuffer sbuf, Object o) { - try { - String oAsString = o.toString(); - sbuf.append(oAsString); - } catch (Throwable t) { - System.err - .println("SLF4J: Failed toString() invocation on an object of type [" - + o.getClass().getName() + ']'); - t.printStackTrace(); - sbuf.append("[FAILED toString()]"); - } - } - - private static void objectArrayAppend(StringBuffer sbuf, Object[] a, - Map seenMap) { - sbuf.append('['); - if (!seenMap.containsKey(a)) { - seenMap.put(a, null); - final int len = a.length; - for (int i = 0; i < len; i++) { - deeplyAppendParameter(sbuf, a[i], seenMap); - if (i != len - 1) { - sbuf.append(", "); - } - } - // allow repeats in siblings - seenMap.remove(a); - } else { - sbuf.append("..."); - } - sbuf.append(']'); - } - - private static void booleanArrayAppend(StringBuffer sbuf, boolean[] a) { - sbuf.append('['); - final int len = a.length; - for (int i = 0; i < len; i++) { - sbuf.append(a[i]); - if (i != len - 1) { - sbuf.append(", "); - } - } - sbuf.append(']'); - } - - private static void byteArrayAppend(StringBuffer sbuf, byte[] a) { - sbuf.append('['); - final int len = a.length; - for (int i = 0; i < len; i++) { - sbuf.append(a[i]); - if (i != len - 1) { - sbuf.append(", "); - } - } - sbuf.append(']'); - } - - private static void charArrayAppend(StringBuffer sbuf, char[] a) { - sbuf.append('['); - final int len = a.length; - for (int i = 0; i < len; i++) { - sbuf.append(a[i]); - if (i != len - 1) { - sbuf.append(", "); - } - } - sbuf.append(']'); - } - - private static void shortArrayAppend(StringBuffer sbuf, short[] a) { - sbuf.append('['); - final int len = a.length; - for (int i = 0; i < len; i++) { - sbuf.append(a[i]); - if (i != len - 1) { - sbuf.append(", "); - } - } - sbuf.append(']'); - } - - private static void intArrayAppend(StringBuffer sbuf, int[] a) { - sbuf.append('['); - final int len = a.length; - for (int i = 0; i < len; i++) { - sbuf.append(a[i]); - if (i != len - 1) { - sbuf.append(", "); - } - } - sbuf.append(']'); - } - - private static void longArrayAppend(StringBuffer sbuf, long[] a) { - sbuf.append('['); - final int len = a.length; - for (int i = 0; i < len; i++) { - sbuf.append(a[i]); - if (i != len - 1) { - sbuf.append(", "); - } - } - sbuf.append(']'); - } - - private static void floatArrayAppend(StringBuffer sbuf, float[] a) { - sbuf.append('['); - final int len = a.length; - for (int i = 0; i < len; i++) { - sbuf.append(a[i]); - if (i != len - 1) { - sbuf.append(", "); - } - } - sbuf.append(']'); - } - - private static void doubleArrayAppend(StringBuffer sbuf, double[] a) { - sbuf.append('['); - final int len = a.length; - for (int i = 0; i < len; i++) { - sbuf.append(a[i]); - if (i != len - 1) { - sbuf.append(", "); - } - } - sbuf.append(']'); - } - - private MessageFormatter() { - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/Slf4JLogger.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/Slf4JLogger.java deleted file mode 100755 index 531570e5e0..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/Slf4JLogger.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.internal.logging; - -import org.slf4j.Logger; - -/** - * SLF4J logger. - */ -class Slf4JLogger extends AbstractInternalLogger { - - private static final long serialVersionUID = 108038972685130825L; - - private final transient Logger logger; - - Slf4JLogger(Logger logger) { - super(logger.getName()); - this.logger = logger; - } - - @Override - public boolean isTraceEnabled() { - return logger.isTraceEnabled(); - } - - @Override - public void trace(String msg) { - logger.trace(msg); - } - - @Override - public void trace(String format, Object arg) { - logger.trace(format, arg); - } - - @Override - public void trace(String format, Object argA, Object argB) { - logger.trace(format, argA, argB); - } - - @Override - public void trace(String format, Object... argArray) { - logger.trace(format, argArray); - } - - @Override - public void trace(String msg, Throwable t) { - logger.trace(msg, t); - } - - @Override - public boolean isDebugEnabled() { - return logger.isDebugEnabled(); - } - - @Override - public void debug(String msg) { - logger.debug(msg); - } - - @Override - public void debug(String format, Object arg) { - logger.debug(format, arg); - } - - @Override - public void debug(String format, Object argA, Object argB) { - logger.debug(format, argA, argB); - } - - @Override - public void debug(String format, Object... argArray) { - logger.debug(format, argArray); - } - - @Override - public void debug(String msg, Throwable t) { - logger.debug(msg, t); - } - - @Override - public boolean isInfoEnabled() { - return logger.isInfoEnabled(); - } - - @Override - public void info(String msg) { - logger.info(msg); - } - - @Override - public void info(String format, Object arg) { - logger.info(format, arg); - } - - @Override - public void info(String format, Object argA, Object argB) { - logger.info(format, argA, argB); - } - - @Override - public void info(String format, Object... argArray) { - logger.info(format, argArray); - } - - @Override - public void info(String msg, Throwable t) { - logger.info(msg, t); - } - - @Override - public boolean isWarnEnabled() { - return logger.isWarnEnabled(); - } - - @Override - public void warn(String msg) { - logger.warn(msg); - } - - @Override - public void warn(String format, Object arg) { - logger.warn(format, arg); - } - - @Override - public void warn(String format, Object... argArray) { - logger.warn(format, argArray); - } - - @Override - public void warn(String format, Object argA, Object argB) { - logger.warn(format, argA, argB); - } - - @Override - public void warn(String msg, Throwable t) { - logger.warn(msg, t); - } - - @Override - public boolean isErrorEnabled() { - return logger.isErrorEnabled(); - } - - @Override - public void error(String msg) { - logger.error(msg); - } - - @Override - public void error(String format, Object arg) { - logger.error(format, arg); - } - - @Override - public void error(String format, Object argA, Object argB) { - logger.error(format, argA, argB); - } - - @Override - public void error(String format, Object... argArray) { - logger.error(format, argArray); - } - - @Override - public void error(String msg, Throwable t) { - logger.error(msg, t); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/Slf4JLoggerFactory.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/Slf4JLoggerFactory.java deleted file mode 100755 index 94fc735d72..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/Slf4JLoggerFactory.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package com.ai.cloud.io.netty.util.internal.logging; - - -import org.slf4j.LoggerFactory; -import org.slf4j.helpers.NOPLoggerFactory; - -import java.io.OutputStream; -import java.io.PrintStream; -import java.io.UnsupportedEncodingException; - -/** - * Logger factory which creates a SLF4J - * logger. - */ -public class Slf4JLoggerFactory extends InternalLoggerFactory { - - public Slf4JLoggerFactory() { - } - - Slf4JLoggerFactory(boolean failIfNOP) { - assert failIfNOP; // Should be always called with true. - - // SFL4J writes it error messages to System.err. Capture them so that the user does not see such a message on - // the console during automatic detection. - final StringBuffer buf = new StringBuffer(); - final PrintStream err = System.err; - try { - System.setErr(new PrintStream(new OutputStream() { - @Override - public void write(int b) { - buf.append((char) b); - } - }, true, "US-ASCII")); - } catch (UnsupportedEncodingException e) { - throw new Error(e); - } - - try { - if (LoggerFactory.getILoggerFactory() instanceof NOPLoggerFactory) { - throw new NoClassDefFoundError(buf.toString()); - } else { - err.print(buf); - err.flush(); - } - } finally { - System.setErr(err); - } - } - - @Override - public InternalLogger newInstance(String name) { - return new Slf4JLogger(LoggerFactory.getLogger(name)); - } -} diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/package-info.java deleted file mode 100755 index 769c4945f4..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/logging/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * Internal-use-only logging API which is not allowed to be used outside Netty. - */ -package com.ai.cloud.io.netty.util.internal.logging; diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/package-info.java deleted file mode 100755 index d5eddfeb19..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/internal/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * Internal-use-only utilities which is not allowed to be used - * outside Netty. - */ -package com.ai.cloud.io.netty.util.internal; diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/package-info.java b/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/package-info.java deleted file mode 100755 index f3d55bc4c1..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/util/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/** - * Utility classes used across multiple packages. - */ -package com.ai.cloud.io.netty.util; diff --git a/skywalking-api/src/main/java/com/ai/cloud/io/netty/version.md b/skywalking-api/src/main/java/com/ai/cloud/io/netty/version.md deleted file mode 100644 index 5e2967222a..0000000000 --- a/skywalking-api/src/main/java/com/ai/cloud/io/netty/version.md +++ /dev/null @@ -1,10 +0,0 @@ -# Sky Walking API -## dependency io.netty -```xml - - io.netty - netty-all - 4.0.33.Final - -``` -* 移除部分代码,移除依赖性编译 \ No newline at end of file diff --git a/skywalking-api/src/main/java/com/ai/cloud/skywalking/sender/DataSender.java b/skywalking-api/src/main/java/com/ai/cloud/skywalking/sender/DataSender.java index 0d90345af5..4737b80088 100644 --- a/skywalking-api/src/main/java/com/ai/cloud/skywalking/sender/DataSender.java +++ b/skywalking-api/src/main/java/com/ai/cloud/skywalking/sender/DataSender.java @@ -1,23 +1,24 @@ package com.ai.cloud.skywalking.sender; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.codec.LengthFieldBasedFrameDecoder; +import io.netty.handler.codec.LengthFieldPrepender; +import io.netty.handler.codec.bytes.ByteArrayDecoder; +import io.netty.handler.codec.bytes.ByteArrayEncoder; + import java.io.IOException; import java.net.InetSocketAddress; -import com.ai.cloud.io.netty.bootstrap.Bootstrap; -import com.ai.cloud.io.netty.channel.Channel; -import com.ai.cloud.io.netty.channel.ChannelHandlerContext; -import com.ai.cloud.io.netty.channel.ChannelInboundHandlerAdapter; -import com.ai.cloud.io.netty.channel.ChannelInitializer; -import com.ai.cloud.io.netty.channel.ChannelOption; -import com.ai.cloud.io.netty.channel.ChannelPipeline; -import com.ai.cloud.io.netty.channel.EventLoopGroup; -import com.ai.cloud.io.netty.channel.nio.NioEventLoopGroup; -import com.ai.cloud.io.netty.channel.socket.SocketChannel; -import com.ai.cloud.io.netty.channel.socket.nio.NioSocketChannel; -import com.ai.cloud.io.netty.handler.codec.LengthFieldBasedFrameDecoder; -import com.ai.cloud.io.netty.handler.codec.LengthFieldPrepender; -import com.ai.cloud.io.netty.handler.codec.bytes.ByteArrayDecoder; -import com.ai.cloud.io.netty.handler.codec.bytes.ByteArrayEncoder; import com.ai.cloud.skywalking.selfexamination.HeathReading; import com.ai.cloud.skywalking.selfexamination.SDKHealthCollector; diff --git a/skywalking-api/src/test/java/test/ai/cloud/bytebuddy/Interceptor.java b/skywalking-api/src/test/java/test/ai/cloud/bytebuddy/Interceptor.java new file mode 100644 index 0000000000..7180f2b1ca --- /dev/null +++ b/skywalking-api/src/test/java/test/ai/cloud/bytebuddy/Interceptor.java @@ -0,0 +1,22 @@ +package test.ai.cloud.bytebuddy; + +import java.lang.reflect.Method; +import java.util.concurrent.Callable; + +import net.bytebuddy.implementation.bind.annotation.AllArguments; +import net.bytebuddy.implementation.bind.annotation.Origin; +import net.bytebuddy.implementation.bind.annotation.RuntimeType; +import net.bytebuddy.implementation.bind.annotation.SuperCall; + +public class Interceptor{ + @RuntimeType + public Object intercept(@AllArguments Object[] allArguments, @Origin Method method, @SuperCall Callable zuper){ + try { + return "intercept_" + zuper.call(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return null; + } + } +} diff --git a/skywalking-api/src/test/java/test/ai/cloud/bytebuddy/SimulateMain.java b/skywalking-api/src/test/java/test/ai/cloud/bytebuddy/SimulateMain.java new file mode 100644 index 0000000000..453c53b6f8 --- /dev/null +++ b/skywalking-api/src/test/java/test/ai/cloud/bytebuddy/SimulateMain.java @@ -0,0 +1,49 @@ +package test.ai.cloud.bytebuddy; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import net.bytebuddy.ByteBuddy; +import net.bytebuddy.dynamic.ClassFileLocator; +import net.bytebuddy.dynamic.loading.ClassLoadingStrategy; +import net.bytebuddy.implementation.MethodDelegation; +import net.bytebuddy.pool.TypePool; + +public class SimulateMain { + public static void main(String[] args) throws NoSuchFieldException, + SecurityException, InstantiationException, IllegalAccessException { + TypePool typePool = TypePool.Default.ofClassPath(); + + Object newClazzObj = new ByteBuddy() + .redefine( + typePool.describe( + "test.ai.cloud.bytebuddy.TestClass") + .resolve(), + ClassFileLocator.ForClassLoader.ofClassPath()) + .name("test.ai.cloud.bytebuddy.TestClass$$Origin") + .make() + .load(ClassLoader.getSystemClassLoader(), + ClassLoadingStrategy.Default.INJECTION).getLoaded().newInstance(); + + TestClass t22 = (TestClass)(new ByteBuddy() + .subclass(newClazzObj.getClass()) + .method(named("testA")) + .intercept(MethodDelegation.to(new Interceptor())) + .name("test.ai.cloud.bytebuddy.TestClass") + .make() + .load(ClassLoader.getSystemClassLoader(), + ClassLoadingStrategy.Default.INJECTION).getLoaded().newInstance()); + + //System.out.println(t22.testA("1")); + + TestClass t = new TestClass(); + System.out.println(t.testA("1")); + + TestClass t2 = null; + try { + t2 = (TestClass)Class.forName("test.ai.cloud.bytebuddy.TestClass").newInstance(); + } catch (ClassNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + System.out.println(t2.testA("1")); + } +} diff --git a/skywalking-api/src/test/java/test/ai/cloud/bytebuddy/TestClass.java b/skywalking-api/src/test/java/test/ai/cloud/bytebuddy/TestClass.java new file mode 100644 index 0000000000..4a2129badd --- /dev/null +++ b/skywalking-api/src/test/java/test/ai/cloud/bytebuddy/TestClass.java @@ -0,0 +1,8 @@ +package test.ai.cloud.bytebuddy; + +public class TestClass { + public String testA(String aa){ +// throw new RuntimeException("adfasdfas"); + return "TestClass.testA"; + } +} -- GitLab