1 /*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 1999, 2013 Oracle and/or its affiliates. All rights reserved.
5 *
6 * $Id$
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
19 static 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 */
27 int
tcl_LogArchive(interp,objc,objv,dbenv)28 tcl_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 */
98 int
tcl_LogCompare(interp,objc,objv)99 tcl_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 */
137 int
tcl_LogFile(interp,objc,objv,dbenv)138 tcl_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 */
196 int
tcl_LogFlush(interp,objc,objv,dbenv)197 tcl_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 */
235 int
tcl_LogGet(interp,objc,objv,dbenv)236 tcl_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 */
257 int
tcl_LogPut(interp,objc,objv,dbenv)258 tcl_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 */
339 int
tcl_LogStat(interp,objc,objv,dbenv)340 tcl_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("Initial fileid allocation", sp->st_fileid_init);
380 MAKE_STAT_LIST("Current fileids in use", sp->st_nfileid);
381 MAKE_STAT_LIST("Maximum fileids ever used", sp->st_maxnfileid);
382 MAKE_WSTAT_LIST("Log file records written", sp->st_record);
383 MAKE_STAT_LIST("Mbytes written", sp->st_w_mbytes);
384 MAKE_STAT_LIST("Bytes written (over Mb)", sp->st_w_bytes);
385 MAKE_STAT_LIST("Mbytes written since checkpoint", sp->st_wc_mbytes);
386 MAKE_STAT_LIST("Bytes written (over Mb) since checkpoint",
387 sp->st_wc_bytes);
388 MAKE_WSTAT_LIST("Times log written", sp->st_wcount);
389 MAKE_STAT_LIST("Times log written because cache filled up",
390 sp->st_wcount_fill);
391 MAKE_WSTAT_LIST("Times log read from disk", sp->st_rcount);
392 MAKE_WSTAT_LIST("Times log flushed to disk", sp->st_scount);
393 MAKE_STAT_LIST("Current log file number", sp->st_cur_file);
394 MAKE_STAT_LIST("Current log file offset", sp->st_cur_offset);
395 MAKE_STAT_LIST("On-disk log file number", sp->st_disk_file);
396 MAKE_STAT_LIST("On-disk log file offset", sp->st_disk_offset);
397 MAKE_STAT_LIST("Max commits in a log flush", sp->st_maxcommitperflush);
398 MAKE_STAT_LIST("Min commits in a log flush", sp->st_mincommitperflush);
399 MAKE_WSTAT_LIST("Number of region lock waits", sp->st_region_wait);
400 MAKE_WSTAT_LIST("Number of region lock nowaits", sp->st_region_nowait);
401 #endif
402 Tcl_SetObjResult(interp, res);
403 error:
404 __os_ufree(dbenv->env, sp);
405 return (result);
406 }
407
408 /*
409 * tcl_LogStatPrint --
410 *
411 * PUBLIC: int tcl_LogStatPrint __P((Tcl_Interp *, int,
412 * PUBLIC: Tcl_Obj * CONST*, DB_ENV *));
413 */
414 int
tcl_LogStatPrint(interp,objc,objv,dbenv)415 tcl_LogStatPrint(interp, objc, objv, dbenv)
416 Tcl_Interp *interp; /* Interpreter */
417 int objc; /* How many arguments? */
418 Tcl_Obj *CONST objv[]; /* The argument objects */
419 DB_ENV *dbenv; /* Environment pointer */
420 { static const char *logstatprtopts[] = {
421 "-all",
422 "-clear",
423 NULL
424 };
425 enum logstatprtopts {
426 LOGSTATPRTALL,
427 LOGSTATPRTCLEAR
428 };
429 u_int32_t flag;
430 int i, optindex, result, ret;
431
432 result = TCL_OK;
433 flag = 0;
434 i = 2;
435
436 while (i < objc) {
437 if (Tcl_GetIndexFromObj(interp, objv[i], logstatprtopts,
438 "option", TCL_EXACT, &optindex) != TCL_OK) {
439 result = IS_HELP(objv[i]);
440 goto error;
441 }
442 i++;
443 switch ((enum logstatprtopts)optindex) {
444 case LOGSTATPRTALL:
445 flag |= DB_STAT_ALL;
446 break;
447 case LOGSTATPRTCLEAR:
448 flag |= DB_STAT_CLEAR;
449 break;
450 }
451 if (result != TCL_OK)
452 break;
453 }
454 if (result != TCL_OK)
455 goto error;
456
457 _debug_check();
458 ret = dbenv->log_stat_print(dbenv, flag);
459 result = _ReturnSetup(interp,
460 ret, DB_RETOK_STD(ret), "dbenv log_stat_print");
461 error:
462 return (result);
463
464 }
465
466 /*
467 * logc_Cmd --
468 * Implements the log cursor command.
469 *
470 * PUBLIC: int logc_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*));
471 */
472 int
logc_Cmd(clientData,interp,objc,objv)473 logc_Cmd(clientData, interp, objc, objv)
474 ClientData clientData; /* Cursor handle */
475 Tcl_Interp *interp; /* Interpreter */
476 int objc; /* How many arguments? */
477 Tcl_Obj *CONST objv[]; /* The argument objects */
478 {
479 static const char *logccmds[] = {
480 "close",
481 "get",
482 "version",
483 NULL
484 };
485 enum logccmds {
486 LOGCCLOSE,
487 LOGCGET,
488 LOGCVERSION
489 };
490 DB_LOGC *logc;
491 DBTCL_INFO *logcip;
492 Tcl_Obj *res;
493 u_int32_t version;
494 int cmdindex, result, ret;
495
496 Tcl_ResetResult(interp);
497 logc = (DB_LOGC *)clientData;
498 logcip = _PtrToInfo((void *)logc);
499 result = TCL_OK;
500
501 if (objc <= 1) {
502 Tcl_WrongNumArgs(interp, 1, objv, "command cmdargs");
503 return (TCL_ERROR);
504 }
505 if (logc == NULL) {
506 Tcl_SetResult(interp, "NULL logc pointer", TCL_STATIC);
507 return (TCL_ERROR);
508 }
509 if (logcip == NULL) {
510 Tcl_SetResult(interp, "NULL logc info pointer", TCL_STATIC);
511 return (TCL_ERROR);
512 }
513
514 /*
515 * Get the command name index from the object based on the berkdbcmds
516 * defined above.
517 */
518 if (Tcl_GetIndexFromObj(interp, objv[1], logccmds, "command",
519 TCL_EXACT, &cmdindex) != TCL_OK)
520 return (IS_HELP(objv[1]));
521 switch ((enum logccmds)cmdindex) {
522 case LOGCCLOSE:
523 /*
524 * No args for this. Error if there are some.
525 */
526 if (objc > 2) {
527 Tcl_WrongNumArgs(interp, 2, objv, NULL);
528 return (TCL_ERROR);
529 }
530 _debug_check();
531 ret = logc->close(logc, 0);
532 result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
533 "logc close");
534 if (result == TCL_OK) {
535 (void)Tcl_DeleteCommand(interp, logcip->i_name);
536 _DeleteInfo(logcip);
537 }
538 break;
539 case LOGCGET:
540 result = tcl_LogcGet(interp, objc, objv, logc);
541 break;
542 case LOGCVERSION:
543 /*
544 * No args for this. Error if there are some.
545 */
546 if (objc > 2) {
547 Tcl_WrongNumArgs(interp, 2, objv, NULL);
548 return (TCL_ERROR);
549 }
550 _debug_check();
551 ret = logc->version(logc, &version, 0);
552 if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
553 "logc version")) == TCL_OK) {
554 res = Tcl_NewIntObj((int)version);
555 Tcl_SetObjResult(interp, res);
556 }
557 break;
558 }
559
560 return (result);
561 }
562
563 static int
tcl_LogcGet(interp,objc,objv,logc)564 tcl_LogcGet(interp, objc, objv, logc)
565 Tcl_Interp *interp;
566 int objc;
567 Tcl_Obj * CONST *objv;
568 DB_LOGC *logc;
569 {
570 static const char *logcgetopts[] = {
571 "-current",
572 "-first",
573 "-last",
574 "-next",
575 "-prev",
576 "-set",
577 NULL
578 };
579 enum logcgetopts {
580 LOGCGET_CURRENT,
581 LOGCGET_FIRST,
582 LOGCGET_LAST,
583 LOGCGET_NEXT,
584 LOGCGET_PREV,
585 LOGCGET_SET
586 };
587 DB_LSN lsn;
588 DBT data;
589 Tcl_Obj *dataobj, *lsnlist, *myobjv[2], *res;
590 u_int32_t flag;
591 int i, myobjc, optindex, result, ret;
592
593 result = TCL_OK;
594 res = NULL;
595 flag = 0;
596
597 if (objc < 3) {
598 Tcl_WrongNumArgs(interp, 2, objv, "?-args? lsn");
599 return (TCL_ERROR);
600 }
601
602 /*
603 * Get the command name index from the object based on the options
604 * defined above.
605 */
606 i = 2;
607 while (i < objc) {
608 if (Tcl_GetIndexFromObj(interp, objv[i],
609 logcgetopts, "option", TCL_EXACT, &optindex) != TCL_OK)
610 return (IS_HELP(objv[i]));
611 i++;
612 switch ((enum logcgetopts)optindex) {
613 case LOGCGET_CURRENT:
614 FLAG_CHECK(flag);
615 flag |= DB_CURRENT;
616 break;
617 case LOGCGET_FIRST:
618 FLAG_CHECK(flag);
619 flag |= DB_FIRST;
620 break;
621 case LOGCGET_LAST:
622 FLAG_CHECK(flag);
623 flag |= DB_LAST;
624 break;
625 case LOGCGET_NEXT:
626 FLAG_CHECK(flag);
627 flag |= DB_NEXT;
628 break;
629 case LOGCGET_PREV:
630 FLAG_CHECK(flag);
631 flag |= DB_PREV;
632 break;
633 case LOGCGET_SET:
634 FLAG_CHECK(flag);
635 flag |= DB_SET;
636 if (i == objc) {
637 Tcl_WrongNumArgs(interp, 2, objv, "?-set lsn?");
638 result = TCL_ERROR;
639 break;
640 }
641 result = _GetLsn(interp, objv[i++], &lsn);
642 break;
643 }
644 }
645
646 if (result == TCL_ERROR)
647 return (result);
648
649 memset(&data, 0, sizeof(data));
650
651 _debug_check();
652 ret = logc->get(logc, &lsn, &data, flag);
653
654 res = Tcl_NewListObj(0, NULL);
655 if (res == NULL)
656 goto memerr;
657
658 if (ret == 0) {
659 /*
660 * Success. Set up return list as {LSN data} where LSN
661 * is a sublist {file offset}.
662 */
663 myobjc = 2;
664 myobjv[0] = Tcl_NewWideIntObj((Tcl_WideInt)lsn.file);
665 myobjv[1] = Tcl_NewWideIntObj((Tcl_WideInt)lsn.offset);
666 lsnlist = Tcl_NewListObj(myobjc, myobjv);
667 if (lsnlist == NULL)
668 goto memerr;
669
670 result = Tcl_ListObjAppendElement(interp, res, lsnlist);
671 dataobj = NewStringObj(data.data, data.size);
672 if (dataobj == NULL) {
673 goto memerr;
674 }
675 result = Tcl_ListObjAppendElement(interp, res, dataobj);
676 } else
677 result = _ReturnSetup(interp, ret, DB_RETOK_LGGET(ret),
678 "DB_LOGC->get");
679
680 Tcl_SetObjResult(interp, res);
681
682 if (0) {
683 memerr: if (res != NULL) {
684 Tcl_DecrRefCount(res);
685 }
686 Tcl_SetResult(interp, "allocation failed", TCL_STATIC);
687 }
688
689 return (result);
690 }
691
692 static const char *confwhich[] = {
693 "autoremove",
694 "direct",
695 "dsync",
696 "inmemory",
697 "zero",
698 NULL
699 };
700 enum logwhich {
701 LOGCONF_AUTO,
702 LOGCONF_DIRECT,
703 LOGCONF_DSYNC,
704 LOGCONF_INMEMORY,
705 LOGCONF_ZERO
706 };
707
708 /*
709 * tcl_LogConfig --
710 * Call DB_ENV->log_set_config().
711 *
712 * PUBLIC: int tcl_LogConfig
713 * PUBLIC: __P((Tcl_Interp *, DB_ENV *, Tcl_Obj *, Tcl_Obj *));
714 */
715 int
tcl_LogConfig(interp,dbenv,which,onoff)716 tcl_LogConfig(interp, dbenv, which, onoff)
717 Tcl_Interp *interp; /* Interpreter */
718 DB_ENV *dbenv; /* Environment pointer */
719 Tcl_Obj *which; /* {which on|off} */
720 Tcl_Obj *onoff;
721 {
722 static const char *confonoff[] = {
723 "off",
724 "on",
725 NULL
726 };
727 enum confonoff {
728 LOGCONF_OFF,
729 LOGCONF_ON
730 };
731 int on, optindex, ret;
732 u_int32_t wh;
733
734 if (Tcl_GetIndexFromObj(interp,
735 which, confwhich, "option", TCL_EXACT, &optindex) != TCL_OK)
736 return (IS_HELP(which));
737
738 switch ((enum logwhich)optindex) {
739 case LOGCONF_AUTO:
740 wh = DB_LOG_AUTO_REMOVE;
741 break;
742 case LOGCONF_DIRECT:
743 wh = DB_LOG_DIRECT;
744 break;
745 case LOGCONF_DSYNC:
746 wh = DB_LOG_DSYNC;
747 break;
748 case LOGCONF_INMEMORY:
749 wh = DB_LOG_IN_MEMORY;
750 break;
751 case LOGCONF_ZERO:
752 wh = DB_LOG_ZERO;
753 break;
754 default:
755 return (TCL_ERROR);
756 }
757 if (Tcl_GetIndexFromObj(interp,
758 onoff, confonoff, "option", TCL_EXACT, &optindex) != TCL_OK)
759 return (IS_HELP(onoff));
760 switch ((enum confonoff)optindex) {
761 case LOGCONF_OFF:
762 on = 0;
763 break;
764 case LOGCONF_ON:
765 on = 1;
766 break;
767 default:
768 return (TCL_ERROR);
769 }
770 ret = dbenv->log_set_config(dbenv, wh, on);
771 return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret),
772 "env rep_config"));
773 }
774
775 /*
776 * tcl_LogGetConfig --
777 * Call DB_ENV->rep_get_config().
778 *
779 * PUBLIC: int tcl_LogGetConfig
780 * PUBLIC: __P((Tcl_Interp *, DB_ENV *, Tcl_Obj *));
781 */
782 int
tcl_LogGetConfig(interp,dbenv,which)783 tcl_LogGetConfig(interp, dbenv, which)
784 Tcl_Interp *interp; /* Interpreter */
785 DB_ENV *dbenv; /* Environment pointer */
786 Tcl_Obj *which; /* which flag */
787 {
788 Tcl_Obj *res;
789 int on, optindex, result, ret;
790 u_int32_t wh;
791
792 if (Tcl_GetIndexFromObj(interp, which, confwhich, "option",
793 TCL_EXACT, &optindex) != TCL_OK)
794 return (IS_HELP(which));
795
796 res = NULL;
797 switch ((enum logwhich)optindex) {
798 case LOGCONF_AUTO:
799 wh = DB_LOG_AUTO_REMOVE;
800 break;
801 case LOGCONF_DIRECT:
802 wh = DB_LOG_DIRECT;
803 break;
804 case LOGCONF_DSYNC:
805 wh = DB_LOG_DSYNC;
806 break;
807 case LOGCONF_INMEMORY:
808 wh = DB_LOG_IN_MEMORY;
809 break;
810 case LOGCONF_ZERO:
811 wh = DB_LOG_ZERO;
812 break;
813 default:
814 return (TCL_ERROR);
815 }
816 ret = dbenv->log_get_config(dbenv, wh, &on);
817 if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
818 "env log_config")) == TCL_OK) {
819 res = Tcl_NewIntObj(on);
820 Tcl_SetObjResult(interp, res);
821 }
822 return (result);
823 }
824 #endif
825