1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1999,2008 Oracle. All rights reserved. 5 * 6 * $Id: log_method.c,v 12.19 2008/05/02 16:35:31 mbrey Exp $ 7 */ 8 9#include "db_config.h" 10 11#include "db_int.h" 12#include "dbinc/log.h" 13 14/* 15 * __log_env_create -- 16 * Log specific initialization of the DB_ENV structure. 17 * 18 * PUBLIC: int __log_env_create __P((DB_ENV *)); 19 */ 20int 21__log_env_create(dbenv) 22 DB_ENV *dbenv; 23{ 24 /* 25 * !!! 26 * Our caller has not yet had the opportunity to reset the panic 27 * state or turn off mutex locking, and so we can neither check 28 * the panic state or acquire a mutex in the DB_ENV create path. 29 */ 30 dbenv->lg_bsize = 0; 31 dbenv->lg_regionmax = LG_BASE_REGION_SIZE; 32 33 return (0); 34} 35 36/* 37 * __log_env_destroy -- 38 * Log specific destruction of the DB_ENV structure. 39 * 40 * PUBLIC: void __log_env_destroy __P((DB_ENV *)); 41 */ 42void 43__log_env_destroy(dbenv) 44 DB_ENV *dbenv; 45{ 46 COMPQUIET(dbenv, NULL); 47} 48 49/* 50 * PUBLIC: int __log_get_lg_bsize __P((DB_ENV *, u_int32_t *)); 51 */ 52int 53__log_get_lg_bsize(dbenv, lg_bsizep) 54 DB_ENV *dbenv; 55 u_int32_t *lg_bsizep; 56{ 57 ENV *env; 58 59 env = dbenv->env; 60 61 ENV_NOT_CONFIGURED(env, 62 env->lg_handle, "DB_ENV->get_lg_bsize", DB_INIT_LOG); 63 64 if (LOGGING_ON(env)) { 65 /* Cannot be set after open, no lock required to read. */ 66 *lg_bsizep = 67 ((LOG *)env->lg_handle->reginfo.primary)->buffer_size; 68 } else 69 *lg_bsizep = dbenv->lg_bsize; 70 return (0); 71} 72 73/* 74 * __log_set_lg_bsize -- 75 * DB_ENV->set_lg_bsize. 76 * 77 * PUBLIC: int __log_set_lg_bsize __P((DB_ENV *, u_int32_t)); 78 */ 79int 80__log_set_lg_bsize(dbenv, lg_bsize) 81 DB_ENV *dbenv; 82 u_int32_t lg_bsize; 83{ 84 ENV *env; 85 86 env = dbenv->env; 87 88 ENV_ILLEGAL_AFTER_OPEN(env, "DB_ENV->set_lg_bsize"); 89 90 dbenv->lg_bsize = lg_bsize; 91 return (0); 92} 93 94/* 95 * PUBLIC: int __log_get_lg_filemode __P((DB_ENV *, int *)); 96 */ 97int 98__log_get_lg_filemode(dbenv, lg_modep) 99 DB_ENV *dbenv; 100 int *lg_modep; 101{ 102 DB_LOG *dblp; 103 DB_THREAD_INFO *ip; 104 ENV *env; 105 106 env = dbenv->env; 107 108 ENV_NOT_CONFIGURED(env, 109 env->lg_handle, "DB_ENV->get_lg_filemode", DB_INIT_LOG); 110 111 if (LOGGING_ON(env)) { 112 dblp = env->lg_handle; 113 ENV_ENTER(env, ip); 114 LOG_SYSTEM_LOCK(env); 115 *lg_modep = ((LOG *)dblp->reginfo.primary)->filemode; 116 LOG_SYSTEM_UNLOCK(env); 117 ENV_LEAVE(env, ip); 118 } else 119 *lg_modep = dbenv->lg_filemode; 120 121 return (0); 122} 123 124/* 125 * __log_set_lg_filemode -- 126 * DB_ENV->set_lg_filemode. 127 * 128 * PUBLIC: int __log_set_lg_filemode __P((DB_ENV *, int)); 129 */ 130int 131__log_set_lg_filemode(dbenv, lg_mode) 132 DB_ENV *dbenv; 133 int lg_mode; 134{ 135 DB_LOG *dblp; 136 DB_THREAD_INFO *ip; 137 ENV *env; 138 LOG *lp; 139 140 env = dbenv->env; 141 142 ENV_NOT_CONFIGURED(env, 143 env->lg_handle, "DB_ENV->set_lg_filemode", DB_INIT_LOG); 144 145 if (LOGGING_ON(env)) { 146 dblp = env->lg_handle; 147 lp = dblp->reginfo.primary; 148 ENV_ENTER(env, ip); 149 LOG_SYSTEM_LOCK(env); 150 lp->filemode = lg_mode; 151 LOG_SYSTEM_UNLOCK(env); 152 ENV_LEAVE(env, ip); 153 } else 154 dbenv->lg_filemode = lg_mode; 155 156 return (0); 157} 158 159/* 160 * PUBLIC: int __log_get_lg_max __P((DB_ENV *, u_int32_t *)); 161 */ 162int 163__log_get_lg_max(dbenv, lg_maxp) 164 DB_ENV *dbenv; 165 u_int32_t *lg_maxp; 166{ 167 DB_LOG *dblp; 168 DB_THREAD_INFO *ip; 169 ENV *env; 170 171 env = dbenv->env; 172 173 ENV_NOT_CONFIGURED(env, 174 env->lg_handle, "DB_ENV->get_lg_max", DB_INIT_LOG); 175 176 if (LOGGING_ON(env)) { 177 dblp = env->lg_handle; 178 ENV_ENTER(env, ip); 179 LOG_SYSTEM_LOCK(env); 180 *lg_maxp = ((LOG *)dblp->reginfo.primary)->log_nsize; 181 LOG_SYSTEM_UNLOCK(env); 182 ENV_LEAVE(env, ip); 183 } else 184 *lg_maxp = dbenv->lg_size; 185 186 return (0); 187} 188 189/* 190 * __log_set_lg_max -- 191 * DB_ENV->set_lg_max. 192 * 193 * PUBLIC: int __log_set_lg_max __P((DB_ENV *, u_int32_t)); 194 */ 195int 196__log_set_lg_max(dbenv, lg_max) 197 DB_ENV *dbenv; 198 u_int32_t lg_max; 199{ 200 DB_LOG *dblp; 201 DB_THREAD_INFO *ip; 202 ENV *env; 203 LOG *lp; 204 int ret; 205 206 env = dbenv->env; 207 ret = 0; 208 209 ENV_NOT_CONFIGURED(env, 210 env->lg_handle, "DB_ENV->set_lg_max", DB_INIT_LOG); 211 212 if (LOGGING_ON(env)) { 213 dblp = env->lg_handle; 214 lp = dblp->reginfo.primary; 215 ENV_ENTER(env, ip); 216 if ((ret = __log_check_sizes(env, lg_max, 0)) == 0) { 217 LOG_SYSTEM_LOCK(env); 218 lp->log_nsize = lg_max; 219 LOG_SYSTEM_UNLOCK(env); 220 } 221 ENV_LEAVE(env, ip); 222 } else 223 dbenv->lg_size = lg_max; 224 225 return (ret); 226} 227 228/* 229 * PUBLIC: int __log_get_lg_regionmax __P((DB_ENV *, u_int32_t *)); 230 */ 231int 232__log_get_lg_regionmax(dbenv, lg_regionmaxp) 233 DB_ENV *dbenv; 234 u_int32_t *lg_regionmaxp; 235{ 236 ENV *env; 237 238 env = dbenv->env; 239 240 ENV_NOT_CONFIGURED(env, 241 env->lg_handle, "DB_ENV->get_lg_regionmax", DB_INIT_LOG); 242 243 if (LOGGING_ON(env)) { 244 /* Cannot be set after open, no lock required to read. */ 245 *lg_regionmaxp = 246 ((LOG *)env->lg_handle->reginfo.primary)->regionmax; 247 } else 248 *lg_regionmaxp = dbenv->lg_regionmax; 249 return (0); 250} 251 252/* 253 * __log_set_lg_regionmax -- 254 * DB_ENV->set_lg_regionmax. 255 * 256 * PUBLIC: int __log_set_lg_regionmax __P((DB_ENV *, u_int32_t)); 257 */ 258int 259__log_set_lg_regionmax(dbenv, lg_regionmax) 260 DB_ENV *dbenv; 261 u_int32_t lg_regionmax; 262{ 263 ENV *env; 264 265 env = dbenv->env; 266 267 ENV_ILLEGAL_AFTER_OPEN(env, "DB_ENV->set_lg_regionmax"); 268 269 /* Let's not be silly. */ 270 if (lg_regionmax != 0 && lg_regionmax < LG_BASE_REGION_SIZE) { 271 __db_errx(env, 272 "log region size must be >= %d", LG_BASE_REGION_SIZE); 273 return (EINVAL); 274 } 275 276 dbenv->lg_regionmax = lg_regionmax; 277 return (0); 278} 279 280/* 281 * PUBLIC: int __log_get_lg_dir __P((DB_ENV *, const char **)); 282 */ 283int 284__log_get_lg_dir(dbenv, dirp) 285 DB_ENV *dbenv; 286 const char **dirp; 287{ 288 *dirp = dbenv->db_log_dir; 289 return (0); 290} 291 292/* 293 * __log_set_lg_dir -- 294 * DB_ENV->set_lg_dir. 295 * 296 * PUBLIC: int __log_set_lg_dir __P((DB_ENV *, const char *)); 297 */ 298int 299__log_set_lg_dir(dbenv, dir) 300 DB_ENV *dbenv; 301 const char *dir; 302{ 303 ENV *env; 304 305 env = dbenv->env; 306 307 if (dbenv->db_log_dir != NULL) 308 __os_free(env, dbenv->db_log_dir); 309 return (__os_strdup(env, dir, &dbenv->db_log_dir)); 310} 311 312/* 313 * __log_get_flags -- 314 * DB_ENV->get_flags. 315 * 316 * PUBLIC: void __log_get_flags __P((DB_ENV *, u_int32_t *)); 317 */ 318void 319__log_get_flags(dbenv, flagsp) 320 DB_ENV *dbenv; 321 u_int32_t *flagsp; 322{ 323 DB_LOG *dblp; 324 ENV *env; 325 LOG *lp; 326 u_int32_t flags; 327 328 env = dbenv->env; 329 330 if ((dblp = env->lg_handle) == NULL) 331 return; 332 333 lp = dblp->reginfo.primary; 334 335 flags = *flagsp; 336 if (lp->db_log_autoremove) 337 LF_SET(DB_LOG_AUTO_REMOVE); 338 else 339 LF_CLR(DB_LOG_AUTO_REMOVE); 340 if (lp->db_log_inmemory) 341 LF_SET(DB_LOG_IN_MEMORY); 342 else 343 LF_CLR(DB_LOG_IN_MEMORY); 344 *flagsp = flags; 345} 346 347/* 348 * __log_set_flags -- 349 * DB_ENV->set_flags. 350 * 351 * PUBLIC: void __log_set_flags __P((ENV *, u_int32_t, int)); 352 */ 353void 354__log_set_flags(env, flags, on) 355 ENV *env; 356 u_int32_t flags; 357 int on; 358{ 359 DB_LOG *dblp; 360 LOG *lp; 361 362 if ((dblp = env->lg_handle) == NULL) 363 return; 364 365 lp = dblp->reginfo.primary; 366 367 if (LF_ISSET(DB_LOG_AUTO_REMOVE)) 368 lp->db_log_autoremove = on ? 1 : 0; 369 if (LF_ISSET(DB_LOG_IN_MEMORY)) 370 lp->db_log_inmemory = on ? 1 : 0; 371} 372 373/* 374 * List of flags we can handle here. DB_LOG_INMEMORY must be 375 * processed before creating the region, leave it out for now. 376 */ 377#undef OK_FLAGS 378#define OK_FLAGS \ 379 (DB_LOG_AUTO_REMOVE | DB_LOG_DIRECT | \ 380 DB_LOG_DSYNC | DB_LOG_IN_MEMORY | DB_LOG_ZERO) 381#ifndef BREW 382static 383#endif 384const FLAG_MAP LogMap[] = { 385 { DB_LOG_AUTO_REMOVE, DBLOG_AUTOREMOVE}, 386 { DB_LOG_DIRECT, DBLOG_DIRECT}, 387 { DB_LOG_DSYNC, DBLOG_DSYNC}, 388 { DB_LOG_IN_MEMORY, DBLOG_INMEMORY}, 389 { DB_LOG_ZERO, DBLOG_ZERO} 390}; 391/* 392 * __log_get_config -- 393 * Configure the logging subsystem. 394 * 395 * PUBLIC: int __log_get_config __P((DB_ENV *, u_int32_t, int *)); 396 */ 397int 398__log_get_config(dbenv, which, onp) 399 DB_ENV *dbenv; 400 u_int32_t which; 401 int *onp; 402{ 403 ENV *env; 404 DB_LOG *dblp; 405 u_int32_t flags; 406 407 env = dbenv->env; 408 if (FLD_ISSET(which, ~OK_FLAGS)) 409 return (__db_ferr(env, "DB_ENV->log_get_config", 0)); 410 dblp = env->lg_handle; 411 ENV_REQUIRES_CONFIG(env, dblp, "DB_ENV->log_get_config", DB_INIT_LOG); 412 413 __env_fetch_flags(LogMap, sizeof(LogMap), &dblp->flags, &flags); 414 __log_get_flags(dbenv, &flags); 415 if (LF_ISSET(which)) 416 *onp = 1; 417 else 418 *onp = 0; 419 420 return (0); 421} 422 423/* 424 * __log_set_config -- 425 * Configure the logging subsystem. 426 * 427 * PUBLIC: int __log_set_config __P((DB_ENV *, u_int32_t, int)); 428 */ 429int 430__log_set_config(dbenv, flags, on) 431 DB_ENV *dbenv; 432 u_int32_t flags; 433 int on; 434{ 435 return (__log_set_config_int(dbenv, flags, on, 0)); 436} 437/* 438 * __log_set_config_int -- 439 * Configure the logging subsystem. 440 * 441 * PUBLIC: int __log_set_config_int __P((DB_ENV *, u_int32_t, int, int)); 442 */ 443int 444__log_set_config_int(dbenv, flags, on, in_open) 445 DB_ENV *dbenv; 446 u_int32_t flags; 447 int on; 448 int in_open; 449{ 450 ENV *env; 451 DB_LOG *dblp; 452 u_int32_t mapped_flags; 453 454 env = dbenv->env; 455 dblp = env->lg_handle; 456 if (FLD_ISSET(flags, ~OK_FLAGS)) 457 return (__db_ferr(env, "DB_ENV->log_set_config", 0)); 458 ENV_NOT_CONFIGURED(env, dblp, "DB_ENV->log_set_config", DB_INIT_LOG); 459 if (LF_ISSET(DB_LOG_DIRECT) && __os_support_direct_io() == 0) { 460 __db_errx(env, 461"DB_ENV->log_set_config: direct I/O either not configured or not supported"); 462 return (EINVAL); 463 } 464 465 if (LOGGING_ON(env)) { 466 if (!in_open && LF_ISSET(DB_LOG_IN_MEMORY)) 467 ENV_ILLEGAL_AFTER_OPEN(env, 468 "DB_ENV->log_set_config: DB_LOG_IN_MEMORY"); 469 __log_set_flags(env, flags, on); 470 mapped_flags = 0; 471 __env_map_flags(LogMap, sizeof(LogMap), &flags, &mapped_flags); 472 if (on) 473 F_SET(dblp, mapped_flags); 474 else 475 F_CLR(dblp, mapped_flags); 476 } else { 477 /* 478 * DB_LOG_IN_MEMORY, DB_TXN_NOSYNC and DB_TXN_WRITE_NOSYNC 479 * are mutually incompatible. If we're setting one of them, 480 * clear all current settings. 481 */ 482 if (on && LF_ISSET(DB_LOG_IN_MEMORY)) 483 F_CLR(dbenv, 484 DB_ENV_TXN_NOSYNC | DB_ENV_TXN_WRITE_NOSYNC); 485 486 if (on) 487 FLD_SET(dbenv->lg_flags, flags); 488 else 489 FLD_CLR(dbenv->lg_flags, flags); 490 } 491 492 return (0); 493} 494 495/* 496 * __log_check_sizes -- 497 * Makes sure that the log file size and log buffer size are compatible. 498 * 499 * PUBLIC: int __log_check_sizes __P((ENV *, u_int32_t, u_int32_t)); 500 */ 501int 502__log_check_sizes(env, lg_max, lg_bsize) 503 ENV *env; 504 u_int32_t lg_max; 505 u_int32_t lg_bsize; 506{ 507 DB_ENV *dbenv; 508 LOG *lp; 509 int inmem; 510 511 dbenv = env->dbenv; 512 513 if (LOGGING_ON(env)) { 514 lp = env->lg_handle->reginfo.primary; 515 inmem = lp->db_log_inmemory; 516 lg_bsize = lp->buffer_size; 517 } else 518 inmem = (FLD_ISSET(dbenv->lg_flags, DB_LOG_IN_MEMORY) != 0); 519 520 if (inmem) { 521 if (lg_bsize == 0) 522 lg_bsize = LG_BSIZE_INMEM; 523 if (lg_max == 0) 524 lg_max = LG_MAX_INMEM; 525 526 if (lg_bsize <= lg_max) { 527 __db_errx(env, 528 "in-memory log buffer must be larger than the log file size"); 529 return (EINVAL); 530 } 531 } 532 533 return (0); 534} 535