1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1996,2008 Oracle. All rights reserved. 5 * 6 * $Id: ex_dbclient.c,v 12.7 2008/01/08 20:58:23 bostic Exp $ 7 */ 8 9#include <sys/types.h> 10 11#include <stdio.h> 12#include <stdlib.h> 13#include <string.h> 14#include <unistd.h> 15 16#include <db.h> 17 18#define DATABASE_HOME "database" 19 20#define DATABASE "access.db" 21 22int db_clientrun __P((DB_ENV *, const char *)); 23int ex_dbclient __P((const char *)); 24int ex_dbclient_run __P((const char *, FILE *, const char *, const char *)); 25int main __P((int, char *[])); 26 27/* 28 * An example of a program creating/configuring a Berkeley DB environment. 29 */ 30int 31main(argc, argv) 32 int argc; 33 char *argv[]; 34{ 35 const char *home; 36 37 if (argc != 2) { 38 fprintf(stderr, "Usage: %s hostname\n", argv[0]); 39 return (EXIT_FAILURE); 40 } 41 42 /* 43 * All of the shared database files live in DATABASE_HOME, but 44 * data files will live in CONFIG_DATA_DIR. 45 */ 46 home = DATABASE_HOME; 47 return (ex_dbclient_run(home, 48 stderr, argv[1], argv[0]) == 0 ? EXIT_SUCCESS : EXIT_FAILURE); 49} 50 51int 52ex_dbclient(host) 53 const char *host; 54{ 55 const char *home; 56 const char *progname = "ex_dbclient"; /* Program name. */ 57 int ret; 58 59 /* 60 * All of the shared database files live in DATABASE_HOME, but 61 * data files will live in CONFIG_DATA_DIR. 62 */ 63 home = DATABASE_HOME; 64 65 if ((ret = ex_dbclient_run(home, stderr, host, progname)) != 0) 66 return (ret); 67 68 return (0); 69} 70 71int 72ex_dbclient_run(home, errfp, host, progname) 73 const char *home, *host, *progname; 74 FILE *errfp; 75{ 76 DB_ENV *dbenv; 77 int ret, retry; 78 79 /* 80 * Create an environment object and initialize it for error 81 * reporting. 82 */ 83 if ((ret = db_env_create(&dbenv, DB_RPCCLIENT)) != 0) { 84 fprintf(errfp, "%s: %s\n", progname, db_strerror(ret)); 85 return (1); 86 } 87 retry = 0; 88loop: 89 while (retry < 5) { 90 /* 91 * Set the server host we are talking to. 92 */ 93 if ((ret = dbenv->set_rpc_server(dbenv, NULL, host, 10000, 94 10000, 0)) != 0) { 95 fprintf(stderr, "Try %d: DB_ENV->set_rpc_server: %s\n", 96 retry, db_strerror(ret)); 97 retry++; 98 sleep(15); 99 } else 100 break; 101 } 102 103 if (retry >= 5) { 104 fprintf(stderr, 105 "DB_ENV->set_rpc_server: %s\n", db_strerror(ret)); 106 dbenv->close(dbenv, 0); 107 return (1); 108 } 109 /* 110 * We want to specify the shared memory buffer pool cachesize, 111 * but everything else is the default. 112 */ 113 if ((ret = dbenv->set_cachesize(dbenv, 0, 64 * 1024, 0)) != 0) { 114 dbenv->err(dbenv, ret, "set_cachesize"); 115 dbenv->close(dbenv, 0); 116 return (1); 117 } 118 /* 119 * We have multiple processes reading/writing these files, so 120 * we need concurrency control and a shared buffer pool, but 121 * not logging or transactions. 122 */ 123 if ((ret = dbenv->open(dbenv, home, 124 DB_CREATE | DB_INIT_LOCK | DB_INIT_MPOOL, 0)) != 0) { 125 dbenv->err(dbenv, ret, "environment open: %s", home); 126 dbenv->close(dbenv, 0); 127 if (ret == DB_NOSERVER) 128 goto loop; 129 return (1); 130 } 131 132 ret = db_clientrun(dbenv, progname); 133 printf("db_clientrun returned %d\n", ret); 134 if (ret == DB_NOSERVER) 135 goto loop; 136 137 /* Close the handle. */ 138 if ((ret = dbenv->close(dbenv, 0)) != 0) { 139 fprintf(stderr, "DB_ENV->close: %s\n", db_strerror(ret)); 140 return (1); 141 } 142 return (0); 143} 144 145int 146db_clientrun(dbenv, progname) 147 DB_ENV *dbenv; 148 const char *progname; 149{ 150 DB *dbp; 151 DBT key, data; 152 u_int32_t len; 153 int ret; 154 char *p, *t, buf[1024], rbuf[1024]; 155 156 /* Remove the previous database. */ 157 158 /* Create and initialize database object, open the database. */ 159 if ((ret = db_create(&dbp, dbenv, 0)) != 0) { 160 fprintf(stderr, 161 "%s: db_create: %s\n", progname, db_strerror(ret)); 162 return (ret); 163 } 164 if ((ret = dbp->set_pagesize(dbp, 1024)) != 0) { 165 dbp->err(dbp, ret, "set_pagesize"); 166 goto err1; 167 } 168 if ((ret = dbp->open(dbp, 169 NULL, DATABASE, NULL, DB_BTREE, DB_CREATE, 0664)) != 0) { 170 dbp->err(dbp, ret, "%s: open", DATABASE); 171 goto err1; 172 } 173 174 /* 175 * Insert records into the database, where the key is the user 176 * input and the data is the user input in reverse order. 177 */ 178 memset(&key, 0, sizeof(DBT)); 179 memset(&data, 0, sizeof(DBT)); 180 for (;;) { 181 printf("input> "); 182 fflush(stdout); 183 if (fgets(buf, sizeof(buf), stdin) == NULL) 184 break; 185 if ((len = strlen(buf)) <= 1) 186 continue; 187 for (t = rbuf, p = buf + (len - 2); p >= buf;) 188 *t++ = *p--; 189 *t++ = '\0'; 190 191 key.data = buf; 192 data.data = rbuf; 193 data.size = key.size = len - 1; 194 195 switch (ret = 196 dbp->put(dbp, NULL, &key, &data, DB_NOOVERWRITE)) { 197 case 0: 198 break; 199 default: 200 dbp->err(dbp, ret, "DB->put"); 201 if (ret != DB_KEYEXIST) 202 goto err1; 203 break; 204 } 205 memset(&data, 0, sizeof(DBT)); 206 switch (ret = dbp->get(dbp, NULL, &key, &data, 0)) { 207 case 0: 208 printf("%.*s : %.*s\n", 209 (int)key.size, (char *)key.data, 210 (int)data.size, (char *)data.data); 211 break; 212 default: 213 dbp->err(dbp, ret, "DB->get"); 214 break; 215 } 216 } 217 if ((ret = dbp->close(dbp, 0)) != 0) { 218 fprintf(stderr, 219 "%s: DB->close: %s\n", progname, db_strerror(ret)); 220 return (1); 221 } 222 return (0); 223 224err1: (void)dbp->close(dbp, 0); 225 return (ret); 226} 227