2
* See the file LICENSE for redistribution information.
4
* Copyright (c) 1996-2001
5
* Sleepycat Software. All rights reserved.
10
static const char revid[] = "$Id: hash_upgrade.c,v 11.26 2001/01/25 18:22:48 bostic Exp $";
13
#ifndef NO_SYSTEM_INCLUDES
14
#include <sys/types.h>
24
#include "db_upgrade.h"
27
* __ham_30_hashmeta --
28
* Upgrade the database from version 4/5 to version 6.
30
* PUBLIC: int __ham_30_hashmeta __P((DB *, char *, u_int8_t *));
33
__ham_30_hashmeta(dbp, real_name, obuf)
41
u_int32_t *o_spares, *n_spares;
42
u_int32_t fillf, maxb, nelem;
43
int i, max_entry, ret;
46
memset(&newmeta, 0, sizeof(newmeta));
48
oldmeta = (HASHHDR *)obuf;
51
* The first 32 bytes are similar. The only change is the version
52
* and that we removed the ovfl_point and have the page type now.
55
newmeta.dbmeta.lsn = oldmeta->lsn;
56
newmeta.dbmeta.pgno = oldmeta->pgno;
57
newmeta.dbmeta.magic = oldmeta->magic;
58
newmeta.dbmeta.version = 6;
59
newmeta.dbmeta.pagesize = oldmeta->pagesize;
60
newmeta.dbmeta.type = P_HASHMETA;
63
newmeta.dbmeta.flags = oldmeta->flags;
65
/* Copy the free list, which has changed its name but works the same. */
66
newmeta.dbmeta.free = oldmeta->last_freed;
68
/* Copy: max_bucket, high_mask, low-mask, ffactor, nelem, h_charkey */
69
newmeta.max_bucket = oldmeta->max_bucket;
70
newmeta.high_mask = oldmeta->high_mask;
71
newmeta.low_mask = oldmeta->low_mask;
72
newmeta.ffactor = oldmeta->ffactor;
73
newmeta.nelem = oldmeta->nelem;
74
newmeta.h_charkey = oldmeta->h_charkey;
77
* There was a bug in 2.X versions where the nelem could go negative.
78
* In general, this is considered "bad." If it does go negative
79
* (that is, very large and positive), we'll die trying to dump and
80
* load this database. So, let's see if we can fix it here.
82
nelem = newmeta.nelem;
83
fillf = newmeta.ffactor;
84
maxb = newmeta.max_bucket;
86
if ((fillf != 0 && fillf * maxb < 2 * nelem) ||
87
(fillf == 0 && nelem > 0x8000000))
91
* We now have to convert the spares array. The old spares array
92
* contained the total number of extra pages allocated prior to
93
* the bucket that begins the next doubling. The new spares array
94
* contains the page number of the first bucket in the next doubling
95
* MINUS the bucket number of that bucket.
97
o_spares = oldmeta->spares;
98
n_spares = newmeta.spares;
99
max_entry = __db_log2(maxb + 1); /* highest spares entry in use */
101
for (i = 1; i < NCACHED && i <= max_entry; i++)
102
n_spares[i] = 1 + o_spares[i - 1];
104
/* Replace the unique ID. */
105
if ((ret = __os_fileid(dbenv, real_name, 1, newmeta.dbmeta.uid)) != 0)
108
/* Overwrite the original. */
109
memcpy(oldmeta, &newmeta, sizeof(newmeta));
115
* __ham_30_sizefix --
116
* Make sure that all hash pages belonging to the current
117
* hash doubling are within the bounds of the file.
119
* PUBLIC: int __ham_30_sizefix __P((DB *, DB_FH *, char *, u_int8_t *));
122
__ham_30_sizefix(dbp, fhp, realname, metabuf)
128
u_int8_t buf[DB_MAX_PGSIZE];
131
db_pgno_t last_actual, last_desired;
137
memset(buf, 0, DB_MAX_PGSIZE);
139
meta = (HMETA30 *)metabuf;
140
pagesize = meta->dbmeta.pagesize;
143
* Get the last page number. To do this, we'll need dbp->pgsize
144
* to be set right, so slam it into place.
146
dbp->pgsize = pagesize;
147
if ((ret = __db_lastpgno(dbp, realname, fhp, &last_actual)) != 0)
151
* The last bucket in the doubling is equal to high_mask; calculate
152
* the page number that implies.
154
last_desired = BS_TO_PAGE(meta->high_mask, meta->spares);
157
* If last_desired > last_actual, we need to grow the file. Write
158
* a zeroed page where last_desired would go.
160
if (last_desired > last_actual) {
161
if ((ret = __os_seek(dbenv,
162
fhp, pagesize, last_desired, 0, 0, DB_OS_SEEK_SET)) != 0)
164
if ((ret = __os_write(dbenv, fhp, buf, pagesize, &nw)) != 0)
166
if (nw != pagesize) {
167
__db_err(dbenv, "Short write during upgrade");
176
* __ham_31_hashmeta --
177
* Upgrade the database from version 6 to version 7.
179
* PUBLIC: int __ham_31_hashmeta
180
* PUBLIC: __P((DB *, char *, u_int32_t, DB_FH *, PAGE *, int *));
183
__ham_31_hashmeta(dbp, real_name, flags, fhp, h, dirtyp)
194
COMPQUIET(dbp, NULL);
195
COMPQUIET(real_name, NULL);
196
COMPQUIET(fhp, NULL);
198
newmeta = (HMETA31 *)h;
199
oldmeta = (HMETA30 *)h;
202
* Copy the fields down the page.
203
* The fields may overlap so start at the bottom and use memmove().
205
memmove(newmeta->spares, oldmeta->spares, sizeof(oldmeta->spares));
206
newmeta->h_charkey = oldmeta->h_charkey;
207
newmeta->nelem = oldmeta->nelem;
208
newmeta->ffactor = oldmeta->ffactor;
209
newmeta->low_mask = oldmeta->low_mask;
210
newmeta->high_mask = oldmeta->high_mask;
211
newmeta->max_bucket = oldmeta->max_bucket;
212
memmove(newmeta->dbmeta.uid,
213
oldmeta->dbmeta.uid, sizeof(oldmeta->dbmeta.uid));
214
newmeta->dbmeta.flags = oldmeta->dbmeta.flags;
215
newmeta->dbmeta.record_count = 0;
216
newmeta->dbmeta.key_count = 0;
217
ZERO_LSN(newmeta->dbmeta.unused3);
219
/* Update the version. */
220
newmeta->dbmeta.version = 7;
222
/* Upgrade the flags. */
223
if (LF_ISSET(DB_DUPSORT))
224
F_SET(&newmeta->dbmeta, DB_HASH_DUPSORT);
232
* Upgrade the database hash leaf pages.
234
* PUBLIC: int __ham_31_hash
235
* PUBLIC: __P((DB *, char *, u_int32_t, DB_FH *, PAGE *, int *));
238
__ham_31_hash(dbp, real_name, flags, fhp, h, dirtyp)
247
db_pgno_t pgno, tpgno;
254
for (indx = 0; indx < NUM_ENT(h); indx += 2) {
255
hk = (HKEYDATA *)H_PAIRDATA(h, indx);
256
if (HPAGE_PTYPE(hk) == H_OFFDUP) {
257
memcpy(&pgno, HOFFDUP_PGNO(hk), sizeof(db_pgno_t));
259
if ((ret = __db_31_offdup(dbp, real_name, fhp,
260
LF_ISSET(DB_DUPSORT) ? 1 : 0, &tpgno)) != 0)
264
memcpy(HOFFDUP_PGNO(hk),
265
&tpgno, sizeof(db_pgno_t));