/**
* 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 backtype.storm.serialization;
import backtype.storm.Config;
import backtype.storm.generated.StormTopology;
import backtype.storm.tuple.MessageId;
import backtype.storm.tuple.Tuple;
import backtype.storm.tuple.TupleExt;
import com.alibaba.jstorm.client.ConfigExtension;
import com.alibaba.jstorm.utils.JStormUtils;
import com.alibaba.jstorm.utils.Pair;
import com.esotericsoftware.kryo.io.Output;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.Map;
public class KryoTupleSerializer implements ITupleSerializer {
KryoValuesSerializer _kryo;
SerializationFactory.IdDictionary _ids;
Output _kryoOut;
int _ackerNum;
boolean _isTransactionTuple;
public KryoTupleSerializer(final Map conf, final StormTopology topology) {
_kryo = new KryoValuesSerializer(conf);
_kryoOut = new Output(2000, 2000000000);
_ackerNum = JStormUtils.parseInt(conf.get(Config.TOPOLOGY_ACKER_EXECUTORS), 0);
_ids = new SerializationFactory.IdDictionary(topology);
_isTransactionTuple = JStormUtils.parseBoolean(conf.get(ConfigExtension.TRANSACTION_TOPOLOGY), false);
}
public byte[] serialize(Tuple tuple) {
_kryoOut.clear();
serializeTuple(_kryoOut, tuple);
return _kryoOut.toBytes();
}
/**
* @see backtype.storm.serialization.ITupleSerializer#serialize(int, backtype.storm.tuple.Tuple)
*/
private void serializeTuple(Output output, Tuple tuple) {
try {
boolean isBatchTuple = false;
if (tuple instanceof TupleExt) {
output.writeInt(((TupleExt) tuple).getTargetTaskId());
output.writeLong(((TupleExt) tuple).getCreationTimeStamp());
output.writeBoolean(((TupleExt) tuple).isBatchTuple());
isBatchTuple = ((TupleExt) tuple).isBatchTuple();
}
output.writeInt(tuple.getSourceTask(), true);
output.writeInt(_ids.getStreamId(tuple.getSourceComponent(), tuple.getSourceStreamId()), true);
if (isBatchTuple) {
if (_isTransactionTuple) {
output.writeLong(((TupleExt) tuple).getBatchId(), true);
}
List<Object> values = tuple.getValues();
int len = values.size();
output.writeInt(len, true);
if (_ackerNum > 0) {
for (Object value : values) {
Pair<MessageId, List<Object>> pairValue = (Pair<MessageId, List<Object>>) value;
if (pairValue.getFirst() != null) {
pairValue.getFirst().serialize(output);
} else {
output.writeInt(0, true);
}
_kryo.serializeInto(pairValue.getSecond(), output);
}
} else {
for (Object value : values) {
Pair<MessageId, List<Object>> pairValue = (Pair<MessageId, List<Object>>) value;
_kryo.serializeInto(pairValue.getSecond(), output);
}
}
} else {
MessageId msgId = tuple.getMessageId();
if (msgId != null) {
msgId.serialize(output);
} else {
output.writeInt(0, true);
}
_kryo.serializeInto(tuple.getValues(), output);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static byte[] serialize(int targetTask) {
ByteBuffer buff = ByteBuffer.allocate((Integer.SIZE / 8));
buff.putInt(targetTask);
return buff.array();
}
// public long crc32(Tuple tuple) {
// try {
// CRC32OutputStream hasher = new CRC32OutputStream();
// _kryo.serializeInto(tuple.getValues(), hasher);
// return hasher.getValue();
// } catch (IOException e) {
// throw new RuntimeException(e);
// }
// }
}