1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1997-2009 Oracle. All rights reserved. 5 * 6 * $Id$ 7 */ 8 9#include <sys/types.h> 10 11#include <errno.h> 12#include <iostream> 13#include <iomanip> 14#include <stddef.h> 15#include <stdio.h> 16#include <stdlib.h> 17#include <string.h> 18 19#include <db_cxx.h> 20 21using std::cout; 22using std::cerr; 23 24#define DATABASE "access.db" 25#define WORDLIST "../test/wordlist" 26 27const char *progname = "BtRecExample"; // Program name. 28 29class BtRecExample 30{ 31public: 32 BtRecExample(FILE *fp); 33 ~BtRecExample(); 34 void run(); 35 void stats(); 36 void show(const char *msg, Dbt *key, Dbt *data); 37 38private: 39 Db *dbp; 40 Dbc *dbcp; 41}; 42 43BtRecExample::BtRecExample(FILE *fp) 44{ 45 char *p, *t, buf[1024], rbuf[1024]; 46 int ret; 47 48 // Remove the previous database. 49 (void)remove(DATABASE); 50 51 dbp = new Db(NULL, 0); 52 53 dbp->set_error_stream(&cerr); 54 dbp->set_errpfx(progname); 55 dbp->set_pagesize(1024); // 1K page sizes. 56 57 dbp->set_flags(DB_RECNUM); // Record numbers. 58 dbp->open(NULL, DATABASE, NULL, DB_BTREE, DB_CREATE, 0664); 59 60 // 61 // Insert records into the database, where the key is the word 62 // preceded by its record number, and the data is the same, but 63 // in reverse order. 64 // 65 66 for (int cnt = 1; cnt <= 1000; ++cnt) { 67 (void)sprintf(buf, "%04d_", cnt); 68 if (fgets(buf + 4, sizeof(buf) - 4, fp) == NULL) 69 break; 70 u_int32_t len = (u_int32_t)strlen(buf); 71 buf[len - 1] = '\0'; 72 for (t = rbuf, p = buf + (len - 2); p >= buf;) 73 *t++ = *p--; 74 *t++ = '\0'; 75 76 // As a convenience for printing, we include the null terminator 77 // in the stored data. 78 // 79 Dbt key(buf, len); 80 Dbt data(rbuf, len); 81 82 if ((ret = dbp->put(NULL, &key, &data, DB_NOOVERWRITE)) != 0) { 83 dbp->err(ret, "Db::put"); 84 if (ret != DB_KEYEXIST) 85 throw DbException(ret); 86 } 87 } 88} 89 90BtRecExample::~BtRecExample() 91{ 92 if (dbcp != 0) 93 dbcp->close(); 94 dbp->close(0); 95 delete dbp; 96} 97 98// 99// Print out the number of records in the database. 100// 101void BtRecExample::stats() 102{ 103 DB_BTREE_STAT *statp; 104 105 dbp->stat(NULL, &statp, 0); 106 cout << progname << ": database contains " 107 << (u_long)statp->bt_ndata << " records\n"; 108 109 // Note: must use free, not delete. 110 // This struct is allocated by C. 111 // 112 free(statp); 113} 114 115void BtRecExample::run() 116{ 117 db_recno_t recno; 118 int ret; 119 char buf[1024]; 120 121 // Acquire a cursor for the database. 122 dbp->cursor(NULL, &dbcp, 0); 123 124 // 125 // Prompt the user for a record number, then retrieve and display 126 // that record. 127 // 128 for (;;) { 129 // Get a record number. 130 cout << "recno #> "; 131 cout.flush(); 132 if (fgets(buf, sizeof(buf), stdin) == NULL) 133 break; 134 recno = atoi(buf); 135 136 // 137 // Start with a fresh key each time, 138 // the dbp->get() routine returns 139 // the key and data pair, not just the key! 140 // 141 Dbt key(&recno, sizeof(recno)); 142 Dbt data; 143 144 if ((ret = dbcp->get(&key, &data, DB_SET_RECNO)) != 0) { 145 dbp->err(ret, "DBcursor->get"); 146 throw DbException(ret); 147 } 148 149 // Display the key and data. 150 show("k/d\t", &key, &data); 151 152 // Move the cursor a record forward. 153 if ((ret = dbcp->get(&key, &data, DB_NEXT)) != 0) { 154 dbp->err(ret, "DBcursor->get"); 155 throw DbException(ret); 156 } 157 158 // Display the key and data. 159 show("next\t", &key, &data); 160 161 // 162 // Retrieve the record number for the following record into 163 // local memory. 164 // 165 data.set_data(&recno); 166 data.set_size(sizeof(recno)); 167 data.set_ulen(sizeof(recno)); 168 data.set_flags(data.get_flags() | DB_DBT_USERMEM); 169 170 if ((ret = dbcp->get(&key, &data, DB_GET_RECNO)) != 0) { 171 if (ret != DB_NOTFOUND && ret != DB_KEYEMPTY) { 172 dbp->err(ret, "DBcursor->get"); 173 throw DbException(ret); 174 } 175 } 176 else { 177 cout << "retrieved recno: " << (u_long)recno << "\n"; 178 } 179 } 180 181 dbcp->close(); 182 dbcp = NULL; 183} 184 185// 186// show -- 187// Display a key/data pair. 188// 189void BtRecExample::show(const char *msg, Dbt *key, Dbt *data) 190{ 191 cout << msg << (char *)key->get_data() 192 << " : " << (char *)data->get_data() << "\n"; 193} 194 195int 196main() 197{ 198 FILE *fp; 199 200 // Open the word database. 201 if ((fp = fopen(WORDLIST, "r")) == NULL) { 202 fprintf(stderr, "%s: open %s: %s\n", 203 progname, WORDLIST, db_strerror(errno)); 204 return (EXIT_FAILURE); 205 } 206 207 try { 208 BtRecExample app(fp); 209 210 // Close the word database. 211 (void)fclose(fp); 212 fp = NULL; 213 214 app.stats(); 215 app.run(); 216 } 217 catch (DbException &dbe) { 218 cerr << "Exception: " << dbe.what() << "\n"; 219 return (EXIT_FAILURE); 220 } 221 222 return (EXIT_SUCCESS); 223} 224