diff options
| author | Lorry <lorry@roadtrain.codethink.co.uk> | 2012-07-20 20:00:05 +0100 |
|---|---|---|
| committer | Lorry <lorry@roadtrain.codethink.co.uk> | 2012-07-20 20:00:05 +0100 |
| commit | 3ef782d3745ea8f25a3151561a3cfb882190210e (patch) | |
| tree | 86b9c2f5fde051dd0bced99b3fc9f5a3ba08db69 /examples/java/src/db/BulkExample.java | |
| download | berkeleydb-3ef782d3745ea8f25a3151561a3cfb882190210e.tar.gz | |
Tarball conversion
Diffstat (limited to 'examples/java/src/db/BulkExample.java')
| -rw-r--r-- | examples/java/src/db/BulkExample.java | 556 |
1 files changed, 556 insertions, 0 deletions
diff --git a/examples/java/src/db/BulkExample.java b/examples/java/src/db/BulkExample.java new file mode 100644 index 00000000..1d752ff4 --- /dev/null +++ b/examples/java/src/db/BulkExample.java @@ -0,0 +1,556 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * $Id$ + */ + +package db; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.ByteBuffer; + +import com.sleepycat.db.*; + +public class BulkExample { + private static final String dbFileName = "BulkExample.db"; + private static final String pDbName = "primary"; + private static final String sDbName = "secondary"; + private static final String home = "BulkExample"; + private static final int buffLen = 1024 * 1024; + + /* Bulk methods demonstrated in the example */ + private enum Operations {BULK_DELETE, BULK_READ, BULK_UPDATE} + + private Database pdb; + private Environment env; + private Operations opt = Operations.BULK_READ; + private SecondaryDatabase sdb; + private int cachesize = 0, dups = 0, pagesize = 0; + private int num = 1000000; + private boolean secondary = false; + + public static void main(String[] args) { + long startTime, endTime; + int count; + + BulkExample app = new BulkExample(); + + /* Parse argument */ + for (int i = 0; i < args.length; i++) { + if (args[i].compareTo("-c") == 0) { + if (i == args.length - 1) + usage(); + i++; + app.cachesize = Integer.parseInt(args[i]); + System.out.println("[CONFIG] cachesize " + app.cachesize); + } else if (args[i].compareTo("-d") == 0) { + if (i == args.length - 1) + usage(); + i++; + app.dups = Integer.parseInt(args[i]); + System.out.println( + "[CONFIG] number of duplicates " + app.dups); + } else if (args[i].compareTo("-n") == 0) { + if (i == args.length - 1) + usage(); + i++; + app.num = Integer.parseInt(args[i]); + System.out.println("[CONFIG] number of keys " + app.num); + } else if (args[i].compareTo("-p") == 0) { + if (i == args.length - 1) + usage(); + i++; + app.pagesize = Integer.parseInt(args[i]); + System.out.println("[CONFIG] pagesize " + app.pagesize); + } else if (args[i].compareTo("-D") == 0) { + app.opt = Operations.BULK_DELETE; + } else if (args[i].compareTo("-R") == 0) { + app.opt = Operations.BULK_READ; + } else if (args[i].compareTo("-S") == 0) { + app.secondary = true; + } else if (args[i].compareTo("-U") == 0) { + app.opt = Operations.BULK_UPDATE; + }else + usage(); + } + + /* Open environment and database(s) */ + try { + /* If perform bulk update or delete, clean environment home */ + app.cleanHome(app.opt != Operations.BULK_READ); + app.initDbs(); + }catch (Exception e) { + e.printStackTrace(); + app.closeDbs(); + } + + try { + /* Perform bulk read from existing primary db */ + if (app.opt == Operations.BULK_READ) { + startTime = System.currentTimeMillis(); + count = app.bulkRead(); + endTime = System.currentTimeMillis(); + app.printBulkOptStat( + Operations.BULK_READ, count, startTime, endTime); + } else { + /* Perform bulk update to populate the db */ + startTime = System.currentTimeMillis(); + app.bulkUpdate(); + endTime = System.currentTimeMillis(); + count = (app.dups == 0) ? app.num : app.num * app.dups; + app.printBulkOptStat( + Operations.BULK_UPDATE, count, startTime, endTime); + + /* Perform bulk delete in primary db or secondary db */ + if (app.opt == Operations.BULK_DELETE) { + startTime = System.currentTimeMillis(); + if (app.secondary == false) { + /* + * Delete from the first key to a random one in + * primary db. + */ + count = new java.util.Random().nextInt(app.num); + count = app.bulkDelete(count); + } else { + /* + * Delete from the first key to a random one in + * secondary db. + */ + count = new java.util.Random().nextInt( + DataVal.tstring.length()); + count = app.bulkSecondaryDelete( + (DataVal.tstring.getBytes())[count], + true); + } + endTime = System.currentTimeMillis(); + + app.printBulkOptStat(Operations.BULK_DELETE, + count, startTime, endTime); + } + } + } catch (DatabaseException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + /* Close dbs */ + app.closeDbs(); + } + } + + /* Perform bulk delete in primary db */ + public int bulkDelete(int value) throws DatabaseException, IOException { + DatabaseEntry key = new DatabaseEntry(); + Transaction txn = env.beginTransaction(null, null); + int count = 0; + + try { + if (dups != 0) { + /* Delete a set of keys */ + MultipleDataEntry keySet = new MultipleDataEntry(); + keySet.setData(new byte[buffLen]); + keySet.setUserBuffer(buffLen, true); + for (int i = 0; i < value; i++) { + key.setData(intToByte(i)); + keySet.append(key); + } + if (pdb.deleteMultiple(txn, keySet) != + OperationStatus.SUCCESS) + count = 0; + else + count = value * dups; + } else { + /* Delete a set of key/value pairs */ + MultipleKeyDataEntry pairSet = new MultipleKeyDataEntry(); + pairSet.setData(new byte[buffLen * 2]); + pairSet.setUserBuffer(buffLen * 2, true); + DatabaseEntry data = new DatabaseEntry(); + for (int i = 0; i < value; i++) { + key.setData(intToByte(i)); + DataVal dataVal = new DataVal(i); + data.setData(dataVal.getBytes()); + pairSet.append(key, data); + } + if (pdb.deleteMultipleKey(txn, pairSet) != + OperationStatus.SUCCESS) + count = 0; + else + count = value; + } + + txn.commit(); + return count; + } catch (DatabaseException e) { + txn.abort(); + throw e; + } + } + + /* Perform bulk read in primary db */ + public int bulkRead() throws DatabaseException { + ByteBuffer buffer1, buffer2; + Cursor cursor; + DatabaseEntry key, data; + MultipleKeyNIODataEntry pairs; + MultipleNIODataEntry keySet, dataSet; + int count; + + key = new DatabaseEntry(); + data = new DatabaseEntry(); + count = 0; + + Transaction txn = env.beginTransaction(null, null); + + try { + cursor = pdb.openCursor(txn, null); + } catch (DatabaseException e) { + txn.abort(); + return 0; + } + + try { + if (dups == 0){ + /* Get all records in a single key/data buffer */ + pairs = new MultipleKeyNIODataEntry(); + buffer1 = ByteBuffer.allocateDirect(buffLen * 2); + pairs.setDataNIO(buffer1); + pairs.setUserBuffer(buffLen * 2, true); + while (cursor.getNext(key, pairs, null) == + OperationStatus.SUCCESS) { + while(pairs.next(key, data)) + count++; + key = new DatabaseEntry(); + } + } else { + /* + * Get all key/data pairs in two buffers, one for all keys, + * the other for all data. + */ + keySet = new MultipleNIODataEntry(); + buffer1 = ByteBuffer.allocateDirect(buffLen); + keySet.setDataNIO(buffer1); + keySet.setUserBuffer(buffLen, true); + dataSet = new MultipleNIODataEntry(); + buffer2 = ByteBuffer.allocateDirect(buffLen); + dataSet.setDataNIO(buffer2); + dataSet.setUserBuffer(buffLen, true); + while (cursor.getNext(keySet, dataSet, null) == + OperationStatus.SUCCESS) + while(keySet.next(key) && dataSet.next(data)) + count++; + } + cursor.close(); + txn.commit(); + return count; + } catch (DatabaseException e) { + cursor.close(); + txn.abort(); + throw e; + } + } + + /* Perform bulk delete in secondary db */ + public int bulkSecondaryDelete(byte value, boolean deletePair) + throws DatabaseException, IOException { + DatabaseEntry key = new DatabaseEntry(); + byte[] valueBytes = new byte[1]; + byte[] tstrBytes = DataVal.tstring.getBytes(); + int i = 0; + int count = 0; + + Transaction txn = env.beginTransaction(null, null); + + try { + /* Prepare the buffer for a set of keys */ + MultipleDataEntry keySet = new MultipleDataEntry(); + keySet.setData(new byte[buffLen]); + keySet.setUserBuffer(buffLen, true); + + /* Delete the given key and all keys prior to it */ + do { + valueBytes[0] = tstrBytes[i]; + key.setData(valueBytes); + keySet.append(key); + } while (value != tstrBytes[i++]); + if (sdb.deleteMultiple(txn, keySet) != OperationStatus.SUCCESS) + count = 0; + else + count = this.num / DataVal.tstring.length() * i; + if (i < this.num % DataVal.tstring.length()) + count += i; + + txn.commit(); + return count; + } catch (DatabaseException e) { + txn.abort(); + throw e; + } + } + + /* Perform bulk update in primary db */ + public void bulkUpdate() throws DatabaseException, IOException { + DatabaseEntry key, data; + MultipleDataEntry keySet, dataSet; + MultipleKeyDataEntry pairSet; + DataVal dataVal; + int i, j; + + Transaction txn = env.beginTransaction(null, null); + key = new DatabaseEntry(); + data = new DatabaseEntry(); + + try { + if (this.dups == 0) { + /* + * Bulk insert non-duplicate key/data pairs. Those pairs + * are filled into one single buffer. + */ + pairSet = new MultipleKeyDataEntry(); + pairSet.setData(new byte[buffLen * 2]); + pairSet.setUserBuffer(buffLen * 2, true); + for (i = 0; i < this.num; i++) { + dataVal = new DataVal(i); + key.setData(intToByte(i)); + data.setData(dataVal.getBytes()); + pairSet.append(key, data); + } + pdb.putMultipleKey(txn, pairSet, true); + } else { + /* Bulk insert duplicate key/data pairs. All keys are + * filled into a buffer, and their data is filled into + * another buffer. + */ + keySet = new MultipleDataEntry(); + keySet.setData(new byte[buffLen]); + keySet.setUserBuffer(buffLen, true); + dataSet = new MultipleDataEntry(); + dataSet.setData(new byte[buffLen]); + dataSet.setUserBuffer(buffLen, true); + + for (i = 0; i < this.num; i++) { + j = 0; + dataVal = new DataVal(i); + do { + key.setData(intToByte(i)); + keySet.append(key); + dataVal.setDataId(j); + data.setData(dataVal.getBytes()); + dataSet.append(data); + } while(++j < this.dups); + } + pdb.putMultiple(txn, keySet, dataSet, true); + } + + txn.commit(); + }catch (DatabaseException e1) { + txn.abort(); + throw e1; + }catch (IOException e2) { + txn.abort(); + throw e2; + } + } + + /* Clean the home directory */ + public void cleanHome(boolean clean) { + File file = new File(home); + /* + * If the home directory doesn't exist, create the directory. + * Unless, if it is requested to be cleaned, delete all and + * create a new one. + */ + if (!file.exists()) + file.mkdir(); + else if (clean == true) { + File[] files = file.listFiles(); + for(int i=0; i< files.length; i++) { + files[i].delete(); + } + file.delete(); + file.mkdir(); + } + } + + /* Close database(s) and environment */ + public void closeDbs() { + try { + if (this.secondary) + sdb.close(); + pdb.close(); + env.close(); + } catch (DatabaseException e) { + System.exit(1); + } + } + + /* Print statistics in bulk operations */ + public void printBulkOptStat( + Operations opt, int count, long startTime, long endTime) { + System.out.print("[STAT] "); + if (opt == Operations.BULK_DELETE && !secondary) + System.out.print("Bulk delete "); + else if (opt == Operations.BULK_DELETE && secondary) + System.out.print("Bulk secondary delete "); + else if (opt == Operations.BULK_READ) + System.out.print("Bulk read "); + else + System.out.print("Bulk update "); + + System.out.print(count + " records"); + System.out.print(" in " + (endTime - startTime) + " ms"); + System.out.println(", that is " + + (int)((double)1000 / (endTime - startTime) * (double)count) + + " records/second"); + } + + /* Initialize environment and database (s) */ + public void initDbs() throws DatabaseException, FileNotFoundException { + /* Open transactional environment */ + EnvironmentConfig envConfig = new EnvironmentConfig(); + envConfig.setAllowCreate(true); + envConfig.setInitializeCache(true); + envConfig.setInitializeLocking(true); + envConfig.setInitializeLogging(true); + envConfig.setTransactional(true); + File envFile = new File(home); + try { + env = new Environment(envFile, envConfig); + } catch (Exception e) { + System.exit(1); + } + + Transaction txn = env.beginTransaction(null, null); + + try { + /* Open primary db in transaction */ + DatabaseConfig dbConfig = new DatabaseConfig(); + dbConfig.setTransactional(true); + dbConfig.setAllowCreate(true); + dbConfig.setCacheSize(this.cachesize); + dbConfig.setPageSize(this.pagesize); + dbConfig.setType(DatabaseType.BTREE); + if (this.dups != 0) + dbConfig.setUnsortedDuplicates(true); + pdb = env.openDatabase(txn, dbFileName, pDbName, dbConfig); + + /* Open secondary db in transaction */ + if (this.secondary) { + SecondaryConfig sdbConfig = new SecondaryConfig(); + sdbConfig.setTransactional(true); + sdbConfig.setAllowCreate(true); + sdbConfig.setCacheSize(this.cachesize); + sdbConfig.setPageSize(this.pagesize); + sdbConfig.setType(DatabaseType.BTREE); + sdbConfig.setKeyCreator(new FirstStrKeyCreator()); + sdbConfig.setSortedDuplicates(true); + sdb = env.openSecondaryDatabase( + txn, dbFileName, sDbName, pdb, sdbConfig); + } + + txn.commit(); + } catch (DatabaseException e1) { + txn.abort(); + throw e1; + } catch (FileNotFoundException e2) { + txn.abort(); + throw e2; + } + } + + /* Convert integer to byte array */ + public byte[] intToByte(int i) { + byte[] dword = new byte[4]; + dword[0] = (byte) (i & 0x00FF); + dword[1] = (byte) ((i >> 8) & 0x000000FF); + dword[2] = (byte) ((i >> 16) & 0x000000FF); + dword[3] = (byte) ((i >> 24) & 0x000000FF); + return dword; + } + + /* Usage of BulkExample */ + private static void usage() { + System.out.println("Usage: BulkExample \n" + + " -c cachesize [1000 * pagesize] \n" + + " -d number of duplicates [none] \n" + + " -n number of keys [1000000] \n" + + " -p pagesize [65536] \n" + + " -D perform bulk delete \n" + + " -R perform bulk read \n" + + " -S perform bulk read in secondary database \n" + + " -U perform bulk update \n"); + System.exit(1); + } + + class DataVal { + /* String template */ + public static final String tstring = "0123456789abcde"; + + private String dataString; + private int dataId; + + /* + * Construct DataVal with given kid and id. The dataString is the + * rotated tstring from the kid position. The dataId is the id. + */ + public DataVal(int kid) { + int rp = kid % tstring.length(); + if (rp == 0) + this.dataString = tstring; + else + this.dataString = tstring.substring(rp) + + tstring.substring(0, rp - 1); + + this.dataId = 0; + } + + /* Parse the object including dataId and dataString to byte array. */ + public byte[] getBytes() throws IOException { + int i; + + byte[] strBytes = dataString.getBytes(); + byte[] intBytes = intToByte(dataId); + byte[] bytes = new byte[4 + strBytes.length]; + for (i = 0; i < 4 + strBytes.length; i++) { + if (i < 4) + bytes[i] = intBytes[i]; + else + bytes[i] = strBytes[i - 4]; + } + + return bytes; + } + + public int getDataId() { + return dataId; + } + + public void setDataId(int id) { + dataId = id; + } + + public String getDataString() { + return dataString; + } + } + + /* Secondary key creator */ + class FirstStrKeyCreator implements SecondaryKeyCreator { + public boolean createSecondaryKey(SecondaryDatabase secondary, + DatabaseEntry key, DatabaseEntry data, DatabaseEntry result) + throws DatabaseException { + /* + * Create the secondary key. It would be the first character in + * dataString of DataVal, that is the 5th byte in data. + */ + byte[] firstStr = new byte[1]; + firstStr[0] = (data.getData())[4]; + result.setData(firstStr); + result.setSize(1); + return true; + } + } +} |
