Permalink
Browse files

Added support for bdb env per store with shared cache.

  • Loading branch information...
1 parent c6bd8fd commit 087e9d72b7239264d53aca79fd7682ae629d1566 @bbansal bbansal committed Feb 10, 2009
View
14 src/java/voldemort/server/VoldemortConfig.java
@@ -56,6 +56,7 @@
private int bdbBtreeFanout;
private long bdbCheckpointBytes;
private long bdbCheckpointMs;
+ private boolean bdbFilePerStore;
private String mysqlUsername;
private String mysqlPassword;
@@ -126,6 +127,7 @@ public VoldemortConfig(Props props) {
this.bdbBtreeFanout = props.getInt("bdb.btree.fanout", 512);
this.bdbCheckpointBytes = props.getLong("bdb.checkpoint.interval.bytes", 20 * 1024 * 1024);
this.bdbCheckpointMs = props.getLong("bdb.checkpoint.interval.ms", 30 * Time.MS_PER_SECOND);
+ this.bdbFilePerStore = props.getBoolean("bdb.use.file.per.store", false);
this.enableReadOnlyEngine = props.getBoolean("enable.readonly.engine", false);
this.readOnlyFileWaitTimeoutMs = props.getLong("readonly.file.wait.timeout.ms", 4000L);
@@ -335,6 +337,18 @@ public void setBdbBtreeFanout(int bdbBtreeFanout) {
}
/**
+ * The bdb Environment setting. use an environment(file) per store (if true)
+ * or use a common environment (default: false)
+ */
+ public boolean getBdbFilePerStore() {
+ return this.bdbFilePerStore;
+ }
+
+ public void setBdbFilePerStore(boolean bdbFilePerStore) {
+ this.bdbFilePerStore = bdbFilePerStore;
+ }
+
+ /**
* The comfortable number of threads the threadpool will attempt to
* maintain. Specified by "core.threads" default: max(1, floor(0.5 *
* max.threads))
View
109 src/java/voldemort/store/bdb/BdbStorageConfiguration.java
@@ -17,6 +17,8 @@
package voldemort.store.bdb;
import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
@@ -47,49 +49,48 @@
private static Logger logger = Logger.getLogger(BdbStorageConfiguration.class);
- private Environment environment;
private EnvironmentConfig environmentConfig;
private DatabaseConfig databaseConfig;
private boolean isInitialized = false;
private Map<String, BdbStorageEngine> stores = Maps.newHashMap();
+ private String bdbMasterDir;
+ private List<Environment> environmentList = new ArrayList<Environment>();
+ private boolean useFilePerStore;
public BdbStorageConfiguration(VoldemortConfig config) {
- try {
- environmentConfig = new EnvironmentConfig();
- environmentConfig.setTransactional(true);
- environmentConfig.setCacheSize(config.getBdbCacheSize());
- if(config.isBdbWriteTransactionsEnabled() && config.isBdbFlushTransactionsEnabled()) {
- environmentConfig.setTxnNoSync(false);
- environmentConfig.setTxnWriteNoSync(false);
- } else if(config.isBdbWriteTransactionsEnabled()
- && !config.isBdbFlushTransactionsEnabled()) {
- environmentConfig.setTxnNoSync(false);
- environmentConfig.setTxnWriteNoSync(true);
- } else {
- environmentConfig.setTxnNoSync(true);
- }
- environmentConfig.setAllowCreate(true);
- environmentConfig.setConfigParam(EnvironmentConfig.LOG_FILE_MAX,
- Long.toString(config.getBdbMaxLogFileSize()));
- environmentConfig.setConfigParam(EnvironmentConfig.CHECKPOINTER_BYTES_INTERVAL,
- Long.toString(config.getBdbCheckpointBytes()));
- environmentConfig.setConfigParam(EnvironmentConfig.CHECKPOINTER_WAKEUP_INTERVAL,
- Long.toString(config.getBdbCheckpointMs()
- * Time.US_PER_MS));
- databaseConfig = new DatabaseConfig();
- databaseConfig.setAllowCreate(true);
- databaseConfig.setNodeMaxEntries(config.getBdbBtreeFanout());
- databaseConfig.setTransactional(true);
- File bdbDir = new File(config.getBdbDataDirectory());
- if(!bdbDir.exists()) {
- logger.info("Creating BDB data directory '" + bdbDir.getAbsolutePath() + "'.");
- bdbDir.mkdirs();
- }
- environment = new Environment(bdbDir, environmentConfig);
- isInitialized = true;
- } catch(DatabaseException e) {
- throw new StorageInitializationException(e);
+ environmentConfig = new EnvironmentConfig();
+ environmentConfig.setTransactional(true);
+ environmentConfig.setCacheSize(config.getBdbCacheSize());
+ if(config.isBdbWriteTransactionsEnabled() && config.isBdbFlushTransactionsEnabled()) {
+ environmentConfig.setTxnNoSync(false);
+ environmentConfig.setTxnWriteNoSync(false);
+ } else if(config.isBdbWriteTransactionsEnabled() && !config.isBdbFlushTransactionsEnabled()) {
+ environmentConfig.setTxnNoSync(false);
+ environmentConfig.setTxnWriteNoSync(true);
+ } else {
+ environmentConfig.setTxnNoSync(true);
}
+ environmentConfig.setAllowCreate(true);
+ environmentConfig.setConfigParam(EnvironmentConfig.LOG_FILE_MAX,
+ Long.toString(config.getBdbMaxLogFileSize()));
+ environmentConfig.setConfigParam(EnvironmentConfig.CHECKPOINTER_BYTES_INTERVAL,
+ Long.toString(config.getBdbCheckpointBytes()));
+ environmentConfig.setConfigParam(EnvironmentConfig.CHECKPOINTER_WAKEUP_INTERVAL,
+ Long.toString(config.getBdbCheckpointMs() * Time.US_PER_MS));
+ environmentConfig.setSharedCache(true);
+
+ // set database config.
+ databaseConfig = new DatabaseConfig();
+ databaseConfig.setAllowCreate(true);
+ databaseConfig.setNodeMaxEntries(config.getBdbBtreeFanout());
+ databaseConfig.setTransactional(true);
+
+ // set bdb Master Dir
+ bdbMasterDir = config.getBdbDataDirectory();
+
+ // set bdb file per store or Old common file setting
+ useFilePerStore = config.getBdbFilePerStore();
+ isInitialized = true;
}
public synchronized StorageEngine<byte[], byte[]> getStore(String storeName) {
@@ -100,6 +101,8 @@ public BdbStorageConfiguration(VoldemortConfig config) {
return stores.get(storeName);
} else {
try {
+
+ Environment environment = getEnvironment(storeName);
Database db = environment.openDatabase(null, storeName, databaseConfig);
BdbStorageEngine engine = new BdbStorageEngine(storeName, environment, db);
stores.put(storeName, engine);
@@ -114,10 +117,40 @@ public StorageEngineType getType() {
return StorageEngineType.BDB;
}
+ private Environment getEnvironment(String storeName) throws DatabaseException {
+ if(useFilePerStore) {
+ File bdbDir = new File(bdbMasterDir + "/" + storeName);
+ if(!bdbDir.exists()) {
+ logger.info("Creating BDB data directory '" + bdbDir.getAbsolutePath()
+ + "' for store'" + storeName + "'.");
+ bdbDir.mkdirs();
+ }
+ Environment environment = new Environment(bdbDir, environmentConfig);
+ environmentList.add(environment);
+ return environment;
+ } else {
+ // use common environment
+ if(environmentList.size() > 0) {
+ return environmentList.get(0);
+ } else {
+ File bdbDir = new File(bdbMasterDir);
+ if(!bdbDir.exists()) {
+ logger.info("Creating BDB data directory '" + bdbDir.getAbsolutePath() + "'.");
+ bdbDir.mkdirs();
+ }
+ Environment environment = new Environment(bdbDir, environmentConfig);
+ environmentList.add(environment);
+ return environment;
+ }
+ }
+ }
+
public void close() {
try {
- this.environment.sync();
- this.environment.close();
+ for(Environment env: environmentList) {
+ env.sync();
+ env.close();
+ }
} catch(DatabaseException e) {
throw new VoldemortException(e);
}
View
125 test/unit/voldemort/store/bdb/BdbSplitStorageEngineTest.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2008-2009 LinkedIn, 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 voldemort.store.bdb;
+
+import java.io.File;
+import java.util.Random;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.io.FileDeleteStrategy;
+
+import voldemort.TestUtils;
+import voldemort.server.VoldemortConfig;
+import voldemort.utils.Props;
+import voldemort.versioning.Versioned;
+
+/**
+ * checks that
+ *
+ * @author bbansal
+ *
+ */
+public class BdbSplitStorageEngineTest extends TestCase {
+
+ private File bdbMasterDir;
+ private BdbStorageEngine storeA;
+ private BdbStorageEngine storeB;
+ private Random random;
+ BdbStorageConfiguration bdbStorage;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ bdbMasterDir = TestUtils.getTempDirectory();
+ FileDeleteStrategy.FORCE.delete(bdbMasterDir);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ try {
+ bdbStorage.close();
+ } finally {
+ FileDeleteStrategy.FORCE.delete(bdbMasterDir);
+ }
+ }
+
+ public void testNoMultipleFiles() {
+ // lets use all the default values.
+ Props props = new Props();
+ props.put("node.id", 1);
+ props.put("voldemort.home", "test/common/voldemort/config");
+ VoldemortConfig voldemortConfig = new VoldemortConfig(props);
+ voldemortConfig.setBdbCacheSize(1 * 1024 * 1024);
+ voldemortConfig.setBdbDataDirectory(bdbMasterDir.toURI().getPath());
+
+ bdbStorage = new BdbStorageConfiguration(voldemortConfig);
+ storeA = (BdbStorageEngine) bdbStorage.getStore("storeA");
+ storeB = (BdbStorageEngine) bdbStorage.getStore("storeB");
+
+ storeA.put("testKey1".getBytes(), new Versioned<byte[]>("value".getBytes()));
+ storeA.put("testKey2".getBytes(), new Versioned<byte[]>("value".getBytes()));
+ storeA.put("testKey3".getBytes(), new Versioned<byte[]>("value".getBytes()));
+
+ storeB.put("testKey1".getBytes(), new Versioned<byte[]>("value".getBytes()));
+ storeB.put("testKey2".getBytes(), new Versioned<byte[]>("value".getBytes()));
+ storeB.put("testKey3".getBytes(), new Versioned<byte[]>("value".getBytes()));
+
+ storeA.close();
+ storeB.close();
+
+ assertEquals("common BDB file should exists.", true, (bdbMasterDir.exists()));
+
+ assertNotSame("StoreA BDB file should not exists.", true, (new File(bdbMasterDir + "/"
+ + "storeA").exists()));
+ assertNotSame("StoreB BDB file should not exists.", true, (new File(bdbMasterDir + "/"
+ + "storeB").exists()));
+ }
+
+ public void testMultipleFiles() {
+ // lets use all the default values.
+ Props props = new Props();
+ props.put("node.id", 1);
+ props.put("voldemort.home", "test/common/voldemort/config");
+ VoldemortConfig voldemortConfig = new VoldemortConfig(props);
+ voldemortConfig.setBdbCacheSize(1 * 1024 * 1024);
+ voldemortConfig.setBdbFilePerStore(true);
+ voldemortConfig.setBdbDataDirectory(bdbMasterDir.toURI().getPath());
+
+ bdbStorage = new BdbStorageConfiguration(voldemortConfig);
+ storeA = (BdbStorageEngine) bdbStorage.getStore("storeA");
+ storeB = (BdbStorageEngine) bdbStorage.getStore("storeB");
+
+ storeA.put("testKey1".getBytes(), new Versioned<byte[]>("value".getBytes()));
+ storeA.put("testKey2".getBytes(), new Versioned<byte[]>("value".getBytes()));
+ storeA.put("testKey3".getBytes(), new Versioned<byte[]>("value".getBytes()));
+
+ storeB.put("testKey1".getBytes(), new Versioned<byte[]>("value".getBytes()));
+ storeB.put("testKey2".getBytes(), new Versioned<byte[]>("value".getBytes()));
+ storeB.put("testKey3".getBytes(), new Versioned<byte[]>("value".getBytes()));
+
+ storeA.close();
+ storeB.close();
+
+ assertEquals("StoreA BDB file should exists.", true, (new File(bdbMasterDir + "/"
+ + "storeA").exists()));
+ assertEquals("StoreB BDB file should exists.", true, (new File(bdbMasterDir + "/"
+ + "storeB").exists()));
+ }
+}

0 comments on commit 087e9d7

Please sign in to comment.