/** * Licensed 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 */ package org.corfudb.infrastructure.log; import io.netty.buffer.ByteBuf; import java.io.File; import io.netty.buffer.Unpooled; import org.corfudb.AbstractCorfuTest; import org.corfudb.infrastructure.ServerContext; import org.corfudb.infrastructure.ServerContextBuilder; import org.corfudb.protocols.wireprotocol.DataType; import org.corfudb.protocols.wireprotocol.IMetadata; import org.corfudb.protocols.wireprotocol.LogData; import org.corfudb.runtime.exceptions.DataOutrankedException; import org.corfudb.runtime.exceptions.ValueAdoptedException; import org.corfudb.util.serializer.Serializers; import org.junit.Ignore; import org.junit.Test; import static org.junit.Assert.*; /** * Created by Konstantin Spirov on 3/15/2017. */ public class StreamLogWithRankedAddressSpaceTest extends AbstractCorfuTest { private static final int RECORDS_TO_WRITE = 10; @Test @Ignore // compact on ranked address space not activated yet public void testCompact() throws Exception { StreamLogFiles log = new StreamLogFiles(getContext(), false); LogAddress address = new LogAddress(0l, null); for (long x = 0; x < RECORDS_TO_WRITE; x++) { writeToLog(log, address, DataType.DATA, "Payload", x); } LogData value1 = log.read(address); long size1 = new File(log.getSegmentHandleForAddress(address).getFileName()).length(); log.compact(); LogData value2 = log.read(address); long size2 = new File(log.getSegmentHandleForAddress(address).getFileName()).length(); assertEquals(value1.getRank(), value2.getRank()); assertNotEquals(size2, size1); } @Test public void testHigherRank() { StreamLogFiles log = new StreamLogFiles(getContext(), false); LogAddress address = new LogAddress(0l, null); writeToLog(log, address, DataType.DATA, "v-1", 1); LogData value1 = log.read(address); assertTrue(new String(value1.getData()).contains("v-1")); writeToLog(log, address, DataType.DATA, "v-2", 2); LogData value2 = log.read(address); assertTrue(new String(value2.getData()).contains("v-2")); log.close(); } @Test public void testLowerRank() { StreamLogFiles log = new StreamLogFiles(getContext(), false); LogAddress address = new LogAddress(0l, null); writeToLog(log, address, DataType.DATA, "v-1", 2); LogData value1 = log.read(address); assertTrue(new String(value1.getData()).contains("v-1")); try { writeToLog(log, address, DataType.DATA, "v-2", 1); fail(); } catch (DataOutrankedException e) { // expected } LogData value2 = log.read(address); assertTrue(new String(value2.getData()).contains("v-1")); log.close(); } @Test public void testHigherRankAgainstProposal() { StreamLogFiles log = new StreamLogFiles(getContext(), false); LogAddress address = new LogAddress(0l, null); writeToLog(log, address, DataType.RANK_ONLY, "v-1", 1); LogData value1 = log.read(address); assertTrue(new String(value1.getData()).contains("v-1")); writeToLog(log, address, DataType.DATA, "v-2", 2); LogData value2 = log.read(address); assertTrue(new String(value2.getData()).contains("v-2")); log.close(); } @Test public void testLowerRankAgainstProposal() { StreamLogFiles log = new StreamLogFiles(getContext(), false); LogAddress address = new LogAddress(0l, null); writeToLog(log, address, DataType.RANK_ONLY, "v-1", 2); LogData value1 = log.read(address); assertTrue(new String(value1.getData()).contains("v-1")); try { writeToLog(log, address, DataType.DATA, "v-2", 1); fail(); } catch (DataOutrankedException e) { // expected } LogData value2 = log.read(address); assertTrue(new String(value2.getData()).contains("v-1")); log.close(); } @Test public void testProposalWithHigherRankAgainstData() { StreamLogFiles log = new StreamLogFiles(getContext(), false); LogAddress address = new LogAddress(0l, null); writeToLog(log, address, DataType.DATA, "v-1", 1); LogData value1 = log.read(address); assertTrue(new String(value1.getData()).contains("v-1")); try { writeToLog(log, address, DataType.RANK_ONLY, "v-2", 2); fail(); } catch (ValueAdoptedException e) { LogData logData = e.getReadResponse().getReadSet().get(0l); assertTrue(new String(logData.getData()).contains("v-1")); } LogData value2 = log.read(address); assertTrue(new String(value2.getData()).contains("v-1")); log.close(); } @Test public void testProposalWithLowerRankAgainstData() { StreamLogFiles log = new StreamLogFiles(getContext(), false); LogAddress address = new LogAddress(0l, null); writeToLog(log, address, DataType.DATA, "v-1", 2); LogData value1 = log.read(address); assertTrue(new String(value1.getData()).contains("v-1")); try { writeToLog(log, address, DataType.RANK_ONLY, "v-2", 1); fail(); } catch (DataOutrankedException e) { // expected } LogData value2 = log.read(address); assertTrue(new String(value2.getData()).contains("v-1")); log.close(); } @Test public void testProposalsHigherRank() { StreamLogFiles log = new StreamLogFiles(getContext(), false); LogAddress address = new LogAddress(0l, null); writeToLog(log, address, DataType.RANK_ONLY, "v-1", 1); LogData value1 = log.read(address); assertTrue(new String(value1.getData()).contains("v-1")); writeToLog(log, address, DataType.RANK_ONLY, "v-2", 2); LogData value2 = log.read(address); assertTrue(new String(value2.getData()).contains("v-2")); log.close(); } @Test public void testProposalsLowerRank() { StreamLogFiles log = new StreamLogFiles(getContext(), false); LogAddress address = new LogAddress(0l, null); writeToLog(log, address, DataType.RANK_ONLY, "v-1", 2); LogData value1 = log.read(address); assertTrue(new String(value1.getData()).contains("v-1")); try { writeToLog(log, address, DataType.RANK_ONLY, "v-2", 1); fail(); } catch (DataOutrankedException e) { // expected } LogData value2 = log.read(address); assertTrue(new String(value2.getData()).contains("v-1")); log.close(); } @Test public void checkProposalIsIdempotent() { StreamLogFiles log = new StreamLogFiles(getContext(), false); LogAddress address = new LogAddress(0l, null); IMetadata.DataRank sameRank = new IMetadata.DataRank(1); writeToLog(log, address, DataType.DATA, "v-1", sameRank); LogData value1 = log.read(address); assertTrue(new String(value1.getData()).contains("v-1")); writeToLog(log, address, DataType.DATA, "v-1", sameRank); LogData value2 = log.read(address); assertTrue(new String(value2.getData()).contains("v-1")); } private void writeToLog(StreamLog log, LogAddress address, DataType dataType, String payload, long rank) { this.writeToLog(log, address, dataType, payload, new IMetadata.DataRank(rank)); } private void writeToLog(StreamLog log, LogAddress address, DataType dataType, String payload, IMetadata.DataRank rank) { ByteBuf b = Unpooled.buffer(); byte[] streamEntry = payload.getBytes(); Serializers.CORFU.serialize(streamEntry, b); LogData data = new LogData(dataType, b); data.setRank(rank); log.append(address, data); } private String getDirPath() { return PARAMETERS.TEST_TEMP_DIR + File.separator; } private ServerContext getContext() { String path = getDirPath(); return new ServerContextBuilder() .setLogPath(path) .setMemory(false) .build(); } }