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 { "mp_mmapsize", 0,POPT_ARG_INT, &db3dbi.dbi_mp_mmapsize, 0,
00194 NULL, NULL },
00195 { "mp_size", 0,POPT_ARG_INT, &db3dbi.dbi_mp_size, 0,
00196 NULL, NULL },
00197 { "pagesize", 0,POPT_ARG_INT, &db3dbi.dbi_pagesize, 0,
00198 NULL, NULL },
00199
00200
00201
00202
00203
00204 { "bt_dup", 0,POPT_BIT_SET, &db3dbi.dbi_bt_flags, DB_DUP,
00205 NULL, NULL },
00206 { "bt_dupsort",0,POPT_BIT_SET, &db3dbi.dbi_bt_flags, DB_DUPSORT,
00207 NULL, NULL },
00208 { "bt_recnum", 0,POPT_BIT_SET, &db3dbi.dbi_bt_flags, DB_RECNUM,
00209 NULL, NULL },
00210 { "bt_revsplitoff", 0,POPT_BIT_SET, &db3dbi.dbi_bt_flags, DB_REVSPLITOFF,
00211 NULL, NULL },
00212
00213 { "h_dup", 0,POPT_BIT_SET, &db3dbi.dbi_h_flags, DB_DUP,
00214 NULL, NULL },
00215 { "h_dupsort", 0,POPT_BIT_SET, &db3dbi.dbi_h_flags, DB_DUPSORT,
00216 NULL, NULL },
00217 { "h_ffactor", 0,POPT_ARG_INT, &db3dbi.dbi_h_ffactor, 0,
00218 NULL, NULL },
00219 { "h_nelem", 0,POPT_ARG_INT, &db3dbi.dbi_h_nelem, 0,
00220 NULL, NULL },
00221
00222 { "re_renumber", 0,POPT_BIT_SET, &db3dbi.dbi_re_flags, DB_RENUMBER,
00223 NULL, NULL },
00224 { "re_snapshot",0,POPT_BIT_SET, &db3dbi.dbi_re_flags, DB_SNAPSHOT,
00225 NULL, NULL },
00226 { "re_delim", 0,POPT_ARG_INT, &db3dbi.dbi_re_delim, 0,
00227 NULL, NULL },
00228 { "re_len", 0,POPT_ARG_INT, &db3dbi.dbi_re_len, 0,
00229 NULL, NULL },
00230 { "re_pad", 0,POPT_ARG_INT, &db3dbi.dbi_re_pad, 0,
00231 NULL, NULL },
00232 { "re_source", 0,POPT_ARG_STRING, &db3dbi.dbi_re_source, 0,
00233 NULL, NULL },
00234
00235 { "q_extentsize", 0,POPT_ARG_INT, &db3dbi.dbi_q_extentsize, 0,
00236 NULL, NULL },
00237
00238 POPT_TABLEEND
00239 };
00240
00241
00242 dbiIndex db3Free(dbiIndex dbi)
00243 {
00244 if (dbi) {
00245 dbi->dbi_root = _free(dbi->dbi_root);
00246 dbi->dbi_home = _free(dbi->dbi_home);
00247 dbi->dbi_file = _free(dbi->dbi_file);
00248 dbi->dbi_subfile = _free(dbi->dbi_subfile);
00249 dbi->dbi_tmpdir = _free(dbi->dbi_tmpdir);
00250 dbi->dbi_host = _free(dbi->dbi_host);
00251 dbi->dbi_errpfx = _free(dbi->dbi_errpfx);
00252 dbi->dbi_re_source = _free(dbi->dbi_re_source);
00253 dbi->dbi_stats = _free(dbi->dbi_stats);
00254 dbi = _free(dbi);
00255 }
00256 return dbi;
00257 }
00258
00260
00261 static const char *db3_config_default =
00262 "db3:hash:mpool:cdb:usecursors:verbose:mp_mmapsize=8Mb:mp_size=512Kb:pagesize=512:perms=0644";
00263
00264
00265 dbiIndex db3New(rpmdb rpmdb, rpmTag rpmtag)
00266 {
00267 dbiIndex dbi = xcalloc(1, sizeof(*dbi));
00268 char dbiTagMacro[128];
00269 char * dbOpts;
00270
00271 sprintf(dbiTagMacro, "%%{_dbi_config_%s}", tagName(rpmtag));
00272 dbOpts = rpmExpand(dbiTagMacro, NULL);
00273 if (!(dbOpts && *dbOpts && *dbOpts != '%')) {
00274 dbOpts = _free(dbOpts);
00275 dbOpts = rpmExpand("%{_dbi_config}", NULL);
00276 if (!(dbOpts && *dbOpts && *dbOpts != '%')) {
00277 dbOpts = rpmExpand(db3_config_default, NULL);
00278 }
00279 }
00280
00281
00282
00283 if (dbOpts && *dbOpts && *dbOpts != '%') {
00284 char *o, *oe;
00285 char *p, *pe;
00286
00287 memset(&db3dbi, 0, sizeof(db3dbi));
00288
00289 for (o = dbOpts; o && *o; o = oe) {
00290 struct poptOption *opt;
00291 const char * tok;
00292 int argInfo;
00293
00294
00295 while (*o && xisspace(*o))
00296 o++;
00297
00298
00299 for (oe = o; oe && *oe; oe++) {
00300 if (xisspace(*oe))
00301 break;
00302 if (oe[0] == ':' && !(oe[1] == '/' && oe[2] == '/'))
00303 break;
00304 }
00305 if (oe && *oe)
00306 *oe++ = '\0';
00307 if (*o == '\0')
00308 continue;
00309
00310
00311 for (pe = o; pe && *pe && *pe != '='; pe++)
00312 {};
00313 p = (pe ? *pe++ = '\0', pe : NULL);
00314
00315
00316 for (tok = o; *tok == '!'; tok++)
00317 {};
00318
00319
00320 for (opt = rdbOptions; opt->longName != NULL; opt++) {
00321 if (strcmp(tok, opt->longName))
00322 continue;
00323 break;
00324 }
00325 if (opt->longName == NULL) {
00326 rpmError(RPMERR_DBCONFIG,
00327 _("unrecognized db option: \"%s\" ignored.\n"), o);
00328 continue;
00329 }
00330
00331
00332 argInfo = opt->argInfo;
00333 if (argInfo == POPT_BIT_SET && *o == '!' && ((tok - o) % 2))
00334 argInfo = POPT_BIT_CLR;
00335
00336
00337 switch (argInfo & POPT_ARG_MASK) {
00338
00339 case POPT_ARG_NONE:
00340 (void) poptSaveInt((int *)opt->arg, argInfo, 1L);
00341 break;
00342 case POPT_ARG_VAL:
00343 (void) poptSaveInt((int *)opt->arg, argInfo, (long)opt->val);
00344 break;
00345 case POPT_ARG_STRING:
00346 { const char ** t = opt->arg;
00347
00348 if (t) {
00349
00350 *t = _free(*t);
00351
00352 *t = xstrdup( (p ? p : "") );
00353 }
00354
00355 } break;
00356
00357 case POPT_ARG_INT:
00358 case POPT_ARG_LONG:
00359 { long aLong = strtol(p, &pe, 0);
00360 if (pe) {
00361 if (!xstrncasecmp(pe, "Mb", 2))
00362 aLong *= 1024 * 1024;
00363 else if (!xstrncasecmp(pe, "Kb", 2))
00364 aLong *= 1024;
00365 else if (*pe != '\0') {
00366 rpmError(RPMERR_DBCONFIG,
00367 _("%s has invalid numeric value, skipped\n"),
00368 opt->longName);
00369 continue;
00370 }
00371 }
00372
00373 if ((argInfo & POPT_ARG_MASK) == POPT_ARG_LONG) {
00374 if (aLong == LONG_MIN || aLong == LONG_MAX) {
00375 rpmError(RPMERR_DBCONFIG,
00376 _("%s has too large or too small long value, skipped\n"),
00377 opt->longName);
00378 continue;
00379 }
00380 (void) poptSaveLong((long *)opt->arg, argInfo, aLong);
00381 break;
00382 } else {
00383 if (aLong > INT_MAX || aLong < INT_MIN) {
00384 rpmError(RPMERR_DBCONFIG,
00385 _("%s has too large or too small integer value, skipped\n"),
00386 opt->longName);
00387 continue;
00388 }
00389 (void) poptSaveInt((int *)opt->arg, argInfo, aLong);
00390 }
00391 } break;
00392 default:
00393 break;
00394 }
00395 }
00396
00397 }
00398
00399
00400 dbOpts = _free(dbOpts);
00401
00402
00403 *dbi = db3dbi;
00404
00405 memset(&db3dbi, 0, sizeof(db3dbi));
00406
00407 if (!(dbi->dbi_perms & 0600))
00408 dbi->dbi_perms = 0644;
00409 dbi->dbi_mode = rpmdb->db_mode;
00410
00411 dbi->dbi_rpmdb = rpmdb;
00412
00413 dbi->dbi_rpmtag = rpmtag;
00414
00415
00416
00417
00418
00419 switch (rpmtag) {
00420 case RPMDBI_PACKAGES:
00421 case RPMDBI_DEPENDS:
00422 dbi->dbi_jlen = 1 * sizeof(int_32);
00423 break;
00424 default:
00425 dbi->dbi_jlen = 2 * sizeof(int_32);
00426 break;
00427 }
00428
00429
00430 dbi->dbi_byteswapped = 0;
00431
00432 if (!dbi->dbi_use_dbenv) {
00433 dbi->dbi_use_dbenv = 1;
00434 dbi->dbi_eflags |= (DB_INIT_MPOOL|DB_JOINENV);
00435 dbi->dbi_mp_mmapsize = 16 * 1024 * 1024;
00436 dbi->dbi_mp_size = 1 * 1024 * 1024;
00437 }
00438
00439 if ((dbi->dbi_bt_flags | dbi->dbi_h_flags) & DB_DUP)
00440 dbi->dbi_permit_dups = 1;
00441
00442
00443 return dbi;
00444
00445 }
00446
00447
00448
00449 const char *const prDbiOpenFlags(int dbflags, int print_dbenv_flags)
00450 {
00451 static char buf[256];
00452 struct poptOption *opt;
00453 char * oe;
00454
00455 oe = buf;
00456 *oe = '\0';
00457 for (opt = rdbOptions; opt->longName != NULL; opt++) {
00458 if (opt->argInfo != POPT_BIT_SET)
00459 continue;
00460 if (print_dbenv_flags) {
00461 if (!(opt->arg == &db3dbi.dbi_oeflags ||
00462 opt->arg == &db3dbi.dbi_eflags))
00463 continue;
00464 } else {
00465 if (!(opt->arg == &db3dbi.dbi_oeflags ||
00466 opt->arg == &db3dbi.dbi_oflags))
00467 continue;
00468 }
00469 if ((dbflags & opt->val) != opt->val)
00470 continue;
00471 if (oe != buf)
00472 *oe++ = ':';
00473 oe = stpcpy(oe, opt->longName);
00474 dbflags &= ~opt->val;
00475 }
00476 if (dbflags) {
00477 if (oe != buf)
00478 *oe++ = ':';
00479 sprintf(oe, "0x%x", (unsigned)dbflags);
00480 }
00481 return buf;
00482 }
00483
00484
00485 #endif