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

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: db_upg_opd.c,v 11.9 2000/11/30 00:58:33 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 "db_swap.h"
  18. #include "btree.h"
  19. #include "hash.h"
  20. #include "qam.h"
  21. static int __db_build_bi __P((DB *, DB_FH *, PAGE *, PAGE *, u_int32_t, int *));
  22. static int __db_build_ri __P((DB *, DB_FH *, PAGE *, PAGE *, u_int32_t, int *));
  23. static int __db_up_ovref __P((DB *, DB_FH *, db_pgno_t));
  24. #define GET_PAGE(dbp, fhp, pgno, page) {
  25. if ((ret = __os_seek(dbp->dbenv,
  26.     fhp, (dbp)->pgsize, pgno, 0, 0, DB_OS_SEEK_SET)) != 0)
  27. goto err;
  28. if ((ret = __os_read(dbp->dbenv,
  29.     fhp, page, (dbp)->pgsize, &n)) != 0)
  30. goto err;
  31. }
  32. #define PUT_PAGE(dbp, fhp, pgno, page) {
  33. if ((ret = __os_seek(dbp->dbenv,
  34.     fhp, (dbp)->pgsize, pgno, 0, 0, DB_OS_SEEK_SET)) != 0)
  35. goto err;
  36. if ((ret = __os_write(dbp->dbenv,
  37.     fhp, page, (dbp)->pgsize, &n)) != 0)
  38. goto err;
  39. }
  40. /*
  41.  * __db_31_offdup --
  42.  * Convert 3.0 off-page duplicates to 3.1 off-page duplicates.
  43.  *
  44.  * PUBLIC: int __db_31_offdup __P((DB *, char *, DB_FH *, int, db_pgno_t *));
  45.  */
  46. int
  47. __db_31_offdup(dbp, real_name, fhp, sorted, pgnop)
  48. DB *dbp;
  49. char *real_name;
  50. DB_FH *fhp;
  51. int sorted;
  52. db_pgno_t *pgnop;
  53. {
  54. PAGE *ipage, *page;
  55. db_indx_t indx;
  56. db_pgno_t cur_cnt, i, next_cnt, pgno, *pgno_cur, pgno_last;
  57. db_pgno_t *pgno_next, pgno_max, *tmp;
  58. db_recno_t nrecs;
  59. size_t n;
  60. int level, nomem, ret;
  61. ipage = page = NULL;
  62. pgno_cur = pgno_next = NULL;
  63. /* Allocate room to hold a page. */
  64. if ((ret = __os_malloc(dbp->dbenv, dbp->pgsize, NULL, &page)) != 0)
  65. goto err;
  66. /*
  67.  * Walk the chain of 3.0 off-page duplicates.  Each one is converted
  68.  * in place to a 3.1 off-page duplicate page.  If the duplicates are
  69.  * sorted, they are converted to a Btree leaf page, otherwise to a
  70.  * Recno leaf page.
  71.  */
  72. for (nrecs = 0, cur_cnt = pgno_max = 0,
  73.     pgno = *pgnop; pgno != PGNO_INVALID;) {
  74. if (pgno_max == cur_cnt) {
  75. pgno_max += 20;
  76. if ((ret = __os_realloc(dbp->dbenv, pgno_max *
  77.     sizeof(db_pgno_t), NULL, &pgno_cur)) != 0)
  78. goto err;
  79. }
  80. pgno_cur[cur_cnt++] = pgno;
  81. GET_PAGE(dbp, fhp, pgno, page);
  82. nrecs += NUM_ENT(page);
  83. LEVEL(page) = LEAFLEVEL;
  84. TYPE(page) = sorted ? P_LDUP : P_LRECNO;
  85. /*
  86.  * !!!
  87.  * DB didn't zero the LSNs on off-page duplicates pages.
  88.  */
  89. ZERO_LSN(LSN(page));
  90. PUT_PAGE(dbp, fhp, pgno, page);
  91. pgno = NEXT_PGNO(page);
  92. }
  93. /* If we only have a single page, it's easy. */
  94. if (cur_cnt > 1) {
  95. /*
  96.  * pgno_cur is the list of pages we just converted.  We're
  97.  * going to walk that list, but we'll need to create a new
  98.  * list while we do so.
  99.  */
  100. if ((ret = __os_malloc(dbp->dbenv,
  101.     cur_cnt * sizeof(db_pgno_t), NULL, &pgno_next)) != 0)
  102. goto err;
  103. /* Figure out where we can start allocating new pages. */
  104. if ((ret = __db_lastpgno(dbp, real_name, fhp, &pgno_last)) != 0)
  105. goto err;
  106. /* Allocate room for an internal page. */
  107. if ((ret = __os_malloc(dbp->dbenv,
  108.     dbp->pgsize, NULL, &ipage)) != 0)
  109. goto err;
  110. PGNO(ipage) = PGNO_INVALID;
  111. }
  112. /*
  113.  * Repeatedly walk the list of pages, building internal pages, until
  114.  * there's only one page at a level.
  115.  */
  116. for (level = LEAFLEVEL + 1; cur_cnt > 1; ++level) {
  117. for (indx = 0, i = next_cnt = 0; i < cur_cnt;) {
  118. if (indx == 0) {
  119. P_INIT(ipage, dbp->pgsize, pgno_last,
  120.     PGNO_INVALID, PGNO_INVALID,
  121.     level, sorted ? P_IBTREE : P_IRECNO);
  122. ZERO_LSN(LSN(ipage));
  123. pgno_next[next_cnt++] = pgno_last++;
  124. }
  125. GET_PAGE(dbp, fhp, pgno_cur[i], page);
  126. /*
  127.  * If the duplicates are sorted, put the first item on
  128.  * the lower-level page onto a Btree internal page. If
  129.  * the duplicates are not sorted, create an internal
  130.  * Recno structure on the page.  If either case doesn't
  131.  * fit, push out the current page and start a new one.
  132.  */
  133. nomem = 0;
  134. if (sorted) {
  135. if ((ret = __db_build_bi(
  136.     dbp, fhp, ipage, page, indx, &nomem)) != 0)
  137. goto err;
  138. } else
  139. if ((ret = __db_build_ri(
  140.     dbp, fhp, ipage, page, indx, &nomem)) != 0)
  141. goto err;
  142. if (nomem) {
  143. indx = 0;
  144. PUT_PAGE(dbp, fhp, PGNO(ipage), ipage);
  145. } else {
  146. ++indx;
  147. ++NUM_ENT(ipage);
  148. ++i;
  149. }
  150. }
  151. /*
  152.  * Push out the last internal page.  Set the top-level record
  153.  * count if we've reached the top.
  154.  */
  155. if (next_cnt == 1)
  156. RE_NREC_SET(ipage, nrecs);
  157. PUT_PAGE(dbp, fhp, PGNO(ipage), ipage);
  158. /* Swap the current and next page number arrays. */
  159. cur_cnt = next_cnt;
  160. tmp = pgno_cur;
  161. pgno_cur = pgno_next;
  162. pgno_next = tmp;
  163. }
  164. *pgnop = pgno_cur[0];
  165. err: if (pgno_cur != NULL)
  166. __os_free(pgno_cur, 0);
  167. if (pgno_next != NULL)
  168. __os_free(pgno_next, 0);
  169. if (ipage != NULL)
  170. __os_free(ipage, dbp->pgsize);
  171. if (page != NULL)
  172. __os_free(page, dbp->pgsize);
  173. return (ret);
  174. }
  175. /*
  176.  * __db_build_bi --
  177.  * Build a BINTERNAL entry for a parent page.
  178.  */
  179. static int
  180. __db_build_bi(dbp, fhp, ipage, page, indx, nomemp)
  181. DB *dbp;
  182. DB_FH *fhp;
  183. PAGE *ipage, *page;
  184. u_int32_t indx;
  185. int *nomemp;
  186. {
  187. BINTERNAL bi, *child_bi;
  188. BKEYDATA *child_bk;
  189. u_int8_t *p;
  190. int ret;
  191. switch (TYPE(page)) {
  192. case P_IBTREE:
  193. child_bi = GET_BINTERNAL(page, 0);
  194. if (P_FREESPACE(ipage) < BINTERNAL_PSIZE(child_bi->len)) {
  195. *nomemp = 1;
  196. return (0);
  197. }
  198. ipage->inp[indx] =
  199.      HOFFSET(ipage) -= BINTERNAL_SIZE(child_bi->len);
  200. p = P_ENTRY(ipage, indx);
  201. bi.len = child_bi->len;
  202. B_TSET(bi.type, child_bi->type, 0);
  203. bi.pgno = PGNO(page);
  204. bi.nrecs = __bam_total(page);
  205. memcpy(p, &bi, SSZA(BINTERNAL, data));
  206. p += SSZA(BINTERNAL, data);
  207. memcpy(p, child_bi->data, child_bi->len);
  208. /* Increment the overflow ref count. */
  209. if (B_TYPE(child_bi->type) == B_OVERFLOW)
  210. if ((ret = __db_up_ovref(dbp, fhp,
  211.     ((BOVERFLOW *)(child_bi->data))->pgno)) != 0)
  212. return (ret);
  213. break;
  214. case P_LDUP:
  215. child_bk = GET_BKEYDATA(page, 0);
  216. switch (B_TYPE(child_bk->type)) {
  217. case B_KEYDATA:
  218. if (P_FREESPACE(ipage) <
  219.     BINTERNAL_PSIZE(child_bk->len)) {
  220. *nomemp = 1;
  221. return (0);
  222. }
  223. ipage->inp[indx] =
  224.     HOFFSET(ipage) -= BINTERNAL_SIZE(child_bk->len);
  225. p = P_ENTRY(ipage, indx);
  226. bi.len = child_bk->len;
  227. B_TSET(bi.type, child_bk->type, 0);
  228. bi.pgno = PGNO(page);
  229. bi.nrecs = __bam_total(page);
  230. memcpy(p, &bi, SSZA(BINTERNAL, data));
  231. p += SSZA(BINTERNAL, data);
  232. memcpy(p, child_bk->data, child_bk->len);
  233. break;
  234. case B_OVERFLOW:
  235. if (P_FREESPACE(ipage) <
  236.     BINTERNAL_PSIZE(BOVERFLOW_SIZE)) {
  237. *nomemp = 1;
  238. return (0);
  239. }
  240. ipage->inp[indx] =
  241.     HOFFSET(ipage) -= BINTERNAL_SIZE(BOVERFLOW_SIZE);
  242. p = P_ENTRY(ipage, indx);
  243. bi.len = BOVERFLOW_SIZE;
  244. B_TSET(bi.type, child_bk->type, 0);
  245. bi.pgno = PGNO(page);
  246. bi.nrecs = __bam_total(page);
  247. memcpy(p, &bi, SSZA(BINTERNAL, data));
  248. p += SSZA(BINTERNAL, data);
  249. memcpy(p, child_bk, BOVERFLOW_SIZE);
  250. /* Increment the overflow ref count. */
  251. if ((ret = __db_up_ovref(dbp, fhp,
  252.     ((BOVERFLOW *)child_bk)->pgno)) != 0)
  253. return (ret);
  254. break;
  255. default:
  256. return (__db_pgfmt(dbp, PGNO(page)));
  257. }
  258. break;
  259. default:
  260. return (__db_pgfmt(dbp, PGNO(page)));
  261. }
  262. return (0);
  263. }
  264. /*
  265.  * __db_build_ri --
  266.  * Build a RINTERNAL entry for an internal parent page.
  267.  */
  268. static int
  269. __db_build_ri(dbp, fhp, ipage, page, indx, nomemp)
  270. DB *dbp;
  271. DB_FH *fhp;
  272. PAGE *ipage, *page;
  273. u_int32_t indx;
  274. int *nomemp;
  275. {
  276. RINTERNAL ri;
  277. COMPQUIET(dbp, NULL);
  278. COMPQUIET(fhp, NULL);
  279. if (P_FREESPACE(ipage) < RINTERNAL_PSIZE) {
  280. *nomemp = 1;
  281. return (0);
  282. }
  283. ri.pgno = PGNO(page);
  284. ri.nrecs = __bam_total(page);
  285. ipage->inp[indx] = HOFFSET(ipage) -= RINTERNAL_SIZE;
  286. memcpy(P_ENTRY(ipage, indx), &ri, RINTERNAL_SIZE);
  287. return (0);
  288. }
  289. /*
  290.  * __db_up_ovref --
  291.  * Increment/decrement the reference count on an overflow page.
  292.  */
  293. static int
  294. __db_up_ovref(dbp, fhp, pgno)
  295. DB *dbp;
  296. DB_FH *fhp;
  297. db_pgno_t pgno;
  298. {
  299. PAGE *page;
  300. size_t n;
  301. int ret;
  302. /* Allocate room to hold a page. */
  303. if ((ret = __os_malloc(dbp->dbenv, dbp->pgsize, NULL, &page)) != 0)
  304. return (ret);
  305. GET_PAGE(dbp, fhp, pgno, page);
  306. ++OV_REF(page);
  307. PUT_PAGE(dbp, fhp, pgno, page);
  308. err: __os_free(page, dbp->pgsize);
  309. return (ret);
  310. }