hash_upgrade.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: hash_upgrade.c,v 11.32 2002/08/06 05:34:58 bostic Exp $";
  10. #endif /* not lint */
  11. #ifndef NO_SYSTEM_INCLUDES
  12. #include <sys/types.h>
  13. #include <limits.h>
  14. #include <string.h>
  15. #endif
  16. #include "db_int.h"
  17. #include "dbinc/db_page.h"
  18. #include "dbinc/hash.h"
  19. #include "dbinc/db_upgrade.h"
  20. /*
  21.  * __ham_30_hashmeta --
  22.  * Upgrade the database from version 4/5 to version 6.
  23.  *
  24.  * PUBLIC: int __ham_30_hashmeta __P((DB *, char *, u_int8_t *));
  25.  */
  26. int
  27. __ham_30_hashmeta(dbp, real_name, obuf)
  28. DB *dbp;
  29. char *real_name;
  30. u_int8_t *obuf;
  31. {
  32. DB_ENV *dbenv;
  33. HASHHDR *oldmeta;
  34. HMETA30 newmeta;
  35. u_int32_t *o_spares, *n_spares;
  36. u_int32_t fillf, maxb, nelem;
  37. int i, max_entry, ret;
  38. dbenv = dbp->dbenv;
  39. memset(&newmeta, 0, sizeof(newmeta));
  40. oldmeta = (HASHHDR *)obuf;
  41. /*
  42.  * The first 32 bytes are similar.  The only change is the version
  43.  * and that we removed the ovfl_point and have the page type now.
  44.  */
  45. newmeta.dbmeta.lsn = oldmeta->lsn;
  46. newmeta.dbmeta.pgno = oldmeta->pgno;
  47. newmeta.dbmeta.magic = oldmeta->magic;
  48. newmeta.dbmeta.version = 6;
  49. newmeta.dbmeta.pagesize = oldmeta->pagesize;
  50. newmeta.dbmeta.type = P_HASHMETA;
  51. /* Move flags */
  52. newmeta.dbmeta.flags = oldmeta->flags;
  53. /* Copy the free list, which has changed its name but works the same. */
  54. newmeta.dbmeta.free = oldmeta->last_freed;
  55. /* Copy: max_bucket, high_mask, low-mask, ffactor, nelem, h_charkey */
  56. newmeta.max_bucket = oldmeta->max_bucket;
  57. newmeta.high_mask = oldmeta->high_mask;
  58. newmeta.low_mask = oldmeta->low_mask;
  59. newmeta.ffactor = oldmeta->ffactor;
  60. newmeta.nelem = oldmeta->nelem;
  61. newmeta.h_charkey = oldmeta->h_charkey;
  62. /*
  63.  * There was a bug in 2.X versions where the nelem could go negative.
  64.  * In general, this is considered "bad."  If it does go negative
  65.  * (that is, very large and positive), we'll die trying to dump and
  66.  * load this database.  So, let's see if we can fix it here.
  67.  */
  68. nelem = newmeta.nelem;
  69. fillf = newmeta.ffactor;
  70. maxb = newmeta.max_bucket;
  71. if ((fillf != 0 && fillf * maxb < 2 * nelem) ||
  72.     (fillf == 0 && nelem > 0x8000000))
  73. newmeta.nelem = 0;
  74. /*
  75.  * We now have to convert the spares array.  The old spares array
  76.  * contained the total number of extra pages allocated prior to
  77.  * the bucket that begins the next doubling.  The new spares array
  78.  * contains the page number of the first bucket in the next doubling
  79.  * MINUS the bucket number of that bucket.
  80.  */
  81. o_spares = oldmeta->spares;
  82. n_spares = newmeta.spares;
  83. max_entry = __db_log2(maxb + 1);   /* highest spares entry in use */
  84. n_spares[0] = 1;
  85. for (i = 1; i < NCACHED && i <= max_entry; i++)
  86. n_spares[i] = 1 + o_spares[i - 1];
  87. /* Replace the unique ID. */
  88. if ((ret = __os_fileid(dbenv, real_name, 1, newmeta.dbmeta.uid)) != 0)
  89. return (ret);
  90. /* Overwrite the original. */
  91. memcpy(oldmeta, &newmeta, sizeof(newmeta));
  92. return (0);
  93. }
  94. /*
  95.  * __ham_30_sizefix --
  96.  * Make sure that all hash pages belonging to the current
  97.  * hash doubling are within the bounds of the file.
  98.  *
  99.  * PUBLIC: int __ham_30_sizefix __P((DB *, DB_FH *, char *, u_int8_t *));
  100.  */
  101. int
  102. __ham_30_sizefix(dbp, fhp, realname, metabuf)
  103. DB *dbp;
  104. DB_FH *fhp;
  105. char *realname;
  106. u_int8_t *metabuf;
  107. {
  108. u_int8_t buf[DB_MAX_PGSIZE];
  109. DB_ENV *dbenv;
  110. HMETA30 *meta;
  111. db_pgno_t last_actual, last_desired;
  112. int ret;
  113. size_t nw;
  114. u_int32_t pagesize;
  115. dbenv = dbp->dbenv;
  116. memset(buf, 0, DB_MAX_PGSIZE);
  117. meta = (HMETA30 *)metabuf;
  118. pagesize = meta->dbmeta.pagesize;
  119. /*
  120.  * Get the last page number.  To do this, we'll need dbp->pgsize
  121.  * to be set right, so slam it into place.
  122.  */
  123. dbp->pgsize = pagesize;
  124. if ((ret = __db_lastpgno(dbp, realname, fhp, &last_actual)) != 0)
  125. return (ret);
  126. /*
  127.  * The last bucket in the doubling is equal to high_mask;  calculate
  128.  * the page number that implies.
  129.  */
  130. last_desired = BS_TO_PAGE(meta->high_mask, meta->spares);
  131. /*
  132.  * If last_desired > last_actual, we need to grow the file.  Write
  133.  * a zeroed page where last_desired would go.
  134.  */
  135. if (last_desired > last_actual) {
  136. if ((ret = __os_seek(dbenv,
  137.     fhp, pagesize, last_desired, 0, 0, DB_OS_SEEK_SET)) != 0)
  138. return (ret);
  139. if ((ret = __os_write(dbenv, fhp, buf, pagesize, &nw)) != 0)
  140. return (ret);
  141. }
  142. return (0);
  143. }
  144. /*
  145.  * __ham_31_hashmeta --
  146.  * Upgrade the database from version 6 to version 7.
  147.  *
  148.  * PUBLIC: int __ham_31_hashmeta
  149.  * PUBLIC:      __P((DB *, char *, u_int32_t, DB_FH *, PAGE *, int *));
  150.  */
  151. int
  152. __ham_31_hashmeta(dbp, real_name, flags, fhp, h, dirtyp)
  153. DB *dbp;
  154. char *real_name;
  155. u_int32_t flags;
  156. DB_FH *fhp;
  157. PAGE *h;
  158. int *dirtyp;
  159. {
  160. HMETA31 *newmeta;
  161. HMETA30 *oldmeta;
  162. COMPQUIET(dbp, NULL);
  163. COMPQUIET(real_name, NULL);
  164. COMPQUIET(fhp, NULL);
  165. newmeta = (HMETA31 *)h;
  166. oldmeta = (HMETA30 *)h;
  167. /*
  168.  * Copy the fields down the page.
  169.  * The fields may overlap so start at the bottom and use memmove().
  170.  */
  171. memmove(newmeta->spares, oldmeta->spares, sizeof(oldmeta->spares));
  172. newmeta->h_charkey = oldmeta->h_charkey;
  173. newmeta->nelem = oldmeta->nelem;
  174. newmeta->ffactor = oldmeta->ffactor;
  175. newmeta->low_mask = oldmeta->low_mask;
  176. newmeta->high_mask = oldmeta->high_mask;
  177. newmeta->max_bucket = oldmeta->max_bucket;
  178. memmove(newmeta->dbmeta.uid,
  179.     oldmeta->dbmeta.uid, sizeof(oldmeta->dbmeta.uid));
  180. newmeta->dbmeta.flags = oldmeta->dbmeta.flags;
  181. newmeta->dbmeta.record_count = 0;
  182. newmeta->dbmeta.key_count = 0;
  183. ZERO_LSN(newmeta->dbmeta.unused3);
  184. /* Update the version. */
  185. newmeta->dbmeta.version = 7;
  186. /* Upgrade the flags. */
  187. if (LF_ISSET(DB_DUPSORT))
  188. F_SET(&newmeta->dbmeta, DB_HASH_DUPSORT);
  189. *dirtyp = 1;
  190. return (0);
  191. }
  192. /*
  193.  * __ham_31_hash --
  194.  * Upgrade the database hash leaf pages.
  195.  *
  196.  * PUBLIC: int __ham_31_hash
  197.  * PUBLIC:      __P((DB *, char *, u_int32_t, DB_FH *, PAGE *, int *));
  198.  */
  199. int
  200. __ham_31_hash(dbp, real_name, flags, fhp, h, dirtyp)
  201. DB *dbp;
  202. char *real_name;
  203. u_int32_t flags;
  204. DB_FH *fhp;
  205. PAGE *h;
  206. int *dirtyp;
  207. {
  208. HKEYDATA *hk;
  209. db_pgno_t pgno, tpgno;
  210. db_indx_t indx;
  211. int ret;
  212. COMPQUIET(flags, 0);
  213. ret = 0;
  214. for (indx = 0; indx < NUM_ENT(h); indx += 2) {
  215. hk = (HKEYDATA *)H_PAIRDATA(dbp, h, indx);
  216. if (HPAGE_PTYPE(hk) == H_OFFDUP) {
  217. memcpy(&pgno, HOFFDUP_PGNO(hk), sizeof(db_pgno_t));
  218. tpgno = pgno;
  219. if ((ret = __db_31_offdup(dbp, real_name, fhp,
  220.     LF_ISSET(DB_DUPSORT) ? 1 : 0, &tpgno)) != 0)
  221. break;
  222. if (pgno != tpgno) {
  223. *dirtyp = 1;
  224. memcpy(HOFFDUP_PGNO(hk),
  225.     &tpgno, sizeof(db_pgno_t));
  226. }
  227. }
  228. }
  229. return (ret);
  230. }