00001
00002
00003
00004
00005
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
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,
00031 NULL,
00032 CDB___ham_31_hash,
00033 NULL,
00034 NULL,
00035 CDB___bam_31_lbtree,
00036 NULL,
00037 NULL,
00038 CDB___ham_31_hashmeta,
00039 CDB___bam_31_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
00047
00048
00049
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
00067 if ((ret = CDB___db_fchk(dbenv, "DB->upgrade", flags, DB_DUPSORT)) != 0)
00068 return (ret);
00069
00070
00071 if ((ret = CDB___db_appname(dbenv,
00072 DB_APP_DATA, NULL, fname, 0, NULL, &real_name)) != 0)
00073 return (ret);
00074
00075
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
00082 if (dbp->db_feedback != NULL)
00083 dbp->db_feedback(dbp, DB_UPGRADE, 0);
00084
00085
00086
00087
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
00098
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
00109 case 7:
00110
00111
00112
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
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
00135
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
00146 case 6:
00147
00148
00149
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
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
00171
00172
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
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
00217 if (dbp->db_feedback != NULL)
00218 dbp->db_feedback(dbp, DB_UPGRADE, 100);
00219
00220 return (ret);
00221 }
00222
00223
00224
00225
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
00245 if ((ret = CDB___db_lastpgno(dbp, real_name, fhp, &pgno_last)) != 0)
00246 return (ret);
00247
00248
00249 if ((ret = CDB___os_malloc(dbenv, dbp->pgsize, NULL, &page)) != 0)
00250 return (ret);
00251
00252
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
00281
00282
00283
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
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 }