log_findckp.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:4k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 1996, 1997, 1998, 1999, 2000
  5.  * Sleepycat Software.  All rights reserved.
  6.  */
  7. #include "db_config.h"
  8. #ifndef lint
  9. static const char revid[] = "$Id: log_findckp.c,v 11.5 2000/11/30 00:58:40 ubell Exp $";
  10. #endif /* not lint */
  11. #ifndef NO_SYSTEM_INCLUDES
  12. #include <sys/types.h>
  13. #include <string.h>
  14. #endif
  15. #include "db_int.h"
  16. #include "log.h"
  17. #include "txn.h"
  18. /*
  19.  * __log_findckp --
  20.  *
  21.  * Looks for the most recent checkpoint that occurs before the most recent
  22.  * checkpoint LSN, subject to the constraint that there must be at least two
  23.  * checkpoints.  The reason you need two checkpoints is that you might have
  24.  * crashed during the most recent one and may not have a copy of all the
  25.  * open files.  This is the point from which recovery can start and the
  26.  * point up to which archival/truncation can take place.  Checkpoints in
  27.  * the log look like:
  28.  *
  29.  * -------------------------------------------------------------------
  30.  *  | ckp A, ckplsn 100 |  .... record .... | ckp B, ckplsn 600 | ...
  31.  * -------------------------------------------------------------------
  32.  *         LSN 500                                 LSN 1000
  33.  *
  34.  * If we read what log returns from using the DB_CKP parameter to logput,
  35.  * we'll get the record at LSN 1000.  The checkpoint LSN there is 600.
  36.  * Now we have to scan backwards looking for a checkpoint before LSN 600.
  37.  * We find one at 500.  This means that we can truncate the log before
  38.  * 500 or run recovery beginning at 500.
  39.  *
  40.  * Returns 0 if we find a suitable checkpoint or we retrieved the first
  41.  * record in the log from which to start.  Returns DB_NOTFOUND if there
  42.  * are no log records, errno on error.
  43.  *
  44.  * PUBLIC: int __log_findckp __P((DB_ENV *, DB_LSN *));
  45.  */
  46. int
  47. __log_findckp(dbenv, lsnp)
  48. DB_ENV *dbenv;
  49. DB_LSN *lsnp;
  50. {
  51. DBT data;
  52. DB_LSN ckp_lsn, final_ckp, last_ckp, next_lsn;
  53. __txn_ckp_args *ckp_args;
  54. int ret;
  55. /*
  56.  * Need to find the appropriate point from which to begin
  57.  * recovery.
  58.  */
  59. memset(&data, 0, sizeof(data));
  60. if (F_ISSET(dbenv, DB_ENV_THREAD))
  61. F_SET(&data, DB_DBT_MALLOC);
  62. ZERO_LSN(ckp_lsn);
  63. if ((ret = log_get(dbenv, &last_ckp, &data, DB_CHECKPOINT)) != 0) {
  64. if (ret == ENOENT)
  65. goto get_first;
  66. else
  67. return (ret);
  68. }
  69. final_ckp = last_ckp;
  70. next_lsn = last_ckp;
  71. do {
  72. if (F_ISSET(dbenv, DB_ENV_THREAD))
  73. __os_free(data.data, data.size);
  74. if ((ret = log_get(dbenv, &next_lsn, &data, DB_SET)) != 0)
  75. return (ret);
  76. if ((ret = __txn_ckp_read(dbenv, data.data, &ckp_args)) != 0) {
  77. if (F_ISSET(dbenv, DB_ENV_THREAD))
  78. __os_free(data.data, data.size);
  79. return (ret);
  80. }
  81. if (IS_ZERO_LSN(ckp_lsn))
  82. ckp_lsn = ckp_args->ckp_lsn;
  83. if (FLD_ISSET(dbenv->verbose, DB_VERB_CHKPOINT)) {
  84. __db_err(dbenv, "Checkpoint at: [%lu][%lu]",
  85.     (u_long)last_ckp.file, (u_long)last_ckp.offset);
  86. __db_err(dbenv, "Checkpoint LSN: [%lu][%lu]",
  87.     (u_long)ckp_args->ckp_lsn.file,
  88.     (u_long)ckp_args->ckp_lsn.offset);
  89. __db_err(dbenv, "Previous checkpoint: [%lu][%lu]",
  90.     (u_long)ckp_args->last_ckp.file,
  91.     (u_long)ckp_args->last_ckp.offset);
  92. }
  93. last_ckp = next_lsn;
  94. next_lsn = ckp_args->last_ckp;
  95. __os_free(ckp_args, sizeof(*ckp_args));
  96. /*
  97.  * Keep looping until either you 1) run out of checkpoints,
  98.  * 2) you've found a checkpoint before the most recent
  99.  * checkpoint's LSN and you have at least 2 checkpoints.
  100.  */
  101. } while (!IS_ZERO_LSN(next_lsn) &&
  102.     (log_compare(&last_ckp, &ckp_lsn) > 0 ||
  103.     log_compare(&final_ckp, &last_ckp) == 0));
  104. if (F_ISSET(dbenv, DB_ENV_THREAD))
  105. __os_free(data.data, data.size);
  106. /*
  107.  * At this point, either, next_lsn is ZERO or ckp_lsn is the
  108.  * checkpoint lsn and last_ckp is the LSN of the last checkpoint
  109.  * before ckp_lsn.  If the compare in the loop is still true, then
  110.  * next_lsn must be 0 and we need to roll forward from the
  111.  * beginning of the log.
  112.  */
  113. if (log_compare(&last_ckp, &ckp_lsn) >= 0 ||
  114.     log_compare(&final_ckp, &last_ckp) == 0) {
  115. get_first: if ((ret = log_get(dbenv, &last_ckp, &data, DB_FIRST)) != 0)
  116. return (ret);
  117. if (F_ISSET(dbenv, DB_ENV_THREAD))
  118. __os_free(data.data, data.size);
  119. }
  120. *lsnp = last_ckp;
  121. return (IS_ZERO_LSN(last_ckp) ? DB_NOTFOUND : 0);
  122. }