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