package org.corfudb.protocols.logprotocol; import io.netty.buffer.ByteBuf; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.RequiredArgsConstructor; import lombok.Setter; import lombok.ToString; import org.corfudb.protocols.wireprotocol.ILogData; import org.corfudb.runtime.CorfuRuntime; import org.corfudb.util.serializer.ICorfuSerializable; import java.util.Arrays; import java.util.Map; import java.util.UUID; import java.util.function.Function; import java.util.stream.Collectors; /** * Created by mwei on 1/8/16. */ @ToString(exclude = {"runtime", "entry"}) @NoArgsConstructor public class LogEntry implements ICorfuSerializable { static final Map<Byte, LogEntryType> typeMap = Arrays.stream(LogEntryType.values()) .collect(Collectors.toMap(LogEntryType::asByte, Function.identity())); ; /** * The runtime to use */ @Setter protected CorfuRuntime runtime; /** * The type of log entry */ @Getter LogEntryType type; /** * An underlying log entry, if present. */ @Getter @Setter ILogData entry; /** * Constructor for generating LogEntries. * * @param type The type of log entry to instantiate. */ public LogEntry(LogEntryType type) { this.type = type; } /** * The base LogEntry format is very simple. The first byte represents the type * of entry, and the rest of the format is dependent on the the entry type. * * @param b The buffer to deserialize. * @return A LogEntry. */ public static ICorfuSerializable deserialize(ByteBuf b, CorfuRuntime rt) { try { LogEntryType let = typeMap.get(b.readByte()); LogEntry l = let.entryType.newInstance(); l.type = let; l.runtime = rt; l.deserializeBuffer(b, rt); return l; } catch (InstantiationException | IllegalAccessException ie) { throw new RuntimeException("Error deserializing entry", ie); } } /** * This function provides the remaining buffer. Child entries * should initialize their contents based on the buffer. * * @param b The remaining buffer. */ void deserializeBuffer(ByteBuf b, CorfuRuntime rt) { // In the base case, we don't do anything. } /** * Serialize the given LogEntry into a given byte buffer. * * @param b The buffer to serialize into. */ @Override public void serialize(ByteBuf b) { b.writeByte(type.asByte()); } /** * Returns whether the entry changes the contents of the stream. * For example, an aborted transaction does not change the content of the stream. * * @return True, if the entry changes the contents of the stream, * False otherwise. */ public boolean isMutation(UUID stream) { return true; } @RequiredArgsConstructor public enum LogEntryType { // Base Messages NOP(0, LogEntry.class), SMR(1, SMREntry.class), STREAM_COW(4, StreamCOWEntry.class), MULTIOBJSMR(7, MultiObjectSMREntry.class), MULTISMR(8, MultiSMREntry.class); public final int type; public final Class<? extends LogEntry> entryType; public byte asByte() { return (byte) type; } } }