package com.jivesoftware.os.amza.service.storage.binary; import com.google.common.collect.Lists; import com.google.common.io.Files; import com.jivesoftware.os.amza.api.filer.UIO; import com.jivesoftware.os.amza.api.scan.RowStream; import com.jivesoftware.os.amza.api.stream.RowType; import com.jivesoftware.os.amza.service.filer.HeapByteBufferFactory; import com.jivesoftware.os.amza.service.filer.MultiAutoGrowingByteBufferBackedFiler; import com.jivesoftware.os.amza.api.IoStats; import com.jivesoftware.os.amza.service.storage.filer.DiskBackedWALFiler; import com.jivesoftware.os.amza.service.storage.filer.MemoryBackedWALFiler; import java.io.File; import java.util.List; import java.util.Random; import java.util.concurrent.Callable; import org.testng.Assert; import org.testng.annotations.Test; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; /** * */ public class BinaryRowIONGTest { @Test public void testDiskWrite() throws Exception { File file = File.createTempFile("BinaryRowIO", "dat"); DiskBackedWALFiler filer = new DiskBackedWALFiler(file.getAbsolutePath(), "rw", false, 0); IoStats ioStats = new IoStats(); BinaryRowIO binaryRowIO = new BinaryRowIO(file, "test", new BinaryRowReader(filer), new BinaryRowWriter(filer), 4096, 64); binaryRowIO.initLeaps(ioStats, -1, 0); write(ioStats, 10_000, () -> binaryRowIO); } @Test public void testMemoryWrite() throws Exception { MemoryBackedWALFiler filer = new MemoryBackedWALFiler(new MultiAutoGrowingByteBufferBackedFiler(1_024, 1_024 * 1_024, new HeapByteBufferFactory())); IoStats ioStats = new IoStats(); BinaryRowIO binaryRowIO = new BinaryRowIO(Files.createTempDir(), "test", new BinaryRowReader(filer), new BinaryRowWriter(filer), 4096, 64); binaryRowIO.initLeaps(ioStats, -1, 0); write(ioStats, 500, () -> binaryRowIO); } private void write(IoStats ioStats, int numRows, Callable<BinaryRowIO> reopen) throws Exception { BinaryRowIO rowIO = reopen.call(); List<Long> rowTxIds = Lists.newArrayList(); List<byte[]> rows = Lists.newArrayList(); long nextTxId = 1; Random r = new Random(); for (long i = 0; i < numRows; i++) { if (r.nextInt(10) == 0) { nextTxId++; } rowTxIds.add(nextTxId); rows.add(UIO.longBytes(i)); byte[] row = UIO.longBytes(i); rowIO.write(ioStats, nextTxId, RowType.primary, 1, row.length, stream -> stream.stream(row), stream -> true, (txId, prefix, key, value, valueTimestamp, valueTombstoned, valueVersion, fp) -> true, true, false); } rowIO = reopen.call(); rowIO.scan(ioStats, 0, false, new RowStream() { private long lastTxId = -1; private long expectedValue = 0; private boolean lastWasLeap = false; @Override public boolean row(long rowFP, long rowTxId, RowType rowType, byte[] row) throws Exception { if (rowType == RowType.primary) { if (lastWasLeap) { assertTrue(rowTxId > lastTxId); lastWasLeap = false; } assertTrue(rowTxId >= lastTxId); lastTxId = rowTxId; assertEquals(UIO.bytesLong(row), expectedValue); expectedValue++; } else if (rowType == RowType.system) { lastWasLeap = true; } return false; } }); } @Test public void testDiskLeap() throws Exception { File file = File.createTempFile("BinaryRowIO", "dat"); DiskBackedWALFiler filer = new DiskBackedWALFiler(file.getAbsolutePath(), "rw", false, 0); IoStats ioStats = new IoStats(); leap(ioStats, () -> { BinaryRowIO io = new BinaryRowIO(file, "test", new BinaryRowReader(filer), new BinaryRowWriter(filer), 4096, 64); io.initLeaps(ioStats, -1, 0); return io; }, 64); } @Test public void testMemoryLeap() throws Exception { MemoryBackedWALFiler filer = new MemoryBackedWALFiler(new MultiAutoGrowingByteBufferBackedFiler(1_024, 1_024 * 1_024, new HeapByteBufferFactory())); IoStats ioStats = new IoStats(); BinaryRowIO binaryRowIO = new BinaryRowIO(Files.createTempDir(), "test", new BinaryRowReader(filer), new BinaryRowWriter(filer), 4096, 64); binaryRowIO.initLeaps(ioStats, -1, 0); leap(ioStats, () -> binaryRowIO, 4096); } private void leap(IoStats ioStats, Callable<BinaryRowIO> reopen, int updatesBetweenLeaps) throws Exception { BinaryRowIO rowIO = reopen.call(); int numRows = 10_000; for (long i = 0; i < numRows; i++) { byte[] row = UIO.longBytes(i); rowIO.write(ioStats, i, RowType.primary, 1, row.length, stream -> stream.stream(row), stream -> true, (txId, prefix, key, value, valueTimestamp, valueTombstoned, valueVersion, fp) -> true, true, false); /*if (i % 10_000 == 0) { System.out.println("Wrote " + i); }*/ } rowIO = reopen.call(); /*long[][] histos = new long[32][]; for (int i = 0; i < histos.length; i++) { histos[i] = new long[16]; } long start = System.currentTimeMillis(); for (long i = 0; i < numRows; i++) { long[] result = rowIO.getInclusive(i); long[] histo = histos[(int) Math.log(i + 1)]; histo[Math.min((int) result[1], histo.length - 1)]++; if (i % 10_000 == 0) { System.out.println("Got " + i + " in " + (System.currentTimeMillis() - start)); start = System.currentTimeMillis(); } } for (int i = 0; i < histos.length; i++) { System.out.println("----------------------------- " + i + " -----------------------------"); for (int j = 0; j < histos[i].length; j++) { System.out.println("[" + j + "] " + histos[i][j]); } }*/ final int[] histo = new int[updatesBetweenLeaps]; for (long i = 0; i < numRows; i += (updatesBetweenLeaps / 10)) { final long txId = i; long nextStartOfRow = rowIO.getInclusiveStartOfRow(txId); rowIO.scan(ioStats, nextStartOfRow, false, new RowStream() { private int count = 0; @Override public boolean row(long rowFP, long rowTxId, RowType rowType, byte[] row) throws Exception { if (rowType == RowType.system) { return true; } else if (rowType == RowType.primary) { if (rowTxId == txId) { histo[count]++; return false; } else if (rowTxId > txId) { Assert.fail("Missed the desired txId: " + rowTxId + " > " + txId); return false; } else { if (count == updatesBetweenLeaps) { Assert.fail("Gave up without seeing the desired txId: " + txId); } count++; return count < updatesBetweenLeaps; } } return true; } }); } /*for (int i = 0; i < histo.length; i++) { System.out.println("[" + i + "] " + histo[i]); }*/ } }