Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.giraph.comm.netty.handler; import io.netty.buffer.ByteBufOutputStream; import org.apache.giraph.comm.requests.WritableRequest; import org.apache.giraph.conf.GiraphConfiguration; import org.apache.giraph.conf.GiraphConstants; import org.apache.giraph.time.SystemTime; import org.apache.giraph.time.Time; import org.apache.giraph.time.Times; import org.apache.log4j.Logger; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelOutboundHandlerAdapter; import io.netty.channel.ChannelPromise; import static org.apache.giraph.utils.ByteUtils.SIZE_OF_BYTE; import static org.apache.giraph.utils.ByteUtils.SIZE_OF_INT; /** * Requests have a request type and an encoded request. */ public class RequestEncoder extends ChannelOutboundHandlerAdapter { /** Class logger */ private static final Logger LOG = Logger.getLogger(RequestEncoder.class); /** Time class to use */ private static final Time TIME = SystemTime.get(); /** Buffer starting size */ private final int bufferStartingSize; /** Start nanoseconds for the encoding time */ private long startEncodingNanoseconds = -1; /** * Constructor. * * @param conf Giraph configuration */ public RequestEncoder(GiraphConfiguration conf) { bufferStartingSize = GiraphConstants.NETTY_REQUEST_ENCODER_BUFFER_SIZE.get(conf); } @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { if (!(msg instanceof WritableRequest)) { throw new IllegalArgumentException("encode: Got a message of type " + msg.getClass()); } // Encode the request if (LOG.isDebugEnabled()) { startEncodingNanoseconds = TIME.getNanoseconds(); } ByteBuf buf; WritableRequest request = (WritableRequest) msg; int requestSize = request.getSerializedSize(); if (requestSize == WritableRequest.UNKNOWN_SIZE) { buf = ctx.alloc().buffer(bufferStartingSize); } else { requestSize += SIZE_OF_INT + SIZE_OF_BYTE; buf = ctx.alloc().buffer(requestSize); } ByteBufOutputStream output = new ByteBufOutputStream(buf); // This will later be filled with the correct size of serialized request output.writeInt(0); output.writeByte(request.getType().ordinal()); try { request.write(output); } catch (IndexOutOfBoundsException e) { LOG.error("write: Most likely the size of request was not properly " + "specified (this buffer is too small) - see getSerializedSize() " + "in " + request.getType().getRequestClass()); throw new IllegalStateException(e); } output.flush(); output.close(); // Set the correct size at the end buf.setInt(0, buf.writerIndex() - SIZE_OF_INT); if (LOG.isDebugEnabled()) { LOG.debug("write: Client " + request.getClientId() + ", " + "requestId " + request.getRequestId() + ", size = " + buf.readableBytes() + ", " + request.getType() + " took " + Times.getNanosSince(TIME, startEncodingNanoseconds) + " ns"); } ctx.write(buf, promise); } }