1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1999,2008 Oracle. All rights reserved. 5 * 6 * $Id: tcl_log.c,v 12.18 2008/01/08 20:58:52 bostic Exp $ 7 */ 8 9#include "db_config.h" 10 11#include "db_int.h" 12#ifdef HAVE_SYSTEM_INCLUDE_FILES 13#include <tcl.h> 14#endif 15#include "dbinc/log.h" 16#include "dbinc/tcl_db.h" 17 18#ifdef CONFIG_TEST 19static int tcl_LogcGet __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_LOGC *)); 20 21/* 22 * tcl_LogArchive -- 23 * 24 * PUBLIC: int tcl_LogArchive __P((Tcl_Interp *, int, 25 * PUBLIC: Tcl_Obj * CONST*, DB_ENV *)); 26 */ 27int 28tcl_LogArchive(interp, objc, objv, dbenv) 29 Tcl_Interp *interp; /* Interpreter */ 30 int objc; /* How many arguments? */ 31 Tcl_Obj *CONST objv[]; /* The argument objects */ 32 DB_ENV *dbenv; /* Environment pointer */ 33{ 34 static const char *archopts[] = { 35 "-arch_abs", "-arch_data", "-arch_log", "-arch_remove", 36 NULL 37 }; 38 enum archopts { 39 ARCH_ABS, ARCH_DATA, ARCH_LOG, ARCH_REMOVE 40 }; 41 Tcl_Obj *fileobj, *res; 42 u_int32_t flag; 43 int i, optindex, result, ret; 44 char **file, **list; 45 46 result = TCL_OK; 47 flag = 0; 48 /* 49 * Get the flag index from the object based on the options 50 * defined above. 51 */ 52 i = 2; 53 while (i < objc) { 54 if (Tcl_GetIndexFromObj(interp, objv[i], 55 archopts, "option", TCL_EXACT, &optindex) != TCL_OK) 56 return (IS_HELP(objv[i])); 57 i++; 58 switch ((enum archopts)optindex) { 59 case ARCH_ABS: 60 flag |= DB_ARCH_ABS; 61 break; 62 case ARCH_DATA: 63 flag |= DB_ARCH_DATA; 64 break; 65 case ARCH_LOG: 66 flag |= DB_ARCH_LOG; 67 break; 68 case ARCH_REMOVE: 69 flag |= DB_ARCH_REMOVE; 70 break; 71 } 72 } 73 _debug_check(); 74 list = NULL; 75 ret = dbenv->log_archive(dbenv, &list, flag); 76 result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "log archive"); 77 if (result == TCL_OK) { 78 res = Tcl_NewListObj(0, NULL); 79 for (file = list; file != NULL && *file != NULL; file++) { 80 fileobj = NewStringObj(*file, strlen(*file)); 81 result = Tcl_ListObjAppendElement(interp, res, fileobj); 82 if (result != TCL_OK) 83 break; 84 } 85 Tcl_SetObjResult(interp, res); 86 } 87 if (list != NULL) 88 __os_ufree(dbenv->env, list); 89 return (result); 90} 91 92/* 93 * tcl_LogCompare -- 94 * 95 * PUBLIC: int tcl_LogCompare __P((Tcl_Interp *, int, 96 * PUBLIC: Tcl_Obj * CONST*)); 97 */ 98int 99tcl_LogCompare(interp, objc, objv) 100 Tcl_Interp *interp; /* Interpreter */ 101 int objc; /* How many arguments? */ 102 Tcl_Obj *CONST objv[]; /* The argument objects */ 103{ 104 DB_LSN lsn0, lsn1; 105 Tcl_Obj *res; 106 int result, ret; 107 108 result = TCL_OK; 109 /* 110 * No flags, must be 4 args. 111 */ 112 if (objc != 4) { 113 Tcl_WrongNumArgs(interp, 2, objv, "lsn1 lsn2"); 114 return (TCL_ERROR); 115 } 116 117 result = _GetLsn(interp, objv[2], &lsn0); 118 if (result == TCL_ERROR) 119 return (result); 120 result = _GetLsn(interp, objv[3], &lsn1); 121 if (result == TCL_ERROR) 122 return (result); 123 124 _debug_check(); 125 ret = log_compare(&lsn0, &lsn1); 126 res = Tcl_NewIntObj(ret); 127 Tcl_SetObjResult(interp, res); 128 return (result); 129} 130 131/* 132 * tcl_LogFile -- 133 * 134 * PUBLIC: int tcl_LogFile __P((Tcl_Interp *, int, 135 * PUBLIC: Tcl_Obj * CONST*, DB_ENV *)); 136 */ 137int 138tcl_LogFile(interp, objc, objv, dbenv) 139 Tcl_Interp *interp; /* Interpreter */ 140 int objc; /* How many arguments? */ 141 Tcl_Obj *CONST objv[]; /* The argument objects */ 142 DB_ENV *dbenv; /* Environment pointer */ 143{ 144 DB_LSN lsn; 145 Tcl_Obj *res; 146 size_t len; 147 int result, ret; 148 char *name; 149 150 result = TCL_OK; 151 /* 152 * No flags, must be 3 args. 153 */ 154 if (objc != 3) { 155 Tcl_WrongNumArgs(interp, 2, objv, "lsn"); 156 return (TCL_ERROR); 157 } 158 159 result = _GetLsn(interp, objv[2], &lsn); 160 if (result == TCL_ERROR) 161 return (result); 162 163 len = MSG_SIZE; 164 ret = ENOMEM; 165 name = NULL; 166 while (ret == ENOMEM) { 167 if (name != NULL) 168 __os_free(dbenv->env, name); 169 ret = __os_malloc(dbenv->env, len, &name); 170 if (ret != 0) { 171 Tcl_SetResult(interp, db_strerror(ret), TCL_STATIC); 172 break; 173 } 174 _debug_check(); 175 ret = dbenv->log_file(dbenv, &lsn, name, len); 176 len *= 2; 177 } 178 result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "log_file"); 179 if (ret == 0) { 180 res = NewStringObj(name, strlen(name)); 181 Tcl_SetObjResult(interp, res); 182 } 183 184 if (name != NULL) 185 __os_free(dbenv->env, name); 186 187 return (result); 188} 189 190/* 191 * tcl_LogFlush -- 192 * 193 * PUBLIC: int tcl_LogFlush __P((Tcl_Interp *, int, 194 * PUBLIC: Tcl_Obj * CONST*, DB_ENV *)); 195 */ 196int 197tcl_LogFlush(interp, objc, objv, dbenv) 198 Tcl_Interp *interp; /* Interpreter */ 199 int objc; /* How many arguments? */ 200 Tcl_Obj *CONST objv[]; /* The argument objects */ 201 DB_ENV *dbenv; /* Environment pointer */ 202{ 203 DB_LSN lsn, *lsnp; 204 int result, ret; 205 206 result = TCL_OK; 207 /* 208 * No flags, must be 2 or 3 args. 209 */ 210 if (objc > 3) { 211 Tcl_WrongNumArgs(interp, 2, objv, "?lsn?"); 212 return (TCL_ERROR); 213 } 214 215 if (objc == 3) { 216 lsnp = &lsn; 217 result = _GetLsn(interp, objv[2], &lsn); 218 if (result == TCL_ERROR) 219 return (result); 220 } else 221 lsnp = NULL; 222 223 _debug_check(); 224 ret = dbenv->log_flush(dbenv, lsnp); 225 result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "log_flush"); 226 return (result); 227} 228 229/* 230 * tcl_LogGet -- 231 * 232 * PUBLIC: int tcl_LogGet __P((Tcl_Interp *, int, 233 * PUBLIC: Tcl_Obj * CONST*, DB_ENV *)); 234 */ 235int 236tcl_LogGet(interp, objc, objv, dbenv) 237 Tcl_Interp *interp; /* Interpreter */ 238 int objc; /* How many arguments? */ 239 Tcl_Obj *CONST objv[]; /* The argument objects */ 240 DB_ENV *dbenv; /* Environment pointer */ 241{ 242 243 COMPQUIET(objv, NULL); 244 COMPQUIET(objc, 0); 245 COMPQUIET(dbenv, NULL); 246 247 Tcl_SetResult(interp, "FAIL: log_get deprecated\n", TCL_STATIC); 248 return (TCL_ERROR); 249} 250 251/* 252 * tcl_LogPut -- 253 * 254 * PUBLIC: int tcl_LogPut __P((Tcl_Interp *, int, 255 * PUBLIC: Tcl_Obj * CONST*, DB_ENV *)); 256 */ 257int 258tcl_LogPut(interp, objc, objv, dbenv) 259 Tcl_Interp *interp; /* Interpreter */ 260 int objc; /* How many arguments? */ 261 Tcl_Obj *CONST objv[]; /* The argument objects */ 262 DB_ENV *dbenv; /* Environment pointer */ 263{ 264 static const char *logputopts[] = { 265 "-flush", 266 NULL 267 }; 268 enum logputopts { 269 LOGPUT_FLUSH 270 }; 271 DB_LSN lsn; 272 DBT data; 273 Tcl_Obj *intobj, *res; 274 void *dtmp; 275 u_int32_t flag; 276 int freedata, optindex, result, ret; 277 278 result = TCL_OK; 279 flag = 0; 280 freedata = 0; 281 if (objc < 3) { 282 Tcl_WrongNumArgs(interp, 2, objv, "?-args? record"); 283 return (TCL_ERROR); 284 } 285 286 /* 287 * Data/record must be the last arg. 288 */ 289 memset(&data, 0, sizeof(data)); 290 ret = _CopyObjBytes(interp, objv[objc-1], &dtmp, 291 &data.size, &freedata); 292 if (ret != 0) { 293 result = _ReturnSetup(interp, ret, 294 DB_RETOK_STD(ret), "log put"); 295 return (result); 296 } 297 data.data = dtmp; 298 299 /* 300 * Get the command name index from the object based on the options 301 * defined above. 302 */ 303 if (objc == 4) { 304 if (Tcl_GetIndexFromObj(interp, objv[2], 305 logputopts, "option", TCL_EXACT, &optindex) != TCL_OK) { 306 return (IS_HELP(objv[2])); 307 } 308 switch ((enum logputopts)optindex) { 309 case LOGPUT_FLUSH: 310 flag = DB_FLUSH; 311 break; 312 } 313 } 314 315 if (result == TCL_ERROR) 316 return (result); 317 318 _debug_check(); 319 ret = dbenv->log_put(dbenv, &lsn, &data, flag); 320 result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "log_put"); 321 if (result == TCL_ERROR) 322 return (result); 323 res = Tcl_NewListObj(0, NULL); 324 intobj = Tcl_NewWideIntObj((Tcl_WideInt)lsn.file); 325 result = Tcl_ListObjAppendElement(interp, res, intobj); 326 intobj = Tcl_NewWideIntObj((Tcl_WideInt)lsn.offset); 327 result = Tcl_ListObjAppendElement(interp, res, intobj); 328 Tcl_SetObjResult(interp, res); 329 if (freedata) 330 __os_free(NULL, dtmp); 331 return (result); 332} 333/* 334 * tcl_LogStat -- 335 * 336 * PUBLIC: int tcl_LogStat __P((Tcl_Interp *, int, 337 * PUBLIC: Tcl_Obj * CONST*, DB_ENV *)); 338 */ 339int 340tcl_LogStat(interp, objc, objv, dbenv) 341 Tcl_Interp *interp; /* Interpreter */ 342 int objc; /* How many arguments? */ 343 Tcl_Obj *CONST objv[]; /* The argument objects */ 344 DB_ENV *dbenv; /* Environment pointer */ 345{ 346 DB_LOG_STAT *sp; 347 Tcl_Obj *res; 348 int result, ret; 349 350 result = TCL_OK; 351 /* 352 * No args for this. Error if there are some. 353 */ 354 if (objc != 2) { 355 Tcl_WrongNumArgs(interp, 2, objv, NULL); 356 return (TCL_ERROR); 357 } 358 _debug_check(); 359 ret = dbenv->log_stat(dbenv, &sp, 0); 360 result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "log stat"); 361 if (result == TCL_ERROR) 362 return (result); 363 364 /* 365 * Have our stats, now construct the name value 366 * list pairs and free up the memory. 367 */ 368 res = Tcl_NewObj(); 369 /* 370 * MAKE_STAT_LIST assumes 'res' and 'error' label. 371 */ 372#ifdef HAVE_STATISTICS 373 MAKE_STAT_LIST("Magic", sp->st_magic); 374 MAKE_STAT_LIST("Log file Version", sp->st_version); 375 MAKE_STAT_LIST("Region size", sp->st_regsize); 376 MAKE_STAT_LIST("Log file mode", sp->st_mode); 377 MAKE_STAT_LIST("Log record cache size", sp->st_lg_bsize); 378 MAKE_STAT_LIST("Current log file size", sp->st_lg_size); 379 MAKE_STAT_LIST("Log file records written", sp->st_record); 380 MAKE_STAT_LIST("Mbytes written", sp->st_w_mbytes); 381 MAKE_STAT_LIST("Bytes written (over Mb)", sp->st_w_bytes); 382 MAKE_STAT_LIST("Mbytes written since checkpoint", sp->st_wc_mbytes); 383 MAKE_STAT_LIST("Bytes written (over Mb) since checkpoint", 384 sp->st_wc_bytes); 385 MAKE_STAT_LIST("Times log written", sp->st_wcount); 386 MAKE_STAT_LIST("Times log written because cache filled up", 387 sp->st_wcount_fill); 388 MAKE_STAT_LIST("Times log read from disk", sp->st_rcount); 389 MAKE_STAT_LIST("Times log flushed to disk", sp->st_scount); 390 MAKE_STAT_LIST("Current log file number", sp->st_cur_file); 391 MAKE_STAT_LIST("Current log file offset", sp->st_cur_offset); 392 MAKE_STAT_LIST("On-disk log file number", sp->st_disk_file); 393 MAKE_STAT_LIST("On-disk log file offset", sp->st_disk_offset); 394 MAKE_STAT_LIST("Max commits in a log flush", sp->st_maxcommitperflush); 395 MAKE_STAT_LIST("Min commits in a log flush", sp->st_mincommitperflush); 396 MAKE_STAT_LIST("Number of region lock waits", sp->st_region_wait); 397 MAKE_STAT_LIST("Number of region lock nowaits", sp->st_region_nowait); 398#endif 399 Tcl_SetObjResult(interp, res); 400error: 401 __os_ufree(dbenv->env, sp); 402 return (result); 403} 404 405/* 406 * logc_Cmd -- 407 * Implements the log cursor command. 408 * 409 * PUBLIC: int logc_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*)); 410 */ 411int 412logc_Cmd(clientData, interp, objc, objv) 413 ClientData clientData; /* Cursor handle */ 414 Tcl_Interp *interp; /* Interpreter */ 415 int objc; /* How many arguments? */ 416 Tcl_Obj *CONST objv[]; /* The argument objects */ 417{ 418 static const char *logccmds[] = { 419 "close", 420 "get", 421 "version", 422 NULL 423 }; 424 enum logccmds { 425 LOGCCLOSE, 426 LOGCGET, 427 LOGCVERSION 428 }; 429 DB_LOGC *logc; 430 DBTCL_INFO *logcip; 431 Tcl_Obj *res; 432 u_int32_t version; 433 int cmdindex, result, ret; 434 435 Tcl_ResetResult(interp); 436 logc = (DB_LOGC *)clientData; 437 logcip = _PtrToInfo((void *)logc); 438 result = TCL_OK; 439 440 if (objc <= 1) { 441 Tcl_WrongNumArgs(interp, 1, objv, "command cmdargs"); 442 return (TCL_ERROR); 443 } 444 if (logc == NULL) { 445 Tcl_SetResult(interp, "NULL logc pointer", TCL_STATIC); 446 return (TCL_ERROR); 447 } 448 if (logcip == NULL) { 449 Tcl_SetResult(interp, "NULL logc info pointer", TCL_STATIC); 450 return (TCL_ERROR); 451 } 452 453 /* 454 * Get the command name index from the object based on the berkdbcmds 455 * defined above. 456 */ 457 if (Tcl_GetIndexFromObj(interp, objv[1], logccmds, "command", 458 TCL_EXACT, &cmdindex) != TCL_OK) 459 return (IS_HELP(objv[1])); 460 switch ((enum logccmds)cmdindex) { 461 case LOGCCLOSE: 462 /* 463 * No args for this. Error if there are some. 464 */ 465 if (objc > 2) { 466 Tcl_WrongNumArgs(interp, 2, objv, NULL); 467 return (TCL_ERROR); 468 } 469 _debug_check(); 470 ret = logc->close(logc, 0); 471 result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), 472 "logc close"); 473 if (result == TCL_OK) { 474 (void)Tcl_DeleteCommand(interp, logcip->i_name); 475 _DeleteInfo(logcip); 476 } 477 break; 478 case LOGCGET: 479 result = tcl_LogcGet(interp, objc, objv, logc); 480 break; 481 case LOGCVERSION: 482 /* 483 * No args for this. Error if there are some. 484 */ 485 if (objc > 2) { 486 Tcl_WrongNumArgs(interp, 2, objv, NULL); 487 return (TCL_ERROR); 488 } 489 _debug_check(); 490 ret = logc->version(logc, &version, 0); 491 if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), 492 "logc version")) == TCL_OK) { 493 res = Tcl_NewIntObj((int)version); 494 Tcl_SetObjResult(interp, res); 495 } 496 break; 497 } 498 499 return (result); 500} 501 502static int 503tcl_LogcGet(interp, objc, objv, logc) 504 Tcl_Interp *interp; 505 int objc; 506 Tcl_Obj * CONST *objv; 507 DB_LOGC *logc; 508{ 509 static const char *logcgetopts[] = { 510 "-current", 511 "-first", 512 "-last", 513 "-next", 514 "-prev", 515 "-set", 516 NULL 517 }; 518 enum logcgetopts { 519 LOGCGET_CURRENT, 520 LOGCGET_FIRST, 521 LOGCGET_LAST, 522 LOGCGET_NEXT, 523 LOGCGET_PREV, 524 LOGCGET_SET 525 }; 526 DB_LSN lsn; 527 DBT data; 528 Tcl_Obj *dataobj, *lsnlist, *myobjv[2], *res; 529 u_int32_t flag; 530 int i, myobjc, optindex, result, ret; 531 532 result = TCL_OK; 533 res = NULL; 534 flag = 0; 535 536 if (objc < 3) { 537 Tcl_WrongNumArgs(interp, 2, objv, "?-args? lsn"); 538 return (TCL_ERROR); 539 } 540 541 /* 542 * Get the command name index from the object based on the options 543 * defined above. 544 */ 545 i = 2; 546 while (i < objc) { 547 if (Tcl_GetIndexFromObj(interp, objv[i], 548 logcgetopts, "option", TCL_EXACT, &optindex) != TCL_OK) 549 return (IS_HELP(objv[i])); 550 i++; 551 switch ((enum logcgetopts)optindex) { 552 case LOGCGET_CURRENT: 553 FLAG_CHECK(flag); 554 flag |= DB_CURRENT; 555 break; 556 case LOGCGET_FIRST: 557 FLAG_CHECK(flag); 558 flag |= DB_FIRST; 559 break; 560 case LOGCGET_LAST: 561 FLAG_CHECK(flag); 562 flag |= DB_LAST; 563 break; 564 case LOGCGET_NEXT: 565 FLAG_CHECK(flag); 566 flag |= DB_NEXT; 567 break; 568 case LOGCGET_PREV: 569 FLAG_CHECK(flag); 570 flag |= DB_PREV; 571 break; 572 case LOGCGET_SET: 573 FLAG_CHECK(flag); 574 flag |= DB_SET; 575 if (i == objc) { 576 Tcl_WrongNumArgs(interp, 2, objv, "?-set lsn?"); 577 result = TCL_ERROR; 578 break; 579 } 580 result = _GetLsn(interp, objv[i++], &lsn); 581 break; 582 } 583 } 584 585 if (result == TCL_ERROR) 586 return (result); 587 588 memset(&data, 0, sizeof(data)); 589 590 _debug_check(); 591 ret = logc->get(logc, &lsn, &data, flag); 592 593 res = Tcl_NewListObj(0, NULL); 594 if (res == NULL) 595 goto memerr; 596 597 if (ret == 0) { 598 /* 599 * Success. Set up return list as {LSN data} where LSN 600 * is a sublist {file offset}. 601 */ 602 myobjc = 2; 603 myobjv[0] = Tcl_NewWideIntObj((Tcl_WideInt)lsn.file); 604 myobjv[1] = Tcl_NewWideIntObj((Tcl_WideInt)lsn.offset); 605 lsnlist = Tcl_NewListObj(myobjc, myobjv); 606 if (lsnlist == NULL) 607 goto memerr; 608 609 result = Tcl_ListObjAppendElement(interp, res, lsnlist); 610 dataobj = NewStringObj(data.data, data.size); 611 if (dataobj == NULL) { 612 goto memerr; 613 } 614 result = Tcl_ListObjAppendElement(interp, res, dataobj); 615 } else 616 result = _ReturnSetup(interp, ret, DB_RETOK_LGGET(ret), 617 "DB_LOGC->get"); 618 619 Tcl_SetObjResult(interp, res); 620 621 if (0) { 622memerr: if (res != NULL) { 623 Tcl_DecrRefCount(res); 624 } 625 Tcl_SetResult(interp, "allocation failed", TCL_STATIC); 626 } 627 628 return (result); 629} 630 631static const char *confwhich[] = { 632 "autoremove", 633 "direct", 634 "dsync", 635 "inmemory", 636 "zero", 637 NULL 638}; 639enum logwhich { 640 LOGCONF_AUTO, 641 LOGCONF_DIRECT, 642 LOGCONF_DSYNC, 643 LOGCONF_INMEMORY, 644 LOGCONF_ZERO 645}; 646 647/* 648 * tcl_LogConfig -- 649 * Call DB_ENV->rep_set_config(). 650 * 651 * PUBLIC: int tcl_LogConfig 652 * PUBLIC: __P((Tcl_Interp *, DB_ENV *, Tcl_Obj *)); 653 */ 654int 655tcl_LogConfig(interp, dbenv, list) 656 Tcl_Interp *interp; /* Interpreter */ 657 DB_ENV *dbenv; /* Environment pointer */ 658 Tcl_Obj *list; /* {which on|off} */ 659{ 660 static const char *confonoff[] = { 661 "off", 662 "on", 663 NULL 664 }; 665 enum confonoff { 666 LOGCONF_OFF, 667 LOGCONF_ON 668 }; 669 Tcl_Obj **myobjv, *onoff, *which; 670 int myobjc, on, optindex, result, ret; 671 u_int32_t wh; 672 673 result = Tcl_ListObjGetElements(interp, list, &myobjc, &myobjv); 674 if (myobjc != 2) 675 Tcl_WrongNumArgs(interp, 2, myobjv, "?{which onoff}?"); 676 which = myobjv[0]; 677 onoff = myobjv[1]; 678 if (result != TCL_OK) 679 return (result); 680 if (Tcl_GetIndexFromObj(interp, which, confwhich, "option", 681 TCL_EXACT, &optindex) != TCL_OK) 682 return (IS_HELP(which)); 683 684 switch ((enum logwhich)optindex) { 685 case LOGCONF_AUTO: 686 wh = DB_LOG_AUTO_REMOVE; 687 break; 688 case LOGCONF_DIRECT: 689 wh = DB_LOG_DIRECT; 690 break; 691 case LOGCONF_DSYNC: 692 wh = DB_LOG_DSYNC; 693 break; 694 case LOGCONF_INMEMORY: 695 wh = DB_LOG_IN_MEMORY; 696 break; 697 case LOGCONF_ZERO: 698 wh = DB_LOG_ZERO; 699 break; 700 default: 701 return (TCL_ERROR); 702 } 703 if (Tcl_GetIndexFromObj(interp, onoff, confonoff, "option", 704 TCL_EXACT, &optindex) != TCL_OK) 705 return (IS_HELP(onoff)); 706 switch ((enum confonoff)optindex) { 707 case LOGCONF_OFF: 708 on = 0; 709 break; 710 case LOGCONF_ON: 711 on = 1; 712 break; 713 default: 714 return (TCL_ERROR); 715 } 716 ret = dbenv->log_set_config(dbenv, wh, on); 717 return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret), 718 "env rep_config")); 719} 720 721/* 722 * tcl_LogGetConfig -- 723 * Call DB_ENV->rep_get_config(). 724 * 725 * PUBLIC: int tcl_LogGetConfig 726 * PUBLIC: __P((Tcl_Interp *, DB_ENV *, Tcl_Obj *)); 727 */ 728int 729tcl_LogGetConfig(interp, dbenv, which) 730 Tcl_Interp *interp; /* Interpreter */ 731 DB_ENV *dbenv; /* Environment pointer */ 732 Tcl_Obj *which; /* which flag */ 733{ 734 Tcl_Obj *res; 735 int on, optindex, result, ret; 736 u_int32_t wh; 737 738 if (Tcl_GetIndexFromObj(interp, which, confwhich, "option", 739 TCL_EXACT, &optindex) != TCL_OK) 740 return (IS_HELP(which)); 741 742 res = NULL; 743 switch ((enum logwhich)optindex) { 744 case LOGCONF_AUTO: 745 wh = DB_LOG_AUTO_REMOVE; 746 break; 747 case LOGCONF_DIRECT: 748 wh = DB_LOG_DIRECT; 749 break; 750 case LOGCONF_DSYNC: 751 wh = DB_LOG_DSYNC; 752 break; 753 case LOGCONF_INMEMORY: 754 wh = DB_LOG_IN_MEMORY; 755 break; 756 case LOGCONF_ZERO: 757 wh = DB_LOG_ZERO; 758 break; 759 default: 760 return (TCL_ERROR); 761 } 762 ret = dbenv->log_get_config(dbenv, wh, &on); 763 if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), 764 "env log_config")) == TCL_OK) { 765 res = Tcl_NewIntObj(on); 766 Tcl_SetObjResult(interp, res); 767 } 768 return (result); 769} 770#endif 771