/* * This file is part of the Wayback archival access software * (http://archive-access.sourceforge.net/projects/wayback/). * * Licensed to the Internet Archive (IA) by one or more individual * contributors. * * The IA licenses this file to You 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.archive.wayback.util.bdb; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.Iterator; import org.archive.wayback.util.ByteOp; import com.sleepycat.je.Cursor; import com.sleepycat.je.Database; import com.sleepycat.je.DatabaseConfig; import com.sleepycat.je.DatabaseEntry; import com.sleepycat.je.DatabaseException; import com.sleepycat.je.Environment; import com.sleepycat.je.EnvironmentConfig; import com.sleepycat.je.LockMode; import com.sleepycat.je.OperationStatus; import com.sleepycat.je.Transaction; /** * * * @author brad * @version $Date$, $Revision$ */ public class BDBRecordSet { /** * Maximum BDBJE file size */ private final static String JE_LOG_FILEMAX = "256000000"; /** * path to directory containing the BDBJE files */ private String path; /** * name of BDBJE db within the path directory */ private String dbName; /** * BDBJE Environment */ Environment env = null; /** * BDBJE Database */ Database db = null; /** * @param thePath Directory where BDBJE files are stored * @param theDbName Name of files in thePath * @throws IOException for usual reasons, plus as database exceptions */ public void initializeDB(final String thePath, final String theDbName) throws IOException { path = thePath; dbName = theDbName; EnvironmentConfig environmentConfig = new EnvironmentConfig(); environmentConfig.setAllowCreate(true); environmentConfig.setTransactional(true); environmentConfig.setConfigParam("je.log.fileMax",JE_LOG_FILEMAX); File file = new File(path); if(!file.isDirectory()) { if(!file.mkdirs()) { throw new IOException("failed mkdirs(" + path + ")"); } } env = new Environment(file, environmentConfig); DatabaseConfig databaseConfig = new DatabaseConfig(); databaseConfig.setAllowCreate(true); databaseConfig.setTransactional(true); // perform other database configurations db = env.openDatabase(null, dbName, databaseConfig); } /** * shut down the BDB. * * @throws DatabaseException */ public synchronized void shutdownDB() throws DatabaseException { if (db != null) { db.close(); db = null; } if (env != null) { env.close(); env = null; } } /** * @param s * @return byte array representation of String s in UTF-8 */ public static byte[] stringToBytes(String s) { return s.getBytes(ByteOp.UTF8); } /** * @param ba * @return String of UTF-8 encoded bytes ba */ public static String bytesToString(byte[] ba) { return new String(ba,ByteOp.UTF8); } /** * @param startKey * @return iterator for BDBRecords * @throws DatabaseException */ public BDBRecordIterator recordIterator(final String startKey) throws DatabaseException { return recordIterator(startKey,true); } /** * @param startKey * @param forward * @return iterator for BDBRecords * @throws DatabaseException */ public BDBRecordIterator recordIterator(final String startKey, final boolean forward) throws DatabaseException { Cursor cursor = db.openCursor(null, null); return new BDBRecordIterator(cursor,startKey,!forward); } /** * @param itr */ public void insertRecords(final Iterator<BDBRecord> itr) { OperationStatus status = null; try { Transaction txn = env.beginTransaction(null, null); try { Cursor cursor = db.openCursor(txn, null); while (itr.hasNext()) { BDBRecord record = (BDBRecord) itr.next(); status = cursor.put(record.getKey(), record.getValue()); if (status != OperationStatus.SUCCESS) { throw new RuntimeException("put() non-success status"); } } cursor.close(); txn.commit(); } catch (DatabaseException e) { if(txn != null) { txn.abort(); } e.printStackTrace(); } } catch (DatabaseException e) { e.printStackTrace(); } } /** * persistantly store key-value pair * @param keyStr * @param valueStr * @throws DatabaseException */ public void put(String keyStr, String valueStr) throws DatabaseException { DatabaseEntry key = new DatabaseEntry(stringToBytes(keyStr)); DatabaseEntry data = new DatabaseEntry(stringToBytes(valueStr)); db.put(null, key, data); } /** * retrieve the value assoicated with keyStr from persistant storage * @param keyStr * @return String value associated with key, or null if no key is found * or an error occurs * @throws DatabaseException */ public String get(String keyStr) throws DatabaseException { String result = null; DatabaseEntry key = new DatabaseEntry(stringToBytes(keyStr)); DatabaseEntry data = new DatabaseEntry(); if (db.get(null, key, data, LockMode.DEFAULT) == OperationStatus.SUCCESS) { result = bytesToString(data.getData()); } return result; } /** * @param keyStr * @throws DatabaseException */ public void delete(String keyStr) throws DatabaseException { db.delete(null,new DatabaseEntry(stringToBytes(keyStr))); } /** * @return Returns the dbName. */ public String getDbName() { return dbName; } /** * @return Returns the path. */ public String getPath() { return path; } /** * @param path the path to set */ public void setPath(String path) { this.path = path; } /** * @param dbName the dbName to set */ public void setDbName(String dbName) { this.dbName = dbName; } }