/** * Creates an instance of this class. * * @param env the Berkeley DB environment * @param timeout the number of milliseconds the transaction should be allowed to run * @throws IllegalArgumentException if timeout is less than {@code 1} * @throws DbDatabaseException if an unexpected database problem occurs */ BdbTransaction(Environment env, long timeout) { if (timeout <= 0) { throw new IllegalArgumentException("Timeout must be greater than 0"); } try { txn = env.beginTransaction(null, null); /* Avoid overflow -- BDB treats 0 as unlimited */ long timeoutMicros = (timeout < (Long.MAX_VALUE / 1000)) ? 1000 * timeout : 0; txn.setTxnTimeout(timeoutMicros); } catch (DatabaseException e) { throw BdbEnvironment.convertException(e, false); } }
/** * Inserts an entity and returns null, or updates it if the primary key already exists and returns * the existing entity. * * <p>If a {@link PrimaryKey#sequence} is used and the primary key field of the given entity is * null or zero, this method will assign the next value from the sequence to the primary key field * of the given entity. * * @param txn the transaction used to protect this operation, null to use auto-commit, or null if * the store is non-transactional. * @param entity the entity to be inserted or updated. * @return the existing entity that was updated, or null if the entity was inserted. * @throws DatabaseException the base class for all BDB exceptions. */ public E put(Transaction txn, E entity) throws DatabaseException { DatabaseEntry keyEntry = new DatabaseEntry(); DatabaseEntry dataEntry = new DatabaseEntry(); assignKey(entity, keyEntry); boolean autoCommit = false; Environment env = db.getEnvironment(); if (transactional && txn == null && DbCompat.getThreadTransaction(env) == null) { txn = env.beginTransaction(null, getAutoCommitTransactionConfig()); autoCommit = true; } CursorConfig cursorConfig = null; if (concurrentDB) { cursorConfig = new CursorConfig(); DbCompat.setWriteCursor(cursorConfig, true); } boolean failed = true; Cursor cursor = db.openCursor(txn, cursorConfig); LockMode lockMode = locking ? LockMode.RMW : null; try { while (true) { OperationStatus status = cursor.getSearchKey(keyEntry, dataEntry, lockMode); if (status == OperationStatus.SUCCESS) { E existing = entityBinding.entryToObject(keyEntry, dataEntry); entityBinding.objectToData(entity, dataEntry); cursor.put(keyEntry, dataEntry); failed = false; return existing; } else { entityBinding.objectToData(entity, dataEntry); status = cursor.putNoOverwrite(keyEntry, dataEntry); if (status != OperationStatus.KEYEXIST) { failed = false; return null; } } } } finally { cursor.close(); if (autoCommit) { if (failed) { txn.abort(); } else { txn.commit(); } } } }
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); }