/**
* Copyright 2013-2015 Seagate Technology LLC.
*
* This Source Code Form is subject to the terms of the Mozilla
* Public License, v. 2.0. If a copy of the MPL was not
* distributed with this file, You can obtain one at
* https://mozilla.org/MP:/2.0/.
*
* This program is distributed in the hope that it will be useful,
* but is provided AS-IS, WITHOUT ANY WARRANTY; including without
* the implied warranty of MERCHANTABILITY, NON-INFRINGEMENT or
* FITNESS FOR A PARTICULAR PURPOSE. See the Mozilla Public
* License for more details.
*
* See www.openkinetic.org for more project information
*/
package com.seagate.kinetic.common.protocol.codec;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.seagate.kinetic.common.lib.KineticMessage;
import com.seagate.kinetic.common.lib.ProtocolMessageUtil;
import com.seagate.kinetic.proto.Kinetic.Message;
import com.seagate.kinetic.proto.Kinetic.Message.Builder;
/**
*
* Kinetic protocol buffer message encoder (version2 protocol).
* <p>
* The client library, simulator, or a Kinetic drive uses the following protocol
* to encode a message.
* <p>
* <ul>
* <li>1. write magic byte 'F'
* <li>2. write protocol buffer message length.
* <li>3. write value length (0 if no value)
* <li>4. write protobuf message byte[]
* <li>5. write value byte[] if any
* </ul>
* <p>
*
* To log/print the encoded message, set the "kinetic.io.out" Java System
* property to true.
* <p>
* For example, set the following Java VM argument when running a Kinetic
* application or Simulator.
* <p>
* -D"kinetic.io.out"=true
*
* @author chiaming
*/
public class KineticEncoder extends MessageToByteEncoder<KineticMessage> {
private final Logger logger = Logger.getLogger(KineticEncoder.class
.getName());
private static boolean printMessage = Boolean.getBoolean("kinetic.io.out");
@Override
protected void encode(ChannelHandlerContext ctx, KineticMessage km,
ByteBuf out) throws Exception {
try {
// get value to write separately
// byte[] value = builder.getValue().toByteArray();
byte[] value = km.getValue();
// 1. write magic number
out.writeByte((byte) 'F');
//get message
Message.Builder messageBuilder = (Builder) km.getMessage();
// build message
Message msg = messageBuilder.build();
// get proto message bytes
byte[] protoMessageBytes = msg.toByteArray();
// 2. write protobuf message message size, 4 byte
out.writeInt(protoMessageBytes.length);
// 3. write attached value size, 4 byte
if (value != null) {
out.writeInt(value.length);
} else {
out.writeInt(0);
}
// 4. write protobuf message byte[]
out.writeBytes(protoMessageBytes);
// 5 (optional) write attached value if any
if (value != null && value.length > 0) {
// write value
out.writeBytes(value);
}
// log message out
if (printMessage) {
logger.info("outbound protocol message:");
String printMsg = ProtocolMessageUtil.toString(km);
logger.info(printMsg);
}
} catch (Exception e) {
logger.log(Level.WARNING, e.getMessage(), e);
throw e;
}
}
}