~ubuntu-branches/ubuntu/edgy/rpm/edgy

« back to all changes in this revision

Viewing changes to db/hash/hash_upgrade.c

  • Committer: Bazaar Package Importer
  • Author(s): Joey Hess
  • Date: 2002-01-22 20:56:57 UTC
  • Revision ID: james.westby@ubuntu.com-20020122205657-l74j50mr9z8ofcl5
Tags: upstream-4.0.3
ImportĀ upstreamĀ versionĀ 4.0.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-
 
2
 * See the file LICENSE for redistribution information.
 
3
 *
 
4
 * Copyright (c) 1996-2001
 
5
 *      Sleepycat Software.  All rights reserved.
 
6
 */
 
7
#include "db_config.h"
 
8
 
 
9
#ifndef lint
 
10
static const char revid[] = "$Id: hash_upgrade.c,v 11.26 2001/01/25 18:22:48 bostic Exp $";
 
11
#endif /* not lint */
 
12
 
 
13
#ifndef NO_SYSTEM_INCLUDES
 
14
#include <sys/types.h>
 
15
 
 
16
#include <limits.h>
 
17
#include <string.h>
 
18
#endif
 
19
 
 
20
#include "db_int.h"
 
21
#include "db_page.h"
 
22
#include "db_swap.h"
 
23
#include "hash.h"
 
24
#include "db_upgrade.h"
 
25
 
 
26
/*
 
27
 * __ham_30_hashmeta --
 
28
 *      Upgrade the database from version 4/5 to version 6.
 
29
 *
 
30
 * PUBLIC: int __ham_30_hashmeta __P((DB *, char *, u_int8_t *));
 
31
 */
 
32
int
 
33
__ham_30_hashmeta(dbp, real_name, obuf)
 
34
        DB *dbp;
 
35
        char *real_name;
 
36
        u_int8_t *obuf;
 
37
{
 
38
        DB_ENV *dbenv;
 
39
        HASHHDR *oldmeta;
 
40
        HMETA30 newmeta;
 
41
        u_int32_t *o_spares, *n_spares;
 
42
        u_int32_t fillf, maxb, nelem;
 
43
        int i, max_entry, ret;
 
44
 
 
45
        dbenv = dbp->dbenv;
 
46
        memset(&newmeta, 0, sizeof(newmeta));
 
47
 
 
48
        oldmeta = (HASHHDR *)obuf;
 
49
 
 
50
        /*
 
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.
 
53
         */
 
54
 
 
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;
 
61
 
 
62
        /* Move flags */
 
63
        newmeta.dbmeta.flags = oldmeta->flags;
 
64
 
 
65
        /* Copy the free list, which has changed its name but works the same. */
 
66
        newmeta.dbmeta.free = oldmeta->last_freed;
 
67
 
 
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;
 
75
 
 
76
        /*
 
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.
 
81
         */
 
82
        nelem = newmeta.nelem;
 
83
        fillf = newmeta.ffactor;
 
84
        maxb = newmeta.max_bucket;
 
85
 
 
86
        if ((fillf != 0 && fillf * maxb < 2 * nelem) ||
 
87
            (fillf == 0 && nelem > 0x8000000))
 
88
                newmeta.nelem = 0;
 
89
 
 
90
        /*
 
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.
 
96
         */
 
97
        o_spares = oldmeta->spares;
 
98
        n_spares = newmeta.spares;
 
99
        max_entry = __db_log2(maxb + 1);   /* highest spares entry in use */
 
100
        n_spares[0] = 1;
 
101
        for (i = 1; i < NCACHED && i <= max_entry; i++)
 
102
                n_spares[i] = 1 + o_spares[i - 1];
 
103
 
 
104
                                        /* Replace the unique ID. */
 
105
        if ((ret = __os_fileid(dbenv, real_name, 1, newmeta.dbmeta.uid)) != 0)
 
106
                return (ret);
 
107
 
 
108
        /* Overwrite the original. */
 
109
        memcpy(oldmeta, &newmeta, sizeof(newmeta));
 
110
 
 
111
        return (0);
 
112
}
 
113
 
 
114
/*
 
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.
 
118
 *
 
119
 * PUBLIC: int __ham_30_sizefix __P((DB *, DB_FH *, char *, u_int8_t *));
 
120
 */
 
121
int
 
122
__ham_30_sizefix(dbp, fhp, realname, metabuf)
 
123
        DB *dbp;
 
124
        DB_FH *fhp;
 
125
        char *realname;
 
126
        u_int8_t *metabuf;
 
