1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1997,2008 Oracle. All rights reserved. 5 * 6 * $Id: ex_mpool.c,v 12.8 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#include <time.h> 15 16#ifdef _WIN32 17extern int getopt(int, char * const *, const char *); 18#else 19#include <unistd.h> 20#endif 21 22#include <db.h> 23 24int init __P((const char *, int, int, const char *)); 25int run __P((int, int, int, int, const char *)); 26int run_mpool __P((int, int, int, int, const char *)); 27int main __P((int, char *[])); 28int usage __P((const char *)); 29#define MPOOL "mpool" /* File. */ 30 31int 32main(argc, argv) 33 int argc; 34 char *argv[]; 35{ 36 extern char *optarg; 37 extern int optind; 38 int cachesize, ch, hits, npages, pagesize; 39 char *progname; 40 41 cachesize = 20 * 1024; 42 hits = 1000; 43 npages = 50; 44 pagesize = 1024; 45 progname = argv[0]; 46 while ((ch = getopt(argc, argv, "c:h:n:p:")) != EOF) 47 switch (ch) { 48 case 'c': 49 if ((cachesize = atoi(optarg)) < 20 * 1024) 50 return (usage(progname)); 51 break; 52 case 'h': 53 if ((hits = atoi(optarg)) <= 0) 54 return (usage(progname)); 55 break; 56 case 'n': 57 if ((npages = atoi(optarg)) <= 0) 58 return (usage(progname)); 59 break; 60 case 'p': 61 if ((pagesize = atoi(optarg)) <= 0) 62 return (usage(progname)); 63 break; 64 case '?': 65 default: 66 return (usage(progname)); 67 } 68 argc -= optind; 69 argv += optind; 70 71 return (run_mpool(pagesize, cachesize, 72 hits, npages, progname) == 0 ? EXIT_SUCCESS : EXIT_FAILURE); 73} 74 75int 76usage(progname) 77 const char *progname; 78{ 79 (void)fprintf(stderr, 80 "usage: %s [-c cachesize] [-h hits] [-n npages] [-p pagesize]\n", 81 progname); 82 return (EXIT_FAILURE); 83} 84 85int 86run_mpool(pagesize, cachesize, hits, npages, progname) 87 int pagesize, cachesize, hits, npages; 88 const char *progname; 89{ 90 int ret; 91 92 /* Initialize the file. */ 93 if ((ret = init(MPOOL, pagesize, npages, progname)) != 0) 94 return (ret); 95 96 /* Get the pages. */ 97 if ((ret = run(hits, cachesize, pagesize, npages, progname)) != 0) 98 return (ret); 99 100 return (0); 101} 102 103/* 104 * init -- 105 * Create a backing file. 106 */ 107int 108init(file, pagesize, npages, progname) 109 const char *file, *progname; 110 int pagesize, npages; 111{ 112 FILE *fp; 113 int cnt; 114 char *p; 115 116 /* 117 * Create a file with the right number of pages, and store a page 118 * number on each page. 119 */ 120 (void)remove(file); 121 if ((fp = fopen(file, "wb")) == NULL) { 122 fprintf(stderr, 123 "%s: %s: %s\n", progname, file, strerror(errno)); 124 return (1); 125 } 126 if ((p = (char *)malloc(pagesize)) == NULL) { 127 fprintf(stderr, "%s: %s\n", progname, strerror(ENOMEM)); 128 return (1); 129 } 130 131 /* 132 * The pages are numbered from 0, not 1. 133 * 134 * Write the index of the page at the beginning of the page in order 135 * to verify the retrieved page (see run()). 136 */ 137 for (cnt = 0; cnt < npages; ++cnt) { 138 *(db_pgno_t *)p = cnt; 139 if (fwrite(p, pagesize, 1, fp) != 1) { 140 fprintf(stderr, 141 "%s: %s: %s\n", progname, file, strerror(errno)); 142 return (1); 143 } 144 } 145 146 (void)fclose(fp); 147 free(p); 148 return (0); 149} 150 151/* 152 * run -- 153 * Get a set of pages. 154 */ 155int 156run(hits, cachesize, pagesize, npages, progname) 157 int hits, cachesize, pagesize, npages; 158 const char *progname; 159{ 160 DB_ENV *dbenv; 161 DB_MPOOLFILE *mfp; 162 db_pgno_t pageno; 163 int cnt, ret; 164 void *p; 165 166 dbenv = NULL; 167 mfp = NULL; 168 169 printf("%s: cachesize: %d; pagesize: %d; N pages: %d\n", 170 progname, cachesize, pagesize, npages); 171 172 /* 173 * Open a memory pool, specify a cachesize, output error messages 174 * to stderr. 175 */ 176 if ((ret = db_env_create(&dbenv, 0)) != 0) { 177 fprintf(stderr, 178 "%s: db_env_create: %s\n", progname, db_strerror(ret)); 179 return (1); 180 } 181 dbenv->set_errfile(dbenv, stderr); 182 dbenv->set_errpfx(dbenv, progname); 183#ifdef HAVE_VXWORKS 184 if ((ret = dbenv->set_shm_key(dbenv, VXSHM_KEY)) != 0) { 185 dbenv->err(dbenv, ret, "set_shm_key"); 186 return (1); 187 } 188#endif 189 190 /* Set the cachesize. */ 191 if ((ret = dbenv->set_cachesize(dbenv, 0, cachesize, 0)) != 0) { 192 dbenv->err(dbenv, ret, "set_cachesize"); 193 goto err; 194 } 195 196 /* Open the environment. */ 197 if ((ret = dbenv->open( 198 dbenv, NULL, DB_CREATE | DB_INIT_MPOOL, 0)) != 0) { 199 dbenv->err(dbenv, ret, "DB_ENV->open"); 200 goto err; 201 } 202 203 /* Open the file in the environment. */ 204 if ((ret = dbenv->memp_fcreate(dbenv, &mfp, 0)) != 0) { 205 dbenv->err(dbenv, ret, "DB_ENV->memp_fcreate: %s", MPOOL); 206 goto err; 207 } 208 if ((ret = mfp->open(mfp, MPOOL, 0, 0, pagesize)) != 0) { 209 dbenv->err(dbenv, ret, "DB_MPOOLFILE->open: %s", MPOOL); 210 goto err; 211 } 212 213 printf("retrieve %d random pages... ", hits); 214 215 srand((u_int)time(NULL)); 216 for (cnt = 0; cnt < hits; ++cnt) { 217 pageno = rand() % npages; 218 if ((ret = mfp->get(mfp, &pageno, NULL, 0, &p)) != 0) { 219 dbenv->err(dbenv, ret, 220 "unable to retrieve page %lu", (u_long)pageno); 221 goto err; 222 } 223 /* Verify the page's number that was written in init(). */ 224 if (*(db_pgno_t *)p != pageno) { 225 dbenv->errx(dbenv, 226 "wrong page retrieved (%lu != %d)", 227 (u_long)pageno, *(int *)p); 228 goto err; 229 } 230 if ((ret = mfp->put(mfp, p, DB_PRIORITY_UNCHANGED, 0)) != 0) { 231 dbenv->err(dbenv, ret, 232 "unable to return page %lu", (u_long)pageno); 233 goto err; 234 } 235 } 236 237 printf("successful.\n"); 238 239 /* Close the file. */ 240 if ((ret = mfp->close(mfp, 0)) != 0) { 241 dbenv->err(dbenv, ret, "DB_MPOOLFILE->close"); 242 goto err; 243 } 244 245 /* Close the pool. */ 246 if ((ret = dbenv->close(dbenv, 0)) != 0) { 247 fprintf(stderr, 248 "%s: db_env_create: %s\n", progname, db_strerror(ret)); 249 return (1); 250 } 251 return (0); 252 253err: if (mfp != NULL) 254 (void)mfp->close(mfp, 0); 255 if (dbenv != NULL) 256 (void)dbenv->close(dbenv, 0); 257 return (1); 258} 259