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

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