package com.alibaba.doris.dataserver.store.log.serialize.impl;
import java.nio.ByteBuffer;
import java.util.Iterator;
import com.alibaba.doris.dataserver.store.log.LogStorageException;
import com.alibaba.doris.dataserver.store.log.entry.ClumpHeadEntry;
import com.alibaba.doris.dataserver.store.log.entry.DeleteLogEntry;
import com.alibaba.doris.dataserver.store.log.entry.LogEntry;
import com.alibaba.doris.dataserver.store.log.entry.SetLogEntry;
import com.alibaba.doris.dataserver.store.log.entry.LogEntry.Type;
import com.alibaba.doris.dataserver.store.log.serialize.LogSerializer;
/**
* @author ajun Email:jack.yuj@alibaba-inc.com
*/
public class DefaultLogSerializer implements LogSerializer {
private static final int LOG_ENTRY_HEADER_LENGTH = 9;
public ClumpHeadEntry readHead(ByteBuffer buffer) {
// 没有head文件,则创建一个空的Head对象。
ClumpHeadEntry head = new ClumpHeadEntry();
if (buffer.remaining() >= 4) {
int vnodeNum = buffer.getInt();
for (int i = 0; i < vnodeNum; i++) {
head.addVnode(buffer.getInt());
}
}
return head;
}
public void writeHead(ByteBuffer buffer, ClumpHeadEntry head) {
buffer.putInt(head.getVnodeNum());
Iterator<Integer> nodes = head.getVnodes();
int count = 0;
while (nodes.hasNext()) {
count++;
buffer.putInt(nodes.next().intValue());
}
if (count != head.getVnodeNum()) {
throw new LogStorageException("Check clump head failed! The vnode number is not equals.");
}
}
public LogEntry readLogEntry(ByteBuffer buffer) {
if (buffer.remaining() < LOG_ENTRY_HEADER_LENGTH) {
return null;
}
int startPos = buffer.position();
// read entry type
byte bType = buffer.get();
Type type = Type.valueOf(bType);
LogEntry logEntry = getLogEntry(type);
// read vnode
logEntry.setVnode(buffer.getInt());
// read data length
int dataLen = buffer.getInt();
if (buffer.remaining() < dataLen) {
buffer.position(startPos);
return null;
}
// read data
logEntry.decode(buffer);
// read data length
int checkDataLen = buffer.getInt();
if (checkDataLen != dataLen) {
throw new LogStorageException("The LogEntry is invalid, Check data len failed! start=" + dataLen + " end="
+ checkDataLen);
}
return logEntry;
}
public boolean writeLogEntry(ByteBuffer buffer, LogEntry logEntry) {
boolean bReturn = false;
int outerPosition = buffer.position();
if (buffer.remaining() > 9) {
Type type = logEntry.getType();
// write entry type.
buffer.put(type.getCode());
// write vnode;
buffer.putInt(logEntry.getVnode());
int startPos = buffer.position();
// write data length
buffer.putInt(0);
// write data
if (logEntry.encode(buffer)) {
int dataLen = buffer.position() - startPos;
if (buffer.remaining() > 4) {
// write data length
buffer.putInt(dataLen);
int pos = buffer.position();
buffer.position(startPos);
buffer.putInt(dataLen);
// back to end position.
buffer.position(pos);
bReturn = true;
}
}
}
if (bReturn) {
return true;
}
buffer.position(outerPosition);
return false;
}
public int readVersion(ByteBuffer buffer) {
return buffer.getInt();
}
public void writeVersion(ByteBuffer buffer, int version) {
buffer.putInt(version);
}
private LogEntry getLogEntry(Type type) {
switch (type) {
case SET:
return new SetLogEntry();
case DELETE:
return new DeleteLogEntry();
default:
throw new LogStorageException("Invalid LogEntry type :" + type);
}
}
// private static final int DEFAULT_HEAD_LENGTH = 100;
}