High-Performance Data Management in Java

by Charles Lamb



Listing One

/* See the file LICENSE for redistribution information.

 * Copyright (c) 2004 Sleepycat Software.  All rights reserved.

 */



package com.sleepycat.examples.je;



import java.io.File;



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;



/* SimpleExample creates a database environment, a database, and a database

 * cursor, inserts and retrieves data.  */

class SimpleExample {

    private static final int EXIT_SUCCESS = 0;

    private static final int EXIT_FAILURE = 1;

    private int numRecords;   // num records to insert or retrieve

    private int offset;       // where we want to start inserting

    private boolean doInsert; // if true, insert, else retrieve

    private File envDir;

    public SimpleExample(int numRecords, boolean doInsert, File envDir,

                         int offset) {

        this.numRecords = numRecords;

        this.doInsert = doInsert;

        this.envDir = envDir;

        this.offset = offset;

    }

    /** Usage string */

    public static void usage() {

        System.out.println("usage: java " +

                           "com.sleepycat.examples.je.SimpleExample " +

                           "<dbEnvHomeDirectory> " +

                           "<insert|retrieve> <numRecords> [offset]");

        System.exit(EXIT_FAILURE);

    }

    /** Main */

    public static void main(String argv[]) {

        if (argv.length < 2) {

            usage();

            return;

        }

        File envHomeDirectory = new File(argv[0]);

        boolean doInsertArg = false;

        if (argv[1].equalsIgnoreCase("insert")) {

            doInsertArg = true;

        } else if (argv[1].equalsIgnoreCase("retrieve")) {

            doInsertArg = false;

        } else {

            usage();

        }

        int startOffset = 0;

        int numRecordsVal = 0;



        if (doInsertArg) {



            if (argv.length > 2) {

                numRecordsVal = Integer.parseInt(argv[2]);

            } else {

                usage();

                return;

            }



            if (argv.length > 3) {

                startOffset = Integer.parseInt(argv[3]);

            }

        }



        try {

            SimpleExample app = new SimpleExample(numRecordsVal, doInsertArg,

                                               envHomeDirectory, startOffset);

            app.run();

        } catch (DatabaseException e) {

            e.printStackTrace();

            System.exit(EXIT_FAILURE);

        }

        System.exit(EXIT_SUCCESS);

    }

    /** Insert or retrieve data */

    public void run() throws DatabaseException {

        /* Create a new, transactional database environment */

        EnvironmentConfig envConfig = new EnvironmentConfig();

        envConfig.setTransactional(true);

        envConfig.setAllowCreate(true);

        Environment exampleEnv = new Environment(envDir, envConfig);



        /* Make a database within that environment */

        Transaction txn = exampleEnv.beginTransaction(null, null);

        DatabaseConfig dbConfig = new DatabaseConfig();

        dbConfig.setTransactional(true);

        dbConfig.setAllowCreate(true);

        dbConfig.setSortedDuplicates(true);

        Database exampleDb = exampleEnv.openDatabase(txn,"simpleDb",dbConfig);

        txn.commit();

        /* Insert or retrieve data. In our example, database records are

         * integer pairs. */

        if (doInsert) {

            /* put some data in */

            for (int i = offset; i < numRecords + offset; i++) {

                /* Note that autocommit mode, described in the Getting

                 * Started Guide, is an alternative to explicitly

                 * creating the transaction object. */

                txn = exampleEnv.beginTransaction(null, null);

                OperationStatus status = exampleDb.put(txn,

                           new IntDatabaseEntry(i), new IntDatabaseEntry(i));



                /* Note that put will throw a DatabaseException when

                 * error conditions are found such as deadlock. However, the

                 * status return conveys a variety of information. For

                 * example, the put might succeed, or it might not succeed if

                 * the record exists and duplicates were not.  */

                if (status != OperationStatus.SUCCESS) {

                    throw new DatabaseException("Data insertion got status " +

                                                status);

                }

                txn.commit();

            }

        } else {

            /* retrieve the data */

            Cursor cursor = exampleDb.openCursor(null, null);

            IntDatabaseEntry foundKey = new IntDatabaseEntry();

            IntDatabaseEntry foundData = new IntDatabaseEntry();



            while (cursor.getNext(foundKey, foundData, LockMode.DEFAULT) ==

                   OperationStatus.SUCCESS) {

                System.out.println("key=" + foundKey.getInt() +

                                   " data=" + foundData.getInt());

            }

            cursor.close();

        }

        exampleDb.close();

        exampleEnv.close();

    }

    /* Here's an example of how you can extend a DatabaseEntry in a

     * straightforward way to allow storage/retrieval of ints, or

     * whatever kind of data you wish.  We've declared it as a static

     * inner class, but it need not be.

     * Also see com.sleepycat.bind and the BindingsExample for how to map

     * between Java objects and DatabaseEntries. */

    static /*nested*/ class IntDatabaseEntry extends DatabaseEntry {

        IntDatabaseEntry() {

        }

        IntDatabaseEntry(int i) {

            setInt(i);

        }

        void setInt(int i) {

            byte[] intData = new byte[4];

            intData[3] = (byte) (i >> 0);

            intData[2] = (byte) (i >> 8);

            intData[1] = (byte) (i >> 16);

            intData[0] = (byte) (i >> 24);

            setData(intData);

        }

        int getInt() {

            byte [] val = getData();

            return ((val[3] & 0xff)+ ((val[2] & 0xff) << 8) +

                    ((val[1] & 0xff) << 16) + ((val[0] & 0xff) << 24));

        }

    }

}









3



