-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathTtlDB.java
More file actions
211 lines (197 loc) · 7.65 KB
/
Copy pathTtlDB.java
File metadata and controls
211 lines (197 loc) · 7.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
package org.rocksdb;
import java.util.List;
/**
* Database with TTL support.
*
* <p><strong>Use case</strong></p>
* <p>This API should be used to open the db when key-values inserted are
* meant to be removed from the db in a non-strict 'ttl' amount of time
* Therefore, this guarantees that key-values inserted will remain in the
* db for >= ttl amount of time and the db will make efforts to remove the
* key-values as soon as possible after ttl seconds of their insertion.
* </p>
*
* <p><strong>Behaviour</strong></p>
* <p>TTL is accepted in seconds
* (int32_t)Timestamp(creation) is suffixed to values in Put internally
* Expired TTL values deleted in compaction only:(Timestamp+ttl<time_now)
* Get/Iterator may return expired entries(compaction not run on them yet)
* Different TTL may be used during different Opens
* </p>
*
* <p><strong>Example</strong></p>
* <ul>
* <li>Open1 at t=0 with ttl=4 and insert k1,k2, close at t=2</li>
* <li>Open2 at t=3 with ttl=5. Now k1,k2 should be deleted at t>=5</li>
* </ul>
*
* <p>
* read_only=true opens in the usual read-only mode. Compactions will not be
* triggered(neither manual nor automatic), so no expired entries removed
* </p>
*
* <p><strong>Constraints</strong></p>
* <p>Not specifying/passing or non-positive TTL behaves
* like TTL = infinity</p>
*
* <p><strong>!!!WARNING!!!</strong></p>
* <p>Calling DB::Open directly to re-open a db created by this API will get
* corrupt values(timestamp suffixed) and no ttl effect will be there
* during the second Open, so use this API consistently to open the db
* Be careful when passing ttl with a small positive value because the
* whole database may be deleted in a small amount of time.</p>
*/
public class TtlDB extends RocksDB {
/**
* <p>Opens a TtlDB.</p>
*
* <p>Database is opened in read-write mode without default TTL.</p>
*
* @param options {@link org.rocksdb.Options} instance.
* @param db_path path to database.
*
* @return TtlDB instance.
*
* @throws RocksDBException thrown if an error occurs within the native
* part of the library.
*/
public static TtlDB open(final Options options, final String db_path)
throws RocksDBException {
return open(options, db_path, 0, false);
}
/**
* <p>Opens a TtlDB.</p>
*
* @param options {@link org.rocksdb.Options} instance.
* @param db_path path to database.
* @param ttl time to live for new entries.
* @param readOnly boolean value indicating if database if db is
* opened read-only.
*
* @return TtlDB instance.
*
* @throws RocksDBException thrown if an error occurs within the native
* part of the library.
*/
public static TtlDB open(final Options options, final String db_path,
final int ttl, final boolean readOnly) throws RocksDBException {
return new TtlDB(open(options.nativeHandle_, db_path, ttl, readOnly));
}
/**
* <p>Opens a TtlDB.</p>
*
* @param options {@link org.rocksdb.Options} instance.
* @param db_path path to database.
* @param columnFamilyDescriptors list of column family descriptors
* @param columnFamilyHandles will be filled with ColumnFamilyHandle instances
* on open.
* @param ttlValues time to live values per column family handle
* @param readOnly boolean value indicating if database if db is
* opened read-only.
*
* @return TtlDB instance.
*
* @throws RocksDBException thrown if an error occurs within the native
* part of the library.
* @throws java.lang.IllegalArgumentException when there is not a ttl value
* per given column family handle.
*/
public static TtlDB open(final DBOptions options, final String db_path,
final List<ColumnFamilyDescriptor> columnFamilyDescriptors,
final List<ColumnFamilyHandle> columnFamilyHandles,
final List<Integer> ttlValues, final boolean readOnly)
throws RocksDBException {
if (columnFamilyDescriptors.size() != ttlValues.size()) {
throw new IllegalArgumentException("There must be a ttl value per column"
+ "family handle.");
}
final byte[][] cfNames = new byte[columnFamilyDescriptors.size()][];
final long[] cfOptionHandles = new long[columnFamilyDescriptors.size()];
for (int i = 0; i < columnFamilyDescriptors.size(); i++) {
final ColumnFamilyDescriptor cfDescriptor =
columnFamilyDescriptors.get(i);
cfNames[i] = cfDescriptor.columnFamilyName();
cfOptionHandles[i] = cfDescriptor.columnFamilyOptions().nativeHandle_;
}
final int ttlVals[] = new int[ttlValues.size()];
for(int i = 0; i < ttlValues.size(); i++) {
ttlVals[i] = ttlValues.get(i);
}
final long[] handles = openCF(options.nativeHandle_, db_path,
cfNames, cfOptionHandles, ttlVals, readOnly);
final TtlDB ttlDB = new TtlDB(handles[0]);
for (int i = 1; i < handles.length; i++) {
columnFamilyHandles.add(new ColumnFamilyHandle(ttlDB, handles[i]));
}
return ttlDB;
}
/**
* <p>Creates a new ttl based column family with a name defined
* in given ColumnFamilyDescriptor and allocates a
* ColumnFamilyHandle within an internal structure.</p>
*
* <p>The ColumnFamilyHandle is automatically disposed with DB
* disposal.</p>
*
* @param columnFamilyDescriptor column family to be created.
* @param ttl TTL to set for this column family.
*
* @return {@link org.rocksdb.ColumnFamilyHandle} instance.
*
* @throws RocksDBException thrown if error happens in underlying
* native library.
*/
public ColumnFamilyHandle createColumnFamilyWithTtl(
final ColumnFamilyDescriptor columnFamilyDescriptor,
final int ttl) throws RocksDBException {
return new ColumnFamilyHandle(this,
createColumnFamilyWithTtl(nativeHandle_,
columnFamilyDescriptor.columnFamilyName(),
columnFamilyDescriptor.columnFamilyOptions().nativeHandle_, ttl));
}
/**
* <p>Close the TtlDB instance and release resource.</p>
*
* <p>Internally, TtlDB owns the {@code rocksdb::DB} pointer
* to its associated {@link org.rocksdb.RocksDB}. The release
* of that RocksDB pointer is handled in the destructor of the
* c++ {@code rocksdb::TtlDB} and should be transparent to
* Java developers.</p>
*/
@Override
public void close() {
super.close();
}
/**
* <p>A protected constructor that will be used in the static
* factory method
* {@link #open(Options, String, int, boolean)}
* and
* {@link #open(DBOptions, String, java.util.List, java.util.List,
* java.util.List, boolean)}.
* </p>
*
* @param nativeHandle The native handle of the C++ TtlDB object
*/
protected TtlDB(final long nativeHandle) {
super(nativeHandle);
}
@Override protected void finalize() throws Throwable {
close(); //TODO(AR) revisit here when implementing AutoCloseable
super.finalize();
}
private native static long open(final long optionsHandle,
final String db_path, final int ttl, final boolean readOnly)
throws RocksDBException;
private native static long[] openCF(final long optionsHandle,
final String db_path, final byte[][] columnFamilyNames,
final long[] columnFamilyOptions, final int[] ttlValues,
final boolean readOnly) throws RocksDBException;
private native long createColumnFamilyWithTtl(final long handle,
final byte[] columnFamilyName, final long columnFamilyOptions, int ttl)
throws RocksDBException;
}