package org.corfudb.protocols.logprotocol; import io.netty.buffer.ByteBuf; import lombok.Getter; import org.corfudb.protocols.wireprotocol.DataType; import org.corfudb.protocols.wireprotocol.ICorfuPayload; import org.corfudb.protocols.wireprotocol.ILogData; import org.corfudb.runtime.CorfuRuntime; import javax.annotation.Nonnull; import java.util.*; import java.util.stream.Collectors; /** * Temporary class for transition to log data. * * Created by mwei on 4/6/17. */ public class StreamedLogData implements ILogData, ICorfuPayload<StreamedLogData>{ /** A map of stream data. */ @Getter public final @Nonnull Map<UUID, StreamData> streamDataMap; /** The metadata for this log entry. */ @Getter final EnumMap<LogUnitMetadataType, Object> metadataMap; /** The serialized form, cached during writing only * and auto-released by the handle. */ protected ByteBuf serializedForm; /** {@inheritDoc} */ @Override public Set<UUID> getStreams() { return streamDataMap.keySet(); } /** {@inheritDoc} */ @Override public boolean containsStream(UUID stream) { return streamDataMap.containsKey(stream); } /** {@inheritDoc} */ @Override public Map<UUID, Long> getBackpointerMap() { return streamDataMap.entrySet().stream() .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue().backpointer)); } /** Serialize to the given buffer, using the cached form * if possible. * @param buf The buffer to serialize. */ @Override public void doSerialize(ByteBuf buf) { // If we don't have a cached version, we serialized directly if (serializedForm == null) { doSerialize(buf); } else { serializedForm.resetReaderIndex(); buf.writeBytes(serializedForm); } } /** This class provides a serialization handle, which * manages the lifetime of the serialized copy of this * entry. */ public static class SerializationHandle implements AutoCloseable { /** A reference to the log data. */ final StreamedLogData data; /** Explicitly request the serialized form of this log data * which only exists for the lifetime of this handle. * @return The serialized form of this handle. */ public StreamedLogData getSerialized() { return data; } /** Create a new serialized handle with a reference * to the log data. * @param data The log data to manage. */ public SerializationHandle(StreamedLogData data) { this.data = data; } /** {@inheritDoc} */ @Override public void close() { data.serializedForm.release(); data.serializedForm = null; } } public StreamedLogData(long address, Map<UUID, StreamData> streamDataMap) { this.setGlobalAddress(address); this.streamDataMap = streamDataMap; this.metadataMap = new EnumMap<>(LogUnitMetadataType.class); } public StreamedLogData(ByteBuf buf) { ICorfuPayload.fromBuffer(buf, DataType.class); streamDataMap = ICorfuPayload.mapFromBuffer(buf, UUID.class, StreamData.class); metadataMap = ICorfuPayload.enumMapFromBuffer(buf, LogUnitMetadataType.class, Object.class); } /** Serialize the data to the given buffer. */ private void serializedDataToBuffer(ByteBuf buf) { ICorfuPayload.serialize(buf, DataType.DATA); ICorfuPayload.serialize(buf, streamDataMap); ICorfuPayload.serialize(buf, metadataMap); } /** The payload of an entry with streams is the map. */ @Override public Object getPayload(CorfuRuntime t) { return streamDataMap; } /** Streamed log data always contain data. */ @Override public DataType getType() { return DataType.DATA; } @Override public void releaseBuffer() { } @Override public void acquireBuffer() { } }