/*- * See the file LICENSE for redistribution information. * * Copyright (c) 1997, 2011 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ #include #include #include #include #include #include #include #include #include using std::cout; using std::cerr; #define DATABASE "access.db" #define WORDLIST "../test/tcl/wordlist" const char *progname = "BtRecExample"; // Program name. class BtRecExample { public: BtRecExample(FILE *fp); ~BtRecExample(); void run(); void stats(); void show(const char *msg, Dbt *key, Dbt *data); private: Db *dbp; Dbc *dbcp; }; BtRecExample::BtRecExample(FILE *fp) { char *p, *t, buf[1024], rbuf[1024]; int ret; // Remove the previous database. (void)remove(DATABASE); dbp = new Db(NULL, 0); dbp->set_error_stream(&cerr); dbp->set_errpfx(progname); dbp->set_pagesize(1024); // 1K page sizes. dbp->set_flags(DB_RECNUM); // Record numbers. dbp->open(NULL, DATABASE, NULL, DB_BTREE, DB_CREATE, 0664); // // Insert records into the database, where the key is the word // preceded by its record number, and the data is the same, but // in reverse order. // for (int cnt = 1; cnt <= 1000; ++cnt) { (void)sprintf(buf, "%04d_", cnt); if (fgets(buf + 4, sizeof(buf) - 4, fp) == NULL) break; u_int32_t len = (u_int32_t)strlen(buf); buf[len - 1] = '\0'; for (t = rbuf, p = buf + (len - 2); p >= buf;) *t++ = *p--; *t++ = '\0'; // As a convenience for printing, we include the null terminator // in the stored data. // Dbt key(buf, len); Dbt data(rbuf, len); if ((ret = dbp->put(NULL, &key, &data, DB_NOOVERWRITE)) != 0) { dbp->err(ret, "Db::put"); if (ret != DB_KEYEXIST) throw DbException(ret); } } } BtRecExample::~BtRecExample() { if (dbcp != 0) dbcp->close(); dbp->close(0); delete dbp; } // // Print out the number of records in the database. // void BtRecExample::stats() { DB_BTREE_STAT *statp; dbp->stat(NULL, &statp, 0); cout << progname << ": database contains " << (u_long)statp->bt_ndata << " records\n"; // Note: must use free, not delete. // This struct is allocated by C. // free(statp); } void BtRecExample::run() { db_recno_t recno; int ret; char buf[1024]; // Acquire a cursor for the database. dbp->cursor(NULL, &dbcp, 0); // // Prompt the user for a record number, then retrieve and display // that record. // for (;;) { // Get a record number. cout << "recno #> "; cout.flush(); if (fgets(buf, sizeof(buf), stdin) == NULL) break; recno = atoi(buf); // // Start with a fresh key each time, // the dbp->get() routine returns // the key and data pair, not just the key! // Dbt key(&recno, sizeof(recno)); Dbt data; if ((ret = dbcp->get(&key, &data, DB_SET_RECNO)) != 0) { dbp->err(ret, "DBcursor->get"); throw DbException(ret); } // Display the key and data. show("k/d\t", &key, &data); // Move the cursor a record forward. if ((ret = dbcp->get(&key, &data, DB_NEXT)) != 0) { dbp->err(ret, "DBcursor->get"); throw DbException(ret); } // Display the key and data. show("next\t", &key, &data); // // Retrieve the record number for the following record into // local memory. // data.set_data(&recno); data.set_size(sizeof(recno)); data.set_ulen(sizeof(recno)); data.set_flags(data.get_flags() | DB_DBT_USERMEM); if ((ret = dbcp->get(&key, &data, DB_GET_RECNO)) != 0) { if (ret != DB_NOTFOUND && ret != DB_KEYEMPTY) { dbp->err(ret, "DBcursor->get"); throw DbException(ret); } } else { cout << "retrieved recno: " << (u_long)recno << "\n"; } } dbcp->close(); dbcp = NULL; } // // show -- // Display a key/data pair. // void BtRecExample::show(const char *msg, Dbt *key, Dbt *data) { cout << msg << (char *)key->get_data() << " : " << (char *)data->get_data() << "\n"; } int main() { FILE *fp; // Open the word database. if ((fp = fopen(WORDLIST, "r")) == NULL) { fprintf(stderr, "%s: open %s: %s\n", progname, WORDLIST, db_strerror(errno)); return (EXIT_FAILURE); } try { BtRecExample app(fp); // Close the word database. (void)fclose(fp); fp = NULL; app.stats(); app.run(); } catch (DbException &dbe) { cerr << "Exception: " << dbe.what() << "\n"; return (EXIT_FAILURE); } return (EXIT_SUCCESS); }