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