/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES 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.msec.net;
import api.monitor.msec.org.AccessMonitor;
import com.google.protobuf.MessageLite;
import org.apache.log4j.Logger;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBufferOutputStream;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
import org.msec.rpc.RpcRequest;
import org.msec.rpc.ServiceFactory;
import srpc.Head;
import com.google.protobuf.ByteString;
import java.io.IOException;
public class RequestEncoder extends OneToOneEncoder {
private static Logger log = Logger.getLogger(RequestEncoder.class.getName());
protected int encodeHead(RpcRequest rpcRequest, ChannelBufferOutputStream stream) throws IOException {
//TODO: set coloring, color_id & caller..
//System.out.println("Start encode request head: " + System.currentTimeMillis());
String serviceMethodName = rpcRequest.getServiceName() + "." + rpcRequest.getMethodName();
long colorId = NettyCodecUtils.generateColorId(serviceMethodName);
Head.CRpcHead.Builder builder = Head.CRpcHead.newBuilder();
builder.clear();
builder.setSequence(rpcRequest.getSeq());
builder.setColoring(0);
builder.setColorId(colorId);
if (rpcRequest.getFlowid() == 0) {
builder.setFlowId(rpcRequest.getSeq() ^ colorId);
} else {
builder.setFlowId(rpcRequest.getFlowid());
}
builder.setErr(0);
builder.setResult(0);
builder.setErrMsg(ByteString.EMPTY);
builder.setCaller(ByteString.copyFromUtf8(ServiceFactory.getModuleName()));
builder.setMethodName(ByteString.copyFrom((serviceMethodName).getBytes()));
builder.addCallerStack(ByteString.EMPTY);
//System.out.println("Start encode request head3: " + System.currentTimeMillis());
Head.CRpcHead rpchead = builder.build();
stream.write(rpchead.toByteArray());
//System.out.println("Start encode request head4: " + System.currentTimeMillis());
AccessMonitor.add("frm.rpc call to " + rpcRequest.getServiceName() + "/" + rpcRequest.getMethodName());
return rpchead.getSerializedSize();
}
protected int encodeBody(RpcRequest rpcRequest, ChannelBufferOutputStream stream) throws IOException {
MessageLite message = (MessageLite)rpcRequest.getParameter();
stream.write(message.toByteArray());
return message.getSerializedSize();
}
protected ChannelBuffer encode(ChannelHandlerContext channelHandlerContext, RpcRequest rpcRequest, ChannelBufferOutputStream stream) throws IOException {
stream.writeByte('(');
stream.writeLong(0);
int headLen = encodeHead(rpcRequest, stream);
int bodyLen = encodeBody(rpcRequest, stream);
stream.writeByte(')');
ChannelBuffer buffer = stream.buffer();
buffer.setInt(1, headLen);
buffer.setInt(5, bodyLen);
return buffer;
}
private static final int estimatedLength = 1024;
@Override
protected Object encode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception {
if (msg instanceof RpcRequest) {
RpcRequest message = (RpcRequest) msg;
try {
ChannelBufferOutputStream bout = new ChannelBufferOutputStream(ChannelBuffers.dynamicBuffer(estimatedLength, ctx.getChannel()
.getConfig().getBufferFactory()));
//Set proto flag = 0
NettyCodecUtils.setAttachment(ctx, Constants.ATTACHMENT_CUSTOM_PROTO_FLAG, new Integer(0));
ChannelBuffer ret = encode(ctx, message, bout);
return ret;
} catch (Exception ex) {
log.error(ex.getMessage(), ex);
throw ex;
}
}
if (msg instanceof Object[]) {
Object[] objects = (Object[])msg;
//Set proto flag=1
NettyCodecUtils.setAttachment(ctx, Constants.ATTACHMENT_CUSTOM_PROTO_FLAG, new Integer(1));
NettyCodecUtils.setAttachment(ctx, Constants.ATTACHMENT_CUSTOM_PROTO_CODEC, objects[1]);
NettyCodecUtils.setAttachment(ctx, Constants.ATTACHMENT_CUSTOM_PROTO_SEQUENCE, objects[2]);
if (objects[0] instanceof byte[]) {
byte[] msgData = (byte[])objects[0];
int tmpLength = estimatedLength;
if (msgData.length > tmpLength) {
tmpLength = msgData.length;
}
ChannelBufferOutputStream bout = new ChannelBufferOutputStream(ChannelBuffers.dynamicBuffer(tmpLength,
ctx.getChannel().getConfig().getBufferFactory()));
bout.write(msgData);
return bout.buffer();
} else {
return objects[0];
}
}
return null;
}
}