1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1997,2008 Oracle. All rights reserved. 5 * 6 * $Id: ex_btrec.c,v 12.7 2008/01/08 20:58:23 bostic Exp $ 7 */ 8 9#include <sys/types.h> 10 11#include <errno.h> 12#include <stdlib.h> 13#include <string.h> 14 15#include <db.h> 16 17#define DATABASE "access.db" 18#define WORDLIST "../test/wordlist" 19int main __P((void)); 20 21int ex_btrec __P((void)); 22void show __P((const char *, DBT *, DBT *)); 23 24int 25main() 26{ 27 return (ex_btrec() == 1 ? EXIT_FAILURE : EXIT_SUCCESS); 28} 29 30int 31ex_btrec() 32{ 33 DB *dbp; 34 DBC *dbcp; 35 DBT key, data; 36 DB_BTREE_STAT *statp; 37 FILE *fp; 38 db_recno_t recno; 39 size_t len; 40 int cnt, ret; 41 char *p, *t, buf[1024], rbuf[1024]; 42 const char *progname = "ex_btrec"; /* Program name. */ 43 44 /* Open the word database. */ 45 if ((fp = fopen(WORDLIST, "r")) == NULL) { 46 fprintf(stderr, "%s: open %s: %s\n", 47 progname, WORDLIST, db_strerror(errno)); 48 return (1); 49 } 50 51 /* Remove the previous database. */ 52 (void)remove(DATABASE); 53 54 /* Create and initialize database object, open the database. */ 55 if ((ret = db_create(&dbp, NULL, 0)) != 0) { 56 fprintf(stderr, 57 "%s: db_create: %s\n", progname, db_strerror(ret)); 58 return (1); 59 } 60 dbp->set_errfile(dbp, stderr); 61 dbp->set_errpfx(dbp, progname); /* 1K page sizes. */ 62 if ((ret = dbp->set_pagesize(dbp, 1024)) != 0) { 63 dbp->err(dbp, ret, "set_pagesize"); 64 return (1); 65 } /* Record numbers. */ 66 if ((ret = dbp->set_flags(dbp, DB_RECNUM)) != 0) { 67 dbp->err(dbp, ret, "set_flags: DB_RECNUM"); 68 return (1); 69 } 70 if ((ret = dbp->open(dbp, 71 NULL, DATABASE, NULL, DB_BTREE, DB_CREATE, 0664)) != 0) { 72 dbp->err(dbp, ret, "open: %s", DATABASE); 73 return (1); 74 } 75 76 /* 77 * Insert records into the database, where the key is the word 78 * preceded by its record number, and the data is the same, but 79 * in reverse order. 80 */ 81 memset(&key, 0, sizeof(DBT)); 82 memset(&data, 0, sizeof(DBT)); 83 for (cnt = 1; cnt <= 1000; ++cnt) { 84 (void)sprintf(buf, "%04d_", cnt); 85 if (fgets(buf + 4, sizeof(buf) - 4, fp) == NULL) 86 break; 87 len = strlen(buf); 88 for (t = rbuf, p = buf + (len - 2); p >= buf;) 89 *t++ = *p--; 90 *t++ = '\0'; 91 92 key.data = buf; 93 data.data = rbuf; 94 data.size = key.size = (u_int32_t)len - 1; 95 96 if ((ret = 97 dbp->put(dbp, NULL, &key, &data, DB_NOOVERWRITE)) != 0) { 98 dbp->err(dbp, ret, "DB->put"); 99 if (ret != DB_KEYEXIST) 100 goto err1; 101 } 102 } 103 104 /* Close the word database. */ 105 (void)fclose(fp); 106 107 /* Print out the number of records in the database. */ 108 if ((ret = dbp->stat(dbp, NULL, &statp, 0)) != 0) { 109 dbp->err(dbp, ret, "DB->stat"); 110 goto err1; 111 } 112 printf("%s: database contains %lu records\n", 113 progname, (u_long)statp->bt_ndata); 114 free(statp); 115 116 /* Acquire a cursor for the database. */ 117 if ((ret = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) { 118 dbp->err(dbp, ret, "DB->cursor"); 119 goto err1; 120 } 121 122 /* 123 * Prompt the user for a record number, then retrieve and display 124 * that record. 125 */ 126 for (;;) { 127 /* Get a record number. */ 128 printf("recno #> "); 129 fflush(stdout); 130 if (fgets(buf, sizeof(buf), stdin) == NULL) 131 break; 132 recno = atoi(buf); 133 134 /* 135 * Reset the key each time, the dbp->get() routine returns 136 * the key and data pair, not just the key! 137 */ 138 key.data = &recno; 139 key.size = sizeof(recno); 140 if ((ret = dbcp->get(dbcp, &key, &data, DB_SET_RECNO)) != 0) 141 goto get_err; 142 143 /* Display the key and data. */ 144 show("k/d\t", &key, &data); 145 146 /* Move the cursor a record forward. */ 147 if ((ret = dbcp->get(dbcp, &key, &data, DB_NEXT)) != 0) 148 goto get_err; 149 150 /* Display the key and data. */ 151 show("next\t", &key, &data); 152 153 /* 154 * Retrieve the record number for the following record into 155 * local memory. 156 */ 157 data.data = &recno; 158 data.size = sizeof(recno); 159 data.ulen = sizeof(recno); 160 data.flags |= DB_DBT_USERMEM; 161 if ((ret = dbcp->get(dbcp, &key, &data, DB_GET_RECNO)) != 0) { 162get_err: dbp->err(dbp, ret, "DBcursor->get"); 163 if (ret != DB_NOTFOUND && ret != DB_KEYEMPTY) 164 goto err2; 165 } else 166 printf("retrieved recno: %lu\n", (u_long)recno); 167 168 /* Reset the data DBT. */ 169 memset(&data, 0, sizeof(data)); 170 } 171 172 if ((ret = dbcp->close(dbcp)) != 0) { 173 dbp->err(dbp, ret, "DBcursor->close"); 174 goto err1; 175 } 176 if ((ret = dbp->close(dbp, 0)) != 0) { 177 fprintf(stderr, 178 "%s: DB->close: %s\n", progname, db_strerror(ret)); 179 return (1); 180 } 181 182 return (0); 183 184err2: (void)dbcp->close(dbcp); 185err1: (void)dbp->close(dbp, 0); 186 return (ret); 187 188} 189 190/* 191 * show -- 192 * Display a key/data pair. 193 */ 194void 195show(msg, key, data) 196 const char *msg; 197 DBT *key, *data; 198{ 199 printf("%s%.*s : %.*s\n", msg, 200 (int)key->size, (char *)key->data, 201 (int)data->size, (char *)data->data); 202} 203