db_rec.c
Upload User: tsgydb
Upload Date: 2007-04-14
Package Size: 10674k
Code Size: 13k
Category:

MySQL

Development Platform:

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: db_rec.c,v 11.10 2000/08/03 15:32:19 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 "db_page.h"
  17. #include "log.h"
  18. #include "hash.h"
  19. /*
  20.  * PUBLIC: int __db_addrem_recover
  21.  * PUBLIC:    __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
  22.  *
  23.  * This log message is generated whenever we add or remove a duplicate
  24.  * to/from a duplicate page.  On recover, we just do the opposite.
  25.  */
  26. int
  27. __db_addrem_recover(dbenv, dbtp, lsnp, op, info)
  28. DB_ENV *dbenv;
  29. DBT *dbtp;
  30. DB_LSN *lsnp;
  31. db_recops op;
  32. void *info;
  33. {
  34. __db_addrem_args *argp;
  35. DB *file_dbp;
  36. DBC *dbc;
  37. DB_MPOOLFILE *mpf;
  38. PAGE *pagep;
  39. u_int32_t change;
  40. int cmp_n, cmp_p, ret;
  41. COMPQUIET(info, NULL);
  42. REC_PRINT(__db_addrem_print);
  43. REC_INTRO(__db_addrem_read, 1);
  44. if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
  45. if (DB_UNDO(op)) {
  46. /*
  47.  * We are undoing and the page doesn't exist.  That
  48.  * is equivalent to having a pagelsn of 0, so we
  49.  * would not have to undo anything.  In this case,
  50.  * don't bother creating a page.
  51.  */
  52. goto done;
  53. } else
  54. if ((ret = memp_fget(mpf,
  55.     &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
  56. goto out;
  57. }
  58. cmp_n = log_compare(lsnp, &LSN(pagep));
  59. cmp_p = log_compare(&LSN(pagep), &argp->pagelsn);
  60. CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->pagelsn);
  61. change = 0;
  62. if ((cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_ADD_DUP) ||
  63.     (cmp_n == 0 && DB_UNDO(op) && argp->opcode == DB_REM_DUP)) {
  64. /* Need to redo an add, or undo a delete. */
  65. if ((ret = __db_pitem(dbc, pagep, argp->indx, argp->nbytes,
  66.     argp->hdr.size == 0 ? NULL : &argp->hdr,
  67.     argp->dbt.size == 0 ? NULL : &argp->dbt)) != 0)
  68. goto out;
  69. change = DB_MPOOL_DIRTY;
  70. } else if ((cmp_n == 0 && DB_UNDO(op) && argp->opcode == DB_ADD_DUP) ||
  71.     (cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_REM_DUP)) {
  72. /* Need to undo an add, or redo a delete. */
  73. if ((ret = __db_ditem(dbc,
  74.     pagep, argp->indx, argp->nbytes)) != 0)
  75. goto out;
  76. change = DB_MPOOL_DIRTY;
  77. }
  78. if (change) {
  79. if (DB_REDO(op))
  80. LSN(pagep) = *lsnp;
  81. else
  82. LSN(pagep) = argp->pagelsn;
  83. }
  84. if ((ret = memp_fput(mpf, pagep, change)) != 0)
  85. goto out;
  86. done: *lsnp = argp->prev_lsn;
  87. ret = 0;
  88. out: REC_CLOSE;
  89. }
  90. /*
  91.  * PUBLIC: int __db_big_recover
  92.  * PUBLIC:     __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
  93.  */
  94. int
  95. __db_big_recover(dbenv, dbtp, lsnp, op, info)
  96. DB_ENV *dbenv;
  97. DBT *dbtp;
  98. DB_LSN *lsnp;
  99. db_recops op;
  100. void *info;
  101. {
  102. __db_big_args *argp;
  103. DB *file_dbp;
  104. DBC *dbc;
  105. DB_MPOOLFILE *mpf;
  106. PAGE *pagep;
  107. u_int32_t change;
  108. int cmp_n, cmp_p, ret;
  109. COMPQUIET(info, NULL);
  110. REC_PRINT(__db_big_print);
  111. REC_INTRO(__db_big_read, 1);
  112. if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
  113. if (DB_UNDO(op)) {
  114. /*
  115.  * We are undoing and the page doesn't exist.  That
  116.  * is equivalent to having a pagelsn of 0, so we
  117.  * would not have to undo anything.  In this case,
  118.  * don't bother creating a page.
  119.  */
  120. ret = 0;
  121. goto ppage;
  122. } else
  123. if ((ret = memp_fget(mpf,
  124.     &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
  125. goto out;
  126. }
  127. /*
  128.  * There are three pages we need to check.  The one on which we are
  129.  * adding data, the previous one whose next_pointer may have
  130.  * been updated, and the next one whose prev_pointer may have
  131.  * been updated.
  132.  */
  133. cmp_n = log_compare(lsnp, &LSN(pagep));
  134. cmp_p = log_compare(&LSN(pagep), &argp->pagelsn);
  135. CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->pagelsn);
  136. change = 0;
  137. if ((cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_ADD_BIG) ||
  138.     (cmp_n == 0 && DB_UNDO(op) && argp->opcode == DB_REM_BIG)) {
  139. /* We are either redo-ing an add, or undoing a delete. */
  140. P_INIT(pagep, file_dbp->pgsize, argp->pgno, argp->prev_pgno,
  141. argp->next_pgno, 0, P_OVERFLOW);
  142. OV_LEN(pagep) = argp->dbt.size;
  143. OV_REF(pagep) = 1;
  144. memcpy((u_int8_t *)pagep + P_OVERHEAD, argp->dbt.data,
  145.     argp->dbt.size);
  146. PREV_PGNO(pagep) = argp->prev_pgno;
  147. change = DB_MPOOL_DIRTY;
  148. } else if ((cmp_n == 0 && DB_UNDO(op) && argp->opcode == DB_ADD_BIG) ||
  149.     (cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_REM_BIG)) {
  150. /*
  151.  * We are either undo-ing an add or redo-ing a delete.
  152.  * The page is about to be reclaimed in either case, so
  153.  * there really isn't anything to do here.
  154.  */
  155. change = DB_MPOOL_DIRTY;
  156. }
  157. if (change)
  158. LSN(pagep) = DB_REDO(op) ? *lsnp : argp->pagelsn;
  159. if ((ret = memp_fput(mpf, pagep, change)) != 0)
  160. goto out;
  161. /* Now check the previous page. */
  162. ppage: if (argp->prev_pgno != PGNO_INVALID) {
  163. change = 0;
  164. if ((ret = memp_fget(mpf, &argp->prev_pgno, 0, &pagep)) != 0) {
  165. if (DB_UNDO(op)) {
  166. /*
  167.  * We are undoing and the page doesn't exist.
  168.  * That is equivalent to having a pagelsn of 0,
  169.  * so we would not have to undo anything.  In
  170.  * this case, don't bother creating a page.
  171.  */
  172. *lsnp = argp->prev_lsn;
  173. ret = 0;
  174. goto npage;
  175. } else
  176. if ((ret = memp_fget(mpf, &argp->prev_pgno,
  177.     DB_MPOOL_CREATE, &pagep)) != 0)
  178. goto out;
  179. }
  180. cmp_n = log_compare(lsnp, &LSN(pagep));
  181. cmp_p = log_compare(&LSN(pagep), &argp->prevlsn);
  182. CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->prevlsn);
  183. if ((cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_ADD_BIG) ||
  184.     (cmp_n == 0 && DB_UNDO(op) && argp->opcode == DB_REM_BIG)) {
  185. /* Redo add, undo delete. */
  186. NEXT_PGNO(pagep) = argp->pgno;
  187. change = DB_MPOOL_DIRTY;
  188. } else if ((cmp_n == 0 &&
  189.     DB_UNDO(op) && argp->opcode == DB_ADD_BIG) ||
  190.     (cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_REM_BIG)) {
  191. /* Redo delete, undo add. */
  192. NEXT_PGNO(pagep) = argp->next_pgno;
  193. change = DB_MPOOL_DIRTY;
  194. }
  195. if (change)
  196. LSN(pagep) = DB_REDO(op) ? *lsnp : argp->prevlsn;
  197. if ((ret = memp_fput(mpf, pagep, change)) != 0)
  198. goto out;
  199. }
  200. /* Now check the next page.  Can only be set on a delete. */
  201. npage: if (argp->next_pgno != PGNO_INVALID) {
  202. change = 0;
  203. if ((ret = memp_fget(mpf, &argp->next_pgno, 0, &pagep)) != 0) {
  204. if (DB_UNDO(op)) {
  205. /*
  206.  * We are undoing and the page doesn't exist.
  207.  * That is equivalent to having a pagelsn of 0,
  208.  * so we would not have to undo anything.  In
  209.  * this case, don't bother creating a page.
  210.  */
  211. goto done;
  212. } else
  213. if ((ret = memp_fget(mpf, &argp->next_pgno,
  214.     DB_MPOOL_CREATE, &pagep)) != 0)
  215. goto out;
  216. }
  217. cmp_n = log_compare(lsnp, &LSN(pagep));
  218. cmp_p = log_compare(&LSN(pagep), &argp->nextlsn);
  219. CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->nextlsn);
  220. if (cmp_p == 0 && DB_REDO(op)) {
  221. PREV_PGNO(pagep) = PGNO_INVALID;
  222. change = DB_MPOOL_DIRTY;
  223. } else if (cmp_n == 0 && DB_UNDO(op)) {
  224. PREV_PGNO(pagep) = argp->pgno;
  225. change = DB_MPOOL_DIRTY;
  226. }
  227. if (change)
  228. LSN(pagep) = DB_REDO(op) ? *lsnp : argp->nextlsn;
  229. if ((ret = memp_fput(mpf, pagep, change)) != 0)
  230. goto out;
  231. }
  232. done: *lsnp = argp->prev_lsn;
  233. ret = 0;
  234. out: REC_CLOSE;
  235. }
  236. /*
  237.  * __db_ovref_recover --
  238.  * Recovery function for __db_ovref().
  239.  *
  240.  * PUBLIC: int __db_ovref_recover __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
  241.  */
  242. int
  243. __db_ovref_recover(dbenv, dbtp, lsnp, op, info)
  244. DB_ENV *dbenv;
  245. DBT *dbtp;
  246. DB_LSN *lsnp;
  247. db_recops op;
  248. void *info;
  249. {
  250. __db_ovref_args *argp;
  251. DB *file_dbp;
  252. DBC *dbc;
  253. DB_MPOOLFILE *mpf;
  254. PAGE *pagep;
  255. int cmp, modified, ret;
  256. COMPQUIET(info, NULL);
  257. REC_PRINT(__db_ovref_print);
  258. REC_INTRO(__db_ovref_read, 1);
  259. if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
  260. if (DB_UNDO(op))
  261. goto done;
  262. (void)__db_pgerr(file_dbp, argp->pgno);
  263. goto out;
  264. }
  265. modified = 0;
  266. cmp = log_compare(&LSN(pagep), &argp->lsn);
  267. CHECK_LSN(op, cmp, &LSN(pagep), &argp->lsn);
  268. if (cmp == 0 && DB_REDO(op)) {
  269. /* Need to redo update described. */
  270. OV_REF(pagep) += argp->adjust;
  271. pagep->lsn = *lsnp;
  272. modified = 1;
  273. } else if (log_compare(lsnp, &LSN(pagep)) == 0 && DB_UNDO(op)) {
  274. /* Need to undo update described. */
  275. OV_REF(pagep) -= argp->adjust;
  276. pagep->lsn = argp->lsn;
  277. modified = 1;
  278. }
  279. if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
  280. goto out;
  281. done: *lsnp = argp->prev_lsn;
  282. ret = 0;
  283. out: REC_CLOSE;
  284. }
  285. /*
  286.  * __db_relink_recover --
  287.  * Recovery function for relink.
  288.  *
  289.  * PUBLIC: int __db_relink_recover
  290.  * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
  291.  */
  292. int
  293. __db_relink_recover(dbenv, dbtp, lsnp, op, info)
  294. DB_ENV *dbenv;
  295. DBT *dbtp;
  296. DB_LSN *lsnp;
  297. db_recops op;
  298. void *info;
  299. {
  300. __db_relink_args *argp;
  301. DB *file_dbp;
  302. DBC *dbc;
  303. DB_MPOOLFILE *mpf;
  304. PAGE *pagep;
  305. int cmp_n, cmp_p, modified, ret;
  306. COMPQUIET(info, NULL);
  307. REC_PRINT(__db_relink_print);
  308. REC_INTRO(__db_relink_read, 1);
  309. /*
  310.  * There are up to three pages we need to check -- the page, and the
  311.  * previous and next pages, if they existed.  For a page add operation,
  312.  * the current page is the result of a split and is being recovered
  313.  * elsewhere, so all we need do is recover the next page.
  314.  */
  315. if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
  316. if (DB_REDO(op)) {
  317. (void)__db_pgerr(file_dbp, argp->pgno);
  318. goto out;
  319. }
  320. goto next2;
  321. }
  322. modified = 0;
  323. if (argp->opcode == DB_ADD_PAGE)
  324. goto next1;
  325. cmp_p = log_compare(&LSN(pagep), &argp->lsn);
  326. CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn);
  327. if (cmp_p == 0 && DB_REDO(op)) {
  328. /* Redo the relink. */
  329. pagep->lsn = *lsnp;
  330. modified = 1;
  331. } else if (log_compare(lsnp, &LSN(pagep)) == 0 && DB_UNDO(op)) {
  332. /* Undo the relink. */
  333. pagep->next_pgno = argp->next;
  334. pagep->prev_pgno = argp->prev;
  335. pagep->lsn = argp->lsn;
  336. modified = 1;
  337. }
  338. next1: if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
  339. goto out;
  340. next2: if ((ret = memp_fget(mpf, &argp->next, 0, &pagep)) != 0) {
  341. if (DB_REDO(op)) {
  342. (void)__db_pgerr(file_dbp, argp->next);
  343. goto out;
  344. }
  345. goto prev;
  346. }
  347. modified = 0;
  348. cmp_n = log_compare(lsnp, &LSN(pagep));
  349. cmp_p = log_compare(&LSN(pagep), &argp->lsn_next);
  350. CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn_next);
  351. if ((argp->opcode == DB_REM_PAGE && cmp_p == 0 && DB_REDO(op)) ||
  352.     (argp->opcode == DB_ADD_PAGE && cmp_n == 0 && DB_UNDO(op))) {
  353. /* Redo the remove or undo the add. */
  354. pagep->prev_pgno = argp->prev;
  355. modified = 1;
  356. } else if ((argp->opcode == DB_REM_PAGE && cmp_n == 0 && DB_UNDO(op)) ||
  357.     (argp->opcode == DB_ADD_PAGE && cmp_p == 0 && DB_REDO(op))) {
  358. /* Undo the remove or redo the add. */
  359. pagep->prev_pgno = argp->pgno;
  360. modified = 1;
  361. }
  362. if (modified == 1) {
  363. if (DB_UNDO(op))
  364. pagep->lsn = argp->lsn_next;
  365. else
  366. pagep->lsn = *lsnp;
  367. }
  368. if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
  369. goto out;
  370. if (argp->opcode == DB_ADD_PAGE)
  371. goto done;
  372. prev: if ((ret = memp_fget(mpf, &argp->prev, 0, &pagep)) != 0) {
  373. if (DB_REDO(op)) {
  374. (void)__db_pgerr(file_dbp, argp->prev);
  375. goto out;
  376. }
  377. goto done;
  378. }
  379. modified = 0;
  380. cmp_p = log_compare(&LSN(pagep), &argp->lsn_prev);
  381. CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn_prev);
  382. if (cmp_p == 0 && DB_REDO(op)) {
  383. /* Redo the relink. */
  384. pagep->next_pgno = argp->next;
  385. modified = 1;
  386. } else if (log_compare(lsnp, &LSN(pagep)) == 0 && DB_UNDO(op)) {
  387. /* Undo the relink. */
  388. pagep->next_pgno = argp->pgno;
  389. modified = 1;
  390. }
  391. if (modified == 1) {
  392. if (DB_UNDO(op))
  393. pagep->lsn = argp->lsn_prev;
  394. else
  395. pagep->lsn = *lsnp;
  396. }
  397. if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
  398. goto out;
  399. done: *lsnp = argp->prev_lsn;
  400. ret = 0;
  401. out: REC_CLOSE;
  402. }
  403. /*
  404.  * __db_debug_recover --
  405.  * Recovery function for debug.
  406.  *
  407.  * PUBLIC: int __db_debug_recover __P((DB_ENV *,
  408.  * PUBLIC:     DBT *, DB_LSN *, db_recops, void *));
  409.  */
  410. int
  411. __db_debug_recover(dbenv, dbtp, lsnp, op, info)
  412. DB_ENV *dbenv;
  413. DBT *dbtp;
  414. DB_LSN *lsnp;
  415. db_recops op;
  416. void *info;
  417. {
  418. __db_debug_args *argp;
  419. int ret;
  420. COMPQUIET(op, 0);
  421. COMPQUIET(dbenv, NULL);
  422. COMPQUIET(info, NULL);
  423. REC_PRINT(__db_debug_print);
  424. REC_NOOP_INTRO(__db_debug_read);
  425. *lsnp = argp->prev_lsn;
  426. ret = 0;
  427. REC_NOOP_CLOSE;
  428. }
  429. /*
  430.  * __db_noop_recover --
  431.  * Recovery function for noop.
  432.  *
  433.  * PUBLIC: int __db_noop_recover __P((DB_ENV *,
  434.  * PUBLIC:      DBT *, DB_LSN *, db_recops, void *));
  435.  */
  436. int
  437. __db_noop_recover(dbenv, dbtp, lsnp, op, info)
  438. DB_ENV *dbenv;
  439. DBT *dbtp;
  440. DB_LSN *lsnp;
  441. db_recops op;
  442. void *info;
  443. {
  444. __db_noop_args *argp;
  445. DB *file_dbp;
  446. DBC *dbc;
  447. DB_MPOOLFILE *mpf;
  448. PAGE *pagep;
  449. u_int32_t change;
  450. int cmp_n, cmp_p, ret;
  451. COMPQUIET(info, NULL);
  452. REC_PRINT(__db_noop_print);
  453. REC_INTRO(__db_noop_read, 0);
  454. if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0)
  455. goto out;
  456. cmp_n = log_compare(lsnp, &LSN(pagep));
  457. cmp_p = log_compare(&LSN(pagep), &argp->prevlsn);
  458. CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->prevlsn);
  459. change = 0;
  460. if (cmp_p == 0 && DB_REDO(op)) {
  461. LSN(pagep) = *lsnp;
  462. change = DB_MPOOL_DIRTY;
  463. } else if (cmp_n == 0 && DB_UNDO(op)) {
  464. LSN(pagep) = argp->prevlsn;
  465. change = DB_MPOOL_DIRTY;
  466. }
  467. ret = memp_fput(mpf, pagep, change);
  468. done: *lsnp = argp->prev_lsn;
  469. out: REC_CLOSE;
  470. }