00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "db_config.h"
00011
00012 #ifndef NO_SYSTEM_INCLUDES
00013 #include <sys/types.h>
00014
00015 #include <string.h>
00016 #endif
00017
00018 #include "db_int.h"
00019 #include "dbinc/db_page.h"
00020 #include "dbinc/db_swap.h"
00021 #include "dbinc/btree.h"
00022 #include "dbinc/hash.h"
00023 #include "dbinc/qam.h"
00024
00025 static int (* const func_31_list[P_PAGETYPE_MAX])
00026 __P((DB *, char *, u_int32_t, DB_FH *, PAGE *, int *)) = {
00027 NULL,
00028 NULL,
00029 __ham_31_hash,
00030 NULL,
00031 NULL,
00032 __bam_31_lbtree,
00033 NULL,
00034 NULL,
00035 __ham_31_hashmeta,
00036 __bam_31_btreemeta,
00037 NULL,
00038 NULL,
00039 NULL,
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
00047
00048
00049
00050
00051 int
00052 __db_upgrade_pp(dbp, fname, flags)
00053 DB *dbp;
00054 const char *fname;
00055 u_int32_t flags;
00056 {
00057 DB_ENV *dbenv;
00058 int ret;
00059
00060 dbenv = dbp->dbenv;
00061
00062 PANIC_CHECK(dbp->dbenv);
00063
00064
00065
00066
00067
00068 if ((ret = __db_fchk(dbenv, "DB->upgrade", flags, DB_DUPSORT)) != 0)
00069 return (ret);
00070
00071 return (__db_upgrade(dbp, fname, flags));
00072 }
00073
00074
00075
00076
00077
00078
00079
00080 int
00081 __db_upgrade(dbp, fname, flags)
00082 DB *dbp;
00083 const char *fname;
00084 u_int32_t flags;
00085 {
00086 DB_ENV *dbenv;
00087 DB_FH *fhp;
00088 size_t n;
00089 int ret, t_ret;
00090 u_int8_t mbuf[256];
00091 char *real_name;
00092
00093 dbenv = dbp->dbenv;
00094 fhp = NULL;
00095
00096
00097 if ((ret = __db_appname(dbenv,
00098 DB_APP_DATA, fname, 0, NULL, &real_name)) != 0)
00099 return (ret);
00100
00101
00102 if ((ret = __os_open(dbenv, real_name, 0, 0, &fhp)) != 0) {
00103 __db_err(dbenv, "%s: %s", real_name, db_strerror(ret));
00104 return (ret);
00105 }
00106
00107
00108 if (dbp->db_feedback != NULL)
00109 dbp->db_feedback(dbp, DB_UPGRADE, 0);
00110
00111
00112
00113
00114
00115 if ((ret = __os_read(dbenv, fhp, mbuf, sizeof(mbuf), &n)) != 0)
00116 goto err;
00117
00118 switch (((DBMETA *)mbuf)->magic) {
00119 case DB_BTREEMAGIC:
00120 switch (((DBMETA *)mbuf)->version) {
00121 case 6:
00122
00123
00124
00125
00126 if ((ret =
00127 __bam_30_btreemeta(dbp, real_name, mbuf)) != 0)
00128 goto err;
00129 if ((ret = __os_seek(dbenv,
00130 fhp, 0, 0, 0, 0, DB_OS_SEEK_SET)) != 0)
00131 goto err;
00132 if ((ret = __os_write(dbenv, fhp, mbuf, 256, &n)) != 0)
00133 goto err;
00134
00135 case 7:
00136
00137
00138
00139
00140 memcpy(&dbp->pgsize, mbuf + 20, sizeof(u_int32_t));
00141
00142 if ((ret = __db_page_pass(
00143 dbp, real_name, flags, func_31_list, fhp)) != 0)
00144 goto err;
00145
00146 case 8:
00147 case 9:
00148 break;
00149 default:
00150 __db_err(dbenv, "%s: unsupported btree version: %lu",
00151 real_name, (u_long)((DBMETA *)mbuf)->version);
00152 ret = DB_OLD_VERSION;
00153 goto err;
00154 }
00155 break;
00156 case DB_HASHMAGIC:
00157 switch (((DBMETA *)mbuf)->version) {
00158 case 4:
00159 case 5:
00160
00161
00162
00163
00164 if ((ret =
00165 __ham_30_hashmeta(dbp, real_name, mbuf)) != 0)
00166 goto err;
00167 if ((ret = __os_seek(dbenv,
00168 fhp, 0, 0, 0, 0, DB_OS_SEEK_SET)) != 0)
00169 goto err;
00170 if ((ret = __os_write(dbenv, fhp, mbuf, 256, &n)) != 0)
00171 goto err;
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188 if ((ret =
00189 __ham_30_sizefix(dbp, fhp, real_name, mbuf)) != 0)
00190 goto err;
00191
00192 case 6:
00193
00194
00195
00196
00197 memcpy(&dbp->pgsize, mbuf + 20, sizeof(u_int32_t));
00198
00199 if ((ret = __db_page_pass(
00200 dbp, real_name, flags, func_31_list, fhp)) != 0)
00201 goto err;
00202
00203 case 7:
00204 case 8:
00205 break;
00206 default:
00207 __db_err(dbenv, "%s: unsupported hash version: %lu",
00208 real_name, (u_long)((DBMETA *)mbuf)->version);
00209 ret = DB_OLD_VERSION;
00210 goto err;
00211 }
00212 break;
00213 case DB_QAMMAGIC:
00214 switch (((DBMETA *)mbuf)->version) {
00215 case 1:
00216
00217
00218
00219
00220
00221 if ((ret = __qam_31_qammeta(dbp, real_name, mbuf)) != 0)
00222 return (ret);
00223
00224 case 2:
00225 if ((ret = __qam_32_qammeta(dbp, real_name, mbuf)) != 0)
00226 return (ret);
00227 if ((ret = __os_seek(dbenv,
00228 fhp, 0, 0, 0, 0, DB_OS_SEEK_SET)) != 0)
00229 goto err;
00230 if ((ret = __os_write(dbenv, fhp, mbuf, 256, &n)) != 0)
00231 goto err;
00232
00233 case 3:
00234 case 4:
00235 break;
00236 default:
00237 __db_err(dbenv, "%s: unsupported queue version: %lu",
00238 real_name, (u_long)((DBMETA *)mbuf)->version);
00239 ret = DB_OLD_VERSION;
00240 goto err;
00241 }
00242 break;
00243 default:
00244 M_32_SWAP(((DBMETA *)mbuf)->magic);
00245 switch (((DBMETA *)mbuf)->magic) {
00246 case DB_BTREEMAGIC:
00247 case DB_HASHMAGIC:
00248 case DB_QAMMAGIC:
00249 __db_err(dbenv,
00250 "%s: DB->upgrade only supported on native byte-order systems",
00251 real_name);
00252 break;
00253 default:
00254 __db_err(dbenv,
00255 "%s: unrecognized file type", real_name);
00256 break;
00257 }
00258 ret = EINVAL;
00259 goto err;
00260 }
00261
00262 ret = __os_fsync(dbenv, fhp);
00263
00264 err: if (fhp != NULL &&
00265 (t_ret = __os_closehandle(dbenv, fhp)) != 0 && ret == 0)
00266 ret = t_ret;
00267 __os_free(dbenv, real_name);
00268
00269
00270 if (dbp->db_feedback != NULL)
00271 dbp->db_feedback(dbp, DB_UPGRADE, 100);
00272
00273 return (ret);
00274 }
00275
00276
00277
00278
00279
00280 static int
00281 __db_page_pass(dbp, real_name, flags, fl, fhp)
00282 DB *dbp;
00283 char *real_name;
00284 u_int32_t flags;
00285 int (* const fl[P_PAGETYPE_MAX])
00286 __P((DB *, char *, u_int32_t, DB_FH *, PAGE *, int *));
00287 DB_FH *fhp;
00288 {
00289 DB_ENV *dbenv;
00290 PAGE *page;
00291 db_pgno_t i, pgno_last;
00292 size_t n;
00293 int dirty, ret;
00294
00295 dbenv = dbp->dbenv;
00296
00297
00298 if ((ret = __db_lastpgno(dbp, real_name, fhp, &pgno_last)) != 0)
00299 return (ret);
00300
00301
00302 if ((ret = __os_malloc(dbenv, dbp->pgsize, &page)) != 0)
00303 return (ret);
00304
00305
00306 for (i = 0; i < pgno_last; ++i) {
00307 if (dbp->db_feedback != NULL)
00308 dbp->db_feedback(
00309 dbp, DB_UPGRADE, (int)((i * 100)/pgno_last));
00310 if ((ret = __os_seek(dbenv,
00311 fhp, dbp->pgsize, i, 0, 0, DB_OS_SEEK_SET)) != 0)
00312 break;
00313 if ((ret = __os_read(dbenv, fhp, page, dbp->pgsize, &n)) != 0)
00314 break;
00315 dirty = 0;
00316 if (fl[TYPE(page)] != NULL && (ret = fl[TYPE(page)]
00317 (dbp, real_name, flags, fhp, page, &dirty)) != 0)
00318 break;
00319 if (dirty) {
00320 if ((ret = __os_seek(dbenv,
00321 fhp, dbp->pgsize, i, 0, 0, DB_OS_SEEK_SET)) != 0)
00322 break;
00323 if ((ret = __os_write(dbenv,
00324 fhp, page, dbp->pgsize, &n)) != 0)
00325 break;
00326 }
00327 }
00328
00329 __os_free(dbp->dbenv, page);
00330 return (ret);
00331 }
00332
00333
00334
00335
00336
00337
00338
00339 int
00340 __db_lastpgno(dbp, real_name, fhp, pgno_lastp)
00341 DB *dbp;
00342 char *real_name;
00343 DB_FH *fhp;
00344 db_pgno_t *pgno_lastp;
00345 {
00346 DB_ENV *dbenv;
00347 db_pgno_t pgno_last;
00348 u_int32_t mbytes, bytes;
00349 int ret;
00350
00351 dbenv = dbp->dbenv;
00352
00353 if ((ret = __os_ioinfo(dbenv,
00354 real_name, fhp, &mbytes, &bytes, NULL)) != 0) {
00355 __db_err(dbenv, "%s: %s", real_name, db_strerror(ret));
00356 return (ret);
00357 }
00358
00359
00360 if (bytes % dbp->pgsize != 0) {
00361 __db_err(dbenv,
00362 "%s: file size not a multiple of the pagesize", real_name);
00363 return (EINVAL);
00364 }
00365 pgno_last = mbytes * (MEGABYTE / dbp->pgsize);
00366 pgno_last += bytes / dbp->pgsize;
00367
00368 *pgno_lastp = pgno_last;
00369 return (0);
00370 }