package lsr.paxos.messages;
import java.io.DataInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import lsr.common.Pair;
import lsr.common.Range;
/**
* Represents the catch-up mechanism request message.
*/
public class CatchUpQuery extends Message {
private static final long serialVersionUID = 1L;
/**
* The instanceIdArray has ID of undecided instances, finishing with ID from
* which we have no higher decided
*/
private int[] instanceIdArray;
private Range[] instanceIdRanges;
/**
* Creates new <code>CatchUpQuery</code> message.
*
* @param view - the view number
* @param instanceIdArray - id of unknown instances
* @param instanceIdRanges - ranges of unknown instances id
*/
public CatchUpQuery(int view, int[] instanceIdArray, Range[] instanceIdRanges) {
super(view);
setInstanceIdRangeArray(instanceIdRanges);
assert instanceIdArray != null;
this.instanceIdArray = instanceIdArray;
}
/**
* Creates new <code>CatchUpQuery</code> message.
*
* @param view - the view number
* @param instanceIdList - id of unknown instances
* @param instanceIdRanges - ranges of unknown instances id
*/
public CatchUpQuery(int view, List<Integer> instanceIdList,
List<Range> instanceIdRanges) {
super(view);
assert instanceIdList != null;
setInstanceIdList(instanceIdList);
setInstanceIdRangeList(instanceIdRanges);
}
/**
* Creates new <code>CatchUpQuery</code> message from input stream with
* serialized message.
*
* @param input - the input stream with serialized message
* @throws IOException if I/O error occurs
*/
public CatchUpQuery(DataInputStream input) throws IOException {
super(input);
instanceIdRanges = new Range[input.readInt()];
for (int i = 0; i < instanceIdRanges.length; ++i) {
instanceIdRanges[i] = new Range(input.readInt(), 0);
instanceIdRanges[i].setValue(input.readInt());
}
instanceIdArray = new int[input.readInt()];
for (int i = 0; i < instanceIdArray.length; ++i) {
instanceIdArray[i] = input.readInt();
}
}
/**
* Sets requested instances IDs from array.
*
* @param instanceIdArray - array of instances IDs
*/
public void setInstanceIdArray(int[] instanceIdArray) {
this.instanceIdArray = instanceIdArray;
}
/**
* Sets requested instances IDs from list.
*
* @param instanceIdList - list of instances IDs
*/
public void setInstanceIdList(List<Integer> instanceIdList) {
instanceIdArray = new int[instanceIdList.size()];
for (int i = 0; i < instanceIdList.size(); ++i) {
instanceIdArray[i] = instanceIdList.get(i);
}
}
/**
* Sets ranges of requested instances IDs from array. For example, if
* instances 2, 3 , 4, 8, 9, 10 are requested, then ranges [2, 4] and [8, 9]
* will be sent in this message.
*
* @param instanceIdRanges - ranges array of requested instances IDs
*/
public void setInstanceIdRangeArray(Range[] instanceIdRanges) {
this.instanceIdRanges = instanceIdRanges;
}
/**
* Sets ranges of requested instances IDs from list. For example, if
* instances 2, 3 , 4, 8, 9, 10 are requested, then ranges [2, 4] and [8, 9]
* will be sent in this message.
*
* @param instanceIdRanges - ranges list of requested instances IDs
*/
public void setInstanceIdRangeList(List<Range> instanceIdRanges) {
this.instanceIdRanges = new Range[instanceIdRanges.size()];
for (int i = 0; i < instanceIdRanges.size(); ++i) {
this.instanceIdRanges[i] = instanceIdRanges.get(i);
}
}
/**
* Returns array of requested instances IDs (unknown for sender).
*
* @return array of requested instances IDs
*/
public int[] getInstanceIdArray() {
return instanceIdArray;
}
/**
* Returns list of requested instances IDs (unknown for sender).
*
* @return list of requested instances IDs
*/
public List<Integer> getInstanceIdList() {
List<Integer> instanceIdList = new ArrayList<Integer>();
for (int i = 0; i < instanceIdArray.length; ++i) {
instanceIdList.add(instanceIdArray[i]);
}
return instanceIdList;
}
public Pair<Integer, Integer>[] getInstanceIdRangeArray() {
return instanceIdRanges;
}
public List<Range> getInstanceIdRangeList() {
List<Range> instanceIdRanges = new ArrayList<Range>();
for (int i = 0; i < this.instanceIdRanges.length; ++i) {
instanceIdRanges.add(this.instanceIdRanges[i]);
}
return instanceIdRanges;
}
public MessageType getType() {
return MessageType.CatchUpQuery;
}
public int byteSize() {
return super.byteSize() + 4 + instanceIdArray.length * 4 + 4 + instanceIdRanges.length *
2 * 4;
}
public String toString() {
return "CatchUpQuery " +
"(" +
super.toString() +
")" +
(instanceIdArray != null ? ((" for ranges:" + getInstanceIdRangeList().toString()) +
" and for instances:" + getInstanceIdList().toString())
: "");
}
protected void write(ByteBuffer bb) {
bb.putInt(instanceIdRanges.length);
for (Pair<Integer, Integer> instance : instanceIdRanges) {
bb.putInt(instance.key());
bb.putInt(instance.value());
}
bb.putInt(instanceIdArray.length);
for (int instance : instanceIdArray) {
bb.putInt(instance);
}
}
}