diff options
Diffstat (limited to 'debian/htdig/htdig-3.2.0b6/db/hash_upgrade.c')
-rw-r--r-- | debian/htdig/htdig-3.2.0b6/db/hash_upgrade.c | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/debian/htdig/htdig-3.2.0b6/db/hash_upgrade.c b/debian/htdig/htdig-3.2.0b6/db/hash_upgrade.c new file mode 100644 index 00000000..ace73719 --- /dev/null +++ b/debian/htdig/htdig-3.2.0b6/db/hash_upgrade.c @@ -0,0 +1,206 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 1997, 1998, 1999 + * Sleepycat Software. All rights reserved. + */ +#include "db_config.h" + +#ifndef lint +static const char sccsid[] = "@(#)hash_upgrade.c 11.7 (Sleepycat) 10/20/99"; +#endif /* not lint */ + +#ifndef NO_SYSTEM_INCLUDES +#include <sys/types.h> + +#include <errno.h> +#include <limits.h> +#include <string.h> +#endif + +#include "db_int.h" +#include "db_page.h" +#include "db_swap.h" +#include "hash.h" + +static int CDB___ham_upgrade5 __P((DB *, int, char *, DB_FH *)); + +/* + * CDB___ham_upgrade -- + * Upgrade Hash databases. + * + * PUBLIC: int CDB___ham_upgrade __P((DB *, int, char *, DB_FH *, char *)); + */ +int +CDB___ham_upgrade(dbp, swapped, real_name, fhp, mbuf) + DB *dbp; + int swapped; + char *real_name, *mbuf; + DB_FH *fhp; +{ + DB_ENV *dbenv; + int ret; + + dbenv = dbp->dbenv; + + /* Check the version. */ + switch (((DBMETA *)mbuf)->version) { + case 4: + case 5: + if ((ret = CDB___ham_upgrade5(dbp, swapped, real_name, fhp)) != 0) + return (ret); + /* FALLTHROUGH */ + case 6: + break; + default: + CDB___db_err(dbenv, "%s: unsupported hash version: %lu", + real_name, (u_long)((DBMETA *)mbuf)->version); + return (DB_OLD_VERSION); + } + return (0); +} + +/* + * CDB___ham_upgrade5 -- + * Upgrade the database from version 4/5 to version 6. + */ +static int +CDB___ham_upgrade5(dbp, swapped, real_name, fhp) + DB *dbp; + int swapped; + char *real_name; + DB_FH *fhp; +{ + DB_ENV *dbenv; + ssize_t n; + u_int32_t *o_spares, *n_spares, version; + u_int32_t fillf, maxb, nelem; + int i, non_zero, ret; + u_int8_t nbuf[256], *new, obuf[256]; + + dbenv = dbp->dbenv; + + if (dbp->db_feedback != NULL) + dbp->db_feedback(dbp, DB_UPGRADE, 0); + + /* + * Seek to the beginning of the file and read the metadata page. We + * read 256 bytes, which is larger than any access method's metadata + * page. + */ + if ((ret = CDB___os_seek(fhp, 0, 0, 0, 0, DB_OS_SEEK_SET)) != 0) + return (ret); + if ((ret = CDB___os_read(fhp, obuf, sizeof(obuf), &n)) != 0) + return (ret); + + /* + * Upgrade a Hash meta-data page. + * Version 5: byte range: Version 6: byte range: + * lsn 00-07 lsn 00-07 + * pgno 08-11 pgno 08-11 + * magic 12-15 magic 12-15 + * version 16-19 version 16-19 + * pagesize 20-23 pagesize 20-23 + * ovfl_point 24-27 unused 24 + * type 25 + * unused 26-27 + * last_freed 28-31 free 28-31 + * max_bucket 32-35 flags 32-35 + * high_mask 36-39 uid 36-55 + * low_mask 40-43 max_bucket 56-59 + * ffactor 44-47 high_mask 60-63 + * nelem 48-51 low_mask 64-67 + * h_charkey 52-55 ffactor 68-71 + * flags 56-59 nelem 72-75 + * spares 60-187 h_charkey 76-79 + * uid 188-207 spares 80-207 + * + */ + + /* + * The first 32 bytes are similar. The only change is the version + * and that we removed the ovfl_point and have the page type now. + */ + memcpy(nbuf, obuf, 32); + + /* Update the version. */ + version = 6; + if (swapped) + M_32_SWAP(version); + memcpy(nbuf + 16, &version, sizeof(u_int32_t)); + + /* Assign unused and type fields. */ + new = nbuf + 24; + *new++ = '\0'; + *new++ = P_HASHMETA; + *new++ = '\0'; + *new = '\0'; + + /* Move flags */ + memcpy(nbuf + 32, obuf + 56, 4); + + /* Copy: max_bucket, high_mask, low-mask, ffactor, nelem, h_charkey */ + memcpy(nbuf + 56, obuf + 32, 24); + + /* + * There was a bug in 2.X versions where the nelem could go negative. + * In general, this is considered "bad." If it does go negative + * (that is, very large and positive), we'll die trying to dump and + * load this database. So, let's see if we can fix it here. + */ + memcpy(&nelem, nbuf + 72, sizeof(u_int32_t)); + memcpy(&fillf, nbuf + 68, sizeof(u_int32_t)); + memcpy(&maxb, nbuf + 56, sizeof(u_int32_t)); + if (swapped) { + M_32_SWAP(nelem); + M_32_SWAP(fillf); + M_32_SWAP(maxb); + } + + if ((fillf != 0 && fillf * maxb < 2 * nelem) || + (fillf == 0 && nelem > 0x8000000)) { + nelem = 0; + memcpy(nbuf + 72, &nelem, sizeof(u_int32_t)); + } + + /* + * We now have to convert the spares array. The old spares array + * contained the total number of extra pages allocated prior to + * the bucket that begins the next doubling. The new spares array + * contains the page number of the first bucket in the next doubling + * MINUS the bucket number of that bucket. + */ + o_spares = (u_int32_t *)(obuf + 60); + n_spares = (u_int32_t *)(nbuf + 80); + non_zero = 0; + n_spares[0] = 1; + for (i = 1; i < NCACHED; i++) { + if (swapped) + M_32_SWAP(o_spares[i -1]); + non_zero = non_zero || o_spares[i - 1] != 0; + if (o_spares[i - 1] == 0 && non_zero) + n_spares[i] = 0; + else + n_spares[i] = 1 + o_spares[i - 1]; + } + + if (swapped) + for (i = 0; i < NCACHED; i++) + M_32_SWAP(n_spares[i]); + + /* Replace the unique ID. */ + if ((ret = CDB___os_fileid(dbenv, real_name, 1, nbuf + 36)) != 0) + return (ret); + + if ((ret = CDB___os_seek(fhp, 0, 0, 0, 1, DB_OS_SEEK_SET)) != 0) + return (ret); + if ((ret = CDB___os_write(fhp, nbuf, 256, &n)) != 0) + return (ret); + if ((ret = CDB___os_fsync(fhp)) != 0) + return (ret); + + if (dbp->db_feedback != NULL) + dbp->db_feedback(dbp, DB_UPGRADE, 100); + + return (0); +} |