tcl_log.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:14k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 1999-2002
  5.  * Sleepycat Software.  All rights reserved.
  6.  */
  7. #include "db_config.h"
  8. #ifndef lint
  9. static const char revid[] = "$Id: tcl_log.c,v 11.52 2002/08/14 20:11:57 bostic Exp $";
  10. #endif /* not lint */
  11. #ifndef NO_SYSTEM_INCLUDES
  12. #include <sys/types.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <tcl.h>
  16. #endif
  17. #include "db_int.h"
  18. #include "dbinc/log.h"
  19. #include "dbinc/tcl_db.h"
  20. #include "dbinc/txn.h"
  21. #ifdef CONFIG_TEST
  22. static int tcl_LogcGet __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_LOGC *));
  23. /*
  24.  * tcl_LogArchive --
  25.  *
  26.  * PUBLIC: int tcl_LogArchive __P((Tcl_Interp *, int,
  27.  * PUBLIC:    Tcl_Obj * CONST*, DB_ENV *));
  28.  */
  29. int
  30. tcl_LogArchive(interp, objc, objv, envp)
  31. Tcl_Interp *interp; /* Interpreter */
  32. int objc; /* How many arguments? */
  33. Tcl_Obj *CONST objv[]; /* The argument objects */
  34. DB_ENV *envp; /* Environment pointer */
  35. {
  36. static char *archopts[] = {
  37. "-arch_abs", "-arch_data", "-arch_log",
  38. NULL
  39. };
  40. enum archopts {
  41. ARCH_ABS, ARCH_DATA, ARCH_LOG
  42. };
  43. Tcl_Obj *fileobj, *res;
  44. u_int32_t flag;
  45. int i, optindex, result, ret;
  46. char **file, **list;
  47. result = TCL_OK;
  48. flag = 0;
  49. /*
  50.  * Get the flag index from the object based on the options
  51.  * defined above.
  52.  */
  53. i = 2;
  54. while (i < objc) {
  55. if (Tcl_GetIndexFromObj(interp, objv[i],
  56.     archopts, "option", TCL_EXACT, &optindex) != TCL_OK)
  57. return (IS_HELP(objv[i]));
  58. i++;
  59. switch ((enum archopts)optindex) {
  60. case ARCH_ABS:
  61. flag |= DB_ARCH_ABS;
  62. break;
  63. case ARCH_DATA:
  64. flag |= DB_ARCH_DATA;
  65. break;
  66. case ARCH_LOG:
  67. flag |= DB_ARCH_LOG;
  68. break;
  69. }
  70. }
  71. _debug_check();
  72. list = NULL;
  73. ret = envp->log_archive(envp, &list, flag);
  74. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "log archive");
  75. if (result == TCL_OK) {
  76. res = Tcl_NewListObj(0, NULL);
  77. for (file = list; file != NULL && *file != NULL; file++) {
  78. fileobj = Tcl_NewStringObj(*file, strlen(*file));
  79. result = Tcl_ListObjAppendElement(interp, res, fileobj);
  80. if (result != TCL_OK)
  81. break;
  82. }
  83. Tcl_SetObjResult(interp, res);
  84. }
  85. if (list != NULL)
  86. __os_ufree(envp, list);
  87. return (result);
  88. }
  89. /*
  90.  * tcl_LogCompare --
  91.  *
  92.  * PUBLIC: int tcl_LogCompare __P((Tcl_Interp *, int,
  93.  * PUBLIC:    Tcl_Obj * CONST*));
  94.  */
  95. int
  96. tcl_LogCompare(interp, objc, objv)
  97. Tcl_Interp *interp; /* Interpreter */
  98. int objc; /* How many arguments? */
  99. Tcl_Obj *CONST objv[]; /* The argument objects */
  100. {
  101. DB_LSN lsn0, lsn1;
  102. Tcl_Obj *res;
  103. int result, ret;
  104. result = TCL_OK;
  105. /*
  106.  * No flags, must be 4 args.
  107.  */
  108. if (objc != 4) {
  109. Tcl_WrongNumArgs(interp, 2, objv, "lsn1 lsn2");
  110. return (TCL_ERROR);
  111. }
  112. result = _GetLsn(interp, objv[2], &lsn0);
  113. if (result == TCL_ERROR)
  114. return (result);
  115. result = _GetLsn(interp, objv[3], &lsn1);
  116. if (result == TCL_ERROR)
  117. return (result);
  118. _debug_check();
  119. ret = log_compare(&lsn0, &lsn1);
  120. res = Tcl_NewIntObj(ret);
  121. Tcl_SetObjResult(interp, res);
  122. return (result);
  123. }
  124. /*
  125.  * tcl_LogFile --
  126.  *
  127.  * PUBLIC: int tcl_LogFile __P((Tcl_Interp *, int,
  128.  * PUBLIC:    Tcl_Obj * CONST*, DB_ENV *));
  129.  */
  130. int
  131. tcl_LogFile(interp, objc, objv, envp)
  132. Tcl_Interp *interp; /* Interpreter */
  133. int objc; /* How many arguments? */
  134. Tcl_Obj *CONST objv[]; /* The argument objects */
  135. DB_ENV *envp; /* Environment pointer */
  136. {
  137. DB_LSN lsn;
  138. Tcl_Obj *res;
  139. size_t len;
  140. int result, ret;
  141. char *name;
  142. result = TCL_OK;
  143. /*
  144.  * No flags, must be 3 args.
  145.  */
  146. if (objc != 3) {
  147. Tcl_WrongNumArgs(interp, 2, objv, "lsn");
  148. return (TCL_ERROR);
  149. }
  150. result = _GetLsn(interp, objv[2], &lsn);
  151. if (result == TCL_ERROR)
  152. return (result);
  153. len = MSG_SIZE;
  154. ret = ENOMEM;
  155. name = NULL;
  156. while (ret == ENOMEM) {
  157. if (name != NULL)
  158. __os_free(envp, name);
  159. ret = __os_malloc(envp, len, &name);
  160. if (ret != 0) {
  161. Tcl_SetResult(interp, db_strerror(ret), TCL_STATIC);
  162. break;
  163. }
  164. _debug_check();
  165. ret = envp->log_file(envp, &lsn, name, len);
  166. len *= 2;
  167. }
  168. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "log_file");
  169. if (ret == 0) {
  170. res = Tcl_NewStringObj(name, strlen(name));
  171. Tcl_SetObjResult(interp, res);
  172. }
  173. if (name != NULL)
  174. __os_free(envp, name);
  175. return (result);
  176. }
  177. /*
  178.  * tcl_LogFlush --
  179.  *
  180.  * PUBLIC: int tcl_LogFlush __P((Tcl_Interp *, int,
  181.  * PUBLIC:    Tcl_Obj * CONST*, DB_ENV *));
  182.  */
  183. int
  184. tcl_LogFlush(interp, objc, objv, envp)
  185. Tcl_Interp *interp; /* Interpreter */
  186. int objc; /* How many arguments? */
  187. Tcl_Obj *CONST objv[]; /* The argument objects */
  188. DB_ENV *envp; /* Environment pointer */
  189. {
  190. DB_LSN lsn, *lsnp;
  191. int result, ret;
  192. result = TCL_OK;
  193. /*
  194.  * No flags, must be 2 or 3 args.
  195.  */
  196. if (objc > 3) {
  197. Tcl_WrongNumArgs(interp, 2, objv, "?lsn?");
  198. return (TCL_ERROR);
  199. }
  200. if (objc == 3) {
  201. lsnp = &lsn;
  202. result = _GetLsn(interp, objv[2], &lsn);
  203. if (result == TCL_ERROR)
  204. return (result);
  205. } else
  206. lsnp = NULL;
  207. _debug_check();
  208. ret = envp->log_flush(envp, lsnp);
  209. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "log_flush");
  210. return (result);
  211. }
  212. /*
  213.  * tcl_LogGet --
  214.  *
  215.  * PUBLIC: int tcl_LogGet __P((Tcl_Interp *, int,
  216.  * PUBLIC:    Tcl_Obj * CONST*, DB_ENV *));
  217.  */
  218. int
  219. tcl_LogGet(interp, objc, objv, envp)
  220. Tcl_Interp *interp; /* Interpreter */
  221. int objc; /* How many arguments? */
  222. Tcl_Obj *CONST objv[]; /* The argument objects */
  223. DB_ENV *envp; /* Environment pointer */
  224. {
  225. COMPQUIET(objv, NULL);
  226. COMPQUIET(objc, 0);
  227. COMPQUIET(envp, NULL);
  228. Tcl_SetResult(interp, "FAIL: log_get deprecatedn", TCL_STATIC);
  229. return (TCL_ERROR);
  230. }
  231. /*
  232.  * tcl_LogPut --
  233.  *
  234.  * PUBLIC: int tcl_LogPut __P((Tcl_Interp *, int,
  235.  * PUBLIC:    Tcl_Obj * CONST*, DB_ENV *));
  236.  */
  237. int
  238. tcl_LogPut(interp, objc, objv, envp)
  239. Tcl_Interp *interp; /* Interpreter */
  240. int objc; /* How many arguments? */
  241. Tcl_Obj *CONST objv[]; /* The argument objects */
  242. DB_ENV *envp; /* Environment pointer */
  243. {
  244. static char *logputopts[] = {
  245. "-flush",
  246. NULL
  247. };
  248. enum logputopts {
  249. LOGPUT_FLUSH
  250. };
  251. DB_LSN lsn;
  252. DBT data;
  253. Tcl_Obj *intobj, *res;
  254. void *dtmp;
  255. u_int32_t flag;
  256. int freedata, optindex, result, ret;
  257. result = TCL_OK;
  258. flag = 0;
  259. freedata = 0;
  260. if (objc < 3) {
  261. Tcl_WrongNumArgs(interp, 2, objv, "?-args? record");
  262. return (TCL_ERROR);
  263. }
  264. /*
  265.  * Data/record must be the last arg.
  266.  */
  267. memset(&data, 0, sizeof(data));
  268. ret = _CopyObjBytes(interp, objv[objc-1], &dtmp,
  269.     &data.size, &freedata);
  270. if (ret != 0) {
  271. result = _ReturnSetup(interp, ret,
  272.     DB_RETOK_STD(ret), "log put");
  273. return (result);
  274. }
  275. data.data = dtmp;
  276. /*
  277.  * Get the command name index from the object based on the options
  278.  * defined above.
  279.  */
  280. if (objc == 4) {
  281. if (Tcl_GetIndexFromObj(interp, objv[2],
  282.     logputopts, "option", TCL_EXACT, &optindex) != TCL_OK) {
  283. return (IS_HELP(objv[2]));
  284. }
  285. switch ((enum logputopts)optindex) {
  286. case LOGPUT_FLUSH:
  287. flag = DB_FLUSH;
  288. break;
  289. }
  290. }
  291. if (result == TCL_ERROR)
  292. return (result);
  293. _debug_check();
  294. ret = envp->log_put(envp, &lsn, &data, flag);
  295. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "log_put");
  296. if (result == TCL_ERROR)
  297. return (result);
  298. res = Tcl_NewListObj(0, NULL);
  299. intobj = Tcl_NewLongObj((long)lsn.file);
  300. result = Tcl_ListObjAppendElement(interp, res, intobj);
  301. intobj = Tcl_NewLongObj((long)lsn.offset);
  302. result = Tcl_ListObjAppendElement(interp, res, intobj);
  303. Tcl_SetObjResult(interp, res);
  304. if (freedata)
  305. (void)__os_free(NULL, dtmp);
  306. return (result);
  307. }
  308. /*
  309.  * tcl_LogStat --
  310.  *
  311.  * PUBLIC: int tcl_LogStat __P((Tcl_Interp *, int,
  312.  * PUBLIC:    Tcl_Obj * CONST*, DB_ENV *));
  313.  */
  314. int
  315. tcl_LogStat(interp, objc, objv, envp)
  316. Tcl_Interp *interp; /* Interpreter */
  317. int objc; /* How many arguments? */
  318. Tcl_Obj *CONST objv[]; /* The argument objects */
  319. DB_ENV *envp; /* Environment pointer */
  320. {
  321. DB_LOG_STAT *sp;
  322. Tcl_Obj *res;
  323. int result, ret;
  324. result = TCL_OK;
  325. /*
  326.  * No args for this.  Error if there are some.
  327.  */
  328. if (objc != 2) {
  329. Tcl_WrongNumArgs(interp, 2, objv, NULL);
  330. return (TCL_ERROR);
  331. }
  332. _debug_check();
  333. ret = envp->log_stat(envp, &sp, 0);
  334. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "log stat");
  335. if (result == TCL_ERROR)
  336. return (result);
  337. /*
  338.  * Have our stats, now construct the name value
  339.  * list pairs and free up the memory.
  340.  */
  341. res = Tcl_NewObj();
  342. /*
  343.  * MAKE_STAT_LIST assumes 'res' and 'error' label.
  344.  */
  345. MAKE_STAT_LIST("Magic", sp->st_magic);
  346. MAKE_STAT_LIST("Log file Version", sp->st_version);
  347. MAKE_STAT_LIST("Region size", sp->st_regsize);
  348. MAKE_STAT_LIST("Log file mode", sp->st_mode);
  349. MAKE_STAT_LIST("Log record cache size", sp->st_lg_bsize);
  350. MAKE_STAT_LIST("Current log file size", sp->st_lg_size);
  351. MAKE_STAT_LIST("Mbytes written", sp->st_w_mbytes);
  352. MAKE_STAT_LIST("Bytes written (over Mb)", sp->st_w_bytes);
  353. MAKE_STAT_LIST("Mbytes written since checkpoint", sp->st_wc_mbytes);
  354. MAKE_STAT_LIST("Bytes written (over Mb) since checkpoint",
  355.     sp->st_wc_bytes);
  356. MAKE_STAT_LIST("Times log written", sp->st_wcount);
  357. MAKE_STAT_LIST("Times log written because cache filled up",
  358.     sp->st_wcount_fill);
  359. MAKE_STAT_LIST("Times log flushed", sp->st_scount);
  360. MAKE_STAT_LIST("Current log file number", sp->st_cur_file);
  361. MAKE_STAT_LIST("Current log file offset", sp->st_cur_offset);
  362. MAKE_STAT_LIST("On-disk log file number", sp->st_disk_file);
  363. MAKE_STAT_LIST("On-disk log file offset", sp->st_disk_offset);
  364. MAKE_STAT_LIST("Max commits in a log flush", sp->st_maxcommitperflush);
  365. MAKE_STAT_LIST("Min commits in a log flush", sp->st_mincommitperflush);
  366. MAKE_STAT_LIST("Number of region lock waits", sp->st_region_wait);
  367. MAKE_STAT_LIST("Number of region lock nowaits", sp->st_region_nowait);
  368. Tcl_SetObjResult(interp, res);
  369. error:
  370. free(sp);
  371. return (result);
  372. }
  373. /*
  374.  * logc_Cmd --
  375.  * Implements the log cursor command.
  376.  *
  377.  * PUBLIC: int logc_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*));
  378.  */
  379. int
  380. logc_Cmd(clientData, interp, objc, objv)
  381. ClientData clientData; /* Cursor handle */
  382. Tcl_Interp *interp; /* Interpreter */
  383. int objc; /* How many arguments? */
  384. Tcl_Obj *CONST objv[]; /* The argument objects */
  385. {
  386. static char *logccmds[] = {
  387. "close",
  388. "get",
  389. NULL
  390. };
  391. enum logccmds {
  392. LOGCCLOSE,
  393. LOGCGET
  394. };
  395. DB_LOGC *logc;
  396. DBTCL_INFO *logcip;
  397. int cmdindex, result, ret;
  398. Tcl_ResetResult(interp);
  399. logc = (DB_LOGC *)clientData;
  400. logcip = _PtrToInfo((void *)logc);
  401. result = TCL_OK;
  402. if (objc <= 1) {
  403. Tcl_WrongNumArgs(interp, 1, objv, "command cmdargs");
  404. return (TCL_ERROR);
  405. }
  406. if (logc == NULL) {
  407. Tcl_SetResult(interp, "NULL logc pointer", TCL_STATIC);
  408. return (TCL_ERROR);
  409. }
  410. if (logcip == NULL) {
  411. Tcl_SetResult(interp, "NULL logc info pointer", TCL_STATIC);
  412. return (TCL_ERROR);
  413. }
  414. /*
  415.  * Get the command name index from the object based on the berkdbcmds
  416.  * defined above.
  417.  */
  418. if (Tcl_GetIndexFromObj(interp, objv[1], logccmds, "command",
  419.     TCL_EXACT, &cmdindex) != TCL_OK)
  420. return (IS_HELP(objv[1]));
  421. switch ((enum logccmds)cmdindex) {
  422. case LOGCCLOSE:
  423. /*
  424.  * No args for this.  Error if there are some.
  425.  */
  426. if (objc > 2) {
  427. Tcl_WrongNumArgs(interp, 2, objv, NULL);
  428. return (TCL_ERROR);
  429. }
  430. _debug_check();
  431. ret = logc->close(logc, 0);
  432. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  433.     "logc close");
  434. if (result == TCL_OK) {
  435. (void)Tcl_DeleteCommand(interp, logcip->i_name);
  436. _DeleteInfo(logcip);
  437. }
  438. break;
  439. case LOGCGET:
  440. result = tcl_LogcGet(interp, objc, objv, logc);
  441. break;
  442. }
  443. return (result);
  444. }
  445. static int
  446. tcl_LogcGet(interp, objc, objv, logc)
  447. Tcl_Interp *interp;
  448. int objc;
  449. Tcl_Obj * CONST *objv;
  450. DB_LOGC *logc;
  451. {
  452. static char *logcgetopts[] = {
  453. "-current",
  454. "-first",
  455. "-last",
  456. "-next",
  457. "-prev",
  458. "-set",
  459. NULL
  460. };
  461. enum logcgetopts {
  462. LOGCGET_CURRENT,
  463. LOGCGET_FIRST,
  464. LOGCGET_LAST,
  465. LOGCGET_NEXT,
  466. LOGCGET_PREV,
  467. LOGCGET_SET
  468. };
  469. DB_LSN lsn;
  470. DBT data;
  471. Tcl_Obj *dataobj, *lsnlist, *myobjv[2], *res;
  472. u_int32_t flag;
  473. int i, myobjc, optindex, result, ret;
  474. result = TCL_OK;
  475. res = NULL;
  476. flag = 0;
  477. if (objc < 3) {
  478. Tcl_WrongNumArgs(interp, 2, objv, "?-args? lsn");
  479. return (TCL_ERROR);
  480. }
  481. /*
  482.  * Get the command name index from the object based on the options
  483.  * defined above.
  484.  */
  485. i = 2;
  486. while (i < objc) {
  487. if (Tcl_GetIndexFromObj(interp, objv[i],
  488.     logcgetopts, "option", TCL_EXACT, &optindex) != TCL_OK)
  489. return (IS_HELP(objv[i]));
  490. i++;
  491. switch ((enum logcgetopts)optindex) {
  492. case LOGCGET_CURRENT:
  493. FLAG_CHECK(flag);
  494. flag |= DB_CURRENT;
  495. break;
  496. case LOGCGET_FIRST:
  497. FLAG_CHECK(flag);
  498. flag |= DB_FIRST;
  499. break;
  500. case LOGCGET_LAST:
  501. FLAG_CHECK(flag);
  502. flag |= DB_LAST;
  503. break;
  504. case LOGCGET_NEXT:
  505. FLAG_CHECK(flag);
  506. flag |= DB_NEXT;
  507. break;
  508. case LOGCGET_PREV:
  509. FLAG_CHECK(flag);
  510. flag |= DB_PREV;
  511. break;
  512. case LOGCGET_SET:
  513. FLAG_CHECK(flag);
  514. flag |= DB_SET;
  515. if (i == objc) {
  516. Tcl_WrongNumArgs(interp, 2, objv, "?-set lsn?");
  517. result = TCL_ERROR;
  518. break;
  519. }
  520. result = _GetLsn(interp, objv[i++], &lsn);
  521. break;
  522. }
  523. }
  524. if (result == TCL_ERROR)
  525. return (result);
  526. memset(&data, 0, sizeof(data));
  527. _debug_check();
  528. ret = logc->get(logc, &lsn, &data, flag);
  529. res = Tcl_NewListObj(0, NULL);
  530. if (res == NULL)
  531. goto memerr;
  532. if (ret == 0) {
  533. /*
  534.  * Success.  Set up return list as {LSN data} where LSN
  535.  * is a sublist {file offset}.
  536.  */
  537. myobjc = 2;
  538. myobjv[0] = Tcl_NewLongObj((long)lsn.file);
  539. myobjv[1] = Tcl_NewLongObj((long)lsn.offset);
  540. lsnlist = Tcl_NewListObj(myobjc, myobjv);
  541. if (lsnlist == NULL)
  542. goto memerr;
  543. result = Tcl_ListObjAppendElement(interp, res, lsnlist);
  544. dataobj = Tcl_NewStringObj(data.data, data.size);
  545. if (dataobj == NULL) {
  546. goto memerr;
  547. }
  548. result = Tcl_ListObjAppendElement(interp, res, dataobj);
  549. } else
  550. result = _ReturnSetup(interp, ret, DB_RETOK_LGGET(ret),
  551.     "DB_LOGC->get");
  552. Tcl_SetObjResult(interp, res);
  553. if (0) {
  554. memerr: if (res != NULL)
  555. Tcl_DecrRefCount(res);
  556. Tcl_SetResult(interp, "allocation failed", TCL_STATIC);
  557. }
  558. return (result);
  559. }
  560. #endif