package com.github.ltsopensource.core.failstore.rocksdb;
import com.github.ltsopensource.core.commons.file.FileUtils;
import com.github.ltsopensource.core.commons.utils.CollectionUtils;
import com.github.ltsopensource.core.domain.Pair;
import com.github.ltsopensource.core.failstore.AbstractFailStore;
import com.github.ltsopensource.core.failstore.FailStoreException;
import com.github.ltsopensource.core.json.JSON;
import org.rocksdb.*;
import org.rocksdb.util.SizeUnit;
import java.io.File;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
/**
* Robert HG (254963746@qq.com) on 5/27/15.
*/
public class RocksdbFailStore extends AbstractFailStore {
private RocksDB db = null;
private Options options;
public RocksdbFailStore(File dbPath, boolean needLock) {
super(dbPath, needLock);
}
public static final String name = "rocksdb";
@Override
protected void init() throws FailStoreException {
try {
options = new Options();
options.setCreateIfMissing(true)
.setWriteBufferSize(8 * SizeUnit.KB)
.setMaxWriteBufferNumber(3)
.setMaxBackgroundCompactions(10)
.setCompressionType(CompressionType.SNAPPY_COMPRESSION)
.setCompactionStyle(CompactionStyle.UNIVERSAL);
Filter bloomFilter = new BloomFilter(10);
BlockBasedTableConfig tableConfig = new BlockBasedTableConfig();
tableConfig.setBlockCacheSize(64 * SizeUnit.KB)
.setFilter(bloomFilter)
.setCacheNumShardBits(6)
.setBlockSizeDeviation(5)
.setBlockRestartInterval(10)
.setCacheIndexAndFilterBlocks(true)
.setHashIndexAllowCollision(false)
.setBlockCacheCompressedSize(64 * SizeUnit.KB)
.setBlockCacheCompressedNumShardBits(10);
options.setTableFormatConfig(tableConfig);
} catch (Exception e) {
throw new FailStoreException(e);
}
}
@Override
protected String getName() {
return name;
}
@Override
public void open() throws FailStoreException {
try {
db = RocksDB.open(options, dbPath.getPath());
} catch (Exception e) {
throw new FailStoreException(e);
}
}
@Override
public void put(String key, Object value) throws FailStoreException {
String valueString = JSON.toJSONString(value);
WriteOptions writeOpts = new WriteOptions();
try {
writeOpts.setSync(true);
writeOpts.setDisableWAL(true);
db.put(writeOpts, key.getBytes("UTF-8"), valueString.getBytes("UTF-8"));
} catch (Exception e) {
throw new FailStoreException(e);
} finally {
writeOpts.dispose();
}
}
@Override
public void delete(String key) throws FailStoreException {
try {
db.remove(key.getBytes("UTF-8"));
} catch (Exception e) {
throw new FailStoreException(e);
}
}
@Override
public void delete(List<String> keys) throws FailStoreException {
if (CollectionUtils.isEmpty(keys)) {
return;
}
for (String key : keys) {
delete(key);
}
}
@Override
public <T> List<Pair<String, T>> fetchTop(int size, Type type) throws FailStoreException {
RocksIterator iterator = null;
try {
List<Pair<String, T>> list = new ArrayList<Pair<String, T>>(size);
iterator = db.newIterator();
for (iterator.seekToFirst(); iterator.isValid(); iterator.next()) {
iterator.status();
String key = new String(iterator.key(), "UTF-8");
T value = JSON.parse(new String(iterator.value(), "UTF-8"), type);
Pair<String, T> pair = new Pair<String, T>(key, value);
list.add(pair);
if (list.size() >= size) {
break;
}
}
return list;
} catch (Exception e) {
throw new FailStoreException(e);
} finally {
if (iterator != null) {
iterator.dispose();
}
}
}
@Override
public void close() throws FailStoreException {
try {
if (db != null) {
db.close();
}
} catch (Exception e) {
throw new FailStoreException(e);
}
}
@Override
public void destroy() throws FailStoreException {
try {
db.close();
options.dispose();
} catch (Exception e) {
throw new FailStoreException(e);
} finally {
if (fileLock != null) {
fileLock.release();
}
FileUtils.delete(dbPath);
}
}
}