00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "db_config.h"
00039
00040 #ifndef NO_SYSTEM_INCLUDES
00041 #include <sys/types.h>
00042
00043 #include <string.h>
00044 #endif
00045
00046 #include "db_int.h"
00047 #include "dbinc/db_page.h"
00048 #include "dbinc/db_shash.h"
00049 #include "dbinc/db_am.h"
00050 #include "dbinc/log.h"
00051 #include "dbinc/mp.h"
00052 #include "dbinc/txn.h"
00053
00054 static int __dbreg_open_file __P((DB_ENV *,
00055 DB_TXN *, __dbreg_register_args *, void *));
00056
00057
00058
00059
00060
00061 int
00062 __dbreg_register_recover(dbenv, dbtp, lsnp, op, info)
00063 DB_ENV *dbenv;
00064 DBT *dbtp;
00065 DB_LSN *lsnp;
00066 db_recops op;
00067 void *info;
00068 {
00069 DB_ENTRY *dbe;
00070 DB_LOG *dblp;
00071 DB *dbp;
00072 __dbreg_register_args *argp;
00073 int do_close, do_open, do_rem, ret, t_ret;
00074 u_int32_t status;
00075
00076 dblp = dbenv->lg_handle;
00077 dbp = NULL;
00078
00079 #ifdef DEBUG_RECOVER
00080 REC_PRINT(__dbreg_register_print);
00081 #endif
00082 do_open = do_close = 0;
00083 if ((ret = __dbreg_register_read(dbenv, dbtp->data, &argp)) != 0)
00084 goto out;
00085
00086 switch (argp->opcode) {
00087 case DBREG_REOPEN:
00088 case DBREG_PREOPEN:
00089 case DBREG_OPEN:
00090
00091
00092
00093
00094
00095
00096 if ((DB_REDO(op) ||
00097 op == DB_TXN_OPENFILES || op == DB_TXN_POPENFILES))
00098 do_open = 1;
00099 else if (argp->opcode != DBREG_REOPEN)
00100 do_close = 1;
00101 break;
00102 case DBREG_CLOSE:
00103 if (DB_UNDO(op))
00104 do_open = 1;
00105 else
00106 do_close = 1;
00107 break;
00108 case DBREG_RCLOSE:
00109
00110
00111
00112
00113
00114
00115
00116
00117 if (DB_UNDO(op) || op == DB_TXN_POPENFILES)
00118 do_open = 1;
00119 else
00120 do_close = 1;
00121 break;
00122 case DBREG_CHKPNT:
00123 if (DB_UNDO(op) ||
00124 op == DB_TXN_OPENFILES || op == DB_TXN_POPENFILES)
00125 do_open = 1;
00126 break;
00127 default:
00128 DB_ASSERT(0);
00129 ret = EINVAL;
00130 break;
00131 }
00132
00133 if (do_open) {
00134
00135
00136
00137
00138 if (op == DB_TXN_OPENFILES && argp->opcode != DBREG_CHKPNT)
00139 F_SET(dblp, DBLOG_FORCE_OPEN);
00140
00141
00142
00143
00144
00145
00146 ret = __dbreg_open_file(dbenv,
00147 op == DB_TXN_ABORT || op == DB_TXN_POPENFILES ?
00148 argp->txnid : NULL, argp, info);
00149 if (ret == DB_PAGE_NOTFOUND && argp->meta_pgno != PGNO_BASE_MD)
00150 ret = ENOENT;
00151 if (ret == ENOENT || ret == EINVAL) {
00152
00153
00154
00155
00156
00157
00158
00159 if (op == DB_TXN_FORWARD_ROLL &&
00160 argp->txnid != 0 &&
00161 dblp->dbentry[argp->fileid].deleted) {
00162 dblp->dbentry[argp->fileid].deleted = 0;
00163 ret =
00164 __dbreg_open_file(dbenv, NULL, argp, info);
00165 if (ret == DB_PAGE_NOTFOUND &&
00166 argp->meta_pgno != PGNO_BASE_MD)
00167 ret = ENOENT;
00168 }
00169
00170
00171
00172
00173
00174 if (ret == ENOENT)
00175 ret = 0;
00176 }
00177 F_CLR(dblp, DBLOG_FORCE_OPEN);
00178 }
00179
00180 if (do_close) {
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193 do_rem = 0;
00194 MUTEX_LOCK(dbenv, dblp->mtx_dbreg);
00195 if (argp->fileid < dblp->dbentry_cnt) {
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 dbe = &dblp->dbentry[argp->fileid];
00213 if (dbe->dbp == NULL && !dbe->deleted) {
00214
00215 if ((DB_REDO(op) &&
00216 argp->opcode != DBREG_RCLOSE) ||
00217 argp->opcode == DBREG_CHKPNT) {
00218 __db_err(dbenv,
00219 "Warning: Improper file close at %lu/%lu",
00220 (u_long)lsnp->file,
00221 (u_long)lsnp->offset);
00222 }
00223 MUTEX_UNLOCK(dbenv, dblp->mtx_dbreg);
00224 goto done;
00225 }
00226
00227
00228 if ((dbp = dbe->dbp) != NULL) {
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238 do_rem = F_ISSET(dbp, DB_AM_RECOVER) ||
00239 op == DB_TXN_ABORT;
00240 MUTEX_UNLOCK(dbenv, dblp->mtx_dbreg);
00241 if (op == DB_TXN_ABORT)
00242 (void)__dbreg_close_id(dbp,
00243 NULL, DBREG_RCLOSE);
00244 else
00245 (void)__dbreg_revoke_id(dbp, 0,
00246 DB_LOGFILEID_INVALID);
00247 } else if (dbe->deleted) {
00248 MUTEX_UNLOCK(dbenv, dblp->mtx_dbreg);
00249 if ((ret = __dbreg_rem_dbentry(
00250 dblp, argp->fileid)) != 0)
00251 goto out;
00252 }
00253 } else
00254 MUTEX_UNLOCK(dbenv, dblp->mtx_dbreg);
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273 if (do_rem && dbp != NULL) {
00274 if (argp->id != TXN_INVALID) {
00275 if ((ret = __db_txnlist_find(dbenv,
00276 info, argp->txnid->txnid, &status))
00277 != DB_NOTFOUND && ret != 0)
00278 goto out;
00279 if (ret == DB_NOTFOUND || status != TXN_COMMIT)
00280 F_SET(dbp, DB_AM_DISCARD);
00281 ret = 0;
00282 }
00283
00284 if (op == DB_TXN_ABORT &&
00285 !F_ISSET(dbp, DB_AM_RECOVER)) {
00286 if ((t_ret = __db_refresh(dbp,
00287 NULL, DB_NOSYNC, NULL, 0)) != 0 && ret == 0)
00288 ret = t_ret;
00289 } else {
00290 if (op == DB_TXN_APPLY &&
00291 (t_ret = __db_sync(dbp)) != 0 && ret == 0)
00292 ret = t_ret;
00293 if ((t_ret = __db_close(
00294 dbp, NULL, DB_NOSYNC)) != 0 && ret == 0)
00295 ret = t_ret;
00296 }
00297 }
00298 }
00299 done: if (ret == 0)
00300 *lsnp = argp->prev_lsn;
00301 out: if (argp != NULL)
00302 __os_free(dbenv, argp);
00303 return (ret);
00304 }
00305
00306
00307
00308
00309
00310
00311
00312 static int
00313 __dbreg_open_file(dbenv, txn, argp, info)
00314 DB_ENV *dbenv;
00315 DB_TXN *txn;
00316 __dbreg_register_args *argp;
00317 void *info;
00318 {
00319 DB_ENTRY *dbe;
00320 DB_LOG *dblp;
00321 DB *dbp;
00322 u_int32_t id, status;
00323 int ret;
00324
00325 dblp = (DB_LOG *)dbenv->lg_handle;
00326
00327
00328
00329
00330
00331
00332 MUTEX_LOCK(dbenv, dblp->mtx_dbreg);
00333 if (argp->fileid != DB_LOGFILEID_INVALID &&
00334 argp->fileid < dblp->dbentry_cnt)
00335 dbe = &dblp->dbentry[argp->fileid];
00336 else
00337 dbe = NULL;
00338
00339 if (dbe != NULL) {
00340 if (dbe->deleted) {
00341 MUTEX_UNLOCK(dbenv, dblp->mtx_dbreg);
00342 return (ENOENT);
00343 }
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357 if ((dbp = dbe->dbp) != NULL) {
00358 if (argp->opcode == DBREG_REOPEN ||
00359 dbp->meta_pgno != argp->meta_pgno ||
00360 argp->name.size == 0 ||
00361 memcmp(dbp->fileid, argp->uid.data,
00362 DB_FILE_ID_LEN) != 0) {
00363 MUTEX_UNLOCK(dbenv, dblp->mtx_dbreg);
00364 (void)__dbreg_revoke_id(dbp, 0,
00365 DB_LOGFILEID_INVALID);
00366 if (F_ISSET(dbp, DB_AM_RECOVER))
00367 (void)__db_close(dbp, NULL, DB_NOSYNC);
00368 goto reopen;
00369 }
00370
00371
00372
00373
00374
00375
00376 DB_ASSERT(dbe->dbp == dbp);
00377 MUTEX_UNLOCK(dbenv, dblp->mtx_dbreg);
00378
00379
00380
00381
00382
00383
00384 if (argp->id != TXN_INVALID &&
00385 (ret = __db_txnlist_update(dbenv, info,
00386 argp->id, TXN_EXPECTED, NULL, &status, 1)) != 0)
00387 return (ret);
00388 return (0);
00389 }
00390 }
00391
00392 MUTEX_UNLOCK(dbenv, dblp->mtx_dbreg);
00393
00394 reopen:
00395
00396
00397
00398
00399
00400
00401
00402 if (argp->name.size == 0) {
00403 (void)__dbreg_add_dbentry(dbenv, dblp, NULL, argp->fileid);
00404 return (ENOENT);
00405 }
00406
00407
00408
00409
00410
00411 if (txn != NULL) {
00412 id = txn->txnid;
00413 memset(txn, 0, sizeof(DB_TXN));
00414 txn->txnid = id;
00415 txn->mgrp = dbenv->tx_handle;
00416 }
00417
00418 return (__dbreg_do_open(dbenv,
00419 txn, dblp, argp->uid.data, argp->name.data, argp->ftype,
00420 argp->fileid, argp->meta_pgno, info, argp->id, argp->opcode));
00421 }