summaryrefslogtreecommitdiff
path: root/examples_java/src/db/TpcbExample.java
diff options
context:
space:
mode:
authorKim Kibum <kb0929.kim@samsung.com>2012-05-21 17:40:46 +0900
committerKim Kibum <kb0929.kim@samsung.com>2012-05-21 17:40:46 +0900
commit2e082c838d2ca750f5daac6dcdabecc22dfd4e46 (patch)
tree01c1dd87d4cc0b62a655c0d768ff695d2d244728 /examples_java/src/db/TpcbExample.java
parenta86e3ca152fb414b376e64c449c201d762e414dd (diff)
downloaddb4-2e082c838d2ca750f5daac6dcdabecc22dfd4e46.tar.gz
db4-2e082c838d2ca750f5daac6dcdabecc22dfd4e46.tar.bz2
db4-2e082c838d2ca750f5daac6dcdabecc22dfd4e46.zip
Upload Tizen:Base source
Diffstat (limited to 'examples_java/src/db/TpcbExample.java')
-rw-r--r--examples_java/src/db/TpcbExample.java789
1 files changed, 789 insertions, 0 deletions
diff --git a/examples_java/src/db/TpcbExample.java b/examples_java/src/db/TpcbExample.java
new file mode 100644
index 0000000..883dca4
--- /dev/null
+++ b/examples_java/src/db/TpcbExample.java
@@ -0,0 +1,789 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+package db;
+
+import com.sleepycat.db.*;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.math.BigDecimal;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Random;
+import java.util.GregorianCalendar;
+
+//
+// This program implements a basic TPC/B driver program. To create the
+// TPC/B database, run with the -i (init) flag. The number of records
+// with which to populate the account, history, branch, and teller tables
+// is specified by the a, s, b, and t flags respectively. To run a TPC/B
+// test, use the n flag to indicate a number of transactions to run in
+// each thread and -T to specify the number of threads.
+//
+class TpcbExample {
+ public static final int TELLERS_PER_BRANCH = 10;
+ public static final int ACCOUNTS_PER_TELLER = 10000;
+ public static final int HISTORY_PER_BRANCH = 2592000;
+
+ //
+ // The default configuration that adheres to TPCB scaling rules requires
+ // nearly 3 GB of space. To avoid requiring that much space for testing,
+ // we set the parameters much lower. If you want to run a valid 10 TPS
+ // configuration, uncomment the VALID_SCALING configuration
+ //
+
+ // VALID_SCALING configuration
+ /*
+ public static final int ACCOUNTS = 1000000;
+ public static final int BRANCHES = 10;
+ public static final int TELLERS = 100;
+ public static final int HISTORY = 25920000;
+ */
+
+ // TINY configuration
+ /*
+ public static final int ACCOUNTS = 1000;
+ public static final int BRANCHES = 10;
+ public static final int TELLERS = 100;
+ public static final int HISTORY = 10000;
+ */
+
+ // Default configuration
+ public static final int ACCOUNTS = 100000;
+ public static final int BRANCHES = 10;
+ public static final int TELLERS = 100;
+ public static final int HISTORY = 259200;
+
+ public static final int HISTORY_LEN = 100;
+ public static final int RECLEN = 100;
+ public static final int BEGID = 1000000;
+
+ // used by random_id()
+ public static final int ACCOUNT = 0;
+ public static final int BRANCH = 1;
+ public static final int TELLER = 2;
+
+ public static boolean verbose = false;
+ public static final String progname = "TpcbExample"; // Program name.
+
+ Environment dbenv;
+ int accounts, branches, tellers, history;
+
+ public TpcbExample(File home,
+ int accounts, int branches, int tellers, int history,
+ int cachesize, boolean noSync)
+ throws DatabaseException, FileNotFoundException {
+
+ this.accounts = accounts;
+ this.branches = branches;
+ this.tellers = tellers;
+ this.history = history;
+
+ EnvironmentConfig config = new EnvironmentConfig();
+ config.setErrorStream(System.err);
+ config.setErrorPrefix(progname);
+ config.setLockDetectMode(LockDetectMode.DEFAULT);
+ config.setCacheSize(cachesize == 0 ? 4 * 1024 * 1024 : cachesize);
+ config.setTxnNoSync(noSync);
+ config.setLockDetectMode(LockDetectMode.DEFAULT);
+ config.setAllowCreate(true);
+
+ config.setInitializeCache(true);
+ config.setTransactional(true);
+ config.setInitializeLocking(true);
+ config.setInitializeLogging(true);
+
+ dbenv = new Environment(home, config);
+ }
+
+ public void close()
+ throws DatabaseException {
+
+ try {
+ if (dbenv != null)
+ dbenv.close();
+ } finally {
+ dbenv = null;
+ }
+ }
+
+ //
+ // Initialize the database to the number of accounts, branches,
+ // history records, and tellers given to the constructor.
+ //
+ public void populate() {
+ Database dbp = null;
+
+ int err;
+ int balance, idnum;
+ int end_anum, end_bnum, end_tnum;
+ int start_anum, start_bnum, start_tnum;
+ int h_nelem;
+
+ idnum = BEGID;
+ balance = 500000;
+
+ h_nelem = accounts;
+
+ try {
+ DatabaseConfig config = new DatabaseConfig();
+ config.setType(DatabaseType.HASH);
+ config.setHashNumElements(h_nelem);
+ config.setAllowCreate(true);
+ dbp = dbenv.openDatabase(null, "account", null, config);
+ } catch (Exception e1) {
+ // can be DatabaseException or FileNotFoundException
+ errExit(e1, "Open of account file failed");
+ }
+
+ start_anum = idnum;
+ populateTable(dbp, idnum, balance, h_nelem, "account");
+ idnum += h_nelem;
+ end_anum = idnum - 1;
+ try {
+ dbp.close();
+ } catch (DatabaseException e2) {
+ errExit(e2, "Account file close failed");
+ }
+
+ if (verbose)
+ System.out.println("Populated accounts: " +
+ String.valueOf(start_anum) + " - " +
+ String.valueOf(end_anum));
+
+ //
+ // Since the number of branches is very small, we want to use very
+ // small pages and only 1 key per page. This is the poor-man's way
+ // of getting key locking instead of page locking.
+ //
+ h_nelem = (int)branches;
+
+ try {
+ DatabaseConfig config = new DatabaseConfig();
+ config.setType(DatabaseType.HASH);
+ config.setHashNumElements(h_nelem);
+ config.setHashFillFactor(1);
+ config.setPageSize(512);
+ config.setAllowCreate(true);
+ dbp = dbenv.openDatabase(null, "branch", null, config);
+ } catch (Exception e3) {
+ // can be DatabaseException or FileNotFoundException
+ errExit(e3, "Branch file create failed");
+ }
+
+ start_bnum = idnum;
+ populateTable(dbp, idnum, balance, h_nelem, "branch");
+ idnum += h_nelem;
+ end_bnum = idnum - 1;
+
+ try {
+ dbp.close();
+ } catch (DatabaseException dbe4) {
+ errExit(dbe4, "Close of branch file failed");
+ }
+
+ if (verbose)
+ System.out.println("Populated branches: " +
+ String.valueOf(start_bnum) + " - " +
+ String.valueOf(end_bnum));
+
+ //
+ // In the case of tellers, we also want small pages, but we'll let
+ // the fill factor dynamically adjust itself.
+ //
+ h_nelem = (int)tellers;
+
+ try {
+ DatabaseConfig config = new DatabaseConfig();
+ config.setType(DatabaseType.HASH);
+ config.setHashNumElements(h_nelem);
+ config.setHashFillFactor(0);
+ config.setPageSize(512);
+ config.setAllowCreate(true);
+ dbp = dbenv.openDatabase(null, "teller", null, config);
+ } catch (Exception e5) {
+ // can be DatabaseException or FileNotFoundException
+ errExit(e5, "Teller file create failed");
+ }
+
+ start_tnum = idnum;
+ populateTable(dbp, idnum, balance, h_nelem, "teller");
+ idnum += h_nelem;
+ end_tnum = idnum - 1;
+
+ try {
+ dbp.close();
+ } catch (DatabaseException e6) {
+ errExit(e6, "Close of teller file failed");
+ }
+
+ if (verbose)
+ System.out.println("Populated tellers: " +
+ String.valueOf(start_tnum) + " - " +
+ String.valueOf(end_tnum));
+
+ try {
+ DatabaseConfig config = new DatabaseConfig();
+ config.setType(DatabaseType.RECNO);
+ config.setRecordLength(HISTORY_LEN);
+ config.setAllowCreate(true);
+ dbp = dbenv.openDatabase(null, "history", null, config);
+ } catch (Exception e7) {
+ // can be DatabaseException or FileNotFoundException
+ errExit(e7, "Create of history file failed");
+ }
+
+ populateHistory(dbp);
+
+ try {
+ dbp.close();
+ } catch (DatabaseException e8) {
+ errExit(e8, "Close of history file failed");
+ }
+ }
+
+ public void populateTable(Database dbp,
+ int start_id, int balance, int nrecs, String msg) {
+ Defrec drec = new Defrec();
+
+ DatabaseEntry kdbt = new DatabaseEntry(drec.data);
+ kdbt.setSize(4); // sizeof(int)
+ DatabaseEntry ddbt = new DatabaseEntry(drec.data);
+ ddbt.setSize(drec.data.length); // uses whole array
+
+ try {
+ for (int i = 0; i < nrecs; i++) {
+ kdbt.setRecordNumber(start_id + (int)i);
+ drec.set_balance(balance);
+ dbp.putNoOverwrite(null, kdbt, ddbt);
+ }
+ } catch (DatabaseException dbe) {
+ System.err.println("Failure initializing " + msg + " file: " +
+ dbe.toString());
+ System.exit(1);
+ }
+ }
+
+ public void populateHistory(Database dbp) {
+ Histrec hrec = new Histrec();
+ hrec.set_amount(10);
+
+ byte[] arr = new byte[4]; // sizeof(int)
+ int i;
+ DatabaseEntry kdbt = new DatabaseEntry(arr);
+ kdbt.setSize(arr.length);
+ DatabaseEntry ddbt = new DatabaseEntry(hrec.data);
+ ddbt.setSize(hrec.data.length);
+
+ try {
+ for (i = 1; i <= history; i++) {
+ kdbt.setRecordNumber(i);
+
+ hrec.set_aid(random_id(ACCOUNT));
+ hrec.set_bid(random_id(BRANCH));
+ hrec.set_tid(random_id(TELLER));
+
+ dbp.append(null, kdbt, ddbt);
+ }
+ } catch (DatabaseException dbe) {
+ errExit(dbe, "Failure initializing history file");
+ }
+ }
+
+ static Random rand = new Random();
+ public static int random_int(int lo, int hi) {
+ int t = rand.nextInt();
+ if (t < 0)
+ t = -t;
+ int ret = (int)(((double)t / ((double)(Integer.MAX_VALUE) + 1)) *
+ (hi - lo + 1));
+ ret += lo;
+ return (ret);
+ }
+
+ public int random_id(int type) {
+ int min, max, num;
+
+ max = min = BEGID;
+ num = accounts;
+ switch(type) {
+ case TELLER:
+ min += branches;
+ num = tellers;
+ // fallthrough
+ case BRANCH:
+ if (type == BRANCH)
+ num = branches;
+ min += accounts;
+ // fallthrough
+ case ACCOUNT:
+ max = min + num - 1;
+ }
+ return (random_int(min, max));
+ }
+
+ // The byte order is our choice.
+ //
+ static long get_int_in_array(byte[] array, int offset) {
+ return
+ ((0xff & array[offset + 0]) << 0) |
+ ((0xff & array[offset + 1]) << 8) |
+ ((0xff & array[offset + 2]) << 16) |
+ ((0xff & array[offset + 3]) << 24);
+ }
+
+ // Note: Value needs to be long to avoid sign extension
+ static void set_int_in_array(byte[] array, int offset, long value) {
+ array[offset + 0] = (byte)((value >> 0) & 0xff);
+ array[offset + 1] = (byte)((value >> 8) & 0xff);
+ array[offset + 2] = (byte)((value >> 16) & 0xff);
+ array[offset + 3] = (byte)((value >> 24) & 0xff);
+ }
+
+ // round 'd' to 'scale' digits, and return result as string
+ static String showRounded(double d, int scale) {
+ return new BigDecimal(d).
+ setScale(scale, BigDecimal.ROUND_HALF_DOWN).toString();
+ }
+
+ public void run(int ntxns, int threads) {
+ double gtps;
+ int txns, failed;
+ long curtime, starttime;
+ TxnThread[] txnList = new TxnThread[threads];
+ for (int i = 0; i < threads; i++)
+ txnList[i] = new TxnThread("Thread " + String.valueOf(i), ntxns);
+
+ starttime = (new Date()).getTime();
+ for (int i = 0; i < threads; i++)
+ txnList[i].start();
+ for (int i = 0; i < threads; i++)
+ try {
+ txnList[i].join();
+ } catch (Exception e1) {
+ errExit(e1, "join failed");
+ }
+
+ curtime = (new Date()).getTime();
+ txns = failed = 0;
+ for (int i = 0; i < threads; i++) {
+ txns += txnList[i].txns;
+ failed += txnList[i].failed;
+ }
+ gtps = (double)(txns - failed) /
+ ((curtime - starttime) / 1000.0);
+ System.out.print("\nTotal: " +
+ String.valueOf(txns) + " txns " +
+ String.valueOf(failed) + " failed ");
+ System.out.println(showRounded(gtps, 2) + " TPS");
+ }
+
+ class TxnThread extends Thread {
+ private int ntxns; /* Number of txns we were asked to run. */
+ public int txns, failed; /* Number that succeeded / failed. */
+ private Database adb, bdb, hdb, tdb;
+
+ public TxnThread(String name, int ntxns) {
+ super(name);
+ this.ntxns = ntxns;
+ }
+
+ public void run() {
+ double gtps, itps;
+ int n, ret;
+ long start_time, end_time;
+
+ //
+ // Open the database files.
+ //
+ int err;
+ try {
+ DatabaseConfig config = new DatabaseConfig();
+ config.setTransactional(true);
+ adb = dbenv.openDatabase(null, "account", null, config);
+ bdb = dbenv.openDatabase(null, "branch", null, config);
+ tdb = dbenv.openDatabase(null, "teller", null, config);
+ hdb = dbenv.openDatabase(null, "history", null, config);
+ } catch (DatabaseException dbe) {
+ TpcbExample.errExit(dbe, "Open of db files failed");
+ } catch (FileNotFoundException fnfe) {
+ TpcbExample.errExit(fnfe, "Open of db files failed, missing file");
+ }
+
+ start_time = (new Date()).getTime();
+ for (txns = n = ntxns, failed = 0; n-- > 0;)
+ if ((ret = txn()) != 0)
+ failed++;
+ end_time = (new Date()).getTime();
+ if (end_time == start_time)
+ end_time++;
+
+ System.out.println(getName() + ": " + (long)txns + " txns: " +
+ failed + " failed, " + TpcbExample.showRounded(
+ (txns - failed) / (double)(end_time - start_time), 2) + " TPS");
+
+ try {
+ adb.close();
+ bdb.close();
+ tdb.close();
+ hdb.close();
+ } catch (DatabaseException dbe2) {
+ TpcbExample.errExit(dbe2, "Close of db files failed");
+ }
+ }
+
+ //
+ // XXX Figure out the appropriate way to pick out IDs.
+ //
+ int txn() {
+ Cursor acurs = null;
+ Cursor bcurs = null;
+ Cursor hcurs = null;
+ Cursor tcurs = null;
+ Transaction t = null;
+
+ Defrec rec = new Defrec();
+ Histrec hrec = new Histrec();
+ int account, branch, teller;
+
+ DatabaseEntry d_dbt = new DatabaseEntry();
+ DatabaseEntry d_histdbt = new DatabaseEntry();
+ DatabaseEntry k_dbt = new DatabaseEntry();
+ DatabaseEntry k_histdbt = new DatabaseEntry();
+
+ account = TpcbExample.this.random_id(TpcbExample.ACCOUNT);
+ branch = TpcbExample.this.random_id(TpcbExample.BRANCH);
+ teller = TpcbExample.this.random_id(TpcbExample.TELLER);
+
+ // The history key will not actually be retrieved,
+ // but it does need to be set to something.
+ byte[] hist_key = new byte[4];
+ k_histdbt.setData(hist_key);
+ k_histdbt.setSize(4 /* == sizeof(int)*/);
+
+ byte[] key_bytes = new byte[4];
+ k_dbt.setData(key_bytes);
+ k_dbt.setSize(4 /* == sizeof(int)*/);
+
+ d_dbt.setData(rec.data);
+ d_dbt.setUserBuffer(rec.length(), true);
+
+ hrec.set_aid(account);
+ hrec.set_bid(branch);
+ hrec.set_tid(teller);
+ hrec.set_amount(10);
+ // Request 0 bytes since we're just positioning.
+ d_histdbt.setPartial(0, 0, true);
+
+ // START PER-TRANSACTION TIMING.
+ //
+ // Technically, TPCB requires a limit on response time, you only
+ // get to count transactions that complete within 2 seconds.
+ // That's not an issue for this sample application -- regardless,
+ // here's where the transaction begins.
+ try {
+ t = dbenv.beginTransaction(null, null);
+
+ acurs = adb.openCursor(t, null);
+ bcurs = bdb.openCursor(t, null);
+ tcurs = tdb.openCursor(t, null);
+ hcurs = hdb.openCursor(t, null);
+
+ // Account record
+ k_dbt.setRecordNumber(account);
+ if (acurs.getSearchKey(k_dbt, d_dbt, null) != OperationStatus.SUCCESS)
+ throw new Exception("acurs get failed");
+ rec.set_balance(rec.get_balance() + 10);
+ acurs.putCurrent(d_dbt);
+
+ // Branch record
+ k_dbt.setRecordNumber(branch);
+ if (bcurs.getSearchKey(k_dbt, d_dbt, null) != OperationStatus.SUCCESS)
+ throw new Exception("bcurs get failed");
+ rec.set_balance(rec.get_balance() + 10);
+ bcurs.putCurrent(d_dbt);
+
+ // Teller record
+ k_dbt.setRecordNumber(teller);
+ if (tcurs.getSearchKey(k_dbt, d_dbt, null) != OperationStatus.SUCCESS)
+ throw new Exception("ccurs get failed");
+ rec.set_balance(rec.get_balance() + 10);
+ tcurs.putCurrent(d_dbt);
+
+ // History record
+ d_histdbt.setPartial(0, 0, false);
+ d_histdbt.setData(hrec.data);
+ d_histdbt.setUserBuffer(hrec.length(), true);
+ if (hdb.append(t, k_histdbt, d_histdbt) != OperationStatus.SUCCESS)
+ throw new DatabaseException("put failed");
+
+ acurs.close();
+ acurs = null;
+ bcurs.close();
+ bcurs = null;
+ tcurs.close();
+ tcurs = null;
+ hcurs.close();
+ hcurs = null;
+
+ // null out t in advance; if the commit fails,
+ // we don't want to abort it in the catch clause.
+ Transaction tmptxn = t;
+ t = null;
+ tmptxn.commit();
+
+ // END TIMING
+ return (0);
+ } catch (Exception e) {
+ try {
+ if (acurs != null)
+ acurs.close();
+ if (bcurs != null)
+ bcurs.close();
+ if (tcurs != null)
+ tcurs.close();
+ if (hcurs != null)
+ hcurs.close();
+ if (t != null)
+ t.abort();
+ } catch (DatabaseException dbe) {
+ // not much we can do here.
+ }
+
+ if (TpcbExample.this.verbose) {
+ System.out.println("Transaction A=" + String.valueOf(account) +
+ " B=" + String.valueOf(branch) +
+ " T=" + String.valueOf(teller) +
+ " failed");
+ System.out.println("Reason: " + e.toString());
+ }
+ return (-1);
+ }
+ }
+ }
+
+ private static void usage() {
+ System.err.println(
+ "usage: TpcbExample [-fiv] [-a accounts] [-b branches]\n" +
+ " [-c cachesize] [-h home] [-n transactions]\n" +
+ " [-T threads] [-S seed] [-s history] [-t tellers]");
+ System.exit(1);
+ }
+
+ private static void invarg(String str) {
+ System.err.println("TpcbExample: invalid argument: " + str);
+ System.exit(1);
+ }
+
+ public static void errExit(Exception err, String s) {
+ System.err.print(progname + ": ");
+ if (s != null) {
+ System.err.print(s + ": ");
+ }
+ System.err.println(err.toString());
+ System.exit(1);
+ }
+
+ public static void main(String[] argv) throws java.io.IOException {
+ File home = new File("TESTDIR");
+ int accounts = ACCOUNTS;
+ int branches = BRANCHES;
+ int tellers = TELLERS;
+ int history = HISTORY;
+ int threads = 1;
+ int mpool = 0;
+ int ntxns = 0;
+ boolean iflag = false;
+ boolean txn_no_sync = false;
+ long seed = (new GregorianCalendar()).get(Calendar.SECOND);
+
+ for (int i = 0; i < argv.length; ++i) {
+ if (argv[i].equals("-a")) {
+ // Number of account records
+ if ((accounts = Integer.parseInt(argv[++i])) <= 0)
+ invarg(argv[i]);
+ } else if (argv[i].equals("-b")) {
+ // Number of branch records
+ if ((branches = Integer.parseInt(argv[++i])) <= 0)
+ invarg(argv[i]);
+ } else if (argv[i].equals("-c")) {
+ // Cachesize in bytes
+ if ((mpool = Integer.parseInt(argv[++i])) <= 0)
+ invarg(argv[i]);
+ } else if (argv[i].equals("-f")) {
+ // Fast mode: no txn sync.
+ txn_no_sync = true;
+ } else if (argv[i].equals("-h")) {
+ // DB home.
+ home = new File(argv[++i]);
+ } else if (argv[i].equals("-i")) {
+ // Initialize the test.
+ iflag = true;
+ } else if (argv[i].equals("-n")) {
+ // Number of transactions
+ if ((ntxns = Integer.parseInt(argv[++i])) <= 0)
+ invarg(argv[i]);
+ } else if (argv[i].equals("-S")) {
+ // Random number seed.
+ seed = Long.parseLong(argv[++i]);
+ if (seed <= 0)
+ invarg(argv[i]);
+ } else if (argv[i].equals("-s")) {
+ // Number of history records
+ if ((history = Integer.parseInt(argv[++i])) <= 0)
+ invarg(argv[i]);
+ } else if (argv[i].equals("-T")) {
+ // Number of threads
+ if ((threads = Integer.parseInt(argv[++i])) <= 0)
+ invarg(argv[i]);
+ } else if (argv[i].equals("-t")) {
+ // Number of teller records
+ if ((tellers = Integer.parseInt(argv[++i])) <= 0)
+ invarg(argv[i]);
+ } else if (argv[i].equals("-v")) {
+ // Verbose option.
+ verbose = true;
+ } else {
+ usage();
+ }
+ }
+
+ rand.setSeed((int)seed);
+
+ // Initialize the database environment.
+ // Must be done in within a try block.
+ //
+ TpcbExample app = null;
+ try {
+ app = new TpcbExample(home, accounts, branches, tellers, history,
+ mpool, iflag || txn_no_sync);
+ } catch (Exception e1) {
+ errExit(e1, "initializing environment failed");
+ }
+
+ if (verbose)
+ System.out.println((long)accounts + " Accounts, " +
+ String.valueOf(branches) + " Branches, " +
+ String.valueOf(tellers) + " Tellers, " +
+ String.valueOf(history) + " History");
+
+ if (iflag) {
+ if (ntxns != 0)
+ usage();
+ app.populate();
+ } else {
+ if (ntxns == 0)
+ usage();
+ app.run(ntxns, threads);
+ }
+
+ // Shut down the application.
+
+ try {
+ app.close();
+ } catch (DatabaseException dbe2) {
+ errExit(dbe2, "appexit failed");
+ }
+
+ System.exit(0);
+ }
+};
+
+// Simulate the following C struct:
+// struct Defrec {
+// u_int32_t id;
+// u_int32_t balance;
+// u_int8_t pad[RECLEN - sizeof(int) - sizeof(int)];
+// };
+
+class Defrec {
+ public Defrec() {
+ data = new byte[TpcbExample.RECLEN];
+ }
+
+ public int length() {
+ return TpcbExample.RECLEN;
+ }
+
+ public long get_id() {
+ return TpcbExample.get_int_in_array(data, 0);
+ }
+
+ public void set_id(long value) {
+ TpcbExample.set_int_in_array(data, 0, value);
+ }
+
+ public long get_balance() {
+ return TpcbExample.get_int_in_array(data, 4);
+ }
+
+ public void set_balance(long value) {
+ TpcbExample.set_int_in_array(data, 4, value);
+ }
+
+ static {
+ Defrec d = new Defrec();
+ d.set_balance(500000);
+ }
+
+ public byte[] data;
+}
+
+// Simulate the following C struct:
+// struct Histrec {
+// u_int32_t aid;
+// u_int32_t bid;
+// u_int32_t tid;
+// u_int32_t amount;
+// u_int8_t pad[RECLEN - 4 * sizeof(u_int32_t)];
+// };
+
+class Histrec {
+ public Histrec() {
+ data = new byte[TpcbExample.RECLEN];
+ }
+
+ public int length() {
+ return TpcbExample.RECLEN;
+ }
+
+ public long get_aid() {
+ return TpcbExample.get_int_in_array(data, 0);
+ }
+
+ public void set_aid(long value) {
+ TpcbExample.set_int_in_array(data, 0, value);
+ }
+
+ public long get_bid() {
+ return TpcbExample.get_int_in_array(data, 4);
+ }
+
+ public void set_bid(long value) {
+ TpcbExample.set_int_in_array(data, 4, value);
+ }
+
+ public long get_tid() {
+ return TpcbExample.get_int_in_array(data, 8);
+ }
+
+ public void set_tid(long value) {
+ TpcbExample.set_int_in_array(data, 8, value);
+ }
+
+ public long get_amount() {
+ return TpcbExample.get_int_in_array(data, 12);
+ }
+
+ public void set_amount(long value) {
+ TpcbExample.set_int_in_array(data, 12, value);
+ }
+
+ public byte[] data;
+}