1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1996,2008 Oracle. All rights reserved. 5 * 6 * $Id: env_config.c,v 12.84 2008/02/12 15:34:06 bostic Exp $ 7 */ 8 9#include "db_config.h" 10 11#include "db_int.h" 12#include "dbinc/lock.h" 13#include "dbinc/log.h" 14#include "dbinc/mp.h" 15#include "dbinc/txn.h" 16 17static int __config_parse __P((ENV *, char *, int)); 18 19/* 20 * __env_read_db_config -- 21 * Read the DB_CONFIG file. 22 * 23 * PUBLIC: int __env_read_db_config __P((ENV *)); 24 */ 25int 26__env_read_db_config(env) 27 ENV *env; 28{ 29 FILE *fp; 30 int lc, ret; 31 char *p, buf[256]; 32 33 /* Parse the config file. */ 34 p = NULL; 35 if ((ret = 36 __db_appname(env, DB_APP_NONE, "DB_CONFIG", 0, NULL, &p)) != 0) 37 return (ret); 38 if (p == NULL) 39 fp = NULL; 40 else { 41 fp = fopen(p, "r"); 42 __os_free(env, p); 43 } 44 45 if (fp == NULL) 46 return (0); 47 48 for (lc = 1; fgets(buf, sizeof(buf), fp) != NULL; ++lc) { 49 if ((p = strchr(buf, '\n')) == NULL) { 50 __db_errx(env, "DB_CONFIG: line %d: illegal input", lc); 51 ret = EINVAL; 52 break; 53 } 54 if (p > buf && p[-1] == '\r') 55 --p; 56 *p = '\0'; 57 for (p = buf; *p != '\0' && isspace((int)*p); ++p) 58 ; 59 if (*p == '\0' || *p == '#') 60 continue; 61 62 if ((ret = __config_parse(env, buf, lc)) != 0) 63 break; 64 } 65 (void)fclose(fp); 66 67 return (ret); 68} 69 70#undef CONFIG_GET_INT 71#define CONFIG_GET_INT(s, vp) do { \ 72 int __ret; \ 73 if ((__ret = \ 74 __db_getlong(env->dbenv, NULL, s, 0, INT_MAX, vp)) != 0) \ 75 return (__ret); \ 76} while (0) 77#undef CONFIG_GET_LONG 78#define CONFIG_GET_LONG(s, vp) do { \ 79 int __ret; \ 80 if ((__ret = \ 81 __db_getlong(env->dbenv, NULL, s, 0, LONG_MAX, vp)) != 0) \ 82 return (__ret); \ 83} while (0) 84#undef CONFIG_INT 85#define CONFIG_INT(s, f) do { \ 86 if (strcasecmp(s, argv[0]) == 0) { \ 87 long __v; \ 88 if (nf != 2) \ 89 goto format; \ 90 CONFIG_GET_INT(argv[1], &__v); \ 91 return (f(env->dbenv, (int)__v)); \ 92 } \ 93} while (0) 94#undef CONFIG_GET_UINT32 95#define CONFIG_GET_UINT32(s, vp) do { \ 96 if (__db_getulong(env->dbenv, NULL, s, 0, UINT32_MAX, vp) != 0) \ 97 return (EINVAL); \ 98} while (0) 99#undef CONFIG_UINT32 100#define CONFIG_UINT32(s, f) do { \ 101 if (strcasecmp(s, argv[0]) == 0) { \ 102 u_long __v; \ 103 if (nf != 2) \ 104 goto format; \ 105 CONFIG_GET_UINT32(argv[1], &__v); \ 106 return (f(env->dbenv, (u_int32_t)__v)); \ 107 } \ 108} while (0) 109 110#undef CONFIG_SLOTS 111#define CONFIG_SLOTS 10 112 113/* 114 * __config_parse -- 115 * Parse a single NAME VALUE pair. 116 */ 117static int 118__config_parse(env, s, lc) 119 ENV *env; 120 char *s; 121 int lc; 122{ 123 DB_ENV *dbenv; 124 u_long uv1, uv2; 125 u_int32_t flags; 126 long lv1, lv2; 127 int nf; 128 char *argv[CONFIG_SLOTS]; 129 130 dbenv = env->dbenv; 131 /* Split the line by white-space. */ 132 if ((nf = __config_split(s, argv)) < 2) { 133format: __db_errx(env, 134 "line %d: %s: incorrect name-value pair", lc, argv[0]); 135 return (EINVAL); 136 } 137 138 CONFIG_UINT32("mutex_set_align", __mutex_set_align); 139 CONFIG_UINT32("mutex_set_increment", __mutex_set_increment); 140 CONFIG_UINT32("mutex_set_max", __mutex_set_max); 141 CONFIG_UINT32("mutex_set_tas_spins", __mutex_set_tas_spins); 142 143 if (strcasecmp(argv[0], "rep_set_clockskew") == 0) { 144 if (nf != 3) 145 goto format; 146 CONFIG_GET_UINT32(argv[1], &uv1); 147 CONFIG_GET_UINT32(argv[2], &uv2); 148 return (__rep_set_clockskew( 149 dbenv, (u_int32_t)uv1, (u_int32_t)uv2)); 150 } 151 152 if (strcasecmp(argv[0], "rep_set_config") == 0) { 153 if (nf != 2) 154 goto format; 155 if (strcasecmp(argv[1], "db_rep_conf_bulk") == 0) 156 return (__rep_set_config(dbenv, 157 DB_REP_CONF_BULK, 1)); 158 if (strcasecmp(argv[1], "db_rep_conf_delayclient") == 0) 159 return (__rep_set_config(dbenv, 160 DB_REP_CONF_DELAYCLIENT, 1)); 161 if (strcasecmp(argv[1], "db_rep_conf_lease") == 0) 162 return (__rep_set_config(dbenv, 163 DB_REP_CONF_LEASE, 1)); 164 if (strcasecmp(argv[1], "db_rep_conf_noautoinit") == 0) 165 return (__rep_set_config(dbenv, 166 DB_REP_CONF_NOAUTOINIT, 1)); 167 if (strcasecmp(argv[1], "db_rep_conf_nowait") == 0) 168 return (__rep_set_config(dbenv, DB_REP_CONF_NOWAIT, 1)); 169 if (strcasecmp(argv[1], "db_repmgr_conf_2site_strict") == 0) 170 return (__rep_set_config(dbenv, 171 DB_REPMGR_CONF_2SITE_STRICT, 1)); 172 goto format; 173 } 174 175 if (strcasecmp(argv[0], "rep_set_limit") == 0) { 176 if (nf != 3) 177 goto format; 178 CONFIG_GET_UINT32(argv[1], &uv1); 179 CONFIG_GET_UINT32(argv[2], &uv2); 180 return (__rep_set_limit( 181 dbenv, (u_int32_t)uv1, (u_int32_t)uv2)); 182 } 183 184 if (strcasecmp(argv[0], "rep_set_nsites") == 0) { 185 if (nf != 2) 186 goto format; 187 CONFIG_GET_UINT32(argv[1], &uv1); 188 return (__rep_set_nsites( 189 dbenv, (u_int32_t)uv1)); 190 } 191 192 if (strcasecmp(argv[0], "rep_set_priority") == 0) { 193 if (nf != 2) 194 goto format; 195 CONFIG_GET_UINT32(argv[1], &uv1); 196 return (__rep_set_priority( 197 dbenv, (u_int32_t)uv1)); 198 } 199 200 if (strcasecmp(argv[0], "rep_set_request") == 0) { 201 if (nf != 3) 202 goto format; 203 CONFIG_GET_UINT32(argv[1], &uv1); 204 CONFIG_GET_UINT32(argv[2], &uv2); 205 return (__rep_set_request( 206 dbenv, (u_int32_t)uv1, (u_int32_t)uv2)); 207 } 208 209 if (strcasecmp(argv[0], "rep_set_timeout") == 0) { 210 if (nf != 3) 211 goto format; 212 CONFIG_GET_UINT32(argv[2], &uv2); 213 if (strcasecmp(argv[1], "db_rep_ack_timeout") == 0) 214 return (__rep_set_timeout( 215 dbenv, DB_REP_ACK_TIMEOUT, (u_int32_t)uv2)); 216 if (strcasecmp(argv[1], "db_rep_checkpoint_delay") == 0) 217 return (__rep_set_timeout( 218 dbenv, DB_REP_CHECKPOINT_DELAY, (u_int32_t)uv2)); 219 if (strcasecmp(argv[1], "db_rep_connection_retry") == 0) 220 return (__rep_set_timeout( 221 dbenv, DB_REP_CONNECTION_RETRY, (u_int32_t)uv2)); 222 if (strcasecmp(argv[1], "db_rep_election_timeout") == 0) 223 return (__rep_set_timeout( 224 dbenv, DB_REP_ELECTION_TIMEOUT, (u_int32_t)uv2)); 225 if (strcasecmp(argv[1], "db_rep_election_retry") == 0) 226 return (__rep_set_timeout( 227 dbenv, DB_REP_ELECTION_RETRY, (u_int32_t)uv2)); 228 if (strcasecmp(argv[1], "db_rep_full_election_timeout") == 0) 229 return (__rep_set_timeout(dbenv, 230 DB_REP_FULL_ELECTION_TIMEOUT, (u_int32_t)uv2)); 231 if (strcasecmp(argv[1], "db_rep_heartbeat_monitor") == 0) 232 return (__rep_set_timeout( 233 dbenv, DB_REP_HEARTBEAT_MONITOR, (u_int32_t)uv2)); 234 if (strcasecmp(argv[1], "db_rep_heartbeat_send") == 0) 235 return (__rep_set_timeout( 236 dbenv, DB_REP_HEARTBEAT_SEND, (u_int32_t)uv2)); 237 if (strcasecmp(argv[1], "db_rep_lease_timeout") == 0) 238 return (__rep_set_timeout( 239 dbenv, DB_REP_LEASE_TIMEOUT, (u_int32_t)uv2)); 240 goto format; 241 } 242 243 if (strcasecmp(argv[0], "repmgr_set_ack_policy") == 0) { 244 if (nf != 2) 245 goto format; 246 if (strcasecmp(argv[1], "db_repmgr_acks_all") == 0) 247 return (__repmgr_set_ack_policy( 248 dbenv, DB_REPMGR_ACKS_ALL)); 249 if (strcasecmp(argv[1], "db_repmgr_acks_all_peers") == 0) 250 return (__repmgr_set_ack_policy( 251 dbenv, DB_REPMGR_ACKS_ALL_PEERS)); 252 if (strcasecmp(argv[1], "db_repmgr_acks_none") == 0) 253 return (__repmgr_set_ack_policy( 254 dbenv, DB_REPMGR_ACKS_NONE)); 255 if (strcasecmp(argv[1], "db_repmgr_acks_one") == 0) 256 return (__repmgr_set_ack_policy( 257 dbenv, DB_REPMGR_ACKS_ONE)); 258 if (strcasecmp(argv[1], "db_repmgr_acks_one_peer") == 0) 259 return (__repmgr_set_ack_policy( 260 dbenv, DB_REPMGR_ACKS_ONE_PEER)); 261 if (strcasecmp(argv[1], "db_repmgr_acks_quorum") == 0) 262 return (__repmgr_set_ack_policy( 263 dbenv, DB_REPMGR_ACKS_QUORUM)); 264 goto format; 265 } 266 267 if (strcasecmp(argv[0], "set_cachesize") == 0) { 268 if (nf != 4) 269 goto format; 270 CONFIG_GET_UINT32(argv[1], &uv1); 271 CONFIG_GET_UINT32(argv[2], &uv2); 272 CONFIG_GET_INT(argv[3], &lv1); 273 return (__memp_set_cachesize( 274 dbenv, (u_int32_t)uv1, (u_int32_t)uv2, (int)lv1)); 275 } 276 277 if (strcasecmp(argv[0], "set_data_dir") == 0 || 278 strcasecmp(argv[0], "db_data_dir") == 0) { /* Compatibility. */ 279 if (nf != 2) 280 goto format; 281 return (__env_set_data_dir(dbenv, argv[1])); 282 } 283 284 /* Compatibility */ 285 if (strcasecmp(argv[0], "set_intermediate_dir") == 0) { 286 if (nf != 2) 287 goto format; 288 CONFIG_GET_INT(argv[1], &lv1); 289 if (lv1 <= 0) 290 goto format; 291 env->dir_mode = (int)lv1; 292 return (0); 293 } 294 if (strcasecmp(argv[0], "set_intermediate_dir_mode") == 0) { 295 if (nf != 2) 296 goto format; 297 return (__env_set_intermediate_dir_mode(dbenv, argv[1])); 298 } 299 300 if (strcasecmp(argv[0], "set_flags") == 0) { 301 if (nf != 2) 302 goto format; 303 if (strcasecmp(argv[1], "db_auto_commit") == 0) 304 return (__env_set_flags(dbenv, DB_AUTO_COMMIT, 1)); 305 if (strcasecmp(argv[1], "db_cdb_alldb") == 0) 306 return (__env_set_flags(dbenv, DB_CDB_ALLDB, 1)); 307 if (strcasecmp(argv[1], "db_direct_db") == 0) 308 return (__env_set_flags(dbenv, DB_DIRECT_DB, 1)); 309 if (strcasecmp(argv[1], "db_dsync_db") == 0) 310 return (__env_set_flags(dbenv, DB_DSYNC_DB, 1)); 311 if (strcasecmp(argv[1], "db_multiversion") == 0) 312 return (__env_set_flags(dbenv, DB_MULTIVERSION, 1)); 313 if (strcasecmp(argv[1], "db_nolocking") == 0) 314 return (__env_set_flags(dbenv, DB_NOLOCKING, 1)); 315 if (strcasecmp(argv[1], "db_nommap") == 0) 316 return (__env_set_flags(dbenv, DB_NOMMAP, 1)); 317 if (strcasecmp(argv[1], "db_nopanic") == 0) 318 return (__env_set_flags(dbenv, DB_NOPANIC, 1)); 319 if (strcasecmp(argv[1], "db_overwrite") == 0) 320 return (__env_set_flags(dbenv, DB_OVERWRITE, 1)); 321 if (strcasecmp(argv[1], "db_region_init") == 0) 322 return (__env_set_flags(dbenv, DB_REGION_INIT, 1)); 323 if (strcasecmp(argv[1], "db_txn_nosync") == 0) 324 return (__env_set_flags(dbenv, DB_TXN_NOSYNC, 1)); 325 if (strcasecmp(argv[1], "db_txn_nowait") == 0) 326 return (__env_set_flags(dbenv, DB_TXN_NOWAIT, 1)); 327 if (strcasecmp(argv[1], "db_txn_snapshot") == 0) 328 return (__env_set_flags(dbenv, DB_TXN_SNAPSHOT, 1)); 329 if (strcasecmp(argv[1], "db_txn_write_nosync") == 0) 330 return ( 331 __env_set_flags(dbenv, DB_TXN_WRITE_NOSYNC, 1)); 332 if (strcasecmp(argv[1], "db_yieldcpu") == 0) 333 return (__env_set_flags(dbenv, DB_YIELDCPU, 1)); 334 if (strcasecmp(argv[1], "db_log_inmemory") == 0) 335 return (__log_set_config(dbenv, DB_LOG_IN_MEMORY, 1)); 336 if (strcasecmp(argv[1], "db_direct_log") == 0) 337 return (__log_set_config(dbenv, DB_LOG_DIRECT, 1)); 338 if (strcasecmp(argv[1], "db_dsync_log") == 0) 339 return (__log_set_config(dbenv, DB_LOG_DSYNC, 1)); 340 if (strcasecmp(argv[1], "db_log_autoremove") == 0) 341 return (__log_set_config(dbenv, DB_LOG_AUTO_REMOVE, 1)); 342 goto format; 343 } 344 if (strcasecmp(argv[0], "set_log_config") == 0) { 345 if (nf != 2) 346 goto format; 347 if (strcasecmp(argv[1], "db_log_auto_remove") == 0) 348 return (__log_set_config(dbenv, DB_LOG_AUTO_REMOVE, 1)); 349 if (strcasecmp(argv[1], "db_log_direct") == 0) 350 return (__log_set_config(dbenv, DB_LOG_DIRECT, 1)); 351 if (strcasecmp(argv[1], "db_log_dsync") == 0) 352 return (__log_set_config(dbenv, DB_LOG_DSYNC, 1)); 353 if (strcasecmp(argv[1], "db_log_in_memory") == 0) 354 return (__log_set_config(dbenv, DB_LOG_IN_MEMORY, 1)); 355 if (strcasecmp(argv[1], "db_log_zero") == 0) 356 return (__log_set_config(dbenv, DB_LOG_ZERO, 1)); 357 goto format; 358 } 359 360 CONFIG_UINT32("set_lg_bsize", __log_set_lg_bsize); 361 CONFIG_INT("set_lg_filemode", __log_set_lg_filemode); 362 CONFIG_UINT32("set_lg_max", __log_set_lg_max); 363 CONFIG_UINT32("set_lg_regionmax", __log_set_lg_regionmax); 364 365 if (strcasecmp(argv[0], "set_lg_dir") == 0 || 366 strcasecmp(argv[0], "db_log_dir") == 0) { /* Compatibility. */ 367 if (nf != 2) 368 goto format; 369 return (__log_set_lg_dir(dbenv, argv[1])); 370 } 371 372 if (strcasecmp(argv[0], "set_lk_detect") == 0) { 373 if (nf != 2) 374 goto format; 375 if (strcasecmp(argv[1], "db_lock_default") == 0) 376 flags = DB_LOCK_DEFAULT; 377 else if (strcasecmp(argv[1], "db_lock_expire") == 0) 378 flags = DB_LOCK_EXPIRE; 379 else if (strcasecmp(argv[1], "db_lock_maxlocks") == 0) 380 flags = DB_LOCK_MAXLOCKS; 381 else if (strcasecmp(argv[1], "db_lock_maxwrite") == 0) 382 flags = DB_LOCK_MAXWRITE; 383 else if (strcasecmp(argv[1], "db_lock_minlocks") == 0) 384 flags = DB_LOCK_MINLOCKS; 385 else if (strcasecmp(argv[1], "db_lock_minwrite") == 0) 386 flags = DB_LOCK_MINWRITE; 387 else if (strcasecmp(argv[1], "db_lock_oldest") == 0) 388 flags = DB_LOCK_OLDEST; 389 else if (strcasecmp(argv[1], "db_lock_random") == 0) 390 flags = DB_LOCK_RANDOM; 391 else if (strcasecmp(argv[1], "db_lock_youngest") == 0) 392 flags = DB_LOCK_YOUNGEST; 393 else 394 goto format; 395 return (__lock_set_lk_detect(dbenv, flags)); 396 } 397 398 CONFIG_UINT32("set_lk_max_locks", __lock_set_lk_max_locks); 399 CONFIG_UINT32("set_lk_max_lockers", __lock_set_lk_max_lockers); 400 CONFIG_UINT32("set_lk_max_objects", __lock_set_lk_max_objects); 401 CONFIG_UINT32("set_lk_partitions", __lock_set_lk_partitions); 402 403 if (strcasecmp(argv[0], "set_lock_timeout") == 0) { 404 if (nf != 2) 405 goto format; 406 CONFIG_GET_UINT32(argv[1], &uv1); 407 return (__lock_set_env_timeout( 408 dbenv, (u_int32_t)uv1, DB_SET_LOCK_TIMEOUT)); 409 } 410 411 CONFIG_INT("set_mp_max_openfd", __memp_set_mp_max_openfd); 412 413 if (strcasecmp(argv[0], "set_mp_max_write") == 0) { 414 if (nf != 3) 415 goto format; 416 CONFIG_GET_INT(argv[1], &lv1); 417 CONFIG_GET_INT(argv[2], &lv2); 418 return (__memp_set_mp_max_write( 419 dbenv, (int)lv1, (db_timeout_t)lv2)); 420 } 421 422 CONFIG_UINT32("set_mp_mmapsize", __memp_set_mp_mmapsize); 423 424 if (strcasecmp(argv[0], "set_region_init") == 0) { 425 if (nf != 2) 426 goto format; 427 CONFIG_GET_INT(argv[1], &lv1); 428 if (lv1 != 0 && lv1 != 1) 429 goto format; 430 return (__env_set_flags( 431 dbenv, DB_REGION_INIT, lv1 == 0 ? 0 : 1)); 432 } 433 434 if (strcasecmp(argv[0], "set_shm_key") == 0) { 435 if (nf != 2) 436 goto format; 437 CONFIG_GET_LONG(argv[1], &lv1); 438 return (__env_set_shm_key(dbenv, lv1)); 439 } 440 441 /* 442 * The set_tas_spins method has been replaced by mutex_set_tas_spins. 443 * The set_tas_spins argv[0] remains for DB_CONFIG compatibility. 444 */ 445 CONFIG_UINT32("set_tas_spins", __mutex_set_tas_spins); 446 447 if (strcasecmp(argv[0], "set_tmp_dir") == 0 || 448 strcasecmp(argv[0], "db_tmp_dir") == 0) { /* Compatibility.*/ 449 if (nf != 2) 450 goto format; 451 return (__env_set_tmp_dir(dbenv, argv[1])); 452 } 453 454 CONFIG_UINT32("set_tx_max", __txn_set_tx_max); 455 456 if (strcasecmp(argv[0], "set_txn_timeout") == 0) { 457 if (nf != 2) 458 goto format; 459 CONFIG_GET_UINT32(argv[1], &uv1); 460 return (__lock_set_env_timeout( 461 dbenv, (u_int32_t)uv1, DB_SET_TXN_TIMEOUT)); 462 } 463 464 if (strcasecmp(argv[0], "set_verbose") == 0) { 465 if (nf != 2) 466 goto format; 467 if (strcasecmp(argv[1], "db_verb_deadlock") == 0) 468 flags = DB_VERB_DEADLOCK; 469 else if (strcasecmp(argv[1], "db_verb_fileops") == 0) 470 flags = DB_VERB_FILEOPS; 471 else if (strcasecmp(argv[1], "db_verb_fileops_all") == 0) 472 flags = DB_VERB_FILEOPS_ALL; 473 else if (strcasecmp(argv[1], "db_verb_recovery") == 0) 474 flags = DB_VERB_RECOVERY; 475 else if (strcasecmp(argv[1], "db_verb_register") == 0) 476 flags = DB_VERB_REGISTER; 477 else if (strcasecmp(argv[1], "db_verb_replication") == 0) 478 flags = DB_VERB_REPLICATION; 479 else if (strcasecmp(argv[1], "db_verb_rep_elect") == 0) 480 flags = DB_VERB_REP_ELECT; 481 else if (strcasecmp(argv[1], "db_verb_rep_lease") == 0) 482 flags = DB_VERB_REP_LEASE; 483 else if (strcasecmp(argv[1], "db_verb_rep_misc") == 0) 484 flags = DB_VERB_REP_MISC; 485 else if (strcasecmp(argv[1], "db_verb_rep_msgs") == 0) 486 flags = DB_VERB_REP_MSGS; 487 else if (strcasecmp(argv[1], "db_verb_rep_sync") == 0) 488 flags = DB_VERB_REP_SYNC; 489 else if (strcasecmp(argv[1], "db_verb_repmgr_connfail") == 0) 490 flags = DB_VERB_REPMGR_CONNFAIL; 491 else if (strcasecmp(argv[1], "db_verb_repmgr_misc") == 0) 492 flags = DB_VERB_REPMGR_MISC; 493 else if (strcasecmp(argv[1], "db_verb_waitsfor") == 0) 494 flags = DB_VERB_WAITSFOR; 495 else 496 goto format; 497 return (__env_set_verbose(dbenv, flags, 1)); 498 } 499 500 __db_errx(env, "unrecognized name-value pair: %s", s); 501 return (EINVAL); 502} 503 504/* 505 * __config_split -- 506 * Split lines into white-space separated fields, returning the count of 507 * fields. 508 * 509 * PUBLIC: int __config_split __P((char *, char *[])); 510 */ 511int 512__config_split(input, argv) 513 char *input, *argv[CONFIG_SLOTS]; 514{ 515 int count; 516 char **ap; 517 518 for (count = 0, ap = argv; (*ap = strsep(&input, " \t\n")) != NULL;) 519 if (**ap != '\0') { 520 ++count; 521 if (++ap == &argv[CONFIG_SLOTS - 1]) { 522 *ap = NULL; 523 break; 524 } 525 } 526 return (count); 527} 528