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

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: qam_rec.c,v 11.69 2002/08/06 06:17:10 bostic 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 "dbinc/db_page.h"
  17. #include "dbinc/db_shash.h"
  18. #include "dbinc/db_am.h"
  19. #include "dbinc/lock.h"
  20. #include "dbinc/log.h"
  21. #include "dbinc/qam.h"
  22. /*
  23.  * __qam_incfirst_recover --
  24.  * Recovery function for incfirst.
  25.  *
  26.  * PUBLIC: int __qam_incfirst_recover
  27.  * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
  28.  */
  29. int
  30. __qam_incfirst_recover(dbenv, dbtp, lsnp, op, info)
  31. DB_ENV *dbenv;
  32. DBT *dbtp;
  33. DB_LSN *lsnp;
  34. db_recops op;
  35. void *info;
  36. {
  37. __qam_incfirst_args *argp;
  38. DB *file_dbp;
  39. DBC *dbc;
  40. DB_LOCK lock;
  41. DB_MPOOLFILE *mpf;
  42. QMETA *meta;
  43. QUEUE_CURSOR *cp;
  44. db_pgno_t metapg;
  45. int exact, modified, ret, rec_ext;
  46. COMPQUIET(info, NULL);
  47. REC_PRINT(__qam_incfirst_print);
  48. REC_INTRO(__qam_incfirst_read, 1);
  49. metapg = ((QUEUE *)file_dbp->q_internal)->q_meta;
  50. if ((ret = __db_lget(dbc,
  51.     LCK_ROLLBACK, metapg,  DB_LOCK_WRITE, 0, &lock)) != 0)
  52. goto done;
  53. if ((ret = mpf->get(mpf, &metapg, 0, &meta)) != 0) {
  54. if (DB_REDO(op)) {
  55. if ((ret = mpf->get(mpf,
  56.     &metapg, DB_MPOOL_CREATE, &meta)) != 0) {
  57. (void)__LPUT(dbc, lock);
  58. goto out;
  59. }
  60. meta->dbmeta.pgno = metapg;
  61. meta->dbmeta.type = P_QAMMETA;
  62. } else {
  63. *lsnp = argp->prev_lsn;
  64. ret = 0;
  65. (void)__LPUT(dbc, lock);
  66. goto out;
  67. }
  68. }
  69. modified = 0;
  70. /*
  71.  * Only move first_recno backwards so we pick up the aborted delete.
  72.  * When going forward we need to be careful since
  73.  * we may have bumped over a locked record.
  74.  */
  75. if (DB_UNDO(op)) {
  76. if (QAM_BEFORE_FIRST(meta, argp->recno)) {
  77. meta->first_recno = argp->recno;
  78. modified = 1;
  79. }
  80. } else {
  81. if (log_compare(&LSN(meta), lsnp) < 0) {
  82. LSN(meta) = *lsnp;
  83. modified = 1;
  84. }
  85. rec_ext = 0;
  86. if (meta->page_ext != 0)
  87. rec_ext = meta->page_ext * meta->rec_page;
  88. cp = (QUEUE_CURSOR *)dbc->internal;
  89. if (meta->first_recno == RECNO_OOB)
  90. meta->first_recno++;
  91. while (meta->first_recno != meta->cur_recno &&
  92.     !QAM_BEFORE_FIRST(meta, argp->recno + 1)) {
  93. if ((ret = __qam_position(dbc,
  94.     &meta->first_recno, QAM_READ, &exact)) != 0)
  95. goto err;
  96. if (cp->page != NULL)
  97. __qam_fput(file_dbp, cp->pgno, cp->page, 0);
  98. if (exact == 1)
  99. break;
  100. if (cp->page != NULL &&
  101.     rec_ext != 0 && meta->first_recno % rec_ext == 0)
  102. if ((ret =
  103.     __qam_fremove(file_dbp, cp->pgno)) != 0)
  104. goto err;
  105. meta->first_recno++;
  106. if (meta->first_recno == RECNO_OOB)
  107. meta->first_recno++;
  108. modified = 1;
  109. }
  110. }
  111. if ((ret = mpf->put(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0)
  112. goto err1;
  113. (void)__LPUT(dbc, lock);
  114. done: *lsnp = argp->prev_lsn;
  115. ret = 0;
  116. if (0) {
  117. err: (void)mpf->put(mpf, meta, 0);
  118. err1: (void)__LPUT(dbc, lock);
  119. }
  120. out: REC_CLOSE;
  121. }
  122. /*
  123.  * __qam_mvptr_recover --
  124.  * Recovery function for mvptr.
  125.  *
  126.  * PUBLIC: int __qam_mvptr_recover
  127.  * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
  128.  */
  129. int
  130. __qam_mvptr_recover(dbenv, dbtp, lsnp, op, info)
  131. DB_ENV *dbenv;
  132. DBT *dbtp;
  133. DB_LSN *lsnp;
  134. db_recops op;
  135. void *info;
  136. {
  137. __qam_mvptr_args *argp;
  138. DB *file_dbp;
  139. DBC *dbc;
  140. DB_LOCK lock;
  141. DB_MPOOLFILE *mpf;
  142. QMETA *meta;
  143. db_pgno_t metapg;
  144. int cmp_n, cmp_p, modified, ret;
  145. COMPQUIET(info, NULL);
  146. REC_PRINT(__qam_mvptr_print);
  147. REC_INTRO(__qam_mvptr_read, 1);
  148. metapg = ((QUEUE *)file_dbp->q_internal)->q_meta;
  149. if ((ret = __db_lget(dbc,
  150.     LCK_ROLLBACK, metapg,  DB_LOCK_WRITE, 0, &lock)) != 0)
  151. goto done;
  152. if ((ret = mpf->get(mpf, &metapg, 0, &meta)) != 0) {
  153. if (DB_REDO(op)) {
  154. if ((ret = mpf->get(mpf,
  155.     &metapg, DB_MPOOL_CREATE, &meta)) != 0) {
  156. (void)__LPUT(dbc, lock);
  157. goto out;
  158. }
  159. meta->dbmeta.pgno = metapg;
  160. meta->dbmeta.type = P_QAMMETA;
  161. } else {
  162. *lsnp = argp->prev_lsn;
  163. ret = 0;
  164. (void)__LPUT(dbc, lock);
  165. goto out;
  166. }
  167. }
  168. modified = 0;
  169. cmp_n = log_compare(lsnp, &LSN(meta));
  170. cmp_p = log_compare(&LSN(meta), &argp->metalsn);
  171. /*
  172.  * Under normal circumstances, we never undo a movement of one of
  173.  * the pointers.  Just move them along regardless of abort/commit.
  174.  *
  175.  * If we're undoing a truncate, we need to reset the pointers to
  176.  * their state before the truncate.
  177.  */
  178. if (DB_UNDO(op) && (argp->opcode & QAM_TRUNCATE)) {
  179. if (cmp_n == 0) {
  180. meta->first_recno = argp->old_first;
  181. meta->cur_recno = argp->old_cur;
  182. modified = 1;
  183. meta->dbmeta.lsn = argp->metalsn;
  184. }
  185. } else if (cmp_p == 0) {
  186. if (argp->opcode & QAM_SETFIRST)
  187. meta->first_recno = argp->new_first;
  188. if (argp->opcode & QAM_SETCUR)
  189. meta->cur_recno = argp->new_cur;
  190. modified = 1;
  191. meta->dbmeta.lsn = *lsnp;
  192. }
  193. if ((ret = mpf->put(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0)
  194. goto out;
  195. (void)__LPUT(dbc, lock);
  196. done: *lsnp = argp->prev_lsn;
  197. ret = 0;
  198. out: REC_CLOSE;
  199. }
  200. /*
  201.  * __qam_del_recover --
  202.  * Recovery function for del.
  203.  * Non-extent version or if there is no data (zero len).
  204.  *
  205.  * PUBLIC: int __qam_del_recover
  206.  * PUBLIC:     __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
  207.  */
  208. int
  209. __qam_del_recover(dbenv, dbtp, lsnp, op, info)
  210. DB_ENV *dbenv;
  211. DBT *dbtp;
  212. DB_LSN *lsnp;
  213. db_recops op;
  214. void *info;
  215. {
  216. __qam_del_args *argp;
  217. DB *file_dbp;
  218. DBC *dbc;
  219. DB_LOCK lock;
  220. DB_MPOOLFILE *mpf;
  221. QAMDATA *qp;
  222. QMETA *meta;
  223. QPAGE *pagep;
  224. db_pgno_t metapg;
  225. int cmp_n, modified, ret;
  226. COMPQUIET(info, NULL);
  227. REC_PRINT(__qam_del_print);
  228. REC_INTRO(__qam_del_read, 1);
  229. if ((ret = __qam_fget(file_dbp,
  230.     &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
  231. goto out;
  232. modified = 0;
  233. if (pagep->pgno == PGNO_INVALID) {
  234. pagep->pgno = argp->pgno;
  235. pagep->type = P_QAMDATA;
  236. modified = 1;
  237. }
  238. cmp_n = log_compare(lsnp, &LSN(pagep));
  239. if (DB_UNDO(op)) {
  240. /* make sure first is behind us */
  241. metapg = ((QUEUE *)file_dbp->q_internal)->q_meta;
  242. if ((ret = __db_lget(dbc,
  243.     LCK_ROLLBACK, metapg, DB_LOCK_WRITE, 0, &lock)) != 0)
  244. goto err;
  245. if ((ret = mpf->get(mpf, &metapg, 0, &meta)) != 0) {
  246. (void)__LPUT(dbc, lock);
  247. goto err;
  248. }
  249. if (meta->first_recno == RECNO_OOB ||
  250.     (QAM_BEFORE_FIRST(meta, argp->recno) &&
  251.     (meta->first_recno <= meta->cur_recno ||
  252.     meta->first_recno -
  253.     argp->recno < argp->recno - meta->cur_recno))) {
  254. meta->first_recno = argp->recno;
  255. (void)mpf->put(mpf, meta, DB_MPOOL_DIRTY);
  256. } else
  257. (void)mpf->put(mpf, meta, 0);
  258. (void)__LPUT(dbc, lock);
  259. /* Need to undo delete - mark the record as present */
  260. qp = QAM_GET_RECORD(file_dbp, pagep, argp->indx);
  261. F_SET(qp, QAM_VALID);
  262. /*
  263.  * Move the LSN back to this point;  do not move it forward.
  264.  * Only move it back if we're in recovery.  If we're in
  265.  * an abort, because we don't hold a page lock, we could
  266.  * foul up a concurrent put.  Having too late an LSN
  267.  * is harmless in queue except when we're determining
  268.  * what we need to roll forward during recovery.  [#2588]
  269.  */
  270. if (op == DB_TXN_BACKWARD_ROLL && cmp_n <= 0)
  271. LSN(pagep) = argp->lsn;
  272. modified = 1;
  273. } else if (cmp_n > 0 && DB_REDO(op)) {
  274. /* Need to redo delete - clear the valid bit */
  275. qp = QAM_GET_RECORD(file_dbp, pagep, argp->indx);
  276. F_CLR(qp, QAM_VALID);
  277. LSN(pagep) = *lsnp;
  278. modified = 1;
  279. }
  280. if ((ret = __qam_fput(file_dbp,
  281.     argp->pgno, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
  282. goto out;
  283. done: *lsnp = argp->prev_lsn;
  284. ret = 0;
  285. if (0) {
  286. err: (void)__qam_fput(file_dbp, argp->pgno, pagep, 0);
  287. }
  288. out: REC_CLOSE;
  289. }
  290. /*
  291.  * __qam_delext_recover --
  292.  * Recovery function for del in an extent based queue.
  293.  *
  294.  * PUBLIC: int __qam_delext_recover __P((DB_ENV *,
  295.  * PUBLIC:     DBT *, DB_LSN *, db_recops, void *));
  296.  */
  297. int
  298. __qam_delext_recover(dbenv, dbtp, lsnp, op, info)
  299. DB_ENV *dbenv;
  300. DBT *dbtp;
  301. DB_LSN *lsnp;
  302. db_recops op;
  303. void *info;
  304. {
  305. __qam_delext_args *argp;
  306. DB *file_dbp;
  307. DBC *dbc;
  308. DB_LOCK lock;
  309. DB_MPOOLFILE *mpf;
  310. QAMDATA *qp;
  311. QMETA *meta;
  312. QPAGE *pagep;
  313. db_pgno_t metapg;
  314. int cmp_n, modified, ret;
  315. COMPQUIET(info, NULL);
  316. REC_PRINT(__qam_delext_print);
  317. REC_INTRO(__qam_delext_read, 1);
  318. if ((ret = __qam_fget(file_dbp, &argp->pgno, 0, &pagep)) != 0) {
  319. if (ret != DB_PAGE_NOTFOUND && ret != ENOENT)
  320. goto out;
  321. /*
  322.  * If we are redoing a delete and the page is not there
  323.  * we are done.
  324.  */
  325. if (DB_REDO(op))
  326. goto done;
  327. if ((ret = __qam_fget(file_dbp,
  328.     &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
  329. goto out;
  330. }
  331. modified = 0;
  332. if (pagep->pgno == PGNO_INVALID) {
  333. pagep->pgno = argp->pgno;
  334. pagep->type = P_QAMDATA;
  335. modified = 1;
  336. }
  337. cmp_n = log_compare(lsnp, &LSN(pagep));
  338. if (DB_UNDO(op)) {
  339. /* make sure first is behind us */
  340. metapg = ((QUEUE *)file_dbp->q_internal)->q_meta;
  341. if ((ret = __db_lget(dbc,
  342.     LCK_ROLLBACK, metapg, DB_LOCK_WRITE, 0, &lock)) != 0)
  343. goto err;
  344. if ((ret = mpf->get(mpf, &metapg, 0, &meta)) != 0) {
  345. (void)__LPUT(dbc, lock);
  346. goto err;
  347. }
  348. if (meta->first_recno == RECNO_OOB ||
  349.     (QAM_BEFORE_FIRST(meta, argp->recno) &&
  350.     (meta->first_recno <= meta->cur_recno ||
  351.     meta->first_recno -
  352.     argp->recno < argp->recno - meta->cur_recno))) {
  353. meta->first_recno = argp->recno;
  354. (void)mpf->put(mpf, meta, DB_MPOOL_DIRTY);
  355. } else
  356. (void)mpf->put(mpf, meta, 0);
  357. (void)__LPUT(dbc, lock);
  358. if ((ret = __qam_pitem(dbc, pagep,
  359.     argp->indx, argp->recno, &argp->data)) != 0)
  360. goto err;
  361. /*
  362.  * Move the LSN back to this point;  do not move it forward.
  363.  * Only move it back if we're in recovery.  If we're in
  364.  * an abort, because we don't hold a page lock, we could
  365.  * foul up a concurrent put.  Having too late an LSN
  366.  * is harmless in queue except when we're determining
  367.  * what we need to roll forward during recovery.  [#2588]
  368.  */
  369. if (op == DB_TXN_BACKWARD_ROLL && cmp_n <= 0)
  370. LSN(pagep) = argp->lsn;
  371. modified = 1;
  372. } else if (cmp_n > 0 && DB_REDO(op)) {
  373. /* Need to redo delete - clear the valid bit */
  374. qp = QAM_GET_RECORD(file_dbp, pagep, argp->indx);
  375. F_CLR(qp, QAM_VALID);
  376. LSN(pagep) = *lsnp;
  377. modified = 1;
  378. }
  379. if ((ret = __qam_fput(file_dbp,
  380.     argp->pgno, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
  381. goto out;
  382. done: *lsnp = argp->prev_lsn;
  383. ret = 0;
  384. if (0) {
  385. err: (void)__qam_fput(file_dbp, argp->pgno, pagep, 0);
  386. }
  387. out: REC_CLOSE;
  388. }
  389. /*
  390.  * __qam_add_recover --
  391.  * Recovery function for add.
  392.  *
  393.  * PUBLIC: int __qam_add_recover
  394.  * PUBLIC:     __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
  395.  */
  396. int
  397. __qam_add_recover(dbenv, dbtp, lsnp, op, info)
  398. DB_ENV *dbenv;
  399. DBT *dbtp;
  400. DB_LSN *lsnp;
  401. db_recops op;
  402. void *info;
  403. {
  404. __qam_add_args *argp;
  405. DB *file_dbp;
  406. DBC *dbc;
  407. DB_MPOOLFILE *mpf;
  408. QAMDATA *qp;
  409. QMETA *meta;
  410. QPAGE *pagep;
  411. db_pgno_t metapg;
  412. int cmp_n, meta_dirty, modified, ret;
  413. COMPQUIET(info, NULL);
  414. REC_PRINT(__qam_add_print);
  415. REC_INTRO(__qam_add_read, 1);
  416. modified = 0;
  417. if ((ret = __qam_fget(file_dbp, &argp->pgno, 0, &pagep)) != 0) {
  418. if (ret != DB_PAGE_NOTFOUND && ret != ENOENT)
  419. goto out;
  420. /*
  421.  * If we are undoing an append and the page is not there
  422.  * we are done.
  423.  */
  424. if (DB_UNDO(op))
  425. goto done;
  426. if ((ret = __qam_fget(file_dbp,
  427.     &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
  428. goto out;
  429. }
  430. if (pagep->pgno == PGNO_INVALID) {
  431. pagep->pgno = argp->pgno;
  432. pagep->type = P_QAMDATA;
  433. modified = 1;
  434. }
  435. cmp_n = log_compare(lsnp, &LSN(pagep));
  436. if (DB_REDO(op)) {
  437. /* Fix meta-data page. */
  438. metapg = ((QUEUE *)file_dbp->q_internal)->q_meta;
  439. if ((ret = mpf->get(mpf, &metapg, 0, &meta)) != 0)
  440. goto err;
  441. meta_dirty = 0;
  442. if (QAM_BEFORE_FIRST(meta, argp->recno)) {
  443. meta->first_recno = argp->recno;
  444. meta_dirty = 1;
  445. }
  446. if (argp->recno == meta->cur_recno ||
  447.    QAM_AFTER_CURRENT(meta, argp->recno)) {
  448. meta->cur_recno = argp->recno + 1;
  449. meta_dirty = 1;
  450. }
  451. if ((ret =
  452.     mpf->put(mpf, meta, meta_dirty? DB_MPOOL_DIRTY : 0)) != 0)
  453. goto err;
  454. /* Now update the actual page if necessary. */
  455. if (cmp_n > 0) {
  456. /* Need to redo add - put the record on page */
  457. if ((ret = __qam_pitem(dbc,
  458.     pagep, argp->indx, argp->recno, &argp->data)) != 0)
  459. goto err;
  460. LSN(pagep) = *lsnp;
  461. modified = 1;
  462. /* Make sure pointers include this record. */
  463. metapg = ((QUEUE *)file_dbp->q_internal)->q_meta;
  464. }
  465. } else if (DB_UNDO(op)) {
  466. /*
  467.  * Need to undo add
  468.  * If this was an overwrite, put old record back.
  469.  * Otherwise just clear the valid bit
  470.  */
  471. if (argp->olddata.size != 0) {
  472. if ((ret = __qam_pitem(dbc, pagep,
  473.     argp->indx, argp->recno, &argp->olddata)) != 0)
  474. goto err;
  475. if (!(argp->vflag & QAM_VALID)) {
  476. qp = QAM_GET_RECORD(
  477.     file_dbp, pagep, argp->indx);
  478. F_CLR(qp, QAM_VALID);
  479. }
  480. modified = 1;
  481. } else {
  482. qp = QAM_GET_RECORD(file_dbp, pagep, argp->indx);
  483. qp->flags = 0;
  484. modified = 1;
  485. }
  486. /*
  487.  * Move the LSN back to this point;  do not move it forward.
  488.  * Only move it back if we're in recovery.  If we're in
  489.  * an abort, because we don't hold a page lock, we could
  490.  * foul up a concurrent put.  Having too late an LSN
  491.  * is harmless in queue except when we're determining
  492.  * what we need to roll forward during recovery.  [#2588]
  493.  */
  494. if (op == DB_TXN_BACKWARD_ROLL && cmp_n <= 0)
  495. LSN(pagep) = argp->lsn;
  496. }
  497. if ((ret = __qam_fput(file_dbp,
  498.     argp->pgno, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
  499. goto out;
  500. done: *lsnp = argp->prev_lsn;
  501. ret = 0;
  502. if (0) {
  503. err: (void)__qam_fput(file_dbp, argp->pgno, pagep, 0);
  504. }
  505. out: REC_CLOSE;
  506. }