/*
Netwrapper - A library for easy networking in Java
Copyright (C) 2014, University of Lugano
This file is part of Netwrapper.
Netwrapper is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package ch.usi.dslab.bezerra.netwrapper;
import java.io.Serializable;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import ch.usi.dslab.bezerra.netwrapper.codecs.Codec;
import ch.usi.dslab.bezerra.netwrapper.codecs.CodecUncompressedKryo;
public class Message implements Serializable {
static Logger logger = LogManager.getLogger(Message.class.getName());
private static final long serialVersionUID = 4104839889665917909L;
private static Codec codec = new CodecUncompressedKryo();
// *******************************************
// LATENCY TIMELINE
// *******************************************
public long t_client_send;
public long t_coord_recv;
public long t_coord_opt_merge;
public long t_batch_ready;
public long t_learner_received;
public long t_learner_delivered;
public long t_learner_deserialized;
public long t_command_enqueued;
public long t_command_dequeued;
public long t_execution_start;
public boolean waitedObject;
public long t_start_waiting_object;
public long t_end_waiting_object;
public long t_server_send;
public long t_client_receive;
public long piggyback_proposer_serialstart;
public long piggyback_proposer_serialend;
// *******************************************
// *******************************************
ArrayList<Object> contents;
transient int next = 0;
int byteArraysAggregatedLength = 0;
boolean packedContents = false;
byte [] contentsPack = null;
private Message(Message original) {
this.contents = original.contents;
this.next = original.next;
this.byteArraysAggregatedLength = original.byteArraysAggregatedLength;
this.packedContents = original.packedContents;
this.contentsPack = original.contentsPack;
this.copyTimelineStamps(original);
}
public Message() {
contents = new ArrayList<Object>();
}
public Message(Object... objs) {
contents = new ArrayList<Object>(objs.length);
addItems(objs);
}
public int packContents() {
assert(packedContents == false);
int packLength = 0;
if (contents != null) {
contentsPack = Message.codec.getBytes(contents);
packLength = contentsPack.length;
}
contents = null;
packedContents = true;
return packLength;
}
@SuppressWarnings("unchecked")
public int unpackContents() {
assert(packedContents == true);
int packLength = 0;
if (contentsPack != null) {
contents = (ArrayList<Object>) Message.codec.createObjectFromBytes(contentsPack);
packLength = contentsPack.length;
}
contentsPack = null;
packedContents = false;
logger.info("Just unpacked a message");
return packLength;
}
public int getPackSize() {
assert(packedContents == true);
if (contentsPack != null)
return contentsPack.length;
else
return 0;
}
public int getByteArraysAggregatedLength() {
return byteArraysAggregatedLength;
}
public void addItems(Object... objs) {
assert(packedContents == false);
contents.ensureCapacity(contents.size() + objs.length);
for (Object o : objs) {
if (o instanceof Object[])
addItems((Object[]) o);
else
contents.add(o);
// counting the total size of added arrays
if (o instanceof byte[]) {
byteArraysAggregatedLength += ((byte[]) o).length;
}
}
}
public void pushFront(Object... objs) {
assert(packedContents == false);
contents.ensureCapacity(contents.size() + objs.length);
int pos = 0;
for (Object o : objs) {
contents.add(pos++, o);
// counting the total size of added arrays
if (o instanceof byte[]) {
byteArraysAggregatedLength += ((byte[]) o).length;
}
}
}
public void rewind() {
assert(packedContents == false);
next = 0;
}
public void seek(int pos) {
assert(packedContents == false);
next = pos;
}
public boolean hasNext() {
assert(packedContents == false);
return next < contents.size();
}
public Object getNext() {
assert(packedContents == false);
return getItem(next++);
}
public Object peekNext() {
assert(packedContents == false);
return getItem(next);
}
public Object getItem(int index) {
assert(packedContents == false);
if (index >= contents.size())
return null;
return contents.get(index);
}
public void setItem(int index, Object o) {
assert(packedContents == false);
contents.set(index, o);
}
public int count() {
assert(packedContents == false);
return contents.size();
}
public void stripContents() {
this.contents = null;
this.contentsPack = null;
}
public void setContents(ArrayList<Object> contents) {
assert(packedContents == false);
this.contents = contents;
}
public ArrayList<Object> getContents() {
assert(packedContents == false);
return this.contents;
}
public void copyContentsList(Message other) {
assert(packedContents == false);
this.contents = new ArrayList<Object>(other.contents);
}
public int getSerializedLengthWithLengthHeader() {
return codec.getByteBufferWithLengthHeader(this).limit();
}
public byte[] getBytes() {
return codec.getBytes(this);
}
public ByteBuffer getByteBufferWithLengthHeader() {
return codec.getByteBufferWithLengthHeader(this);
}
public static Message createFromBytes(byte[] bytes) {
return (Message) codec.createObjectFromBytes(bytes);
}
public static Message createFromByteBufferWithLengthHeader(ByteBuffer buffer) {
return (Message) codec.createObjectFromByteBufferWithLengthHeader(buffer);
}
public static void setCodec(Codec codec) {
Message.codec = codec;
}
public Message duplicate() {
return new Message(this);
}
public Message deepDuplicate() {
Codec codec = new CodecUncompressedKryo();
Message copy = (Message) codec.deepDuplicate(this);
return copy;
}
public void copyTimelineStamps(Message other) {
this.t_client_send = other.t_client_send;
this.t_coord_recv = other.t_coord_recv;
this.t_coord_opt_merge = other.t_coord_opt_merge;
this.t_batch_ready = other.t_batch_ready;
this.t_learner_received = other.t_learner_received;
this.t_learner_delivered = other.t_learner_delivered;
this.t_learner_deserialized = other.t_learner_deserialized;
this.t_command_enqueued = other.t_command_enqueued;
this.t_command_dequeued = other.t_command_dequeued;
this.t_execution_start = other.t_execution_start;
this.t_server_send = other.t_server_send;
this.t_client_receive = other.t_client_receive;
this.t_start_waiting_object = other.t_start_waiting_object;
this.t_end_waiting_object = other.t_end_waiting_object;
this.waitedObject = other.waitedObject;
}
@Override
public String toString() {
String msgString = "[";
for (int i = 0 ; i < contents.size() ; i++) {
Object obj = contents.get(i);
if (i == next) msgString += "next = ";
msgString += obj == null ? "null" : obj.toString();
if (i < contents.size() - 1) msgString += ", ";
}
msgString += "]";
return msgString;
}
}