00001
00005 #include "system.h"
00006
00007 #include <rpmlib.h>
00008 #include <rpmmacro.h>
00009
00010 #include "rpmdb.h"
00011 #include "debug.h"
00012
00013
00014
00015
00016
00017 #if (DB_VERSION_MAJOR == 3) || (DB_VERSION_MAJOR == 4)
00018 #define __USE_DB3 1
00019
00020
00021
00022 struct _dbiIndex db3dbi;
00023
00024
00025
00026 static int dbi_use_cursors;
00027
00028
00029 static int dbi_tear_down;
00030
00031
00034
00035 struct poptOption rdbOptions[] = {
00036
00037 { "client", 0,POPT_BIT_SET, &db3dbi.dbi_ecflags, DB_CLIENT,
00038 NULL, NULL },
00039
00040 { "xa_create", 0,POPT_BIT_SET, &db3dbi.dbi_cflags, DB_XA_CREATE,
00041 NULL, NULL },
00042
00043 { "create", 0,POPT_BIT_SET, &db3dbi.dbi_oeflags, DB_CREATE,
00044 NULL, NULL },
00045 { "thread", 0,POPT_BIT_SET, &db3dbi.dbi_oeflags, DB_THREAD,
00046 NULL, NULL },
00047
00048 { "force", 0,POPT_BIT_SET, &db3dbi.dbi_eflags, DB_FORCE,
00049 NULL, NULL },
00050 { "cdb", 0,POPT_BIT_SET, &db3dbi.dbi_eflags, DB_INIT_CDB,
00051 NULL, NULL },
00052 { "lock", 0,POPT_BIT_SET, &db3dbi.dbi_eflags, DB_INIT_LOCK,
00053 NULL, NULL },
00054 { "log", 0,POPT_BIT_SET, &db3dbi.dbi_eflags, DB_INIT_LOG,
00055 NULL, NULL },
00056 { "mpool", 0,POPT_BIT_SET, &db3dbi.dbi_eflags, DB_INIT_MPOOL,
00057 NULL, NULL },
00058 { "txn", 0,POPT_BIT_SET, &db3dbi.dbi_eflags, DB_INIT_TXN,
00059 NULL, NULL },
00060 { "joinenv", 0,POPT_BIT_SET, &db3dbi.dbi_eflags, DB_JOINENV,
00061 NULL, NULL },
00062 { "recover", 0,POPT_BIT_SET, &db3dbi.dbi_eflags, DB_RECOVER,
00063 NULL, NULL },
00064 { "recover_fatal", 0,POPT_BIT_SET, &db3dbi.dbi_eflags, DB_RECOVER_FATAL,
00065 NULL, NULL },
00066 { "shared", 0,POPT_BIT_SET, &db3dbi.dbi_eflags, DB_SYSTEM_MEM,
00067 NULL, NULL },
00068 { "txn_nosync", 0,POPT_BIT_SET, &db3dbi.dbi_eflags, DB_TXN_NOSYNC,
00069 NULL, NULL },
00070 { "use_environ_root", 0,POPT_BIT_SET, &db3dbi.dbi_eflags, DB_USE_ENVIRON_ROOT,
00071 NULL, NULL },
00072 { "use_environ", 0,POPT_BIT_SET, &db3dbi.dbi_eflags, DB_USE_ENVIRON,
00073 NULL, NULL },
00074 { "lockdown", 0,POPT_BIT_SET, &db3dbi.dbi_eflags, DB_LOCKDOWN,
00075 NULL, NULL },
00076 { "private", 0,POPT_BIT_SET, &db3dbi.dbi_eflags, DB_PRIVATE,
00077 NULL, NULL },
00078
00079 { "txn_sync", 0,POPT_BIT_SET, &db3dbi.dbi_tflags, DB_TXN_SYNC,
00080 NULL, NULL },
00081 { "txn_nowait",0,POPT_BIT_SET, &db3dbi.dbi_tflags, DB_TXN_NOWAIT,
00082 NULL, NULL },
00083
00084 { "excl", 0,POPT_BIT_SET, &db3dbi.dbi_oflags, DB_EXCL,
00085 NULL, NULL },
00086 { "nommap", 0,POPT_BIT_SET, &db3dbi.dbi_oflags, DB_NOMMAP,
00087 NULL, NULL },
00088 { "rdonly", 0,POPT_BIT_SET, &db3dbi.dbi_oflags, DB_RDONLY,
00089 NULL, NULL },
00090 { "truncate", 0,POPT_BIT_SET, &db3dbi.dbi_oflags, DB_TRUNCATE,
00091 NULL, NULL },
00092 { "fcntl_locking",0,POPT_BIT_SET, &db3dbi.dbi_oflags, DB_FCNTL_LOCKING,
00093 NULL, NULL },
00094
00095 { "btree", 0,POPT_ARG_VAL, &db3dbi.dbi_type, DB_BTREE,
00096 NULL, NULL },
00097 { "hash", 0,POPT_ARG_VAL, &db3dbi.dbi_type, DB_HASH,
00098 NULL, NULL },
00099 { "recno", 0,POPT_ARG_VAL, &db3dbi.dbi_type, DB_RECNO,
00100 NULL, NULL },
00101 { "queue", 0,POPT_ARG_VAL, &db3dbi.dbi_type, DB_QUEUE,
00102 NULL, NULL },
00103 { "unknown", 0,POPT_ARG_VAL, &db3dbi.dbi_type, DB_UNKNOWN,
00104 NULL, NULL },
00105
00106 { "root", 0,POPT_ARG_STRING, &db3dbi.dbi_root, 0,
00107 NULL, NULL },
00108 { "home", 0,POPT_ARG_STRING, &db3dbi.dbi_home, 0,
00109 NULL, NULL },
00110 { "file", 0,POPT_ARG_STRING, &db3dbi.dbi_file, 0,
00111 NULL, NULL },
00112 { "subfile", 0,POPT_ARG_STRING, &db3dbi.dbi_subfile, 0,
00113 NULL, NULL },
00114 { "mode", 0,POPT_ARG_INT, &db3dbi.dbi_mode, 0,
00115 NULL, NULL },
00116 { "perms", 0,POPT_ARG_INT, &db3dbi.dbi_perms, 0,
00117 NULL, NULL },
00118 { "shmkey", 0,POPT_ARG_LONG, &db3dbi.dbi_shmkey, 0,
00119 NULL, NULL },
00120 { "tmpdir", 0,POPT_ARG_STRING, &db3dbi.dbi_tmpdir, 0,
00121 NULL, NULL },
00122
00123 { "host", 0,POPT_ARG_STRING, &db3dbi.dbi_host, 0,
00124 NULL, NULL },
00125 { "server", 0,POPT_ARG_STRING, &db3dbi.dbi_host, 0,
00126 NULL, NULL },
00127 { "cl_timeout", 0,POPT_ARG_LONG, &db3dbi.dbi_cl_timeout, 0,
00128 NULL, NULL },
00129 { "sv_timeout", 0,POPT_ARG_LONG, &db3dbi.dbi_sv_timeout, 0,
00130 NULL, NULL },
00131
00132 { "verify", 0,POPT_ARG_NONE, &db3dbi.dbi_verify_on_close, 0,
00133 NULL, NULL },
00134 { "teardown", 0,POPT_ARG_NONE, &dbi_tear_down, 0,
00135 NULL, NULL },
00136 { "usecursors",0,POPT_ARG_NONE, &dbi_use_cursors, 0,
00137 NULL, NULL },
00138 { "usedbenv", 0,POPT_ARG_NONE, &db3dbi.dbi_use_dbenv, 0,
00139 NULL, NULL },
00140 { "nofsync", 0,POPT_ARG_NONE, &db3dbi.dbi_no_fsync, 0,
00141 NULL, NULL },
00142 { "nodbsync", 0,POPT_ARG_NONE, &db3dbi.dbi_no_dbsync, 0,
00143 NULL, NULL },
00144 { "lockdbfd", 0,POPT_ARG_NONE, &db3dbi.dbi_lockdbfd, 0,
00145 NULL, NULL },
00146 { "temporary", 0,POPT_ARG_NONE, &db3dbi.dbi_temporary, 0,
00147 NULL, NULL },
00148 { "debug", 0,POPT_ARG_NONE, &db3dbi.dbi_debug, 0,
00149 NULL, NULL },
00150
00151 { "cachesize", 0,POPT_ARG_INT, &db3dbi.dbi_cachesize, 0,
00152 NULL, NULL },
00153 { "errpfx", 0,POPT_ARG_STRING, &db3dbi.dbi_errpfx, 0,
00154 NULL, NULL },
00155 { "region_init", 0,POPT_ARG_VAL, &db3dbi.dbi_region_init, 1,
00156 NULL, NULL },
00157 { "tas_spins", 0,POPT_ARG_INT, &db3dbi.dbi_tas_spins, 0,
00158 NULL, NULL },
00159
00160 { "chkpoint", 0,POPT_BIT_SET, &db3dbi.dbi_verbose, DB_VERB_CHKPOINT,
00161 NULL, NULL },
00162 { "deadlock", 0,POPT_BIT_SET, &db3dbi.dbi_verbose, DB_VERB_DEADLOCK,
00163 NULL, NULL },
00164 { "recovery", 0,POPT_BIT_SET, &db3dbi.dbi_verbose, DB_VERB_RECOVERY,
00165 NULL, NULL },
00166 { "waitsfor", 0,POPT_BIT_SET, &db3dbi.dbi_verbose, DB_VERB_WAITSFOR,
00167 NULL, NULL },
00168 { "verbose", 0,POPT_ARG_VAL, &db3dbi.dbi_verbose, -1,
00169 NULL, NULL },
00170
00171 { "lk_oldest", 0,POPT_ARG_VAL, &db3dbi.dbi_lk_detect, DB_LOCK_OLDEST,
00172 NULL, NULL },
00173 { "lk_random", 0,POPT_ARG_VAL, &db3dbi.dbi_lk_detect, DB_LOCK_RANDOM,
00174 NULL, NULL },
00175 { "lk_youngest",0, POPT_ARG_VAL, &db3dbi.dbi_lk_detect, DB_LOCK_YOUNGEST,
00176 NULL, NULL },
00177
00178 { "lk_max", 0,POPT_ARG_INT, &db3dbi.dbi_lk_max, 0,
00179 NULL, NULL },
00180
00181 { "lg_bsize", 0,POPT_ARG_INT, &db3dbi.dbi_lg_bsize, 0,
00182 NULL, NULL },
00183 { "lg_max", 0,POPT_ARG_INT, &db3dbi.dbi_lg_max, 0,
00184 NULL, NULL },
00185
00186
00187 { "tx_max", 0,POPT_ARG_INT, &db3dbi.dbi_tx_max, 0,
00188 NULL, NULL },
00189
00190 { "lorder", 0,POPT_ARG_INT, &db3dbi.dbi_lorder, 0,
00191 NULL, NULL },
00192
00193 { "mmapsize", 0,POPT_ARG_INT, &db3dbi.dbi_mmapsize, 0,
00194 NULL, NULL },
00195 { "mp_mmapsize", 0,POPT_ARG_INT, &db3dbi.dbi_mmapsize, 0,
00196 NULL, NULL },
00197 { "mp_size", 0,POPT_ARG_INT, &db3dbi.dbi_cachesize, 0,
00198 NULL, NULL },
00199 { "pagesize", 0,POPT_ARG_INT, &db3dbi.dbi_pagesize, 0,
00200 NULL, NULL },
00201
00202
00203
00204
00205
00206 { "bt_dup", 0,POPT_BIT_SET, &db3dbi.dbi_bt_flags, DB_DUP,
00207 NULL, NULL },
00208 { "bt_dupsort",0,POPT_BIT_SET, &db3dbi.dbi_bt_flags, DB_DUPSORT,
00209 NULL, NULL },
00210 { "bt_recnum", 0,POPT_BIT_SET, &db3dbi.dbi_bt_flags, DB_RECNUM,
00211 NULL, NULL },
00212 { "bt_revsplitoff", 0,POPT_BIT_SET, &db3dbi.dbi_bt_flags, DB_REVSPLITOFF,
00213 NULL, NULL },
00214
00215 { "h_dup", 0,POPT_BIT_SET, &db3dbi.dbi_h_flags, DB_DUP,
00216 NULL, NULL },
00217 { "h_dupsort", 0,POPT_BIT_SET, &db3dbi.dbi_h_flags, DB_DUPSORT,
00218 NULL, NULL },
00219 { "h_ffactor", 0,POPT_ARG_INT, &db3dbi.dbi_h_ffactor, 0,
00220 NULL, NULL },
00221 { "h_nelem", 0,POPT_ARG_INT, &db3dbi.dbi_h_nelem, 0,
00222 NULL, NULL },
00223
00224 { "re_renumber", 0,POPT_BIT_SET, &db3dbi.dbi_re_flags, DB_RENUMBER,
00225 NULL, NULL },
00226 { "re_snapshot",0,POPT_BIT_SET, &db3dbi.dbi_re_flags, DB_SNAPSHOT,
00227 NULL, NULL },
00228 { "re_delim", 0,POPT_ARG_INT, &db3dbi.dbi_re_delim, 0,
00229 NULL, NULL },
00230 { "re_len", 0,POPT_ARG_INT, &db3dbi.dbi_re_len, 0,
00231 NULL, NULL },
00232 { "re_pad", 0,POPT_ARG_INT, &db3dbi.dbi_re_pad, 0,
00233 NULL, NULL },
00234 { "re_source", 0,POPT_ARG_STRING, &db3dbi.dbi_re_source, 0,
00235 NULL, NULL },
00236
00237 { "q_extentsize", 0,POPT_ARG_INT, &db3dbi.dbi_q_extentsize, 0,
00238 NULL, NULL },
00239
00240 POPT_TABLEEND
00241 };
00242
00243
00244 dbiIndex db3Free(dbiIndex dbi)
00245 {
00246 if (dbi) {
00247 dbi->dbi_root = _free(dbi->dbi_root);
00248 dbi->dbi_home = _free(dbi->dbi_home);
00249 dbi->dbi_file = _free(dbi->dbi_file);
00250 dbi->dbi_subfile = _free(dbi->dbi_subfile);
00251 dbi->dbi_tmpdir = _free(dbi->dbi_tmpdir);
00252 dbi->dbi_host = _free(dbi->dbi_host);
00253 dbi->dbi_errpfx = _free(dbi->dbi_errpfx);
00254 dbi->dbi_re_source = _free(dbi->dbi_re_source);
00255 dbi->dbi_stats = _free(dbi->dbi_stats);
00256 dbi = _free(dbi);
00257 }
00258 return dbi;
00259 }
00260
00262
00263 static const char *db3_config_default =
00264 "db3:hash:mpool:cdb:usecursors:verbose:mp_mmapsize=8Mb:cachesize=512Kb:pagesize=512:perms=0644";
00265
00266
00267 dbiIndex db3New(rpmdb rpmdb, rpmTag rpmtag)
00268 {
00269 dbiIndex dbi = xcalloc(1, sizeof(*dbi));
00270 char dbiTagMacro[128];
00271 char * dbOpts;
00272
00273 sprintf(dbiTagMacro, "%%{_dbi_config_%s}", tagName(rpmtag));
00274 dbOpts = rpmExpand(dbiTagMacro, NULL);
00275 if (!(dbOpts && *dbOpts && *dbOpts != '%')) {
00276 dbOpts = _free(dbOpts);
00277 dbOpts = rpmExpand("%{_dbi_config}", NULL);
00278 if (!(dbOpts && *dbOpts && *dbOpts != '%')) {
00279 dbOpts = rpmExpand(db3_config_default, NULL);
00280 }
00281 }
00282
00283
00284
00285 if (dbOpts && *dbOpts && *dbOpts != '%') {
00286 char *o, *oe;
00287 char *p, *pe;
00288
00289 memset(&db3dbi, 0, sizeof(db3dbi));
00290
00291 for (o = dbOpts; o && *o; o = oe) {
00292 struct poptOption *opt;
00293 const char * tok;
00294 int argInfo;
00295
00296
00297 while (*o && xisspace(*o))
00298 o++;
00299
00300
00301 for (oe = o; oe && *oe; oe++) {
00302 if (xisspace(*oe))
00303 break;
00304 if (oe[0] == ':' && !(oe[1] == '/' && oe[2] == '/'))
00305 break;
00306 }
00307 if (oe && *oe)
00308 *oe++ = '\0';
00309 if (*o == '\0')
00310 continue;
00311
00312
00313 for (pe = o; pe && *pe && *pe != '='; pe++)
00314 {};
00315 p = (pe ? *pe++ = '\0', pe : NULL);
00316
00317
00318 for (tok = o; *tok == '!'; tok++)
00319 {};
00320
00321
00322 for (opt = rdbOptions; opt->longName != NULL; opt++) {
00323 if (strcmp(tok, opt->longName))
00324 continue;
00325 break;
00326 }
00327 if (opt->longName == NULL) {
00328 rpmError(RPMERR_DBCONFIG,
00329 _("unrecognized db option: \"%s\" ignored.\n"), o);
00330 continue;
00331 }
00332
00333
00334 argInfo = opt->argInfo;
00335 if (argInfo == POPT_BIT_SET && *o == '!' && ((tok - o) % 2))
00336 argInfo = POPT_BIT_CLR;
00337
00338
00339 switch (argInfo & POPT_ARG_MASK) {
00340
00341 case POPT_ARG_NONE:
00342 (void) poptSaveInt((int *)opt->arg, argInfo, 1L);
00343 break;
00344 case POPT_ARG_VAL:
00345 (void) poptSaveInt((int *)opt->arg, argInfo, (long)opt->val);
00346 break;
00347 case POPT_ARG_STRING:
00348 { const char ** t = opt->arg;
00349
00350 if (t) {
00351
00352 *t = _free(*t);
00353
00354 *t = xstrdup( (p ? p : "") );
00355 }
00356
00357 } break;
00358
00359 case POPT_ARG_INT:
00360 case POPT_ARG_LONG:
00361 { long aLong = strtol(p, &pe, 0);
00362 if (pe) {
00363 if (!xstrncasecmp(pe, "Mb", 2))
00364 aLong *= 1024 * 1024;
00365 else if (!xstrncasecmp(pe, "Kb", 2))
00366 aLong *= 1024;
00367 else if (*pe != '\0') {
00368 rpmError(RPMERR_DBCONFIG,
00369 _("%s has invalid numeric value, skipped\n"),
00370 opt->longName);
00371 continue;
00372 }
00373 }
00374
00375 if ((argInfo & POPT_ARG_MASK) == POPT_ARG_LONG) {
00376 if (aLong == LONG_MIN || aLong == LONG_MAX) {
00377 rpmError(RPMERR_DBCONFIG,
00378 _("%s has too large or too small long value, skipped\n"),
00379 opt->longName);
00380 continue;
00381 }
00382 (void) poptSaveLong((long *)opt->arg, argInfo, aLong);
00383 break;
00384 } else {
00385 if (aLong > INT_MAX || aLong < INT_MIN) {
00386 rpmError(RPMERR_DBCONFIG,
00387 _("%s has too large or too small integer value, skipped\n"),
00388 opt->longName);
00389 continue;
00390 }
00391 (void) poptSaveInt((int *)opt->arg, argInfo, aLong);
00392 }
00393 } break;
00394 default:
00395 break;
00396 }
00397 }
00398
00399 }
00400
00401
00402 dbOpts = _free(dbOpts);
00403
00404
00405 *dbi = db3dbi;
00406
00407 memset(&db3dbi, 0, sizeof(db3dbi));
00408
00409 if (!(dbi->dbi_perms & 0600))
00410 dbi->dbi_perms = 0644;
00411 dbi->dbi_mode = rpmdb->db_mode;
00412
00413 dbi->dbi_rpmdb = rpmdb;
00414
00415 dbi->dbi_rpmtag = rpmtag;
00416
00417
00418
00419
00420
00421 switch (rpmtag) {
00422 case RPMDBI_PACKAGES:
00423 case RPMDBI_DEPENDS:
00424 dbi->dbi_jlen = 1 * sizeof(int_32);
00425 break;
00426 default:
00427 dbi->dbi_jlen = 2 * sizeof(int_32);
00428 break;
00429 }
00430
00431
00432 dbi->dbi_byteswapped = 0;
00433
00434 if (!dbi->dbi_use_dbenv) {
00435 dbi->dbi_use_dbenv = 1;
00436 dbi->dbi_eflags |= (DB_INIT_MPOOL|DB_JOINENV);
00437 dbi->dbi_mmapsize = 16 * 1024 * 1024;
00438 dbi->dbi_cachesize = 1 * 1024 * 1024;
00439 }
00440
00441 if ((dbi->dbi_bt_flags | dbi->dbi_h_flags) & DB_DUP)
00442 dbi->dbi_permit_dups = 1;
00443
00444
00445 return dbi;
00446
00447 }
00448
00449
00450
00451 const char *const prDbiOpenFlags(int dbflags, int print_dbenv_flags)
00452 {
00453 static char buf[256];
00454 struct poptOption *opt;
00455 char * oe;
00456
00457 oe = buf;
00458 *oe = '\0';
00459 for (opt = rdbOptions; opt->longName != NULL; opt++) {
00460 if (opt->argInfo != POPT_BIT_SET)
00461 continue;
00462 if (print_dbenv_flags) {
00463 if (!(opt->arg == &db3dbi.dbi_oeflags ||
00464 opt->arg == &db3dbi.dbi_eflags))
00465 continue;
00466 } else {
00467 if (!(opt->arg == &db3dbi.dbi_oeflags ||
00468 opt->arg == &db3dbi.dbi_oflags))
00469 continue;
00470 }
00471 if ((dbflags & opt->val) != opt->val)
00472 continue;
00473 if (oe != buf)
00474 *oe++ = ':';
00475 oe = stpcpy(oe, opt->longName);
00476 dbflags &= ~opt->val;
00477 }
00478 if (dbflags) {
00479 if (oe != buf)
00480 *oe++ = ':';
00481 sprintf(oe, "0x%x", (unsigned)dbflags);
00482 }
00483 return buf;
00484 }
00485
00486
00487 #endif