/* $Id$ */
package ibis.ipl.impl;
import ibis.io.SerializationInput;
import ibis.ipl.IbisConfigurationException;
import ibis.ipl.PortType;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ReadOnlyBufferException;
/**
* Implementation of the {@link ibis.ipl.ReadMessage} interface.
* This is a complete implementation, but may be extended by an implementation.
* In that case, the {@link ReceivePort#createReadMessage(SerializationInput, ReceivePortConnectionInfo)}
* method must also be redefined.
*/
public class ReadMessage implements ibis.ipl.ReadMessage {
protected SerializationInput in;
protected ReceivePortConnectionInfo info;
protected boolean isFinished = false;
protected long before;
protected long sequenceNr = -1;
protected boolean inUpcall = false;
protected boolean finishCalledFromUpcall = false;
public ReadMessage(SerializationInput in, ReceivePortConnectionInfo info) {
this.in = in;
this.info = info;
this.before = info.bytesRead();
}
public ibis.ipl.ReceivePort localPort() {
return info.port;
}
/**
* May be called by an implementation to allow for detection of finish()
* calls within an upcall.
* @param val the value to set.
*/
public void setInUpcall(boolean val) {
inUpcall = val;
}
/**
* May be called by an implementation to allow for detection of finish()
* calls within an upcall.
*/
public boolean getInUpcall() {
return inUpcall;
}
public boolean finishCalledInUpcall() {
return finishCalledFromUpcall;
}
public long bytesRead() {
long after = info.bytesRead();
return after - before;
}
public int remaining() throws IOException {
return -1;
}
public int size() throws IOException {
return -1;
}
public ReceivePortConnectionInfo getInfo() {
return info;
}
public void setInfo(ReceivePortConnectionInfo info) {
this.info = info;
}
protected final void checkNotFinished() throws IOException {
if (isFinished) {
throw new IOException(
"Operating on a message that was already finished");
}
}
public ibis.ipl.SendPortIdentifier origin() {
return info.origin;
}
protected int available() throws IOException {
checkNotFinished();
return in.available();
}
public boolean readBoolean() throws IOException {
checkNotFinished();
return in.readBoolean();
}
public byte readByte() throws IOException {
checkNotFinished();
return in.readByte();
}
public char readChar() throws IOException {
checkNotFinished();
return in.readChar();
}
public short readShort() throws IOException {
checkNotFinished();
return in.readShort();
}
public int readInt() throws IOException {
checkNotFinished();
return in.readInt();
}
public long readLong() throws IOException {
checkNotFinished();
return in.readLong();
}
public float readFloat() throws IOException {
checkNotFinished();
return in.readFloat();
}
public double readDouble() throws IOException {
checkNotFinished();
return in.readDouble();
}
public String readString() throws IOException {
checkNotFinished();
return in.readString();
}
public Object readObject() throws IOException, ClassNotFoundException {
checkNotFinished();
return in.readObject();
}
public void readArray(boolean[] destination) throws IOException {
readArray(destination, 0, destination.length);
}
public void readArray(byte[] destination) throws IOException {
readArray(destination, 0, destination.length);
}
public void readArray(char[] destination) throws IOException {
readArray(destination, 0, destination.length);
}
public void readArray(short[] destination) throws IOException {
readArray(destination, 0, destination.length);
}
public void readArray(int[] destination) throws IOException {
readArray(destination, 0, destination.length);
}
public void readArray(long[] destination) throws IOException {
readArray(destination, 0, destination.length);
}
public void readArray(float[] destination) throws IOException {
readArray(destination, 0, destination.length);
}
public void readArray(double[] destination) throws IOException {
readArray(destination, 0, destination.length);
}
public void readArray(Object[] destination) throws IOException,
ClassNotFoundException {
readArray(destination, 0, destination.length);
}
public void readArray(boolean[] destination, int offset, int size)
throws IOException {
checkNotFinished();
in.readArray(destination, offset, size);
}
public void readArray(byte[] destination, int offset, int size)
throws IOException {
checkNotFinished();
in.readArray(destination, offset, size);
}
public void readArray(char[] destination, int offset, int size)
throws IOException {
checkNotFinished();
in.readArray(destination, offset, size);
}
public void readArray(short[] destination, int offset, int size)
throws IOException {
checkNotFinished();
in.readArray(destination, offset, size);
}
public void readArray(int[] destination, int offset, int size)
throws IOException {
checkNotFinished();
in.readArray(destination, offset, size);
}
public void readArray(long[] destination, int offset, int size)
throws IOException {
checkNotFinished();
in.readArray(destination, offset, size);
}
public void readArray(float[] destination, int offset, int size)
throws IOException {
checkNotFinished();
in.readArray(destination, offset, size);
}
public void readArray(double[] destination, int offset, int size)
throws IOException {
checkNotFinished();
in.readArray(destination, offset, size);
}
public void readArray(Object[] destination, int offset, int size)
throws IOException, ClassNotFoundException {
checkNotFinished();
in.readArray(destination, offset, size);
}
public void setSequenceNumber(long s) {
sequenceNr = s;
}
public long sequenceNumber() {
if (! info.port.type.hasCapability(PortType.COMMUNICATION_NUMBERED)) {
throw new IbisConfigurationException("No COMMUNICATION_NUMBERED "
+ "specified in port type");
}
return sequenceNr;
}
public long finish() throws IOException {
checkNotFinished();
in.clear();
isFinished = true;
if (inUpcall) {
finishCalledFromUpcall = true;
getInfo().upcallCalledFinish();
}
long after = info.bytesRead();
long retval = after - before;
before = after;
info.port.finishMessage(this, retval);
return retval;
}
public void finish(IOException e) {
if (isFinished) {
return;
}
if (inUpcall) {
finishCalledFromUpcall = true;
}
info.port.finishMessage(this, e);
}
public boolean isFinished() {
return isFinished;
}
public void setFinished(boolean val) {
isFinished = val;
if (! isFinished) {
before = info.bytesRead();
finishCalledFromUpcall = false;
}
}
public void readByteBuffer(ByteBuffer value) throws IOException,
ReadOnlyBufferException {
checkNotFinished();
in.readByteBuffer(value);
}
}