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 #include "config.h"
00037
00038 #ifndef lint
00039 static const char revid[] = "$Id: log__rec_8c-source.html,v 1.1 2008/06/08 10:20:28 sebdiaz Exp $";
00040 #endif
00041
00042 #ifndef NO_SYSTEM_INCLUDES
00043 #include <sys/types.h>
00044
00045 #include <errno.h>
00046 #include <string.h>
00047 #endif
00048
00049 #include "db_int.h"
00050 #include "db_page.h"
00051 #include "db_ext.h"
00052 #include "log.h"
00053
00054 static int __log_do_open __P((DB_ENV *, DB_LOG *,
00055 u_int8_t *, char *, DBTYPE, int32_t, db_pgno_t));
00056 static int __log_lid_to_fname __P((DB_LOG *, int32_t, FNAME **));
00057 static int __log_open_file __P((DB_ENV *, DB_LOG *, __log_register_args *));
00058
00059
00060
00061
00062
00063 int
00064 CDB___log_register_recover(dbenv, dbtp, lsnp, op, info)
00065 DB_ENV *dbenv;
00066 DBT *dbtp;
00067 DB_LSN *lsnp;
00068 db_recops op;
00069 void *info;
00070 {
00071 DB_ENTRY *dbe;
00072 DB_LOG *logp;
00073 DB *dbp;
00074 __log_register_args *argp;
00075 int do_rem, ret, t_ret;
00076
00077 logp = dbenv->lg_handle;
00078 dbp = NULL;
00079
00080 #ifdef DEBUG_RECOVER
00081 CDB___log_register_print(logp, dbtp, lsnp, op, info);
00082 #endif
00083 COMPQUIET(lsnp, NULL);
00084
00085 if ((ret = CDB___log_register_read(dbenv, dbtp->data, &argp)) != 0)
00086 goto out;
00087
00088 if ((argp->opcode == LOG_OPEN &&
00089 (DB_REDO(op) || op == DB_TXN_OPENFILES)) ||
00090 (argp->opcode == LOG_CLOSE && DB_UNDO(op))) {
00091
00092
00093
00094
00095
00096 if (op == DB_TXN_OPENFILES)
00097 F_SET(logp, DBLOG_FORCE_OPEN);
00098 ret = __log_open_file(dbenv, logp, argp);
00099 F_CLR(logp, DBLOG_FORCE_OPEN);
00100 if (ret == ENOENT || ret == EINVAL) {
00101 if (op == DB_TXN_OPENFILES && argp->name.size != 0 &&
00102 (ret = CDB___db_txnlist_delete(dbenv, info,
00103 argp->name.data, argp->fileid, 0)) != 0)
00104 goto out;
00105 ret = 0;
00106 }
00107 } else if (argp->opcode != LOG_CHECKPOINT) {
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117 do_rem = 0;
00118 MUTEX_THREAD_LOCK(logp->mutexp);
00119 if (argp->fileid < logp->dbentry_cnt) {
00120 dbe = &logp->dbentry[argp->fileid];
00121 if (dbe->refcount == 1) {
00122 ret = CDB___db_txnlist_close(info,
00123 argp->fileid, dbe->count);
00124 if ((dbp = TAILQ_FIRST(&dbe->dblist)) != NULL)
00125 (void) CDB_log_unregister(dbenv, dbp);
00126 do_rem = 1;
00127 } else
00128 dbe->refcount--;
00129 }
00130 MUTEX_THREAD_UNLOCK(logp->mutexp);
00131 if (do_rem) {
00132 (void)CDB___log_rem_logid(logp, dbp, argp->fileid);
00133
00134
00135
00136
00137 if (dbp != NULL &&
00138 (t_ret = dbp->close(dbp,
00139 dbp->mpf == NULL ? DB_NOSYNC : 0)) != 0 && ret == 0)
00140 ret = t_ret;
00141 }
00142 } else if (DB_UNDO(op) || op == DB_TXN_OPENFILES) {
00143
00144
00145
00146
00147
00148
00149
00150 ret = __log_open_file(dbenv, logp, argp);
00151 if (ret == ENOENT || ret == EINVAL) {
00152 if (argp->name.size != 0 && (ret =
00153 CDB___db_txnlist_delete(dbenv, info,
00154 argp->name.data, argp->fileid, 0)) != 0)
00155 goto out;
00156 ret = 0;
00157 }
00158 }
00159
00160 out: if (argp != NULL)
00161 CDB___os_free(argp, 0);
00162 return (ret);
00163 }
00164
00165
00166
00167
00168
00169
00170
00171 static int
00172 __log_open_file(dbenv, lp, argp)
00173 DB_ENV *dbenv;
00174 DB_LOG *lp;
00175 __log_register_args *argp;
00176 {
00177 DB_ENTRY *dbe;
00178 DB *dbp;
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188 if (argp->name.size == 0) {
00189 (void)CDB___log_add_logid(dbenv, lp, NULL, argp->fileid);
00190 return (ENOENT);
00191 }
00192
00193
00194
00195
00196
00197
00198
00199 MUTEX_THREAD_LOCK(lp->mutexp);
00200 if (argp->fileid < lp->dbentry_cnt)
00201 dbe = &lp->dbentry[argp->fileid];
00202 else
00203 dbe = NULL;
00204
00205 if (dbe != NULL) {
00206 dbe->deleted = 0;
00207 if ((dbp = TAILQ_FIRST(&dbe->dblist)) != NULL) {
00208 if (dbp->meta_pgno != argp->meta_pgno ||
00209 memcmp(dbp->fileid,
00210 argp->uid.data, DB_FILE_ID_LEN) != 0) {
00211 MUTEX_THREAD_UNLOCK(lp->mutexp);
00212 goto reopen;
00213 }
00214 if (!F_ISSET(lp, DBLOG_RECOVER))
00215 dbe->refcount++;
00216 MUTEX_THREAD_UNLOCK(lp->mutexp);
00217 return (0);
00218 }
00219 }
00220
00221 MUTEX_THREAD_UNLOCK(lp->mutexp);
00222 if (0) {
00223 reopen: (void) CDB_log_unregister(dbp->dbenv, dbp);
00224 (void) CDB___log_rem_logid(lp, dbp, argp->fileid);
00225 dbp->close(dbp, 0);
00226 }
00227
00228 return (__log_do_open(dbenv, lp,
00229 argp->uid.data, argp->name.data,
00230 argp->ftype, argp->fileid, argp->meta_pgno));
00231 }
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241 int
00242 CDB___log_reopen_file(dbenv, name, ndx, fileid, meta_pgno)
00243 DB_ENV *dbenv;
00244 char *name;
00245 int32_t ndx;
00246 u_int8_t *fileid;
00247 db_pgno_t meta_pgno;
00248 {
00249 DB *dbp;
00250 DB_LOG *logp;
00251 DBTYPE ftype;
00252 int ret;
00253
00254 logp = dbenv->lg_handle;
00255
00256 if ((ret = CDB___db_fileid_to_db(dbenv, &dbp, ndx, 0)) != 0)
00257 goto out;
00258 ftype = dbp->type;
00259 (void) CDB_log_unregister(dbenv, dbp);
00260 (void) CDB___log_rem_logid(logp, dbp, ndx);
00261 (void) dbp->close(dbp, 0);
00262
00263 ret = __log_do_open(dbenv, logp, fileid, name, ftype, ndx, meta_pgno);
00264
00265 out: return (ret);
00266 }
00267
00268
00269
00270
00271
00272
00273 static int
00274 __log_do_open(dbenv, lp, uid, name, ftype, ndx, meta_pgno)
00275 DB_ENV *dbenv;
00276 DB_LOG *lp;
00277 u_int8_t *uid;
00278 char *name;
00279 DBTYPE ftype;
00280 int32_t ndx;
00281 db_pgno_t meta_pgno;
00282 {
00283 DB *dbp;
00284 int ret;
00285 u_int8_t zeroid[DB_FILE_ID_LEN];
00286
00287 if ((ret = CDB_db_create(&dbp, lp->dbenv, 0)) != 0)
00288 return (ret);
00289
00290 dbp->log_fileid = ndx;
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302 F_SET(dbp, DB_AM_RECOVER);
00303 if (meta_pgno != PGNO_BASE_MD)
00304 memcpy(dbp->fileid, uid, DB_FILE_ID_LEN);
00305 dbp->type = ftype;
00306 if ((ret = CDB___db_dbopen(dbp, name, 0, 0600, meta_pgno)) == 0) {
00307
00308
00309
00310
00311 if (memcmp(uid, dbp->fileid, DB_FILE_ID_LEN) != 0) {
00312 memset(zeroid, 0, DB_FILE_ID_LEN);
00313 if (memcmp(dbp->fileid, zeroid, DB_FILE_ID_LEN) != 0)
00314 goto not_right;
00315 memcpy(dbp->fileid, uid, DB_FILE_ID_LEN);
00316 }
00317 if (IS_RECOVERING(dbenv)) {
00318 (void)CDB_log_register(dbp->dbenv, dbp, name);
00319 (void)CDB___log_add_logid(dbenv, lp, dbp, ndx);
00320 }
00321 return (0);
00322 }
00323
00324 not_right:
00325 (void)dbp->close(dbp, 0);
00326 (void)CDB___log_add_logid(dbenv, lp, NULL, ndx);
00327
00328 return (ENOENT);
00329 }
00330
00331
00332
00333
00334
00335
00336
00337 int
00338 CDB___log_add_logid(dbenv, logp, dbp, ndx)
00339 DB_ENV *dbenv;
00340 DB_LOG *logp;
00341 DB *dbp;
00342 int32_t ndx;
00343 {
00344 int32_t i;
00345 int ret;
00346
00347 ret = 0;
00348
00349 MUTEX_THREAD_LOCK(logp->mutexp);
00350
00351
00352
00353
00354
00355
00356 if (logp->dbentry_cnt <= ndx) {
00357 if ((ret = CDB___os_realloc(dbenv,
00358 (ndx + DB_GROW_SIZE) * sizeof(DB_ENTRY),
00359 NULL, &logp->dbentry)) != 0)
00360 goto err;
00361
00362
00363 for (i = logp->dbentry_cnt; i < ndx + DB_GROW_SIZE; i++) {
00364 logp->dbentry[i].count = 0;
00365 TAILQ_INIT(&logp->dbentry[i].dblist);
00366 logp->dbentry[i].deleted = 0;
00367 logp->dbentry[i].refcount = 0;
00368 }
00369
00370 logp->dbentry_cnt = i;
00371 }
00372
00373 if (logp->dbentry[ndx].deleted == 0 &&
00374 TAILQ_FIRST(&logp->dbentry[ndx].dblist) == NULL) {
00375 logp->dbentry[ndx].count = 0;
00376 if (dbp != NULL)
00377 TAILQ_INSERT_HEAD(&logp->dbentry[ndx].dblist,
00378 dbp, links);
00379 logp->dbentry[ndx].deleted = dbp == NULL;
00380 logp->dbentry[ndx].refcount = 1;
00381 } else if (!F_ISSET(logp, DBLOG_RECOVER)) {
00382 if (dbp != NULL)
00383 TAILQ_INSERT_HEAD(&logp->dbentry[ndx].dblist,
00384 dbp, links);
00385 logp->dbentry[ndx].refcount++;
00386 }
00387
00388 err: MUTEX_THREAD_UNLOCK(logp->mutexp);
00389 return (ret);
00390 }
00391
00392
00393
00394
00395
00396
00397
00398 int
00399 CDB___db_fileid_to_db(dbenv, dbpp, ndx, inc)
00400 DB_ENV *dbenv;
00401 DB **dbpp;
00402 int32_t ndx;
00403 int inc;
00404 {
00405 DB_LOG *logp;
00406 DB *dbp;
00407 FNAME *fname;
00408 int ret;
00409 char *name;
00410
00411 ret = 0;
00412 logp = dbenv->lg_handle;
00413
00414 MUTEX_THREAD_LOCK(logp->mutexp);
00415
00416
00417
00418
00419
00420
00421
00422 if (ndx >= logp->dbentry_cnt ||
00423 (!logp->dbentry[ndx].deleted &&
00424 (dbp = TAILQ_FIRST(&logp->dbentry[ndx].dblist)) == NULL)) {
00425 if (F_ISSET(logp, DBLOG_RECOVER)) {
00426 ret = ENOENT;
00427 goto err;
00428 }
00429 if (__log_lid_to_fname(logp, ndx, &fname) != 0) {
00430
00431 CDB___db_err(dbenv, "Missing log fileid entry");
00432 ret = EINVAL;
00433 goto err;
00434 }
00435 name = R_ADDR(&logp->reginfo, fname->name_off);
00436
00437
00438
00439
00440
00441 MUTEX_THREAD_UNLOCK(logp->mutexp);
00442
00443
00444
00445
00446
00447
00448
00449
00450 if ((ret = __log_do_open(dbenv, logp,
00451 fname->ufid, name, fname->s_type,
00452 ndx, fname->meta_pgno)) != 0)
00453 return (ret);
00454
00455 *dbpp = TAILQ_FIRST(&logp->dbentry[ndx].dblist);
00456 return (0);
00457 }
00458
00459
00460
00461
00462 if (logp->dbentry[ndx].deleted) {
00463 ret = DB_DELETED;
00464 if (inc)
00465 logp->dbentry[ndx].count++;
00466 goto err;
00467 }
00468
00469
00470
00471
00472
00473 if ((*dbpp = TAILQ_FIRST(&logp->dbentry[ndx].dblist)) == NULL)
00474 ret = ENOENT;
00475
00476 err: MUTEX_THREAD_UNLOCK(logp->mutexp);
00477 return (ret);
00478 }
00479
00480
00481
00482
00483
00484
00485 void
00486 CDB___log_close_files(dbenv)
00487 DB_ENV *dbenv;
00488 {
00489 DB_ENTRY *dbe;
00490 DB_LOG *logp;
00491 DB *dbp;
00492 int32_t i;
00493
00494 logp = dbenv->lg_handle;
00495 MUTEX_THREAD_LOCK(logp->mutexp);
00496 for (i = 0; i < logp->dbentry_cnt; i++) {
00497 dbe = &logp->dbentry[i];
00498 while ((dbp = TAILQ_FIRST(&dbe->dblist)) != NULL) {
00499 (void)CDB_log_unregister(dbenv, dbp);
00500 TAILQ_REMOVE(&dbe->dblist, dbp, links);
00501 (void)dbp->close(dbp, 0);
00502 }
00503 dbe->deleted = 0;
00504 dbe->refcount = 0;
00505 }
00506 MUTEX_THREAD_UNLOCK(logp->mutexp);
00507 }
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517 void
00518 CDB___log_rem_logid(logp, dbp, ndx)
00519 DB_LOG *logp;
00520 DB *dbp;
00521 int32_t ndx;
00522 {
00523 DB *xdbp;
00524
00525 MUTEX_THREAD_LOCK(logp->mutexp);
00526 if (--logp->dbentry[ndx].refcount == 0) {
00527 TAILQ_INIT(&logp->dbentry[ndx].dblist);
00528 logp->dbentry[ndx].deleted = 0;
00529 } else if (dbp != NULL)
00530 for (xdbp = TAILQ_FIRST(&logp->dbentry[ndx].dblist);
00531 xdbp != NULL;
00532 xdbp = TAILQ_NEXT(xdbp, links))
00533 if (xdbp == dbp) {
00534 TAILQ_REMOVE(&logp->dbentry[ndx].dblist,
00535 xdbp, links);
00536 break;
00537 }
00538
00539 MUTEX_THREAD_UNLOCK(logp->mutexp);
00540 }
00541
00542
00543
00544
00545
00546
00547 static int
00548 __log_lid_to_fname(dblp, lid, fnamep)
00549 DB_LOG *dblp;
00550 int32_t lid;
00551 FNAME **fnamep;
00552 {
00553 FNAME *fnp;
00554 LOG *lp;
00555
00556 lp = dblp->reginfo.primary;
00557
00558 for (fnp = SH_TAILQ_FIRST(&lp->fq, __fname);
00559 fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) {
00560 if (fnp->ref == 0)
00561 continue;
00562 if (fnp->id == lid) {
00563 *fnamep = fnp;
00564 return (0);
00565 }
00566 }
00567 return (-1);
00568 }