diff options
Diffstat (limited to 'examples_java/src/persist')
-rw-r--r-- | examples_java/src/persist/CustomKeyOrderExample.java | 126 | ||||
-rw-r--r-- | examples_java/src/persist/DplDump.java | 148 | ||||
-rw-r--r-- | examples_java/src/persist/EventExample.java | 424 | ||||
-rw-r--r-- | examples_java/src/persist/EventExampleDPL.java | 273 | ||||
-rw-r--r-- | examples_java/src/persist/PersonExample.java | 256 | ||||
-rw-r--r-- | examples_java/src/persist/gettingStarted/SimpleDA.java | 51 | ||||
-rw-r--r-- | examples_java/src/persist/gettingStarted/SimpleEntityClass.java | 42 | ||||
-rw-r--r-- | examples_java/src/persist/gettingStarted/SimpleStoreGet.java | 112 | ||||
-rw-r--r-- | examples_java/src/persist/gettingStarted/SimpleStorePut.java | 116 | ||||
-rw-r--r-- | examples_java/src/persist/txn/PayloadDataEntity.java | 33 | ||||
-rw-r--r-- | examples_java/src/persist/txn/StoreWriter.java | 176 | ||||
-rw-r--r-- | examples_java/src/persist/txn/TxnGuideDPL.java | 162 |
12 files changed, 1919 insertions, 0 deletions
diff --git a/examples_java/src/persist/CustomKeyOrderExample.java b/examples_java/src/persist/CustomKeyOrderExample.java new file mode 100644 index 0000000..aee8c8b --- /dev/null +++ b/examples_java/src/persist/CustomKeyOrderExample.java @@ -0,0 +1,126 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2002-2009 Oracle. All rights reserved. + * + * $Id$ + */ + +package persist; + +import java.io.File; +import java.io.FileNotFoundException; + +import com.sleepycat.db.DatabaseException; +import com.sleepycat.db.Environment; +import com.sleepycat.db.EnvironmentConfig; +import com.sleepycat.persist.EntityCursor; +import com.sleepycat.persist.EntityStore; +import com.sleepycat.persist.PrimaryIndex; +import com.sleepycat.persist.StoreConfig; +import com.sleepycat.persist.model.Entity; +import com.sleepycat.persist.model.KeyField; +import com.sleepycat.persist.model.Persistent; +import com.sleepycat.persist.model.PrimaryKey; + +public class CustomKeyOrderExample { + + @Entity + static class Person { + + @PrimaryKey + ReverseOrder name; + + Person(String name) { + this.name = new ReverseOrder(name); + } + + private Person() {} // For deserialization + + @Override + public String toString() { + return name.value; + } + } + + @Persistent + static class ReverseOrder implements Comparable<ReverseOrder> { + + @KeyField(1) + String value; + + ReverseOrder(String value) { + this.value = value; + } + + private ReverseOrder() {} // For deserialization + + public int compareTo(ReverseOrder o) { + return o.value.compareTo(value); + } + } + + public static void main(String[] args) + throws DatabaseException, FileNotFoundException { + + if (args.length != 2 || !"-h".equals(args[0])) { + System.err.println + ("Usage: java " + CustomKeyOrderExample.class.getName() + + " -h <envHome>"); + System.exit(2); + } + CustomKeyOrderExample example = + new CustomKeyOrderExample(new File(args[1])); + example.run(); + example.close(); + } + + private Environment env; + private EntityStore store; + + private CustomKeyOrderExample(File envHome) + throws DatabaseException, FileNotFoundException { + + /* Open a transactional Berkeley DB engine environment. */ + EnvironmentConfig envConfig = new EnvironmentConfig(); + envConfig.setAllowCreate(true); + envConfig.setTransactional(true); + envConfig.setInitializeCache(true); + envConfig.setInitializeLocking(true); + env = new Environment(envHome, envConfig); + + /* Open a transactional entity store. */ + StoreConfig storeConfig = new StoreConfig(); + storeConfig.setAllowCreate(true); + storeConfig.setTransactional(true); + store = new EntityStore(env, "TestStore", storeConfig); + } + + private void run() + throws DatabaseException { + + PrimaryIndex<ReverseOrder,Person> index = + store.getPrimaryIndex(ReverseOrder.class, Person.class); + + index.put(new Person("Andy")); + index.put(new Person("Lisa")); + index.put(new Person("Zola")); + + /* Print the entities in key order. */ + EntityCursor<Person> people = index.entities(); + try { + for (Person person : people) { + System.out.println(person); + } + } finally { + people.close(); + } + } + + private void close() + throws DatabaseException { + + store.close(); + env.close(); + } +} diff --git a/examples_java/src/persist/DplDump.java b/examples_java/src/persist/DplDump.java new file mode 100644 index 0000000..f677bc6 --- /dev/null +++ b/examples_java/src/persist/DplDump.java @@ -0,0 +1,148 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2002-2009 Oracle. All rights reserved. + * + * $Id$ + */ + +package persist; + +import java.io.File; +import java.io.FileNotFoundException; + +import com.sleepycat.db.DatabaseException; +import com.sleepycat.db.Environment; +import com.sleepycat.db.EnvironmentConfig; +import com.sleepycat.persist.EntityCursor; +import com.sleepycat.persist.EntityStore; +import com.sleepycat.persist.PrimaryIndex; +import com.sleepycat.persist.StoreConfig; +import com.sleepycat.persist.model.EntityMetadata; +import com.sleepycat.persist.model.EntityModel; +import com.sleepycat.persist.raw.RawObject; +import com.sleepycat.persist.raw.RawStore; +import com.sleepycat.persist.raw.RawType; + +/** + * Dumps a store or all stores to standard output in raw XML format. This + * sample is intended to be modifed to dump in application specific ways. + * @see #usage + */ +public class DplDump { + + private File envHome; + private String storeName; + private boolean dumpMetadata; + private Environment env; + + public static void main(String[] args) { + try { + DplDump dump = new DplDump(args); + dump.open(); + dump.dump(); + dump.close(); + } catch (Throwable e) { + e.printStackTrace(); + System.exit(1); + } + } + + private DplDump(String[] args) { + + for (int i = 0; i < args.length; i += 1) { + String name = args[i]; + String val = null; + if (i < args.length - 1 && !args[i + 1].startsWith("-")) { + i += 1; + val = args[i]; + } + if (name.equals("-h")) { + if (val == null) { + usage("No value after -h"); + } + envHome = new File(val); + } else if (name.equals("-s")) { + if (val == null) { + usage("No value after -s"); + } + storeName = val; + } else if (name.equals("-meta")) { + dumpMetadata = true; + } else { + usage("Unknown arg: " + name); + } + } + + if (storeName == null) { + usage("-s not specified"); + } + if (envHome == null) { + usage("-h not specified"); + } + } + + private void usage(String msg) { + + if (msg != null) { + System.out.println(msg); + } + + System.out.println + ("usage:" + + "\njava " + DplDump.class.getName() + + "\n -h <envHome>" + + "\n # Environment home directory" + + "\n [-meta]" + + "\n # Dump metadata; default: false" + + "\n -s <storeName>" + + "\n # Store to dump"); + + System.exit(2); + } + + private void open() + throws DatabaseException, FileNotFoundException { + + EnvironmentConfig envConfig = new EnvironmentConfig(); + envConfig.setInitializeCache(true); + envConfig.setInitializeLocking(true); + env = new Environment(envHome, envConfig); + } + + private void close() + throws DatabaseException { + + env.close(); + } + + private void dump() + throws DatabaseException { + + StoreConfig storeConfig = new StoreConfig(); + storeConfig.setReadOnly(true); + RawStore store = new RawStore(env, storeName, storeConfig); + + EntityModel model = store.getModel(); + for (String clsName : model.getKnownClasses()) { + EntityMetadata meta = model.getEntityMetadata(clsName); + if (meta != null) { + if (dumpMetadata) { + for (RawType type : model.getAllRawTypeVersions(clsName)) { + System.out.println(type); + } + } else { + PrimaryIndex<Object,RawObject> index = + store.getPrimaryIndex(clsName); + EntityCursor<RawObject> entities = index.entities(); + for (RawObject entity : entities) { + System.out.println(entity); + } + entities.close(); + } + } + } + + store.close(); + } +} diff --git a/examples_java/src/persist/EventExample.java b/examples_java/src/persist/EventExample.java new file mode 100644 index 0000000..5a3ee44 --- /dev/null +++ b/examples_java/src/persist/EventExample.java @@ -0,0 +1,424 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2004-2009 Oracle. All rights reserved. + * + * $Id$ + */ + +package persist; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.Serializable; +import java.util.Calendar; +import java.util.Date; +import java.util.HashSet; +import java.util.Random; +import java.util.Set; + +import com.sleepycat.bind.EntryBinding; +import com.sleepycat.bind.serial.SerialBinding; +import com.sleepycat.bind.serial.StoredClassCatalog; +import com.sleepycat.bind.tuple.IntegerBinding; +import com.sleepycat.bind.tuple.LongBinding; +import com.sleepycat.db.Cursor; +import com.sleepycat.db.Database; +import com.sleepycat.db.DatabaseConfig; +import com.sleepycat.db.DatabaseEntry; +import com.sleepycat.db.DatabaseException; +import com.sleepycat.db.DatabaseType; +import com.sleepycat.db.Environment; +import com.sleepycat.db.EnvironmentConfig; +import com.sleepycat.db.OperationStatus; +import com.sleepycat.db.SecondaryConfig; +import com.sleepycat.db.SecondaryCursor; +import com.sleepycat.db.SecondaryDatabase; +import com.sleepycat.db.SecondaryKeyCreator; +import com.sleepycat.db.Transaction; + +/** + * EventExample is a trivial example which stores Java objects that represent + * an event. Events are primarily indexed by a timestamp, but have other + * attributes, such as price, account reps, customer name and quantity. + * Some of those other attributes are indexed. + * <p> + * The example simply shows the creation of a BDB environment and database, + * inserting some events, and retrieving the events. + * <p> + * This example is meant to be paired with its twin, EventExampleDPL.java. + * EventExample.java and EventExampleDPL.java perform the same functionality, + * but use the Base API and the Direct Persistence Layer API, respectively. + * This may be a useful way to compare the two APIs. + * <p> + * To run the example: + * <pre> + * cd jehome/examples + * javac je/EventExample.java + * java je.EventExample -h <environmentDirectory> + * </pre> + */ +public class EventExample { + + /* + * The Event class embodies our example event and is the application + * data. BDB data records are represented at key/data tuples. In this + * example, the key portion of the record is the event time, and the data + * portion is the Event instance. + */ + static class Event implements Serializable { + + /* This example will add secondary indices on price and accountReps. */ + private int price; + private Set<String> accountReps; + + private String customerName; + private int quantity; + + Event(int price, + String customerName) { + + this.price = price; + this.customerName = customerName; + this.accountReps = new HashSet<String>(); + } + + void addRep(String rep) { + accountReps.add(rep); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(" price=").append(price); + sb.append(" customerName=").append(customerName); + sb.append(" reps="); + if (accountReps.size() == 0) { + sb.append("none"); + } else { + for (String rep: accountReps) { + sb.append(rep).append(" "); + } + } + return sb.toString(); + } + + int getPrice() { + return price; + } + } + + /* A BDB environment is roughly equivalent to a relational database. */ + private Environment env; + + /* + * A BDB table is roughly equivalent to a relational table with a + * primary index. + */ + private Database eventDb; + + /* A secondary database indexes an additional field of the data record */ + private SecondaryDatabase eventByPriceDb; + + /* + * The catalogs and bindings are used to convert Java objects to the byte + * array format used by BDB key/data in the base API. The Direct + * Persistence Layer API supports Java objects as arguments directly. + */ + private Database catalogDb; + private EntryBinding eventBinding; + + /* Used for generating example data. */ + private Calendar cal; + + + /* + * First manually make a directory to house the BDB environment. + * Usage: java EventExample -h <envHome> + * All BDB on-disk storage is held within envHome. + */ + public static void main(String[] args) + throws DatabaseException, FileNotFoundException { + + if (args.length != 2 || !"-h".equals(args[0])) { + System.err.println + ("Usage: java " + EventExample.class.getName() + + " -h <envHome>"); + System.exit(2); + } + EventExample example = new EventExample(new File(args[1])); + example.run(); + example.close(); + } + + private EventExample(File envHome) + throws DatabaseException, FileNotFoundException { + + /* Open a transactional Berkeley DB engine environment. */ + System.out.println("-> Creating a BDB environment"); + EnvironmentConfig envConfig = new EnvironmentConfig(); + envConfig.setAllowCreate(true); + envConfig.setTransactional(true); + envConfig.setInitializeCache(true); + envConfig.setInitializeLocking(true); + env = new Environment(envHome, envConfig); + + init(); + cal = Calendar.getInstance(); + } + + /** + * Create all primary and secondary indices. + */ + private void init() + throws DatabaseException, FileNotFoundException { + + System.out.println("-> Creating a BDB database"); + DatabaseConfig dbConfig = new DatabaseConfig(); + dbConfig.setTransactional(true); + dbConfig.setAllowCreate(true); + dbConfig.setType(DatabaseType.BTREE); + eventDb = env.openDatabase(null, // use auto-commit txn + "eventDb", // file name + null, // database name + dbConfig); + + + /* + * In our example, the database record is composed of a key portion + * which represents the event timestamp, and a data portion holds an + * instance of the Event class. + * + * BDB's base API accepts and returns key and data as byte arrays, so + * we need some support for marshaling between objects and byte arrays. + * We call this binding, and supply a package of helper classes to + * support this. It's entirely possible to do all binding on your own. + * + * A class catalog database is needed for storing class descriptions + * for the serial binding used below. This avoids storing class + * descriptions redundantly in each record. + */ + DatabaseConfig catalogConfig = new DatabaseConfig(); + catalogConfig.setTransactional(true); + catalogConfig.setAllowCreate(true); + catalogConfig.setType(DatabaseType.BTREE); + catalogDb = env.openDatabase(null, "catalogDb", null, catalogConfig); + StoredClassCatalog catalog = new StoredClassCatalog(catalogDb); + + /* + * Create a serial binding for Event data objects. Serial + * bindings can be used to store any Serializable object. + * We can use some pre-defined binding classes to convert + * primitives like the long key value to the a byte array. + */ + eventBinding = new SerialBinding(catalog, Event.class); + + /* + * Open a secondary database to allow accessing the primary + * database a secondary key value. In this case, access events + * by price. + */ + SecondaryConfig secConfig = new SecondaryConfig(); + secConfig.setTransactional(true); + secConfig.setAllowCreate(true); + secConfig.setType(DatabaseType.BTREE); + secConfig.setSortedDuplicates(true); + secConfig.setKeyCreator(new PriceKeyCreator(eventBinding)); + eventByPriceDb = env.openSecondaryDatabase(null, + "priceDb", + null, + eventDb, + secConfig); + + } + + private void run() + throws DatabaseException { + + Random rand = new Random(); + + /* DatabaseEntry represents the key and data of each record */ + DatabaseEntry key = new DatabaseEntry(); + DatabaseEntry data = new DatabaseEntry(); + + /* + * Create a set of events. Each insertion is a separate, auto-commit + * transaction. + */ + System.out.println("-> Inserting 4 events"); + LongBinding.longToEntry(makeDate(1), key); + eventBinding.objectToEntry(new Event(100, "Company_A"), + data); + eventDb.put(null, key, data); + + LongBinding.longToEntry(makeDate(2), key); + eventBinding.objectToEntry(new Event(2, "Company_B"), + data); + eventDb.put(null, key, data); + + LongBinding.longToEntry(makeDate(3), key); + eventBinding.objectToEntry(new Event(20, "Company_C"), + data); + eventDb.put(null, key, data); + + LongBinding.longToEntry(makeDate(4), key); + eventBinding.objectToEntry(new Event(40, "CompanyD"), + data); + eventDb.put(null, key, data); + + /* Load a whole set of events transactionally. */ + Transaction txn = env.beginTransaction(null, null); + int maxPrice = 50; + System.out.println("-> Inserting some randomly generated events"); + for (int i = 0; i < 25; i++) { + long time = makeDate(rand.nextInt(365)); + Event e = new Event(rand.nextInt(maxPrice),"Company_X"); + if ((i%2) ==0) { + e.addRep("Jane"); + e.addRep("Nikunj"); + } else { + e.addRep("Yongmin"); + } + LongBinding.longToEntry(time, key); + eventBinding.objectToEntry(e, data); + eventDb.put(txn, key, data); + } + txn.commitWriteNoSync(); + + /* + * Windows of events - display the events between June 1 and Aug 31 + */ + System.out.println("\n-> Display the events between June 1 and Aug 31"); + long endDate = makeDate(Calendar.AUGUST, 31); + + /* Position the cursor and print the first event. */ + Cursor eventWindow = eventDb.openCursor(null, null); + LongBinding.longToEntry(makeDate(Calendar.JUNE, 1), key); + + if ((eventWindow.getSearchKeyRange(key, data, null)) != + OperationStatus.SUCCESS) { + System.out.println("No events found!"); + eventWindow.close(); + return; + } + try { + printEvents(key, data, eventWindow, endDate); + } finally { + eventWindow.close(); + } + + /* + * Display all events, ordered by a secondary index on price. + */ + System.out.println("\n-> Display all events, ordered by price"); + SecondaryCursor priceCursor = + eventByPriceDb.openSecondaryCursor(null, null); + try { + printEvents(priceCursor); + } finally { + priceCursor.close(); + } + } + + private void close() + throws DatabaseException { + + eventByPriceDb.close(); + eventDb.close(); + catalogDb.close(); + env.close(); + } + + /** + * Print all events covered by this cursor up to the end date. We know + * that the cursor operates on long keys and Event data items, but there's + * no type-safe way of expressing that within the BDB base API. + */ + private void printEvents(DatabaseEntry firstKey, + DatabaseEntry firstData, + Cursor cursor, + long endDate) + throws DatabaseException { + + System.out.println("time=" + + new Date(LongBinding.entryToLong(firstKey)) + + eventBinding.entryToObject(firstData)); + DatabaseEntry key = new DatabaseEntry(); + DatabaseEntry data = new DatabaseEntry(); + + while (cursor.getNext(key, data, null) == + OperationStatus.SUCCESS) { + if (LongBinding.entryToLong(key) > endDate) { + break; + } + System.out.println("time=" + + new Date(LongBinding.entryToLong(key)) + + eventBinding.entryToObject(data)); + } + } + + private void printEvents(SecondaryCursor cursor) + throws DatabaseException { + DatabaseEntry timeKey = new DatabaseEntry(); + DatabaseEntry priceKey = new DatabaseEntry(); + DatabaseEntry eventData = new DatabaseEntry(); + + while (cursor.getNext(priceKey, timeKey, eventData, null) == + OperationStatus.SUCCESS) { + System.out.println("time=" + + new Date(LongBinding.entryToLong(timeKey)) + + eventBinding.entryToObject(eventData)); + } + } + + /** + * Little utility for making up java.util.Dates for different days, just + * to generate test data. + */ + private long makeDate(int day) { + + cal.set((Calendar.DAY_OF_YEAR), day); + return cal.getTime().getTime(); + } + /** + * Little utility for making up java.util.Dates for different days, just + * to make the test data easier to read. + */ + private long makeDate(int month, int day) { + + cal.set((Calendar.MONTH), month); + cal.set((Calendar.DAY_OF_MONTH), day); + return cal.getTime().getTime(); + } + + /** + * A key creator that knows how to extract the secondary key from the data + * entry of the primary database. To do so, it uses both the dataBinding + * of the primary database and the secKeyBinding. + */ + private static class PriceKeyCreator implements SecondaryKeyCreator { + + private EntryBinding dataBinding; + + PriceKeyCreator(EntryBinding eventBinding) { + this.dataBinding = eventBinding; + } + + public boolean createSecondaryKey(SecondaryDatabase secondaryDb, + DatabaseEntry keyEntry, + DatabaseEntry dataEntry, + DatabaseEntry resultEntry) + throws DatabaseException { + + /* + * Convert the data entry to an Event object, extract the secondary + * key value from it, and then convert it to the resulting + * secondary key entry. + */ + Event e = (Event) dataBinding.entryToObject(dataEntry); + int price = e.getPrice(); + IntegerBinding.intToEntry(price, resultEntry); + return true; + } + } +} diff --git a/examples_java/src/persist/EventExampleDPL.java b/examples_java/src/persist/EventExampleDPL.java new file mode 100644 index 0000000..283b121 --- /dev/null +++ b/examples_java/src/persist/EventExampleDPL.java @@ -0,0 +1,273 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2004-2009 Oracle. All rights reserved. + * + * $Id$ + */ + +package persist; + +import static com.sleepycat.persist.model.Relationship.MANY_TO_ONE; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.Calendar; +import java.util.Date; +import java.util.HashSet; +import java.util.Random; +import java.util.Set; + +import com.sleepycat.db.DatabaseException; +import com.sleepycat.db.Environment; +import com.sleepycat.db.EnvironmentConfig; +import com.sleepycat.db.Transaction; +import com.sleepycat.persist.EntityCursor; +import com.sleepycat.persist.EntityStore; +import com.sleepycat.persist.PrimaryIndex; +import com.sleepycat.persist.SecondaryIndex; +import com.sleepycat.persist.StoreConfig; +import com.sleepycat.persist.model.Entity; +import com.sleepycat.persist.model.PrimaryKey; +import com.sleepycat.persist.model.SecondaryKey; + +/** + * EventExampleDPL is a trivial example which stores Java objects that + * represent an event. Events are primarily indexed by a timestamp, but have + * other attributes, such as price, account reps, customer name and + * quantity. Some of those other attributes are indexed. + * <p> + * The example simply shows the creation of a BDB environment and database, + * inserting some events, and retrieving the events using the Direct + * Persistence layer. + * <p> + * This example is meant to be paired with its twin, EventExample.java. + * EventExample.java and EventExampleDPL.java perform the same functionality, + * but use the Base API and the Direct Persistence Layer API, respectively. + * This may be a useful way to compare the two APIs. + * <p> + * To run the example: + * <pre> + * javac EventExampleDPL.java + * java EventExampleDPL -h <environmentDirectory> + * </pre> + */ +public class EventExampleDPL { + + /* + * The Event class embodies our example event and is the application + * data. The @Entity annotation indicates that this class defines the + * objects stored in a BDB database. + */ + @Entity + static class Event { + + @PrimaryKey + private Date time; + + @SecondaryKey(relate=MANY_TO_ONE) + private int price; + + private Set<String> accountReps; + + private String customerName; + private int quantity; + + Event(Date time, + int price, + String customerName) { + + this.time = time; + this.price = price; + this.customerName = customerName; + this.accountReps = new HashSet<String>(); + } + + private Event() {} // For deserialization + + void addRep(String rep) { + accountReps.add(rep); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("time=").append(time); + sb.append(" price=").append(price); + sb.append(" customerName=").append(customerName); + sb.append(" reps="); + if (accountReps.size() == 0) { + sb.append("none"); + } else { + for (String rep: accountReps) { + sb.append(rep).append(" "); + } + } + return sb.toString(); + } + } + + /* A BDB environment is roughly equivalent to a relational database. */ + private Environment env; + private EntityStore store; + + /* + * Event accessors let us access events by the primary index (time) + * as well as by the rep and price fields + */ + PrimaryIndex<Date,Event> eventByTime; + SecondaryIndex<Integer,Date,Event> eventByPrice; + + /* Used for generating example data. */ + private Calendar cal; + + /* + * First manually make a directory to house the BDB environment. + * Usage: java EventExampleDPL -h <envHome> + * All BDB on-disk storage is held within envHome. + */ + public static void main(String[] args) + throws DatabaseException, FileNotFoundException { + + if (args.length != 2 || !"-h".equals(args[0])) { + System.err.println + ("Usage: java " + EventExampleDPL.class.getName() + + " -h <envHome>"); + System.exit(2); + } + EventExampleDPL example = new EventExampleDPL(new File(args[1])); + example.run(); + example.close(); + } + + private EventExampleDPL(File envHome) + throws DatabaseException, FileNotFoundException { + + /* Open a transactional Berkeley DB engine environment. */ + System.out.println("-> Creating a BDB environment"); + EnvironmentConfig envConfig = new EnvironmentConfig(); + envConfig.setAllowCreate(true); + envConfig.setTransactional(true); + envConfig.setInitializeCache(true); + envConfig.setInitializeLocking(true); + env = new Environment(envHome, envConfig); + + /* Initialize the data access object. */ + init(); + cal = Calendar.getInstance(); + } + + /** + * Create all primary and secondary indices. + */ + private void init() + throws DatabaseException { + + /* Open a transactional entity store. */ + System.out.println("-> Creating a BDB database"); + StoreConfig storeConfig = new StoreConfig(); + storeConfig.setAllowCreate(true); + storeConfig.setTransactional(true); + store = new EntityStore(env, "ExampleStore", storeConfig); + + eventByTime = store.getPrimaryIndex(Date.class, Event.class); + eventByPrice = store.getSecondaryIndex(eventByTime, + Integer.class, + "price"); + } + + private void run() + throws DatabaseException { + + Random rand = new Random(); + + /* + * Create a set of events. Each insertion is a separate, auto-commit + * transaction. + */ + System.out.println("-> Inserting 4 events"); + eventByTime.put(new Event(makeDate(1), 100, "Company_A")); + eventByTime.put(new Event(makeDate(2), 2, "Company_B")); + eventByTime.put(new Event(makeDate(3), 20, "Company_C")); + eventByTime.put(new Event(makeDate(4), 40, "CompanyD")); + + /* Load a whole set of events transactionally. */ + Transaction txn = env.beginTransaction(null, null); + int maxPrice = 50; + System.out.println("-> Inserting some randomly generated events"); + for (int i = 0; i < 25; i++) { + Event e = new Event(makeDate(rand.nextInt(365)), + rand.nextInt(maxPrice), + "Company_X"); + if ((i%2) ==0) { + e.addRep("Bob"); + e.addRep("Nikunj"); + } else { + e.addRep("Yongmin"); + } + eventByTime.put(e); + } + txn.commitWriteNoSync(); + + /* + * Windows of events - display the events between June 1 and Aug 31 + */ + System.out.println("\n-> Display the events between June 1 and Aug 31"); + Date startDate = makeDate(Calendar.JUNE, 1); + Date endDate = makeDate(Calendar.AUGUST, 31); + + EntityCursor<Event> eventWindow = + eventByTime.entities(startDate, true, endDate, true); + printEvents(eventWindow); + + /* + * Display all events, ordered by a secondary index on price. + */ + System.out.println("\n-> Display all events, ordered by price"); + EntityCursor<Event> byPriceEvents = eventByPrice.entities(); + printEvents(byPriceEvents); + } + + private void close() + throws DatabaseException { + + store.close(); + env.close(); + } + + /** + * Print all events covered by this cursor. + */ + private void printEvents(EntityCursor<Event> eCursor) + throws DatabaseException { + try { + for (Event e: eCursor) { + System.out.println(e); + } + } finally { + /* Be sure to close the cursor. */ + eCursor.close(); + } + } + + /** + * Little utility for making up java.util.Dates for different days, just + * to generate test data. + */ + private Date makeDate(int day) { + + cal.set((Calendar.DAY_OF_YEAR), day); + return cal.getTime(); + } + + /** + * Little utility for making up java.util.Dates for different days, just + * to make the test data easier to read. + */ + private Date makeDate(int month, int day) { + + cal.set((Calendar.MONTH), month); + cal.set((Calendar.DAY_OF_MONTH), day); + return cal.getTime(); + } +} diff --git a/examples_java/src/persist/PersonExample.java b/examples_java/src/persist/PersonExample.java new file mode 100644 index 0000000..484f1e7 --- /dev/null +++ b/examples_java/src/persist/PersonExample.java @@ -0,0 +1,256 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2002-2009 Oracle. All rights reserved. + * + * $Id$ + */ + +package persist; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.HashSet; +import java.util.Set; + +import com.sleepycat.db.DatabaseException; +import com.sleepycat.db.Environment; +import com.sleepycat.db.EnvironmentConfig; +import com.sleepycat.persist.EntityCursor; +import com.sleepycat.persist.EntityIndex; +import com.sleepycat.persist.EntityStore; +import com.sleepycat.persist.PrimaryIndex; +import com.sleepycat.persist.SecondaryIndex; +import com.sleepycat.persist.StoreConfig; +import com.sleepycat.persist.model.Entity; +import com.sleepycat.persist.model.Persistent; +import com.sleepycat.persist.model.PrimaryKey; +import com.sleepycat.persist.model.SecondaryKey; +import static com.sleepycat.persist.model.DeleteAction.NULLIFY; +import static com.sleepycat.persist.model.Relationship.ONE_TO_ONE; +import static com.sleepycat.persist.model.Relationship.ONE_TO_MANY; +import static com.sleepycat.persist.model.Relationship.MANY_TO_ONE; +import static com.sleepycat.persist.model.Relationship.MANY_TO_MANY; + +public class PersonExample { + + /* An entity class. */ + @Entity + static class Person { + + @PrimaryKey + String ssn; + + String name; + Address address; + + @SecondaryKey(relate=MANY_TO_ONE, relatedEntity=Person.class) + String parentSsn; + + @SecondaryKey(relate=ONE_TO_MANY) + Set<String> emailAddresses = new HashSet<String>(); + + @SecondaryKey(relate=MANY_TO_MANY, + relatedEntity=Employer.class, + onRelatedEntityDelete=NULLIFY) + Set<Long> employerIds = new HashSet<Long>(); + + Person(String name, String ssn, String parentSsn) { + this.name = name; + this.ssn = ssn; + this.parentSsn = parentSsn; + } + + private Person() {} // For deserialization + } + + /* Another entity class. */ + @Entity + static class Employer { + + @PrimaryKey(sequence="ID") + long id; + + @SecondaryKey(relate=ONE_TO_ONE) + String name; + + Address address; + + Employer(String name) { + this.name = name; + } + + private Employer() {} // For deserialization + } + + /* A persistent class used in other classes. */ + @Persistent + static class Address { + String street; + String city; + String state; + int zipCode; + private Address() {} // For deserialization + } + + /* The data accessor class for the entity model. */ + static class PersonAccessor { + + /* Person accessors */ + PrimaryIndex<String,Person> personBySsn; + SecondaryIndex<String,String,Person> personByParentSsn; + SecondaryIndex<String,String,Person> personByEmailAddresses; + SecondaryIndex<Long,String,Person> personByEmployerIds; + + /* Employer accessors */ + PrimaryIndex<Long,Employer> employerById; + SecondaryIndex<String,Long,Employer> employerByName; + + /* Opens all primary and secondary indices. */ + public PersonAccessor(EntityStore store) + throws DatabaseException { + + personBySsn = store.getPrimaryIndex( + String.class, Person.class); + + personByParentSsn = store.getSecondaryIndex( + personBySsn, String.class, "parentSsn"); + + personByEmailAddresses = store.getSecondaryIndex( + personBySsn, String.class, "emailAddresses"); + + personByEmployerIds = store.getSecondaryIndex( + personBySsn, Long.class, "employerIds"); + + employerById = store.getPrimaryIndex( + Long.class, Employer.class); + + employerByName = store.getSecondaryIndex( + employerById, String.class, "name"); + } + } + + public static void main(String[] args) + throws DatabaseException, FileNotFoundException { + + if (args.length != 2 || !"-h".equals(args[0])) { + System.err.println + ("Usage: java " + PersonExample.class.getName() + + " -h <envHome>"); + System.exit(2); + } + PersonExample example = new PersonExample(new File(args[1])); + example.run(); + example.close(); + } + + private Environment env; + private EntityStore store; + private PersonAccessor dao; + + private PersonExample(File envHome) + throws DatabaseException, FileNotFoundException { + + /* Open a transactional Berkeley DB engine environment. */ + EnvironmentConfig envConfig = new EnvironmentConfig(); + envConfig.setAllowCreate(true); + envConfig.setTransactional(true); + envConfig.setInitializeCache(true); + envConfig.setInitializeLocking(true); + env = new Environment(envHome, envConfig); + + /* Open a transactional entity store. */ + StoreConfig storeConfig = new StoreConfig(); + storeConfig.setAllowCreate(true); + storeConfig.setTransactional(true); + store = new EntityStore(env, "PersonStore", storeConfig); + + /* Initialize the data access object. */ + dao = new PersonAccessor(store); + } + + private void run() + throws DatabaseException { + + /* + * Add a parent and two children using the Person primary index. + * Specifying a non-null parentSsn adds the child Person to the + * sub-index of children for that parent key. + */ + dao.personBySsn.put + (new Person("Bob Smith", "111-11-1111", null)); + dao.personBySsn.put + (new Person("Mary Smith", "333-33-3333", "111-11-1111")); + dao.personBySsn.put + (new Person("Jack Smith", "222-22-2222", "111-11-1111")); + + /* Print the children of a parent using a sub-index and a cursor. */ + EntityCursor<Person> children = + dao.personByParentSsn.subIndex("111-11-1111").entities(); + try { + for (Person child : children) { + System.out.println(child.ssn + ' ' + child.name); + } + } finally { + children.close(); + } + + /* Get Bob by primary key using the primary index. */ + Person bob = dao.personBySsn.get("111-11-1111"); + assert bob != null; + + /* + * Create two employers if they do not already exist. Their primary + * keys are assigned from a sequence. + */ + Employer gizmoInc = dao.employerByName.get("Gizmo Inc"); + if (gizmoInc == null) { + gizmoInc = new Employer("Gizmo Inc"); + dao.employerById.put(gizmoInc); + } + Employer gadgetInc = dao.employerByName.get("Gadget Inc"); + if (gadgetInc == null) { + gadgetInc = new Employer("Gadget Inc"); + dao.employerById.put(gadgetInc); + } + + /* Bob has two jobs and two email addresses. */ + bob.employerIds.add(gizmoInc.id); + bob.employerIds.add(gadgetInc.id); + bob.emailAddresses.add("bob@bob.com"); + bob.emailAddresses.add("bob@gmail.com"); + + /* Update Bob's record. */ + dao.personBySsn.put(bob); + + /* Bob can now be found by both email addresses. */ + bob = dao.personByEmailAddresses.get("bob@bob.com"); + assert bob != null; + bob = dao.personByEmailAddresses.get("bob@gmail.com"); + assert bob != null; + + /* Bob can also be found as an employee of both employers. */ + EntityIndex<String,Person> employees; + employees = dao.personByEmployerIds.subIndex(gizmoInc.id); + assert employees.contains("111-11-1111"); + employees = dao.personByEmployerIds.subIndex(gadgetInc.id); + assert employees.contains("111-11-1111"); + + /* + * When an employer is deleted, the onRelatedEntityDelete=NULLIFY for + * the employerIds key causes the deleted ID to be removed from Bob's + * employerIds. + */ + dao.employerById.delete(gizmoInc.id); + bob = dao.personBySsn.get("111-11-1111"); + assert bob != null; + assert !bob.employerIds.contains(gizmoInc.id); + } + + private void close() + throws DatabaseException { + + store.close(); + env.close(); + } +} diff --git a/examples_java/src/persist/gettingStarted/SimpleDA.java b/examples_java/src/persist/gettingStarted/SimpleDA.java new file mode 100644 index 0000000..ab4c6e9 --- /dev/null +++ b/examples_java/src/persist/gettingStarted/SimpleDA.java @@ -0,0 +1,51 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2008-2009 Oracle. All rights reserved. + * + * $Id$ + */ + +package persist.gettingStarted; + +import java.io.File; + +import com.sleepycat.db.DatabaseException; +import com.sleepycat.persist.EntityStore; +import com.sleepycat.persist.PrimaryIndex; +import com.sleepycat.persist.SecondaryIndex; +import com.sleepycat.persist.EntityCursor; + +public class SimpleDA { + // Open the indices + public SimpleDA(EntityStore store) + throws DatabaseException { + + // Primary key for SimpleEntityClass classes + pIdx = store.getPrimaryIndex( + String.class, SimpleEntityClass.class); + + // Secondary key for SimpleEntityClass classes + // Last field in the getSecondaryIndex() method must be + // the name of a class member; in this case, an + // SimpleEntityClass.class data member. + sIdx = store.getSecondaryIndex( + pIdx, String.class, "sKey"); + + sec_pcursor = pIdx.entities(); + sec_scursor = sIdx.subIndex("skeyone").entities(); + } + + public void close() + throws DatabaseException { + sec_pcursor.close(); + sec_scursor.close(); + } + + // Index Accessors + PrimaryIndex<String,SimpleEntityClass> pIdx; + SecondaryIndex<String,String,SimpleEntityClass> sIdx; + + EntityCursor<SimpleEntityClass> sec_pcursor; + EntityCursor<SimpleEntityClass> sec_scursor; +} diff --git a/examples_java/src/persist/gettingStarted/SimpleEntityClass.java b/examples_java/src/persist/gettingStarted/SimpleEntityClass.java new file mode 100644 index 0000000..c4c0d81 --- /dev/null +++ b/examples_java/src/persist/gettingStarted/SimpleEntityClass.java @@ -0,0 +1,42 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2008-2009 Oracle. All rights reserved. + * + * $Id$ + */ + +package persist.gettingStarted; + +import com.sleepycat.persist.model.Entity; +import com.sleepycat.persist.model.PrimaryKey; +import static com.sleepycat.persist.model.Relationship.*; +import com.sleepycat.persist.model.SecondaryKey; + +@Entity +public class SimpleEntityClass { + + // Primary key is pKey + @PrimaryKey + private String pKey; + + // Secondary key is the sKey + @SecondaryKey(relate=MANY_TO_ONE) + private String sKey; + + public void setpKey(String data) { + pKey = data; + } + + public void setsKey(String data) { + sKey = data; + } + + public String getpKey() { + return pKey; + } + + public String getsKey() { + return sKey; + } +} diff --git a/examples_java/src/persist/gettingStarted/SimpleStoreGet.java b/examples_java/src/persist/gettingStarted/SimpleStoreGet.java new file mode 100644 index 0000000..44ac2dc --- /dev/null +++ b/examples_java/src/persist/gettingStarted/SimpleStoreGet.java @@ -0,0 +1,112 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2008-2009 Oracle. All rights reserved. + * + * $Id$ + */ + +package persist.gettingStarted; + +import java.io.File; + +import com.sleepycat.db.DatabaseException; +import com.sleepycat.db.Environment; +import com.sleepycat.db.EnvironmentConfig; + +import com.sleepycat.persist.EntityStore; +import com.sleepycat.persist.StoreConfig; + +import java.io.FileNotFoundException; + +public class SimpleStoreGet { + + private static File envHome = new File("./JEDB"); + + private Environment envmnt; + private EntityStore store; + private SimpleDA sda; + + // The setup() method opens the environment and store + // for us. + public void setup() + throws DatabaseException { + + try { + EnvironmentConfig envConfig = new EnvironmentConfig(); + StoreConfig storeConfig = new StoreConfig(); + + // Open the environment and entity store + envmnt = new Environment(envHome, envConfig); + store = new EntityStore(envmnt, "EntityStore", storeConfig); + } catch (FileNotFoundException fnfe) { + System.err.println("setup(): " + fnfe.toString()); + System.exit(-1); + } + } + + public void shutdown() + throws DatabaseException { + + store.close(); + envmnt.close(); + } + + + private void run() + throws DatabaseException { + + setup(); + + // Open the data accessor. This is used to store + // persistent objects. + sda = new SimpleDA(store); + + // Instantiate and store some entity classes + SimpleEntityClass sec1 = sda.pIdx.get("keyone"); + SimpleEntityClass sec2 = sda.pIdx.get("keytwo"); + + SimpleEntityClass sec4 = sda.sIdx.get("skeythree"); + + System.out.println("sec1: " + sec1.getpKey()); + System.out.println("sec2: " + sec2.getpKey()); + System.out.println("sec4: " + sec4.getpKey()); + + System.out.println("############ Doing pcursor ##########"); + for (SimpleEntityClass seci : sda.sec_pcursor ) { + System.out.println("sec from pcursor : " + seci.getpKey() ); + } + + sda.pIdx.delete("keyone"); + System.out.println("############ Doing pcursor ##########"); + System.out.println("sec from pcursor : " + sda.sec_pcursor.first().getpKey()); + for (SimpleEntityClass seci : sda.sec_pcursor ) { + System.out.println("sec from pcursor : " + seci.getpKey() ); + } + + System.out.println("############ Doing scursor ##########"); + for (SimpleEntityClass seci : sda.sec_scursor ) { + System.out.println("sec from scursor : " + seci.getpKey() ); + } + + + + sda.close(); + shutdown(); + } + + public static void main(String args[]) { + SimpleStoreGet ssg = new SimpleStoreGet(); + try { + ssg.run(); + } catch (DatabaseException dbe) { + System.err.println("SimpleStoreGet: " + dbe.toString()); + dbe.printStackTrace(); + } catch (Exception e) { + System.out.println("Exception: " + e.toString()); + e.printStackTrace(); + } + System.out.println("All done."); + } + +} diff --git a/examples_java/src/persist/gettingStarted/SimpleStorePut.java b/examples_java/src/persist/gettingStarted/SimpleStorePut.java new file mode 100644 index 0000000..0e48a5b --- /dev/null +++ b/examples_java/src/persist/gettingStarted/SimpleStorePut.java @@ -0,0 +1,116 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2008-2009 Oracle. All rights reserved. + * + * $Id$ + */ + +package persist.gettingStarted; + +import java.io.File; + +import com.sleepycat.db.DatabaseException; +import com.sleepycat.db.Environment; +import com.sleepycat.db.EnvironmentConfig; + +import com.sleepycat.persist.EntityStore; +import com.sleepycat.persist.StoreConfig; + +import java.io.FileNotFoundException; + +public class SimpleStorePut { + + private static File envHome = new File("./JEDB"); + + private Environment envmnt; + private EntityStore store; + private SimpleDA sda; + + // The setup() method opens the environment and store + // for us. + public void setup() + throws DatabaseException { + + EnvironmentConfig envConfig = new EnvironmentConfig(); + StoreConfig storeConfig = new StoreConfig(); + + envConfig.setAllowCreate(true); + storeConfig.setAllowCreate(true); + + try { + // Open the environment and entity store + envmnt = new Environment(envHome, envConfig); + store = new EntityStore(envmnt, "EntityStore", storeConfig); + } catch (FileNotFoundException fnfe) { + System.err.println("setup(): " + fnfe.toString()); + System.exit(-1); + } + } + + // Close our environment and store. + public void shutdown() + throws DatabaseException { + + store.close(); + envmnt.close(); + } + + + private void run() + throws DatabaseException { + + setup(); + + // Open the data accessor. This is used to store + // persistent objects. + sda = new SimpleDA(store); + + // Instantiate and store some entity classes + SimpleEntityClass sec1 = new SimpleEntityClass(); + SimpleEntityClass sec2 = new SimpleEntityClass(); + SimpleEntityClass sec3 = new SimpleEntityClass(); + SimpleEntityClass sec4 = new SimpleEntityClass(); + SimpleEntityClass sec5 = new SimpleEntityClass(); + + sec1.setpKey("keyone"); + sec1.setsKey("skeyone"); + + sec2.setpKey("keytwo"); + sec2.setsKey("skeyone"); + + sec3.setpKey("keythree"); + sec3.setsKey("skeytwo"); + + sec4.setpKey("keyfour"); + sec4.setsKey("skeythree"); + + sec5.setpKey("keyfive"); + sec5.setsKey("skeyfour"); + + sda.pIdx.put(sec1); + sda.pIdx.put(sec2); + sda.pIdx.put(sec3); + sda.pIdx.put(sec4); + sda.pIdx.put(sec5); + + sda.close(); + + shutdown(); + } + + public static void main(String args[]) { + SimpleStorePut ssp = new SimpleStorePut(); + try { + ssp.run(); + } catch (DatabaseException dbe) { + System.err.println("SimpleStorePut: " + dbe.toString()); + dbe.printStackTrace(); + } catch (Exception e) { + System.out.println("Exception: " + e.toString()); + e.printStackTrace(); + } + System.out.println("All done."); + } + +} diff --git a/examples_java/src/persist/txn/PayloadDataEntity.java b/examples_java/src/persist/txn/PayloadDataEntity.java new file mode 100644 index 0000000..9d464ff --- /dev/null +++ b/examples_java/src/persist/txn/PayloadDataEntity.java @@ -0,0 +1,33 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2008-2009 Oracle. All rights reserved. + * + * $Id$ + */ + +package persist.txn; + +import com.sleepycat.persist.model.Entity; +import com.sleepycat.persist.model.PrimaryKey; +import static com.sleepycat.persist.model.Relationship.*; + +@Entity +public class PayloadDataEntity { + @PrimaryKey + private int oID; + + private String threadName; + + private double doubleData; + + PayloadDataEntity() {} + + public double getDoubleData() { return doubleData; } + public int getID() { return oID; } + public String getThreadName() { return threadName; } + + public void setDoubleData(double dd) { doubleData = dd; } + public void setID(int id) { oID = id; } + public void setThreadName(String tn) { threadName = tn; } +} diff --git a/examples_java/src/persist/txn/StoreWriter.java b/examples_java/src/persist/txn/StoreWriter.java new file mode 100644 index 0000000..fb8b4e5 --- /dev/null +++ b/examples_java/src/persist/txn/StoreWriter.java @@ -0,0 +1,176 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2008-2009 Oracle. All rights reserved. + * + * $Id$ + */ + +package persist.txn; + +import com.sleepycat.db.CursorConfig; +import com.sleepycat.db.DatabaseException; +import com.sleepycat.db.DeadlockException; +import com.sleepycat.db.Environment; +import com.sleepycat.db.Transaction; + +import com.sleepycat.persist.EntityCursor; +import com.sleepycat.persist.EntityStore; +import com.sleepycat.persist.PrimaryIndex; + +import java.util.Iterator; +import java.util.Random; +import java.io.UnsupportedEncodingException; + +public class StoreWriter extends Thread +{ + private EntityStore myStore = null; + private Environment myEnv = null; + private PrimaryIndex<Integer,PayloadDataEntity> pdKey; + private Random generator = new Random(); + private boolean passTxn = false; + + + private static final int MAX_RETRY = 20; + + // Constructor. Get our handles from here + StoreWriter(Environment env, EntityStore store) + + throws DatabaseException { + myStore = store; + myEnv = env; + + // Open the data accessor. This is used to store persistent + // objects. + pdKey = myStore.getPrimaryIndex(Integer.class, + PayloadDataEntity.class); + } + + // Thread method that writes a series of objects + // to the store using transaction protection. + // Deadlock handling is demonstrated here. + public void run () { + Transaction txn = null; + + // Perform 50 transactions + for (int i=0; i<50; i++) { + + boolean retry = true; + int retry_count = 0; + // while loop is used for deadlock retries + while (retry) { + // try block used for deadlock detection and + // general exception handling + try { + + // Get a transaction + txn = myEnv.beginTransaction(null, null); + + // Write 10 PayloadDataEntity objects to the + // store for each transaction + for (int j = 0; j < 10; j++) { + // Instantiate an object + PayloadDataEntity pd = new PayloadDataEntity(); + + // Set the Object ID. This is used as the primary key. + pd.setID(i + j); + + // The thread name is used as a secondary key, and + // it is retrieved by this class's getName() method. + pd.setThreadName(getName()); + + // The last bit of data that we use is a double + // that we generate randomly. This data is not + // indexed. + pd.setDoubleData(generator.nextDouble()); + + // Do the put + pdKey.put(txn, pd); + } + + // commit + System.out.println(getName() + " : committing txn : " + i); + System.out.println(getName() + " : Found " + + countObjects(txn) + " objects in the store."); + try { + txn.commit(); + txn = null; + } catch (DatabaseException e) { + System.err.println("Error on txn commit: " + + e.toString()); + } + retry = false; + + } catch (DeadlockException de) { + System.out.println("################# " + getName() + + " : caught deadlock"); + // retry if necessary + if (retry_count < MAX_RETRY) { + System.err.println(getName() + + " : Retrying operation."); + retry = true; + retry_count++; + } else { + System.err.println(getName() + + " : out of retries. Giving up."); + retry = false; + } + } catch (DatabaseException e) { + // abort and don't retry + retry = false; + System.err.println(getName() + + " : caught exception: " + e.toString()); + System.err.println(getName() + + " : errno: " + e.getErrno()); + e.printStackTrace(); + } finally { + if (txn != null) { + try { + txn.abort(); + } catch (Exception e) { + System.err.println("Error aborting transaction: " + + e.toString()); + e.printStackTrace(); + } + } + } + } + } + } + + // This simply counts the number of objects contained in the + // store and returns the result. You can use this method + // in three ways: + // + // First call it with an active txn handle. + // + // Secondly, configure the cursor for dirty reads + // + // Third, call countObjects AFTER the writer has committed + // its transaction. + // + // If you do none of these things, the writer thread will + // self-deadlock. + private int countObjects(Transaction txn) throws DatabaseException { + int count = 0; + + CursorConfig cc = new CursorConfig(); + // This is ignored if the store is not opened with uncommitted read + // support. + cc.setReadUncommitted(true); + EntityCursor<PayloadDataEntity> cursor = pdKey.entities(txn, cc); + + try { + for (PayloadDataEntity pdi : cursor) { + count++; + } + } finally { + if (cursor != null) { + cursor.close(); + } + } + + return count; + + } +} diff --git a/examples_java/src/persist/txn/TxnGuideDPL.java b/examples_java/src/persist/txn/TxnGuideDPL.java new file mode 100644 index 0000000..d429507 --- /dev/null +++ b/examples_java/src/persist/txn/TxnGuideDPL.java @@ -0,0 +1,162 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2008-2009 Oracle. All rights reserved. + * + * $Id$ + */ + +// File TxnGuideDPL.java + +package persist.txn; + +import com.sleepycat.db.DatabaseConfig; +import com.sleepycat.db.DatabaseException; +import com.sleepycat.db.DatabaseType; +import com.sleepycat.db.LockDetectMode; + +import com.sleepycat.db.Environment; +import com.sleepycat.db.EnvironmentConfig; + +import com.sleepycat.persist.EntityStore; +import com.sleepycat.persist.StoreConfig; + +import java.io.File; +import java.io.FileNotFoundException; + +public class TxnGuideDPL { + + private static String myEnvPath = "./"; + private static String storeName = "exampleStore"; + + // Handles + private static EntityStore myStore = null; + private static Environment myEnv = null; + + private static final int NUMTHREADS = 5; + + private static void usage() { + System.out.println("TxnGuideDPL [-h <env directory>]"); + System.exit(-1); + } + + public static void main(String args[]) { + try { + // Parse the arguments list + parseArgs(args); + // Open the environment and store + openEnv(); + + // Start the threads + StoreWriter[] threadArray; + threadArray = new StoreWriter[NUMTHREADS]; + for (int i = 0; i < NUMTHREADS; i++) { + threadArray[i] = new StoreWriter(myEnv, myStore); + threadArray[i].start(); + } + + for (int i = 0; i < NUMTHREADS; i++) { + threadArray[i].join(); + } + } catch (Exception e) { + System.err.println("TxnGuideDPL: " + e.toString()); + e.printStackTrace(); + } finally { + closeEnv(); + } + System.out.println("All done."); + } + + + private static void openEnv() throws DatabaseException { + System.out.println("opening env and store"); + + // Set up the environment. + EnvironmentConfig myEnvConfig = new EnvironmentConfig(); + myEnvConfig.setAllowCreate(true); + myEnvConfig.setInitializeCache(true); + myEnvConfig.setInitializeLocking(true); + myEnvConfig.setInitializeLogging(true); + myEnvConfig.setRunRecovery(true); + myEnvConfig.setTransactional(true); + // EnvironmentConfig.setThreaded(true) is the default behavior + // in Java, so we do not have to do anything to cause the + // environment handle to be free-threaded. + + // Indicate that we want db to internally perform deadlock + // detection. Also indicate that the transaction that has + // performed the least amount of write activity to + // receive the deadlock notification, if any. + myEnvConfig.setLockDetectMode(LockDetectMode.MINWRITE); + + // Set up the entity store + StoreConfig myStoreConfig = new StoreConfig(); + myStoreConfig.setAllowCreate(true); + myStoreConfig.setTransactional(true); + + // Need a DatabaseConfig object so as to set uncommitted read + // support. + DatabaseConfig myDbConfig = new DatabaseConfig(); + myDbConfig.setType(DatabaseType.BTREE); + myDbConfig.setAllowCreate(true); + myDbConfig.setTransactional(true); + myDbConfig.setReadUncommitted(true); + + try { + // Open the environment + myEnv = new Environment(new File(myEnvPath), // Env home + myEnvConfig); + + // Open the store + myStore = new EntityStore(myEnv, storeName, myStoreConfig); + + // Set the DatabaseConfig object, so that the underlying + // database is configured for uncommitted reads. + myStore.setPrimaryConfig(PayloadDataEntity.class, myDbConfig); + } catch (FileNotFoundException fnfe) { + System.err.println("openEnv: " + fnfe.toString()); + System.exit(-1); + } + } + + private static void closeEnv() { + System.out.println("Closing env and store"); + if (myStore != null ) { + try { + myStore.close(); + } catch (DatabaseException e) { + System.err.println("closeEnv: myStore: " + + e.toString()); + e.printStackTrace(); + } + } + + if (myEnv != null ) { + try { + myEnv.close(); + } catch (DatabaseException e) { + System.err.println("closeEnv: " + e.toString()); + e.printStackTrace(); + } + } + } + + private TxnGuideDPL() {} + + private static void parseArgs(String args[]) { + int nArgs = args.length; + for(int i = 0; i < args.length; ++i) { + if (args[i].startsWith("-")) { + switch(args[i].charAt(1)) { + case 'h': + if (i < nArgs - 1) { + myEnvPath = new String(args[++i]); + } + break; + default: + usage(); + } + } + } + } +} |