1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. 2 // This source code is licensed under both the GPLv2 (found in the 3 // COPYING file in the root directory) and Apache 2.0 License 4 // (found in the LICENSE.Apache file in the root directory). 5 6 package org.rocksdb; 7 8 import static org.assertj.core.api.Assertions.assertThat; 9 import static org.junit.Assert.assertEquals; 10 import static org.junit.Assert.fail; 11 12 import java.io.File; 13 import java.io.IOException; 14 import java.nio.ByteBuffer; 15 import java.util.ArrayList; 16 import java.util.List; 17 import org.junit.Rule; 18 import org.junit.Test; 19 import org.junit.rules.TemporaryFolder; 20 import org.rocksdb.util.BytewiseComparator; 21 22 public class SstFileReaderTest { 23 private static final String SST_FILE_NAME = "test.sst"; 24 25 class KeyValueWithOp { 26 KeyValueWithOp(String key, String value, OpType opType) { 27 this.key = key; 28 this.value = value; 29 this.opType = opType; 30 } 31 32 String getKey() { 33 return key; 34 } 35 AP(A)36 String getValue() { 37 return value; 38 } 39 40 OpType getOpType() { 41 return opType; 42 } 43 44 private String key; 45 private String value; 46 private OpType opType; 47 } 48 49 @Rule public TemporaryFolder parentFolder = new TemporaryFolder(); 50 51 enum OpType { PUT, PUT_BYTES, MERGE, MERGE_BYTES, DELETE, DELETE_BYTES } 52 53 private File newSstFile(final List<KeyValueWithOp> keyValues) 54 throws IOException, RocksDBException { 55 final EnvOptions envOptions = new EnvOptions(); 56 final StringAppendOperator stringAppendOperator = new StringAppendOperator(); 57 final Options options = new Options().setMergeOperator(stringAppendOperator); update(uint8_t Value)58 SstFileWriter sstFileWriter; 59 sstFileWriter = new SstFileWriter(envOptions, options); 60 61 final File sstFile = parentFolder.newFile(SST_FILE_NAME); 62 try { 63 sstFileWriter.open(sstFile.getAbsolutePath()); 64 for (KeyValueWithOp keyValue : keyValues) { 65 Slice keySlice = new Slice(keyValue.getKey()); 66 Slice valueSlice = new Slice(keyValue.getValue()); 67 byte[] keyBytes = keyValue.getKey().getBytes(); 68 byte[] valueBytes = keyValue.getValue().getBytes(); 69 switch (keyValue.getOpType()) { 70 case PUT: 71 sstFileWriter.put(keySlice, valueSlice); 72 break; 73 case PUT_BYTES: 74 sstFileWriter.put(keyBytes, valueBytes); 75 break; 76 case MERGE: 77 sstFileWriter.merge(keySlice, valueSlice); 78 break; 79 case MERGE_BYTES: 80 sstFileWriter.merge(keyBytes, valueBytes); 81 break; 82 case DELETE: 83 sstFileWriter.delete(keySlice); 84 break; 85 case DELETE_BYTES: 86 sstFileWriter.delete(keyBytes); 87 break; 88 default: 89 fail("Unsupported op type"); 90 } 91 keySlice.close(); 92 valueSlice.close(); 93 } 94 sstFileWriter.finish(); 95 } finally { 96 assertThat(sstFileWriter).isNotNull(); 97 sstFileWriter.close(); 98 options.close(); 99 envOptions.close(); 100 } 101 return sstFile; 102 } 103 104 @Test 105 public void readSstFile() throws RocksDBException, IOException { 106 final List<KeyValueWithOp> keyValues = new ArrayList<>(); 107 keyValues.add(new KeyValueWithOp("key1", "value1", OpType.PUT)); 108 109 final File sstFile = newSstFile(keyValues); 110 try (final StringAppendOperator stringAppendOperator = new StringAppendOperator(); 111 final Options options = 112 new Options().setCreateIfMissing(true).setMergeOperator(stringAppendOperator); 113 final SstFileReader reader = new SstFileReader(options)) { 114 // Open the sst file and iterator 115 reader.open(sstFile.getAbsolutePath()); 116 final ReadOptions readOptions = new ReadOptions(); 117 final SstFileReaderIterator iterator = reader.newIterator(readOptions); 118 119 // Use the iterator to read sst file 120 iterator.seekToFirst(); 121 122 // Verify Checksum 123 reader.verifyChecksum(); 124 125 // Verify Table Properties 126 assertEquals(reader.getTableProperties().getNumEntries(), 1); 127 128 // Check key and value 129 assertThat(iterator.key()).isEqualTo("key1".getBytes()); 130 assertThat(iterator.value()).isEqualTo("value1".getBytes()); 131 132 ByteBuffer direct = ByteBuffer.allocateDirect(128); 133 direct.put("key1".getBytes()).flip(); 134 iterator.seek(direct); 135 assertThat(direct.position()).isEqualTo(4); 136 assertThat(direct.limit()).isEqualTo(4); 137 138 assertThat(iterator.isValid()).isTrue(); 139 assertThat(iterator.key()).isEqualTo("key1".getBytes()); 140 assertThat(iterator.value()).isEqualTo("value1".getBytes()); 141 142 direct.clear(); 143 assertThat(iterator.key(direct)).isEqualTo("key1".getBytes().length); 144 byte[] dst = new byte["key1".getBytes().length]; 145 direct.get(dst); 146 assertThat(new String(dst)).isEqualTo("key1"); 147 148 direct.clear(); 149 assertThat(iterator.value(direct)).isEqualTo("value1".getBytes().length); 150 dst = new byte["value1".getBytes().length]; 151 direct.get(dst); 152 assertThat(new String(dst)).isEqualTo("value1"); 153 } 154 } 155 } 156