com.liferay.portal.kernel.nio.intraband.Datagram Maven / Gradle / Ivy
/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library 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.
*/
package com.liferay.portal.kernel.nio.intraband;
import com.liferay.petra.string.StringPool;
import com.liferay.portal.kernel.io.BigEndianCodec;
import com.liferay.portal.kernel.util.StringBundler;
import java.io.EOFException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
import java.util.EnumSet;
/**
* Represents the communication unit of Intraband.
*
*
* Encodes/decodes data to/from big-endian byte order data format:
*
*
*
*
*
*
* Name Type Size(byte) Offset
*
*
* Status Flag byte 1 0
*
*
* Sequence ID long 8 1
*
*
* Data Type byte 1 9
*
*
* Data Size int 4 10
*
*
* Data Chunk
* byte[]
*
* ${Data Size}
14
*
*
*
*
* @author Shuyang Zhou
*/
public class Datagram {
public static Datagram createRequestDatagram(byte type, byte[] data) {
return createRequestDatagram(type, ByteBuffer.wrap(data));
}
public static Datagram createRequestDatagram(
byte type, ByteBuffer dataByteBuffer) {
Datagram datagram = new Datagram();
// Status flag
datagram._headerBufferArray[_INDEX_STATUS_FLAG] = _FLAG_REQUEST;
// Request datagram does not set the sequence ID
// Data type
datagram._headerBufferArray[_INDEX_DATA_TYPE] = type;
// Data size
BigEndianCodec.putInt(
datagram._headerBufferArray, _INDEX_DATA_SIZE,
dataByteBuffer.remaining());
// Data chunk
datagram._dataByteBuffer = dataByteBuffer;
return datagram;
}
public static Datagram createResponseDatagram(
Datagram requestDatagram, byte[] data) {
return createResponseDatagram(requestDatagram, ByteBuffer.wrap(data));
}
public static Datagram createResponseDatagram(
Datagram requestDatagram, ByteBuffer byteBuffer) {
Datagram datagram = new Datagram();
// Status flag
datagram._headerBufferArray[_INDEX_STATUS_FLAG] = _FLAG_RESPONSE;
// Sequence ID
BigEndianCodec.putLong(
datagram._headerBufferArray, _INDEX_SEQUENCE_ID,
requestDatagram.getSequenceId());
// Response datagram does not set the data type
// Data size
BigEndianCodec.putInt(
datagram._headerBufferArray, _INDEX_DATA_SIZE,
byteBuffer.remaining());
// Data chunk
datagram._dataByteBuffer = byteBuffer;
return datagram;
}
public ByteBuffer getDataByteBuffer() {
return _dataByteBuffer;
}
public byte getType() {
return _headerBufferArray[_INDEX_DATA_TYPE];
}
@Override
public String toString() {
StringBundler sb = new StringBundler(11);
sb.append("{dataChunk=");
ByteBuffer byteBuffer = _dataByteBuffer;
if (byteBuffer == null) {
sb.append(StringPool.NULL);
}
else {
sb.append(byteBuffer.toString());
}
sb.append(", dataSize=");
sb.append(BigEndianCodec.getInt(_headerBufferArray, _INDEX_DATA_SIZE));
sb.append(", dataType=");
sb.append(_headerBufferArray[_INDEX_DATA_TYPE]);
sb.append(", sequenceId=");
sb.append(
BigEndianCodec.getLong(_headerBufferArray, _INDEX_SEQUENCE_ID));
sb.append(", statusFlag=");
sb.append(_headerBufferArray[_INDEX_STATUS_FLAG]);
sb.append("}");
return sb.toString();
}
protected static Datagram createACKResponseDatagram(long sequenceId) {
Datagram datagram = new Datagram();
// Status flag
datagram._headerBufferArray[_INDEX_STATUS_FLAG] = _FLAG_ACK_RESPONSE;
// Sequence ID
BigEndianCodec.putLong(
datagram._headerBufferArray, _INDEX_SEQUENCE_ID, sequenceId);
// ACK response datagram does not set the data type
// Data size
BigEndianCodec.putInt(datagram._headerBufferArray, _INDEX_DATA_SIZE, 0);
// Data chunk
datagram._dataByteBuffer = _EMPTY_BUFFER;
return datagram;
}
protected static Datagram createReceiveDatagram() {
return new Datagram();
}
protected long getSequenceId() {
return BigEndianCodec.getLong(_headerBufferArray, _INDEX_SEQUENCE_ID);
}
protected boolean isAckRequest() {
byte statusFlag = _headerBufferArray[_INDEX_STATUS_FLAG];
if ((statusFlag & _FLAG_ACK_REQUEST) != 0) {
return true;
}
return false;
}
protected boolean isAckResponse() {
byte statusFlag = _headerBufferArray[_INDEX_STATUS_FLAG];
if ((statusFlag & _FLAG_ACK_RESPONSE) != 0) {
return true;
}
return false;
}
protected boolean isRequest() {
byte statusFlag = _headerBufferArray[_INDEX_STATUS_FLAG];
if ((statusFlag & _FLAG_REQUEST) != 0) {
return true;
}
return false;
}
protected boolean isResponse() {
byte statusFlag = _headerBufferArray[_INDEX_STATUS_FLAG];
if ((statusFlag & _FLAG_RESPONSE) != 0) {
return true;
}
return false;
}
protected boolean readFrom(ScatteringByteChannel scatteringByteChannel)
throws IOException {
if (_headerByteBuffer.hasRemaining()) {
if (scatteringByteChannel.read(_headerByteBuffer) == -1) {
throw new EOFException();
}
if (_headerByteBuffer.hasRemaining()) {
return false;
}
int dataSize = BigEndianCodec.getInt(
_headerBufferArray, _INDEX_DATA_SIZE);
if (dataSize == 0) {
_dataByteBuffer = _EMPTY_BUFFER;
return true;
}
_dataByteBuffer = ByteBuffer.allocate(dataSize);
}
if (scatteringByteChannel.read(_dataByteBuffer) == -1) {
throw new EOFException();
}
if (_dataByteBuffer.hasRemaining()) {
return false;
}
_dataByteBuffer.flip();
return true;
}
protected void setAckRequest(boolean ackRequest) {
byte statusFlag = _headerBufferArray[_INDEX_STATUS_FLAG];
if (ackRequest) {
statusFlag |= _FLAG_ACK_REQUEST;
}
else {
statusFlag &= ~_FLAG_ACK_REQUEST;
}
_headerBufferArray[_INDEX_STATUS_FLAG] = statusFlag;
}
protected void setSequenceId(long sequenceId) {
BigEndianCodec.putLong(
_headerBufferArray, _INDEX_SEQUENCE_ID, sequenceId);
}
protected boolean writeTo(GatheringByteChannel gatheringByteChannel)
throws IOException {
if (_headerByteBuffer.hasRemaining()) {
ByteBuffer[] byteBuffers = new ByteBuffer[2];
byteBuffers[0] = _headerByteBuffer;
byteBuffers[1] = _dataByteBuffer;
gatheringByteChannel.write(byteBuffers);
}
else {
gatheringByteChannel.write(_dataByteBuffer);
}
if (_dataByteBuffer.hasRemaining()) {
return false;
}
_dataByteBuffer = null;
return true;
}
protected Object attachment;
protected CompletionHandler