127
{
 
128
        u_int8_t buf[DB_MAX_PGSIZE];
 
129
        DB_ENV *dbenv;
 
130
        HMETA30 *meta;
 
131
        db_pgno_t last_actual, last_desired;
 
132
        int ret;
 
133
        size_t nw;
 
134
        u_int32_t pagesize;
 
135
 
 
136
        dbenv = dbp->dbenv;
 
137
        memset(buf, 0, DB_MAX_PGSIZE);
 
138
 
 
139
        meta = (HMETA30 *)metabuf;
 
140
        pagesize = meta->dbmeta.pagesize;
 
141
 
 
142
        /*
 
143
         * Get the last page number.  To do this, we'll need dbp->pgsize
 
144
         * to be set right, so slam it into place.
 
145
         */
 
146
        dbp->pgsize = pagesize;
 
147
        if ((ret = __db_lastpgno(dbp, realname, fhp, &last_actual)) != 0)
 
148
                return (ret);
 
149
 
 
150
        /*
 
151
         * The last bucket in the doubling is equal to high_mask;  calculate
 
152
         * the page number that implies.
 
153
         */
 
154
        last_desired = BS_TO_PAGE(meta->high_mask, meta->spares);
 
155
 
 
156
        /*
 
157
         * If last_desired > last_actual, we need to grow the file.  Write
 
158
         * a zeroed page where last_desired would go.
 
159
         */
 
160
        if (last_desired > last_actual) {
 
161
                if ((ret = __os_seek(dbenv,
 
162
                    fhp, pagesize, last_desired, 0, 0, DB_OS_SEEK_SET)) != 0)
 
163
                        return (ret);
 
164
                if ((ret = __os_write(dbenv, fhp, buf, pagesize, &nw)) != 0)
 
165
                        return (ret);
 
166
                if (nw != pagesize) {
 
167
                        __db_err(dbenv, "Short write during upgrade");
 
168
                        return (EIO);
 
169
                }
 
170
        }
 
171
 
 
172
        return (0);
 
173
}
 
174
 
 
175
/*
 
176
 * __ham_31_hashmeta --
 
177
 *      Upgrade the database from version 6 to version 7.
 
178
 *
 
179
 * PUBLIC: int __ham_31_hashmeta
 
180
 * PUBLIC:      __P((DB *, char *, u_int32_t, DB_FH *, PAGE *, int *));
 
181
 */
 
182
int
 
183
__ham_31_hashmeta(dbp, real_name, flags, fhp, h, dirtyp)
 
184
        DB *dbp;
 
185
        char *real_name;
 
186
        u_int32_t flags;
 
187
        DB_FH *fhp;
 
188
        PAGE *h;
 
189
        int *dirtyp;
 
190
{
 
191
        HMETA31 *newmeta;
 
192
        HMETA30 *oldmeta;
 
193
 
 
194
        COMPQUIET(dbp, NULL);
 
195
        COMPQUIET(real_name, NULL);
 
196
        COMPQUIET(fhp, NULL);
 
197
 
 
198
        newmeta = (HMETA31 *)h;
 
199
        oldmeta = (HMETA30 *)h;
 
200
 
 
201
        /*
 
202
         * Copy the fields down the page.
 
203
         * The fields may overlap so start at the bottom and use memmove().
 
204
         */
 
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);
 
218
 
 
219
        /* Update the version. */
 
220
        newmeta->dbmeta.version = 7;
 
221
 
 
222
        /* Upgrade the flags. */
 
223
        if (LF_ISSET(DB_DUPSORT))
 
224
                F_SET(&newmeta->dbmeta, DB_HASH_DUPSORT);
 
225
 
 
226
        *dirtyp = 1;
 
227
        return (0);
 
228
}
 
229
 
 
230
/*
 
231
 * __ham_31_hash --
 
232
 *      Upgrade the database hash leaf pages.
 
233
 *
 
234
 * PUBLIC: int __ham_31_hash
 
235
 * PUBLIC:      __P((DB *, char *, u_int32_t, DB_FH *, PAGE *, int *));
 
236
 */
 
237
int
 
238
__ham_31_hash(dbp, real_name, flags, fhp, h, dirtyp)
 
239
        DB *dbp;
 
240
        char *real_name;
 
241
        u_int32_t flags;
 
242
        DB_FH *fhp;
 
243
        PAGE *h;
 
244
        int *dirtyp;
 
245
{
 
246
        HKEYDATA *hk;
 
247
        db_pgno_t pgno, tpgno;
 
248
        db_indx_t indx;
 
249
        int ret;
 
250
 
 
251
        COMPQUIET(flags, 0);
 
252
 
 
253
        ret = 0;
 
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));
 
258
                        tpgno = pgno;
 
259
                        if ((ret = __db_31_offdup(dbp, real_name, fhp,
 
260
                            LF_ISSET(DB_DUPSORT) ? 1 : 0, &tpgno)) != 0)
 
261
                                break;
 
262
                        if (pgno != tpgno) {
 
263
                                *dirtyp = 1;
 
264
                                memcpy(HOFFDUP_PGNO(hk),
 
265
                                    &tpgno, sizeof(db_pgno_t));
 
266
                        }
 
267
                }
 
268
        }
 
269
 
 
270
        return (ret);
 
271
}