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

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 1996-2002
  5.  * Sleepycat Software.  All rights reserved.
  6.  */
  7. #include "db_config.h"
  8. #ifndef lint
  9. static const char revid[] = "$Id: db_reclaim.c,v 11.28 2002/08/06 06:11:17 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/btree.h"
  19. #include "dbinc/lock.h"
  20. /*
  21.  * __db_traverse_big
  22.  * Traverse a chain of overflow pages and call the callback routine
  23.  * on each one.  The calling convention for the callback is:
  24.  * callback(dbp, page, cookie, did_put),
  25.  * where did_put is a return value indicating if the page in question has
  26.  * already been returned to the mpool.
  27.  *
  28.  * PUBLIC: int __db_traverse_big __P((DB *,
  29.  * PUBLIC:     db_pgno_t, int (*)(DB *, PAGE *, void *, int *), void *));
  30.  */
  31. int
  32. __db_traverse_big(dbp, pgno, callback, cookie)
  33. DB *dbp;
  34. db_pgno_t pgno;
  35. int (*callback) __P((DB *, PAGE *, void *, int *));
  36. void *cookie;
  37. {
  38. DB_MPOOLFILE *mpf;
  39. PAGE *p;
  40. int did_put, ret;
  41. mpf = dbp->mpf;
  42. do {
  43. did_put = 0;
  44. if ((ret = mpf->get(mpf, &pgno, 0, &p)) != 0)
  45. return (ret);
  46. pgno = NEXT_PGNO(p);
  47. if ((ret = callback(dbp, p, cookie, &did_put)) == 0 &&
  48.     !did_put)
  49. ret = mpf->put(mpf, p, 0);
  50. } while (ret == 0 && pgno != PGNO_INVALID);
  51. return (ret);
  52. }
  53. /*
  54.  * __db_reclaim_callback
  55.  * This is the callback routine used during a delete of a subdatabase.
  56.  * we are traversing a btree or hash table and trying to free all the
  57.  * pages.  Since they share common code for duplicates and overflow
  58.  * items, we traverse them identically and use this routine to do the
  59.  * actual free.  The reason that this is callback is because hash uses
  60.  * the same traversal code for statistics gathering.
  61.  *
  62.  * PUBLIC: int __db_reclaim_callback __P((DB *, PAGE *, void *, int *));
  63.  */
  64. int
  65. __db_reclaim_callback(dbp, p, cookie, putp)
  66. DB *dbp;
  67. PAGE *p;
  68. void *cookie;
  69. int *putp;
  70. {
  71. int ret;
  72. COMPQUIET(dbp, NULL);
  73. if ((ret = __db_free(cookie, p)) != 0)
  74. return (ret);
  75. *putp = 1;
  76. return (0);
  77. }
  78. /*
  79.  * __db_truncate_callback
  80.  * This is the callback routine used during a truncate.
  81.  * we are traversing a btree or hash table and trying to free all the
  82.  * pages.
  83.  *
  84.  * PUBLIC: int __db_truncate_callback __P((DB *, PAGE *, void *, int *));
  85.  */
  86. int
  87. __db_truncate_callback(dbp, p, cookie, putp)
  88. DB *dbp;
  89. PAGE *p;
  90. void *cookie;
  91. int *putp;
  92. {
  93. DBMETA *meta;
  94. DBT ldbt;
  95. DB_LOCK metalock;
  96. DB_MPOOLFILE *mpf;
  97. db_indx_t indx, len, off, tlen, top;
  98. db_pgno_t pgno;
  99. db_trunc_param *param;
  100. u_int8_t *hk, type;
  101. int ret;
  102. top = NUM_ENT(p);
  103. mpf = dbp->mpf;
  104. param = cookie;
  105. *putp = 1;
  106. switch (TYPE(p)) {
  107. case P_LBTREE:
  108. /* Skip for off-page duplicates and deleted items. */
  109. for (indx = 0; indx < top; indx += P_INDX) {
  110. type = GET_BKEYDATA(dbp, p, indx + O_INDX)->type;
  111. if (!B_DISSET(type) && B_TYPE(type) != B_DUPLICATE)
  112. ++param->count;
  113. }
  114. /* FALLTHROUGH */
  115. case P_IBTREE:
  116. case P_IRECNO:
  117. case P_INVALID:
  118. if (dbp->type != DB_HASH &&
  119.     ((BTREE *)dbp->bt_internal)->bt_root == PGNO(p)) {
  120. type = dbp->type == DB_RECNO ? P_LRECNO : P_LBTREE;
  121. goto reinit;
  122. }
  123. break;
  124. case P_OVERFLOW:
  125. if (DBC_LOGGING(param->dbc)) {
  126. if ((ret = __db_ovref_log(dbp, param->dbc->txn,
  127.     &LSN(p), 0, p->pgno, -1, &LSN(p))) != 0)
  128. return (ret);
  129. } else
  130. LSN_NOT_LOGGED(LSN(p));
  131. if (--OV_REF(p) != 0)
  132. *putp = 0;
  133. break;
  134. case P_LRECNO:
  135. param->count += top;
  136. if (((BTREE *)dbp->bt_internal)->bt_root == PGNO(p)) {
  137. type = P_LRECNO;
  138. goto reinit;
  139. }
  140. break;
  141. case P_LDUP:
  142. /* Correct for deleted items. */
  143. for (indx = 0; indx < top; indx += O_INDX)
  144. if (!B_DISSET(GET_BKEYDATA(dbp, p, indx)->type))
  145. ++param->count;
  146. break;
  147. case P_HASH:
  148. /* Correct for on-page duplicates and deleted items. */
  149. for (indx = 0; indx < top; indx += P_INDX) {
  150. switch (*H_PAIRDATA(dbp, p, indx)) {
  151. case H_OFFDUP:
  152. case H_OFFPAGE:
  153. break;
  154. case H_KEYDATA:
  155. ++param->count;
  156. break;
  157. case H_DUPLICATE:
  158. tlen = LEN_HDATA(dbp, p, 0, indx);
  159. hk = H_PAIRDATA(dbp, p, indx);
  160. for (off = 0; off < tlen;
  161.     off += len + 2 * sizeof (db_indx_t)) {
  162. ++param->count;
  163. memcpy(&len,
  164.     HKEYDATA_DATA(hk)
  165.     + off, sizeof(db_indx_t));
  166. }
  167. }
  168. }
  169. /* Don't free the head of the bucket. */
  170. if (PREV_PGNO(p) == PGNO_INVALID) {
  171. type = P_HASH;
  172. reinit: *putp = 0;
  173. if (DBC_LOGGING(param->dbc)) {
  174. pgno = PGNO_BASE_MD;
  175. if ((ret = __db_lget(param->dbc, LCK_ALWAYS,
  176.     pgno, DB_LOCK_WRITE, 0, &metalock)) != 0)
  177. return (ret);
  178. if ((ret = mpf->get(mpf,
  179.     &pgno, 0, (PAGE **)&meta)) != 0) {
  180. goto err;
  181. }
  182. memset(&ldbt, 0, sizeof(ldbt));
  183. ldbt.data = p;
  184. ldbt.size = P_OVERHEAD(dbp);
  185. if ((ret = __db_pg_free_log(dbp,
  186.     param->dbc->txn, &LSN(meta), 0,
  187.     p->pgno, &LSN(meta),
  188.     PGNO_BASE_MD, &ldbt, meta->free)) != 0)
  189. goto err;
  190. LSN(p) = LSN(meta);
  191. if ((ret =
  192.     __db_pg_alloc_log(dbp,
  193.     param->dbc->txn, &LSN(meta), 0,
  194.     &LSN(meta), PGNO_BASE_MD,
  195.     &p->lsn, p->pgno, type, meta->free)) != 0) {
  196. err: (void)mpf->put(mpf, (PAGE *)meta, 0);
  197. (void)__TLPUT(param->dbc, metalock);
  198. return (ret);
  199. }
  200. LSN(p) = LSN(meta);
  201. if ((ret = mpf->put(mpf,
  202.     (PAGE *)meta, DB_MPOOL_DIRTY)) != 0) {
  203. (void)__TLPUT(param->dbc, metalock);
  204. return (ret);
  205. }
  206. if ((ret = __TLPUT(param->dbc, metalock)) != 0)
  207. return (ret);
  208. } else
  209. LSN_NOT_LOGGED(LSN(p));
  210. P_INIT(p, dbp->pgsize, PGNO(p), PGNO_INVALID,
  211.     PGNO_INVALID, type == P_HASH ? 0 : 1, type);
  212. }
  213. break;
  214. default:
  215. return (__db_pgfmt(dbp->dbenv, p->pgno));
  216. }
  217. if (*putp == 1) {
  218. if ((ret = __db_free(param->dbc, p)) != 0)
  219. return (ret);
  220. } else {
  221. if ((ret = mpf->put(mpf, p, DB_MPOOL_DIRTY)) != 0)
  222. return (ret);
  223. *putp = 1;
  224. }
  225. return (0);
  226. }