Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
*
* 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 org.apache.bookkeeper.proto;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.util.Recycler;
import io.netty.util.Recycler.Handle;
import io.netty.util.ReferenceCountUtil;
import io.netty.util.ReferenceCounted;
import org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage;
/**
* The packets of the Bookie protocol all have a 4-byte integer indicating the
* type of request or response at the very beginning of the packet followed by a
* payload.
*
*/
public interface BookieProtocol {
/**
* Lowest protocol version which will work with the bookie.
*/
byte LOWEST_COMPAT_PROTOCOL_VERSION = 0;
/**
* Current version of the protocol, which client will use.
*/
byte CURRENT_PROTOCOL_VERSION = 2;
/**
* Entry Entry ID. To be used when no valid entry id can be assigned.
*/
long INVALID_ENTRY_ID = -1;
/**
* Entry identifier representing a request to obtain the last add entry confirmed.
*/
long LAST_ADD_CONFIRMED = -1;
/**
* The length of the master key in add packets. This
* is fixed at 20 for historic reasons. This is because it
* is always generated using the MacDigestManager regardless
* of whether Mac is being used for the digest or not
*/
int MASTER_KEY_LENGTH = 20;
/**
* The first int of a packet is the header.
* It contains the version, opCode and flags.
* The initial versions of BK didn't have this structure
* and just had an int representing the opCode as the
* first int. This handles that case also.
*/
final class PacketHeader {
public static int toInt(byte version, byte opCode, short flags) {
if (version == 0) {
return (int) opCode;
} else {
return ((version & 0xFF) << 24)
| ((opCode & 0xFF) << 16)
| (flags & 0xFFFF);
}
}
public static byte getVersion(int packetHeader) {
return (byte) (packetHeader >> 24);
}
public static byte getOpCode(int packetHeader) {
int version = getVersion(packetHeader);
if (version == 0) {
return (byte) packetHeader;
} else {
return (byte) ((packetHeader >> 16) & 0xFF);
}
}
public static short getFlags(int packetHeader) {
byte version = (byte) (packetHeader >> 24);
if (version == 0) {
return 0;
} else {
return (short) (packetHeader & 0xFFFF);
}
}
}
/**
* The Add entry request payload will be a ledger entry exactly as it should
* be logged. The response payload will be a 4-byte integer that has the
* error code followed by the 8-byte ledger number and 8-byte entry number
* of the entry written.
*/
byte ADDENTRY = 1;
/**
* The Read entry request payload will be the ledger number and entry number
* to read. (The ledger number is an 8-byte integer and the entry number is
* a 8-byte integer.) The response payload will be a 4-byte integer
* representing an error code and a ledger entry if the error code is EOK,
* otherwise it will be the 8-byte ledger number and the 4-byte entry number
* requested. (Note that the first sixteen bytes of the entry happen to be
* the ledger number and entry number as well.)
*/
byte READENTRY = 2;
/**
* Auth message. This code is for passing auth messages between the auth
* providers on the client and bookie. The message payload is determined
* by the auth providers themselves.
*/
byte AUTH = 3;
byte READ_LAC = 4;
byte WRITE_LAC = 5;
byte GET_BOOKIE_INFO = 6;
/**
* The error code that indicates success.
*/
int EOK = 0;
/**
* The error code that indicates that the ledger does not exist.
*/
int ENOLEDGER = 1;
/**
* The error code that indicates that the requested entry does not exist.
*/
int ENOENTRY = 2;
/**
* The error code that indicates an invalid request type.
*/
int EBADREQ = 100;
/**
* General error occurred at the server.
*/
int EIO = 101;
/**
* Unauthorized access to ledger.
*/
int EUA = 102;
/**
* The server version is incompatible with the client.
*/
int EBADVERSION = 103;
/**
* Attempt to write to fenced ledger.
*/
int EFENCED = 104;
/**
* The server is running as read-only mode.
*/
int EREADONLY = 105;
/**
* Too many concurrent requests.
*/
int ETOOMANYREQUESTS = 106;
/**
* Ledger in unknown state.
*/
int EUNKNOWNLEDGERSTATE = 107;
short FLAG_NONE = 0x0;
short FLAG_DO_FENCING = 0x0001;
short FLAG_RECOVERY_ADD = 0x0002;
short FLAG_HIGH_PRIORITY = 0x0004;
/**
* A Bookie request object.
*/
class Request {
byte protocolVersion;
byte opCode;
long ledgerId;
long entryId;
short flags;
byte[] masterKey;
protected void init(byte protocolVersion, byte opCode, long ledgerId,
long entryId, short flags, byte[] masterKey) {
this.protocolVersion = protocolVersion;
this.opCode = opCode;
this.ledgerId = ledgerId;
this.entryId = entryId;
this.flags = flags;
this.masterKey = masterKey;
}
byte getProtocolVersion() {
return protocolVersion;
}
byte getOpCode() {
return opCode;
}
long getLedgerId() {
return ledgerId;
}
long getEntryId() {
return entryId;
}
short getFlags() {
return flags;
}
boolean hasMasterKey() {
return masterKey != null;
}
byte[] getMasterKey() {
assert hasMasterKey();
return masterKey;
}
boolean isHighPriority() {
return (flags & FLAG_HIGH_PRIORITY) == FLAG_HIGH_PRIORITY;
}
@Override
public String toString() {
return String.format("Op(%d)[Ledger:%d,Entry:%d]", opCode, ledgerId, entryId);
}
public void recycle() {}
}
/**
* This is similar to add request, but it used when processing the request on the bookie side.
*/
class ParsedAddRequest extends Request {
ByteBuf data;
static ParsedAddRequest create(byte protocolVersion, long ledgerId, long entryId, short flags, byte[] masterKey,
ByteBuf data) {
ParsedAddRequest add = RECYCLER.get();
add.protocolVersion = protocolVersion;
add.opCode = ADDENTRY;
add.ledgerId = ledgerId;
add.entryId = entryId;
add.flags = flags;
add.masterKey = masterKey;
add.data = data.retain();
return add;
}
ByteBuf getData() {
// We need to have different ByteBufList instances for each bookie write
return data;
}
boolean isRecoveryAdd() {
return (flags & FLAG_RECOVERY_ADD) == FLAG_RECOVERY_ADD;
}
void release() {
ReferenceCountUtil.release(data);
}
private final Handle recyclerHandle;
private ParsedAddRequest(Handle recyclerHandle) {
this.recyclerHandle = recyclerHandle;
}
private static final Recycler RECYCLER = new Recycler() {
@Override
protected ParsedAddRequest newObject(Handle handle) {
return new ParsedAddRequest(handle);
}
};
@Override
public void recycle() {
ledgerId = -1;
entryId = -1;
masterKey = null;
data = null;
recyclerHandle.recycle(this);
}
}
/**
* A Request that reads data.
*/
class ReadRequest extends Request {
static ReadRequest create(byte protocolVersion, long ledgerId, long entryId,
short flags, byte[] masterKey) {
ReadRequest read = RECYCLER.get();
read.protocolVersion = protocolVersion;
read.opCode = READENTRY;
read.ledgerId = ledgerId;
read.entryId = entryId;
read.flags = flags;
read.masterKey = masterKey;
return read;
}
boolean isFencing() {
return (flags & FLAG_DO_FENCING) == FLAG_DO_FENCING;
}
private final Handle recyclerHandle;
private ReadRequest(Handle recyclerHandle) {
this.recyclerHandle = recyclerHandle;
}
private static final Recycler RECYCLER = new Recycler() {
@Override
protected ReadRequest newObject(Handle handle) {
return new ReadRequest(handle);
}
};
@Override
public void recycle() {
ledgerId = -1;
entryId = -1;
masterKey = null;
recyclerHandle.recycle(this);
}
}
/**
* An authentication request.
*/
class AuthRequest extends Request {
final AuthMessage authMessage;
AuthRequest(byte protocolVersion, AuthMessage authMessage) {
init(protocolVersion, AUTH, -1, -1, FLAG_NONE, null);
this.authMessage = authMessage;
}
AuthMessage getAuthMessage() {
return authMessage;
}
}
/**
* A response object.
*/
abstract class Response {
byte protocolVersion;
byte opCode;
int errorCode;
long ledgerId;
long entryId;
protected void init(byte protocolVersion, byte opCode,
int errorCode, long ledgerId, long entryId) {
this.protocolVersion = protocolVersion;
this.opCode = opCode;
this.errorCode = errorCode;
this.ledgerId = ledgerId;
this.entryId = entryId;
}
byte getProtocolVersion() {
return protocolVersion;
}
byte getOpCode() {
return opCode;
}
long getLedgerId() {
return ledgerId;
}
long getEntryId() {
return entryId;
}
int getErrorCode() {
return errorCode;
}
@Override
public String toString() {
return String.format("Op(%d)[Ledger:%d,Entry:%d,errorCode=%d]",
opCode, ledgerId, entryId, errorCode);
}
boolean release() {
return true;
}
void recycle() {
}
}
/**
* A request that reads data.
*/
class ReadResponse extends Response implements ReferenceCounted {
final ByteBuf data;
ReadResponse(byte protocolVersion, int errorCode, long ledgerId, long entryId) {
this(protocolVersion, errorCode, ledgerId, entryId, Unpooled.EMPTY_BUFFER);
}
ReadResponse(byte protocolVersion, int errorCode, long ledgerId, long entryId, ByteBuf data) {
init(protocolVersion, READENTRY, errorCode, ledgerId, entryId);
this.data = data;
}
boolean hasData() {
return data.readableBytes() > 0;
}
ByteBuf getData() {
return data;
}
@Override
public int refCnt() {
return data.refCnt();
}
@Override
public ReferenceCounted retain() {
data.retain();
return this;
}
@Override
public ReferenceCounted retain(int increment) {
return data.retain(increment);
}
@Override
public ReferenceCounted touch() {
data.touch();
return this;
}
@Override
public ReferenceCounted touch(Object hint) {
data.touch(hint);
return this;
}
@Override
public boolean release() {
return data.release();
}
@Override
public boolean release(int decrement) {
return data.release(decrement);
}
}
/**
* A response that adds data.
*/
class AddResponse extends Response {
static AddResponse create(byte protocolVersion, int errorCode, long ledgerId, long entryId) {
AddResponse response = RECYCLER.get();
response.init(protocolVersion, ADDENTRY, errorCode, ledgerId, entryId);
return response;
}
private final Handle recyclerHandle;
private AddResponse(Handle recyclerHandle) {
this.recyclerHandle = recyclerHandle;
}
private static final Recycler RECYCLER = new Recycler() {
@Override
protected AddResponse newObject(Handle handle) {
return new AddResponse(handle);
}
};
@Override
public void recycle() {
recyclerHandle.recycle(this);
}
}
/**
* An error response.
*/
class ErrorResponse extends Response {
ErrorResponse(byte protocolVersion, byte opCode, int errorCode,
long ledgerId, long entryId) {
init(protocolVersion, opCode, errorCode, ledgerId, entryId);
}
}
/**
* A response with an authentication message.
*/
class AuthResponse extends Response {
final AuthMessage authMessage;
AuthResponse(byte protocolVersion, AuthMessage authMessage) {
init(protocolVersion, AUTH, EOK, -1, -1);
this.authMessage = authMessage;
}
AuthMessage getAuthMessage() {
return authMessage;
}
}
}