00001 /*- 00002 * See the file LICENSE for redistribution information. 00003 * 00004 * Copyright (c) 1996, 1997, 1998, 1999, 2000 00005 * Sleepycat Software. All rights reserved. 00006 */ 00007 #include "config.h" 00008 00009 #ifndef lint 00010 static const char revid[] = "$Id: hash__upgrade_8c-source.html,v 1.1 2008年06月08日 10:19:39 sebdiaz Exp $"; 00011 #endif /* not lint */ 00012 00013 #ifndef NO_SYSTEM_INCLUDES 00014 #include <sys/types.h> 00015 00016 #include <errno.h> 00017 #include <limits.h> 00018 #include <string.h> 00019 #endif 00020 00021 #include "db_int.h" 00022 #include "db_page.h" 00023 #include "db_swap.h" 00024 #include "hash.h" 00025 #include "db_upgrade.h" 00026 00027 /* 00028 * CDB___ham_30_hashmeta -- 00029 * Upgrade the database from version 4/5 to version 6. 00030 * 00031 * PUBLIC: int CDB___ham_30_hashmeta __P((DB *, char *, u_int8_t *)); 00032 */ 00033 int 00034 CDB___ham_30_hashmeta(dbp, real_name, obuf) 00035 DB *dbp; 00036 char *real_name; 00037 u_int8_t *obuf; 00038 { 00039 DB_ENV *dbenv; 00040 HASHHDR *oldmeta; 00041 HMETA30 newmeta; 00042 u_int32_t *o_spares, *n_spares; 00043 u_int32_t fillf, maxb, nelem; 00044 int i, non_zero, ret; 00045 00046 dbenv = dbp->dbenv; 00047 memset(&newmeta, 0, sizeof(newmeta)); 00048 00049 oldmeta = (HASHHDR *)obuf; 00050 00051 /* 00052 * The first 32 bytes are similar. The only change is the version 00053 * and that we removed the ovfl_point and have the page type now. 00054 */ 00055 00056 newmeta.dbmeta.lsn = oldmeta->lsn; 00057 newmeta.dbmeta.pgno = oldmeta->pgno; 00058 newmeta.dbmeta.magic = oldmeta->magic; 00059 newmeta.dbmeta.version = 6; 00060 newmeta.dbmeta.pagesize = oldmeta->pagesize; 00061 newmeta.dbmeta.type = P_HASHMETA; 00062 00063 /* Move flags */ 00064 newmeta.dbmeta.flags = oldmeta->flags; 00065 00066 /* Copy: max_bucket, high_mask, low-mask, ffactor, nelem, h_charkey */ 00067 newmeta.max_bucket = oldmeta->max_bucket; 00068 newmeta.high_mask = oldmeta->high_mask; 00069 newmeta.low_mask = oldmeta->low_mask; 00070 newmeta.ffactor = oldmeta->ffactor; 00071 newmeta.nelem = oldmeta->nelem; 00072 newmeta.h_charkey = oldmeta->h_charkey; 00073 00074 /* 00075 * There was a bug in 2.X versions where the nelem could go negative. 00076 * In general, this is considered "bad." If it does go negative 00077 * (that is, very large and positive), we'll die trying to dump and 00078 * load this database. So, let's see if we can fix it here. 00079 */ 00080 nelem = newmeta.nelem; 00081 fillf = newmeta.ffactor; 00082 maxb = newmeta.max_bucket; 00083 00084 if ((fillf != 0 && fillf * maxb < 2 * nelem) || 00085 (fillf == 0 && nelem > 0x8000000)) 00086 newmeta.nelem = 0; 00087 00088 /* 00089 * We now have to convert the spares array. The old spares array 00090 * contained the total number of extra pages allocated prior to 00091 * the bucket that begins the next doubling. The new spares array 00092 * contains the page number of the first bucket in the next doubling 00093 * MINUS the bucket number of that bucket. 00094 */ 00095 o_spares = oldmeta->spares; 00096 n_spares = newmeta.spares; 00097 non_zero = 0; 00098 n_spares[0] = 1; 00099 for (i = 1; i < NCACHED; i++) { 00100 non_zero = non_zero || o_spares[i - 1] != 0; 00101 if (o_spares[i - 1] == 0 && non_zero) 00102 n_spares[i] = 0; 00103 else 00104 n_spares[i] = 1 + o_spares[i - 1]; 00105 } 00106 00107 /* Replace the unique ID. */ 00108 if ((ret = CDB___os_fileid(dbenv, real_name, 1, newmeta.dbmeta.uid)) != 0) 00109 return (ret); 00110 00111 /* Overwrite the original. */ 00112 memcpy(oldmeta, &newmeta, sizeof(newmeta)); 00113 00114 return (0); 00115 } 00116 00117 /* 00118 * CDB___ham_31_hashmeta -- 00119 * Upgrade the database from version 6 to version 7. 00120 * 00121 * PUBLIC: int CDB___ham_31_hashmeta 00122 * PUBLIC: __P((DB *, char *, u_int32_t, DB_FH *, PAGE *, int *)); 00123 */ 00124 int 00125 CDB___ham_31_hashmeta(dbp, real_name, flags, fhp, h, dirtyp) 00126 DB *dbp; 00127 char *real_name; 00128 u_int32_t flags; 00129 DB_FH *fhp; 00130 PAGE *h; 00131 int *dirtyp; 00132 { 00133 HMETA31 *newmeta; 00134 HMETA30 *oldmeta; 00135 00136 COMPQUIET(dbp, NULL); 00137 COMPQUIET(real_name, NULL); 00138 COMPQUIET(fhp, NULL); 00139 00140 newmeta = (HMETA31 *)h; 00141 oldmeta = (HMETA30 *)h; 00142 00143 /* 00144 * Copy the fields down the page. 00145 * The fields may overlap so start at the bottom and use memmove(). 00146 */ 00147 memmove(newmeta->spares, oldmeta->spares, sizeof(oldmeta->spares)); 00148 newmeta->h_charkey = oldmeta->h_charkey; 00149 newmeta->nelem = oldmeta->nelem; 00150 newmeta->ffactor = oldmeta->ffactor; 00151 newmeta->low_mask = oldmeta->low_mask; 00152 newmeta->high_mask = oldmeta->high_mask; 00153 newmeta->max_bucket = oldmeta->max_bucket; 00154 memmove(newmeta->dbmeta.uid, 00155 oldmeta->dbmeta.uid, sizeof(oldmeta->dbmeta.uid)); 00156 newmeta->dbmeta.flags = oldmeta->dbmeta.flags; 00157 newmeta->dbmeta.record_count = 0; 00158 newmeta->dbmeta.key_count = 0; 00159 ZERO_LSN(newmeta->dbmeta.alloc_lsn); 00160 00161 /* Update the version. */ 00162 newmeta->dbmeta.version = 7; 00163 00164 /* Upgrade the flags. */ 00165 if (LF_ISSET(DB_DUPSORT)) 00166 F_SET(&newmeta->dbmeta, DB_HASH_DUPSORT); 00167 00168 *dirtyp = 1; 00169 return (0); 00170 } 00171 00172 /* 00173 * CDB___ham_31_hash -- 00174 * Upgrade the database hash leaf pages. 00175 * 00176 * PUBLIC: int CDB___ham_31_hash 00177 * PUBLIC: __P((DB *, char *, u_int32_t, DB_FH *, PAGE *, int *)); 00178 */ 00179 int 00180 CDB___ham_31_hash(dbp, real_name, flags, fhp, h, dirtyp) 00181 DB *dbp; 00182 char *real_name; 00183 u_int32_t flags; 00184 DB_FH *fhp; 00185 PAGE *h; 00186 int *dirtyp; 00187 { 00188 HKEYDATA *hk; 00189 db_pgno_t pgno, tpgno; 00190 db_indx_t indx; 00191 int ret; 00192 00193 COMPQUIET(flags, 0); 00194 00195 ret = 0; 00196 for (indx = 0; indx < NUM_ENT(h); indx += 2) { 00197 hk = (HKEYDATA *)H_PAIRDATA(h, indx); 00198 if (HPAGE_PTYPE(hk) == H_OFFDUP) { 00199 memcpy(&pgno, HOFFDUP_PGNO(hk), sizeof(db_pgno_t)); 00200 tpgno = pgno; 00201 if ((ret = CDB___db_31_offdup(dbp, real_name, fhp, 00202 LF_ISSET(DB_DUPSORT) ? 1 : 0, &tpgno)) != 0) 00203 break; 00204 if (pgno != tpgno) { 00205 *dirtyp = 1; 00206 memcpy(HOFFDUP_PGNO(hk), 00207 &tpgno, sizeof(db_pgno_t)); 00208 } 00209 } 00210 } 00211 00212 return (ret); 00213 }