db

db_upg.c

Go to the documentation of this file.
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 
00008 #include "config.h"
00009 
00010 #ifndef lint
00011 static const char revid[] = "$Id: db__upg_8c-source.html,v 1.1 2008年06月08日 10:18:20 sebdiaz Exp $";
00012 #endif /* not lint */
00013 
00014 #ifndef NO_SYSTEM_INCLUDES
00015 #include <sys/types.h>
00016 
00017 #include <errno.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 "btree.h"
00025 #include "hash.h"
00026 #include "qam.h"
00027 
00028 static int (* const func_31_list[P_PAGETYPE_MAX])
00029 __P((DB *, char *, u_int32_t, DB_FH *, PAGE *, int *)) = {
00030 NULL, /* P_INVALID */
00031 NULL, /* __P_DUPLICATE */
00032 CDB___ham_31_hash, /* P_HASH */
00033 NULL, /* P_IBTREE */
00034 NULL, /* P_IRECNO */
00035 CDB___bam_31_lbtree, /* P_LBTREE */
00036 NULL, /* P_LRECNO */
00037 NULL, /* P_OVERFLOW */
00038 CDB___ham_31_hashmeta, /* P_HASHMETA */
00039 CDB___bam_31_btreemeta, /* P_BTREEMETA */
00040 };
00041 
00042 static int __db_page_pass __P((DB *, char *, u_int32_t, int (* const [])
00043 (DB *, char *, u_int32_t, DB_FH *, PAGE *, int *), DB_FH *));
00044 
00045 /*
00046  * CDB___db_upgrade --
00047  * Upgrade an existing database.
00048  *
00049  * PUBLIC: int CDB___db_upgrade __P((DB *, const char *, u_int32_t));
00050  */
00051 int
00052 CDB___db_upgrade(dbp, fname, flags)
00053 DB *dbp;
00054 const char *fname;
00055 u_int32_t flags;
00056 {
00057 DB_ENV *dbenv;
00058 DB_FH fh;
00059 size_t n;
00060 int ret, t_ret;
00061 u_int8_t mbuf[256];
00062 char *real_name;
00063 
00064 dbenv = dbp->dbenv;
00065 
00066 /* Validate arguments. */
00067 if ((ret = CDB___db_fchk(dbenv, "DB->upgrade", flags, DB_DUPSORT)) != 0)
00068 return (ret);
00069 
00070 /* Get the real backing file name. */
00071 if ((ret = CDB___db_appname(dbenv,
00072 DB_APP_DATA, NULL, fname, 0, NULL, &real_name)) != 0)
00073 return (ret);
00074 
00075 /* Open the file. */
00076 if ((ret = CDB___os_open(dbenv, real_name, 0, 0, &fh)) != 0) {
00077 CDB___db_err(dbenv, "%s: %s", real_name, CDB_db_strerror(ret));
00078 return (ret);
00079 }
00080 
00081 /* Initialize the feedback. */
00082 if (dbp->db_feedback != NULL)
00083 dbp->db_feedback(dbp, DB_UPGRADE, 0);
00084 
00085 /*
00086  * Read the metadata page. We read 256 bytes, which is larger than
00087  * any access method's metadata page and smaller than any disk sector.
00088  */
00089 if ((ret = CDB___os_read(dbenv, &fh, mbuf, sizeof(mbuf), &n)) != 0)
00090 goto err;
00091 
00092 switch (((DBMETA *)mbuf)->magic) {
00093 case DB_BTREEMAGIC:
00094 switch (((DBMETA *)mbuf)->version) {
00095 case 6:
00096 /*
00097  * Before V7 not all pages had page types, so we do the
00098  * single meta-data page by hand.
00099  */
00100 if ((ret =
00101 CDB___bam_30_btreemeta(dbp, real_name, mbuf)) != 0)
00102 goto err;
00103 if ((ret = CDB___os_seek(dbenv,
00104 &fh, 0, 0, 0, 0, DB_OS_SEEK_SET)) != 0)
00105 goto err;
00106 if ((ret = CDB___os_write(dbenv, &fh, mbuf, 256, &n)) != 0)
00107 goto err;
00108 /* FALLTHROUGH */
00109 case 7:
00110 /*
00111  * We need the page size to do more. Rip it out of
00112  * the meta-data page.
00113  */
00114 memcpy(&dbp->pgsize, mbuf + 20, sizeof(u_int32_t));
00115 
00116 if ((ret = __db_page_pass(
00117 dbp, real_name, flags, func_31_list, &fh)) != 0)
00118 goto err;
00119 /* FALLTHROUGH */
00120 case 8:
00121 break;
00122 default:
00123 CDB___db_err(dbenv, "%s: unsupported btree version: %lu",
00124 real_name, (u_long)((DBMETA *)mbuf)->version);
00125 ret = DB_OLD_VERSION;
00126 goto err;
00127 }
00128 break;
00129 case DB_HASHMAGIC:
00130 switch (((DBMETA *)mbuf)->version) {
00131 case 4:
00132 case 5:
00133 /*
00134  * Before V6 not all pages had page types, so we do the
00135  * single meta-data page by hand.
00136  */
00137 if ((ret =
00138 CDB___ham_30_hashmeta(dbp, real_name, mbuf)) != 0)
00139 goto err;
00140 if ((ret = CDB___os_seek(dbenv,
00141 &fh, 0, 0, 0, 0, DB_OS_SEEK_SET)) != 0)
00142 goto err;
00143 if ((ret = CDB___os_write(dbenv, &fh, mbuf, 256, &n)) != 0)
00144 goto err;
00145 /* FALLTHROUGH */
00146 case 6:
00147 /*
00148  * We need the page size to do more. Rip it out of
00149  * the meta-data page.
00150  */
00151 memcpy(&dbp->pgsize, mbuf + 20, sizeof(u_int32_t));
00152 
00153 if ((ret = __db_page_pass(
00154 dbp, real_name, flags, func_31_list, &fh)) != 0)
00155 goto err;
00156 /* FALLTHROUGH */
00157 case 7:
00158 break;
00159 default:
00160 CDB___db_err(dbenv, "%s: unsupported hash version: %lu",
00161 real_name, (u_long)((DBMETA *)mbuf)->version);
00162 ret = DB_OLD_VERSION;
00163 goto err;
00164 }
00165 break;
00166 case DB_QAMMAGIC:
00167 switch (((DBMETA *)mbuf)->version) {
00168 case 1:
00169 /*
00170  * If we're in a Queue database, the only page that
00171  * needs upgrading is the meta-database page, don't
00172  * bother with a full pass.
00173  */
00174 if ((ret = CDB___qam_31_qammeta(dbp, real_name, mbuf)) != 0)
00175 return (ret);
00176 if ((ret = CDB___os_seek(dbenv,
00177 &fh, 0, 0, 0, 0, DB_OS_SEEK_SET)) != 0)
00178 goto err;
00179 if ((ret = CDB___os_write(dbenv, &fh, mbuf, 256, &n)) != 0)
00180 goto err;
00181 /* FALLTHROUGH */
00182 case 2:
00183 break;
00184 default:
00185 CDB___db_err(dbenv, "%s: unsupported queue version: %lu",
00186 real_name, (u_long)((DBMETA *)mbuf)->version);
00187 ret = DB_OLD_VERSION;
00188 goto err;
00189 }
00190 break;
00191 default:
00192 M_32_SWAP(((DBMETA *)mbuf)->magic);
00193 switch (((DBMETA *)mbuf)->magic) {
00194 case DB_BTREEMAGIC:
00195 case DB_HASHMAGIC:
00196 case DB_QAMMAGIC:
00197 CDB___db_err(dbenv,
00198 "%s: DB->upgrade only supported on native byte-order systems",
00199 real_name);
00200 break;
00201 default:
00202 CDB___db_err(dbenv,
00203 "%s: unrecognized file type", real_name);
00204 break;
00205 }
00206 ret = EINVAL;
00207 goto err;
00208 }
00209 
00210 ret = CDB___os_fsync(dbenv, &fh);
00211 
00212 err: if ((t_ret = CDB___os_closehandle(&fh)) != 0 && ret == 0)
00213 ret = t_ret;
00214 CDB___os_freestr(real_name);
00215 
00216 /* We're done. */
00217 if (dbp->db_feedback != NULL)
00218 dbp->db_feedback(dbp, DB_UPGRADE, 100);
00219 
00220 return (ret);
00221 }
00222 
00223 /*
00224  * __db_page_pass --
00225  * Walk the pages of the database, upgrading whatever needs it.
00226  */
00227 static int
00228 __db_page_pass(dbp, real_name, flags, fl, fhp)
00229 DB *dbp;
00230 char *real_name;
00231 u_int32_t flags;
00232 int (* const fl[P_PAGETYPE_MAX])
00233 __P((DB *, char *, u_int32_t, DB_FH *, PAGE *, int *));
00234 DB_FH *fhp;
00235 {
00236 DB_ENV *dbenv;
00237 PAGE *page;
00238 db_pgno_t i, pgno_last;
00239 size_t n;
00240 int dirty, ret;
00241 
00242 dbenv = dbp->dbenv;
00243 
00244 /* Determine the last page of the file. */
00245 if ((ret = CDB___db_lastpgno(dbp, real_name, fhp, &pgno_last)) != 0)
00246 return (ret);
00247 
00248 /* Allocate memory for a single page. */
00249 if ((ret = CDB___os_malloc(dbenv, dbp->pgsize, NULL, &page)) != 0)
00250 return (ret);
00251 
00252 /* Walk the file, calling the underlying conversion functions. */
00253 for (i = 0; i < pgno_last; ++i) {
00254 if (dbp->db_feedback != NULL)
00255 dbp->db_feedback(dbp, DB_UPGRADE, (i * 100)/pgno_last);
00256 if ((ret = CDB___os_seek(dbenv,
00257 fhp, dbp->pgsize, i, 0, 0, DB_OS_SEEK_SET)) != 0)
00258 break;
00259 if ((ret = CDB___os_read(dbenv, fhp, page, dbp->pgsize, &n)) != 0)
00260 break;
00261 dirty = 0;
00262 if (fl[TYPE(page)] != NULL && (ret = fl[TYPE(page)]
00263 (dbp, real_name, flags, fhp, page, &dirty)) != 0)
00264 break;
00265 if (dirty) {
00266 if ((ret = CDB___os_seek(dbenv,
00267 fhp, dbp->pgsize, i, 0, 0, DB_OS_SEEK_SET)) != 0)
00268 break;
00269 if ((ret = CDB___os_write(dbenv,
00270 fhp, page, dbp->pgsize, &n)) != 0)
00271 break;
00272 }
00273 }
00274 
00275 CDB___os_free(page, dbp->pgsize);
00276 return (ret);
00277 }
00278 
00279 /*
00280  * CDB___db_lastpgno --
00281  * Return the current last page number of the file.
00282  *
00283  * PUBLIC: int CDB___db_lastpgno __P((DB *, char *, DB_FH *, db_pgno_t *));
00284  */
00285 int
00286 CDB___db_lastpgno(dbp, real_name, fhp, pgno_lastp)
00287 DB *dbp;
00288 char *real_name;
00289 DB_FH *fhp;
00290 db_pgno_t *pgno_lastp;
00291 {
00292 DB_ENV *dbenv;
00293 db_pgno_t pgno_last;
00294 u_int32_t mbytes, bytes;
00295 int ret;
00296 
00297 dbenv = dbp->dbenv;
00298 
00299 if ((ret = CDB___os_ioinfo(dbenv,
00300 real_name, fhp, &mbytes, &bytes, NULL)) != 0) {
00301 CDB___db_err(dbenv, "%s: %s", real_name, CDB_db_strerror(ret));
00302 return (ret);
00303 }
00304 
00305 /* Page sizes have to be a power-of-two. */
00306 if (bytes % dbp->pgsize != 0) {
00307 CDB___db_err(dbenv,
00308 "%s: file size not a multiple of the pagesize", real_name);
00309 return (EINVAL);
00310 }
00311 pgno_last = mbytes * (MEGABYTE / dbp->pgsize);
00312 pgno_last += bytes / dbp->pgsize;
00313 
00314 *pgno_lastp = pgno_last;
00315 return (0);
00316 }

Generated on Sun Jun 8 10:56:36 2008 for GNUmifluz by doxygen 1.5.5

AltStyle によって変換されたページ (->オリジナル) /