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).
8 import org
.junit
.ClassRule
;
10 import org
.junit
.Test
;
11 import org
.junit
.rules
.TemporaryFolder
;
13 import java
.util
.ArrayList
;
14 import java
.util
.Arrays
;
15 import java
.util
.List
;
18 import static org
.assertj
.core
.api
.Assertions
.assertThat
;
19 import static org
.rocksdb
.util
.ByteUtil
.bytes
;
20 import static org
.rocksdb
.util
.TestUtil
.*;
22 public class WalFilterTest
{
25 public static final RocksNativeLibraryResource ROCKS_NATIVE_LIBRARY_RESOURCE
=
26 new RocksNativeLibraryResource();
29 public TemporaryFolder dbFolder
= new TemporaryFolder();
32 public void walFilter() throws RocksDBException
{
33 // Create 3 batches with two keys each
34 final byte[][][] batchKeys
= {
50 final List
<ColumnFamilyDescriptor
> cfDescriptors
= Arrays
.asList(
51 new ColumnFamilyDescriptor(RocksDB
.DEFAULT_COLUMN_FAMILY
),
52 new ColumnFamilyDescriptor(bytes("pikachu"))
54 final List
<ColumnFamilyHandle
> cfHandles
= new ArrayList
<>();
56 // Test with all WAL processing options
57 for (final WalProcessingOption option
: WalProcessingOption
.values()) {
58 try (final Options options
= optionsForLogIterTest();
59 final DBOptions dbOptions
= new DBOptions(options
)
60 .setCreateMissingColumnFamilies(true);
61 final RocksDB db
= RocksDB
.open(dbOptions
,
62 dbFolder
.getRoot().getAbsolutePath(),
63 cfDescriptors
, cfHandles
)) {
64 try (final WriteOptions writeOptions
= new WriteOptions()) {
65 // Write given keys in given batches
66 for (int i
= 0; i
< batchKeys
.length
; i
++) {
67 final WriteBatch batch
= new WriteBatch();
68 for (int j
= 0; j
< batchKeys
[i
].length
; j
++) {
69 batch
.put(cfHandles
.get(0), batchKeys
[i
][j
], dummyString(1024));
71 db
.write(writeOptions
, batch
);
74 for (final ColumnFamilyHandle cfHandle
: cfHandles
) {
81 // Create a test filter that would apply wal_processing_option at the first
83 final int applyOptionForRecordIndex
= 1;
84 try (final TestableWalFilter walFilter
=
85 new TestableWalFilter(option
, applyOptionForRecordIndex
)) {
87 try (final Options options
= optionsForLogIterTest();
88 final DBOptions dbOptions
= new DBOptions(options
)
89 .setWalFilter(walFilter
)) {
91 try (final RocksDB db
= RocksDB
.open(dbOptions
,
92 dbFolder
.getRoot().getAbsolutePath(),
93 cfDescriptors
, cfHandles
)) {
96 assertThat(walFilter
.logNumbers
).isNotEmpty();
97 assertThat(walFilter
.logFileNames
).isNotEmpty();
99 for (final ColumnFamilyHandle cfHandle
: cfHandles
) {
104 } catch (final RocksDBException e
) {
105 if (option
!= WalProcessingOption
.CORRUPTED_RECORD
) {
106 // exception is expected when CORRUPTED_RECORD!
116 private static class TestableWalFilter
extends AbstractWalFilter
{
117 private final WalProcessingOption walProcessingOption
;
118 private final int applyOptionForRecordIndex
;
119 Map
<Integer
, Long
> cfLognumber
;
120 Map
<String
, Integer
> cfNameId
;
121 final List
<Long
> logNumbers
= new ArrayList
<>();
122 final List
<String
> logFileNames
= new ArrayList
<>();
123 private int currentRecordIndex
= 0;
125 public TestableWalFilter(final WalProcessingOption walProcessingOption
,
126 final int applyOptionForRecordIndex
) {
128 this.walProcessingOption
= walProcessingOption
;
129 this.applyOptionForRecordIndex
= applyOptionForRecordIndex
;
133 public void columnFamilyLogNumberMap(final Map
<Integer
, Long
> cfLognumber
,
134 final Map
<String
, Integer
> cfNameId
) {
135 this.cfLognumber
= cfLognumber
;
136 this.cfNameId
= cfNameId
;
140 public LogRecordFoundResult
logRecordFound(
141 final long logNumber
, final String logFileName
, final WriteBatch batch
,
142 final WriteBatch newBatch
) {
144 logNumbers
.add(logNumber
);
145 logFileNames
.add(logFileName
);
147 final WalProcessingOption optionToReturn
;
148 if (currentRecordIndex
== applyOptionForRecordIndex
) {
149 optionToReturn
= walProcessingOption
;
152 optionToReturn
= WalProcessingOption
.CONTINUE_PROCESSING
;
155 currentRecordIndex
++;
157 return new LogRecordFoundResult(optionToReturn
, false);
161 public String
name() {
162 return "testable-wal-filter";