org.cloudgraph.rocksdb.connect.RocksDBConnection Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cloudgraph-rocksdb Show documentation
Show all versions of cloudgraph-rocksdb Show documentation
CloudGraph(tm) is a suite of Service Data Object (SDO) 2.1 services designed for relational and big-table style "cloud" databases, such as HBase and others.
The newest version!
/**
* Copyright 2017 TerraMeta Software, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.cloudgraph.rocksdb.connect;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import javax.xml.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.pool2.ObjectPool;
import org.cloudgraph.core.Connection;
import org.cloudgraph.core.ServiceContext;
import org.cloudgraph.core.client.Admin;
import org.cloudgraph.core.client.BufferedMutator;
import org.cloudgraph.core.client.RegionLocator;
import org.cloudgraph.core.client.Table;
import org.cloudgraph.core.client.TableName;
import org.cloudgraph.rocksdb.client.RocksDBTable;
import org.cloudgraph.rocksdb.service.CloudGraphContext;
import org.cloudgraph.store.mapping.StoreMapping;
import org.cloudgraph.store.mapping.StoreMappingContext;
import org.cloudgraph.store.mapping.StoreMappingProp;
import org.cloudgraph.store.mapping.TableMapping;
import org.cloudgraph.store.service.GraphServiceException;
import org.rocksdb.BlockBasedTableConfig;
import org.rocksdb.BloomFilter;
import org.rocksdb.Cache;
import org.rocksdb.ColumnFamilyDescriptor;
import org.rocksdb.ColumnFamilyHandle;
import org.rocksdb.ColumnFamilyOptions;
import org.rocksdb.CompactionStyle;
import org.rocksdb.CompressionType;
import org.rocksdb.DBOptions;
import org.rocksdb.Filter;
import org.rocksdb.HashLinkedListMemTableConfig;
import org.rocksdb.HashSkipListMemTableConfig;
import org.rocksdb.LRUCache;
import org.rocksdb.Options;
import org.rocksdb.PlainTableConfig;
import org.rocksdb.RateLimiter;
import org.rocksdb.ReadOptions;
import org.rocksdb.RocksDB;
import org.rocksdb.RocksDBException;
import org.rocksdb.SkipListMemTableConfig;
import org.rocksdb.Statistics;
import org.rocksdb.VectorMemTableConfig;
import org.rocksdb.util.SizeUnit;
import org.apache.jena.ext.com.google.common.cache.CacheBuilder;
import org.apache.jena.ext.com.google.common.cache.CacheLoader;
import org.apache.jena.ext.com.google.common.cache.LoadingCache;
import org.apache.jena.ext.com.google.common.cache.RemovalListener;
import org.apache.jena.ext.com.google.common.cache.RemovalNotification;
/**
* Pooled HBase connection wrapper which complies with Apache pool semantics and
* maintains a cache or table handles for each connection. Depending in the
* complexity of a particular application, there may be many tables needed, for
* example some tables for actual data and some for metadata or other
* application data. Caching table API handles greatly reduces round trips and
* resource costs for some HBase implementations.
*
* The new HBase 1.x Client API changes removed the existing connection pool
* implementation and placed the responsibility of managing the lifecycle of
* connections on the caller. A pool is necessary as creating connections to the
* cluster via. zookeeper is fairly expensive.
*
*
*
* For some HBase implementations, e.g. MAPR, the management of connections and
* table handles is super critical, as the API is extremely performance and
* resource costly at scale.
*
*
* @author Scott Cinnamond
* @since 0.6.3
*/
public class RocksDBConnection implements Connection {
private static Log log = LogFactory.getLog(RocksDBConnection.class);
private ObjectPool pool;
private LoadingCache tableCache;
private RocksDB connection;
private List columnFamilyHandles = new ArrayList<>();
public RocksDBConnection(ObjectPool pool) {
super();
this.pool = pool;
final Options options = new Options();
final Filter bloomFilter = new BloomFilter(10);
final ReadOptions readOptions = new ReadOptions().setFillCache(false);
final Statistics stats = new Statistics();
final RateLimiter rateLimiter = new RateLimiter(10000000, 10000, 10);
options.setCreateIfMissing(true);
options.setStatistics(stats);
options.setWriteBufferSize(8 * SizeUnit.KB);
options.setMaxWriteBufferNumber(3);
options.setMaxBackgroundJobs(10);
options.setCompressionType(CompressionType.SNAPPY_COMPRESSION);
options.setCompactionStyle(CompactionStyle.UNIVERSAL);
options.setMemTableConfig(new HashSkipListMemTableConfig().setHeight(4).setBranchingFactor(4)
.setBucketCount(2000000));
options.setMergeOperatorName("uint64add");
// options.setMemTableConfig(new
// HashLinkedListMemTableConfig().setBucketCount(100000));
// options.setMemTableConfig(new
// VectorMemTableConfig().setReservedSize(10000));
// options.setMemTableConfig(new SkipListMemTableConfig());
PlainTableConfig tableConfig = new PlainTableConfig();
options.setTableFormatConfig(tableConfig);
// Plain-Table requires mmap read
options.setAllowMmapReads(true);
options.setRateLimiter(rateLimiter);
final BlockBasedTableConfig tableOptions = new BlockBasedTableConfig();
Cache cache = new LRUCache(64 * 1024, 6);
tableOptions.setBlockCache(cache);
tableOptions.setFilterPolicy(bloomFilter);
tableOptions.setBlockSizeDeviation(5);
tableOptions.setBlockRestartInterval(10);
tableOptions.setCacheIndexAndFilterBlocks(true);
tableOptions.setBlockCacheCompressed(new LRUCache(64 * 1000, 10));
byte[] cfBytes = "f1".getBytes();
ColumnFamilyDescriptor cf = new ColumnFamilyDescriptor(cfBytes, new ColumnFamilyOptions());
RocksDB db;
try {
Options createOptions = new Options();
createOptions.setCreateIfMissing(true);
// createOptions.setMergeOperatorName("uint64add");
List list = RocksDB.listColumnFamilies(createOptions, "/home/rocksdbdata");
boolean found = false;
for (byte[] famBytes : list) {
if (Arrays.equals(famBytes, cfBytes)) {
found = true;
break;
}
}
if (!found) {
db = RocksDB.open(createOptions, "/home/rocksdbdata");
db.createColumnFamily(cf);
db.close();
}
} catch (RocksDBException e1) {
throw new GraphServiceException(e1);
}
DBOptions dbOptions = new DBOptions();
dbOptions.setCreateIfMissing(true);
final List columnFamilyDescriptors = new ArrayList<>();
// have to open default column family
columnFamilyDescriptors.add(new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY,
new ColumnFamilyOptions()));
// open the new one, too
columnFamilyDescriptors.add(cf);
try {
this.connection = RocksDB.open(dbOptions, "/home/rocksdbdata", columnFamilyDescriptors,
columnFamilyHandles);
} catch (RocksDBException e) {
throw new GraphServiceException(e);
}
final int cacheMax = StoreMappingProp.getConnectionTablecacheSizeMax();
final int cacheTimeout = StoreMappingProp.getConnectionTablecacheTimeoutSeconds();
Map propsMap = StoreMappingProp.getConnectionTableConfigProperties();
Iterator keys = propsMap.keySet().iterator();
while (keys.hasNext()) {
String key = keys.next();
String value = propsMap.get(key);
}
this.tableCache = CacheBuilder.newBuilder().maximumSize(cacheMax)
.expireAfterAccess(cacheTimeout, TimeUnit.SECONDS)
.removalListener(new RemovalListener() {
@Override
public void onRemoval(RemovalNotification event) {
}
}).build(new CacheLoader() {
@Override
public RocksDBTable load(TableName tableName) throws Exception {
if (log.isDebugEnabled())
log.debug("loading table " + this + " " + tableName.getNamespace() + "."
+ tableName.getTableName());
StringBuilder logicalTableNameKey = new StringBuilder();
if (tableName.getNamespace() != null) {
logicalTableNameKey.append(tableName.getNamespace());
logicalTableNameKey.append("/");
}
logicalTableNameKey.append(tableName.getTableName());
// // Uses a path as the single key for internal table mapping
// String qualifiedLogicalName = StoreMapping.getInstance()
// .qualifiedLogicalTableNameFromPhysicalTablePath(null,
// logicalTableNameKey.toString(), serviceContext);
return new RocksDBTable(tableName, connection);
}
});
if (log.isDebugEnabled())
log.debug("created " + this + " pool active/idle " + pool.getNumActive() + "/"
+ pool.getNumIdle());
}
public void close() throws IOException {
try {
this.pool.returnObject(this);
} catch (Exception e) {
throw new GraphServiceException(e);
}
}
public void destroy() throws IOException {
this.tableCache.invalidateAll();
this.tableCache.cleanUp();
for (ColumnFamilyHandle handle : columnFamilyHandles) {
handle.close();
}
if (log.isDebugEnabled())
log.debug("destroyed " + this + " pool active/idle " + pool.getNumActive() + "/"
+ pool.getNumIdle());
}
public boolean isClosed() {
return false;
}
public void abort(String why, Throwable e) {
}
public boolean isAborted() {
return false;
}
public boolean tableExists(TableName tableName) throws IOException {
boolean exists = true;
return exists;
}
@Override
public Table getTable(TableName tableName) throws IOException {
Table result = null;
try {
result = this.tableCache.get(tableName);
} catch (ExecutionException e) {
log.error(e.getMessage(), e);
}
return result;
}
@Override
public Table getTable(TableName tableName, ExecutorService pool) throws IOException {
Table result = null;
try {
result = this.tableCache.get(tableName);
} catch (ExecutionException e) {
log.error(e.getMessage(), e);
}
return result;
}
@Override
public RegionLocator getRegionLocator(TableName tableName) throws IOException {
// TODO Auto-generated method stub
return null;
}
@Override
public BufferedMutator getBufferedMutator(TableName tableName) throws IOException {
// TODO Auto-generated method stub
return null;
}
@Override
public Admin getAdmin() throws IOException {
// TODO Auto-generated method stub
return null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy