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 #include <string.h>
00015 #endif
00016
00017 #include "db_int.h"
00018 #include "dbinc/db_page.h"
00019 #include "dbinc/db_am.h"
00020 #include "dbinc/db_shash.h"
00021 #include "dbinc/fop.h"
00022 #include "dbinc/log.h"
00023 #include "dbinc/mp.h"
00024 #include "dbinc/txn.h"
00025
00026 static int __dbreg_check_master __P((DB_ENV *, u_int8_t *, char *));
00027
00028
00029
00030
00031
00032
00033
00034 int
00035 __dbreg_add_dbentry(dbenv, dblp, dbp, ndx)
00036 DB_ENV *dbenv;
00037 DB_LOG *dblp;
00038 DB *dbp;
00039 int32_t ndx;
00040 {
00041 int32_t i;
00042 int ret;
00043
00044 ret = 0;
00045
00046 MUTEX_LOCK(dbenv, dblp->mtx_dbreg);
00047
00048
00049
00050
00051
00052
00053 if (dblp->dbentry_cnt <= ndx) {
00054 if ((ret = __os_realloc(dbenv,
00055 (size_t)(ndx + DB_GROW_SIZE) * sizeof(DB_ENTRY),
00056 &dblp->dbentry)) != 0)
00057 goto err;
00058
00059
00060 for (i = dblp->dbentry_cnt; i < ndx + DB_GROW_SIZE; i++) {
00061 dblp->dbentry[i].dbp = NULL;
00062 dblp->dbentry[i].deleted = 0;
00063 }
00064 dblp->dbentry_cnt = i;
00065 }
00066
00067 DB_ASSERT(dblp->dbentry[ndx].dbp == NULL);
00068 dblp->dbentry[ndx].deleted = dbp == NULL;
00069 dblp->dbentry[ndx].dbp = dbp;
00070
00071 err: MUTEX_UNLOCK(dbenv, dblp->mtx_dbreg);
00072 return (ret);
00073 }
00074
00075
00076
00077
00078
00079
00080
00081 int
00082 __dbreg_rem_dbentry(dblp, ndx)
00083 DB_LOG *dblp;
00084 int32_t ndx;
00085 {
00086 MUTEX_LOCK(dblp->dbenv, dblp->mtx_dbreg);
00087 if (dblp->dbentry_cnt > ndx) {
00088 dblp->dbentry[ndx].dbp = NULL;
00089 dblp->dbentry[ndx].deleted = 0;
00090 }
00091 MUTEX_UNLOCK(dblp->dbenv, dblp->mtx_dbreg);
00092
00093 return (0);
00094 }
00095
00096
00097
00098
00099
00100
00101
00102 int
00103 __dbreg_log_files(dbenv)
00104 DB_ENV *dbenv;
00105 {
00106 DB_LOG *dblp;
00107 DB_LSN r_unused;
00108 DBT *dbtp, fid_dbt, t;
00109 FNAME *fnp;
00110 LOG *lp;
00111 int ret;
00112
00113 dblp = dbenv->lg_handle;
00114 lp = dblp->reginfo.primary;
00115
00116 ret = 0;
00117
00118 MUTEX_LOCK(dbenv, lp->mtx_filelist);
00119
00120 for (fnp = SH_TAILQ_FIRST(&lp->fq, __fname);
00121 fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) {
00122
00123 if (fnp->name_off == INVALID_ROFF)
00124 dbtp = NULL;
00125 else {
00126 memset(&t, 0, sizeof(t));
00127 t.data = R_ADDR(&dblp->reginfo, fnp->name_off);
00128 t.size = (u_int32_t)strlen(t.data) + 1;
00129 dbtp = &t;
00130 }
00131 memset(&fid_dbt, 0, sizeof(fid_dbt));
00132 fid_dbt.data = fnp->ufid;
00133 fid_dbt.size = DB_FILE_ID_LEN;
00134
00135
00136
00137
00138
00139
00140
00141
00142 if ((ret = __dbreg_register_log(dbenv,
00143 NULL, &r_unused,
00144 F_ISSET(fnp, DB_FNAME_DURABLE) ? 0 : DB_LOG_NOT_DURABLE,
00145 F_ISSET(dblp, DBLOG_RECOVER) ? DBREG_RCLOSE : DBREG_CHKPNT,
00146 dbtp, &fid_dbt, fnp->id, fnp->s_type, fnp->meta_pgno,
00147 TXN_INVALID)) != 0)
00148 break;
00149 }
00150
00151 MUTEX_UNLOCK(dbenv, lp->mtx_filelist);
00152
00153 return (ret);
00154 }
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166 int
00167 __dbreg_close_files(dbenv)
00168 DB_ENV *dbenv;
00169 {
00170 DB_LOG *dblp;
00171 DB *dbp;
00172 int ret, t_ret;
00173 int32_t i;
00174
00175
00176 if (!LOGGING_ON(dbenv))
00177 return (0);
00178
00179 dblp = dbenv->lg_handle;
00180 ret = 0;
00181 MUTEX_LOCK(dbenv, dblp->mtx_dbreg);
00182 for (i = 0; i < dblp->dbentry_cnt; i++) {
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197 if ((dbp = dblp->dbentry[i].dbp) != NULL) {
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209 MUTEX_UNLOCK(dbenv, dblp->mtx_dbreg);
00210 if (F_ISSET(dbp, DB_AM_RECOVER))
00211 t_ret = __db_close(dbp,
00212 NULL, dbp->mpf == NULL ? DB_NOSYNC : 0);
00213 else
00214 t_ret = __dbreg_revoke_id(
00215 dbp, 0, DB_LOGFILEID_INVALID);
00216 if (ret == 0)
00217 ret = t_ret;
00218 MUTEX_LOCK(dbenv, dblp->mtx_dbreg);
00219 }
00220
00221 dblp->dbentry[i].deleted = 0;
00222 dblp->dbentry[i].dbp = NULL;
00223 }
00224 MUTEX_UNLOCK(dbenv, dblp->mtx_dbreg);
00225 return (ret);
00226 }
00227
00228
00229
00230
00231
00232
00233
00234 int
00235 __dbreg_id_to_db(dbenv, txn, dbpp, ndx, inc)
00236 DB_ENV *dbenv;
00237 DB_TXN *txn;
00238 DB **dbpp;
00239 int32_t ndx;
00240 int inc;
00241 {
00242 return (__dbreg_id_to_db_int(dbenv, txn, dbpp, ndx, inc, 1));
00243 }
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 int
00259 __dbreg_id_to_db_int(dbenv, txn, dbpp, ndx, inc, tryopen)
00260 DB_ENV *dbenv;
00261 DB_TXN *txn;
00262 DB **dbpp;
00263 int32_t ndx;
00264 int inc, tryopen;
00265 {
00266 DB_LOG *dblp;
00267 FNAME *fname;
00268 int ret;
00269 char *name;
00270
00271 ret = 0;
00272 dblp = dbenv->lg_handle;
00273 COMPQUIET(inc, 0);
00274
00275 MUTEX_LOCK(dbenv, dblp->mtx_dbreg);
00276
00277
00278
00279
00280
00281
00282
00283 if (ndx >= dblp->dbentry_cnt ||
00284 (!dblp->dbentry[ndx].deleted && dblp->dbentry[ndx].dbp == NULL)) {
00285 if (!tryopen || F_ISSET(dblp, DBLOG_RECOVER)) {
00286 ret = ENOENT;
00287 goto err;
00288 }
00289
00290
00291
00292
00293
00294
00295
00296 MUTEX_UNLOCK(dbenv, dblp->mtx_dbreg);
00297
00298 if (__dbreg_id_to_fname(dblp, ndx, 0, &fname) != 0)
00299
00300
00301
00302
00303
00304
00305 return (ENOENT);
00306
00307
00308
00309
00310
00311
00312
00313
00314 name = R_ADDR(&dblp->reginfo, fname->name_off);
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325 if ((ret = __dbreg_do_open(dbenv, txn, dblp,
00326 fname->ufid, name, fname->s_type,
00327 ndx, fname->meta_pgno, NULL, 0, DBREG_OPEN)) != 0)
00328 return (ret);
00329
00330 *dbpp = dblp->dbentry[ndx].dbp;
00331 return (0);
00332 }
00333
00334
00335
00336
00337 if (dblp->dbentry[ndx].deleted) {
00338 ret = DB_DELETED;
00339 goto err;
00340 }
00341
00342
00343 if ((*dbpp = dblp->dbentry[ndx].dbp) == NULL)
00344 ret = ENOENT;
00345 else
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355 if ((*dbpp)->mpf != NULL && (*dbpp)->mpf->mfp != NULL)
00356 (*dbpp)->mpf->mfp->file_written = 1;
00357
00358 err: MUTEX_UNLOCK(dbenv, dblp->mtx_dbreg);
00359 return (ret);
00360 }
00361
00362
00363
00364
00365
00366
00367
00368
00369 int
00370 __dbreg_id_to_fname(dblp, id, have_lock, fnamep)
00371 DB_LOG *dblp;
00372 int32_t id;
00373 int have_lock;
00374 FNAME **fnamep;
00375 {
00376 DB_ENV *dbenv;
00377 FNAME *fnp;
00378 LOG *lp;
00379 int ret;
00380
00381 dbenv = dblp->dbenv;
00382 lp = dblp->reginfo.primary;
00383
00384 ret = -1;
00385
00386 if (!have_lock)
00387 MUTEX_LOCK(dbenv, lp->mtx_filelist);
00388 for (fnp = SH_TAILQ_FIRST(&lp->fq, __fname);
00389 fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) {
00390 if (fnp->id == id) {
00391 *fnamep = fnp;
00392 ret = 0;
00393 break;
00394 }
00395 }
00396 if (!have_lock)
00397 MUTEX_UNLOCK(dbenv, lp->mtx_filelist);
00398
00399 return (ret);
00400 }
00401
00402
00403
00404
00405
00406
00407
00408 int
00409 __dbreg_fid_to_fname(dblp, fid, have_lock, fnamep)
00410 DB_LOG *dblp;
00411 u_int8_t *fid;
00412 int have_lock;
00413 FNAME **fnamep;
00414 {
00415 DB_ENV *dbenv;
00416 FNAME *fnp;
00417 LOG *lp;
00418 int ret;
00419
00420 dbenv = dblp->dbenv;
00421 lp = dblp->reginfo.primary;
00422
00423 ret = -1;
00424
00425 if (!have_lock)
00426 MUTEX_LOCK(dbenv, lp->mtx_filelist);
00427 for (fnp = SH_TAILQ_FIRST(&lp->fq, __fname);
00428 fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) {
00429 if (memcmp(fnp->ufid, fid, DB_FILE_ID_LEN) == 0) {
00430 *fnamep = fnp;
00431 ret = 0;
00432 break;
00433 }
00434 }
00435 if (!have_lock)
00436 MUTEX_UNLOCK(dbenv, lp->mtx_filelist);
00437
00438 return (ret);
00439 }
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450 int
00451 __dbreg_get_name(dbenv, fid, namep)
00452 DB_ENV *dbenv;
00453 u_int8_t *fid;
00454 char **namep;
00455 {
00456 DB_LOG *dblp;
00457 FNAME *fnp;
00458
00459 dblp = dbenv->lg_handle;
00460
00461 if (dblp != NULL && __dbreg_fid_to_fname(dblp, fid, 0, &fnp) == 0) {
00462 *namep = R_ADDR(&dblp->reginfo, fnp->name_off);
00463 return (0);
00464 }
00465
00466 return (-1);
00467 }
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477 int
00478 __dbreg_do_open(dbenv,
00479 txn, lp, uid, name, ftype, ndx, meta_pgno, info, id, opcode)
00480 DB_ENV *dbenv;
00481 DB_TXN *txn;
00482 DB_LOG *lp;
00483 u_int8_t *uid;
00484 char *name;
00485 DBTYPE ftype;
00486 int32_t ndx;
00487 db_pgno_t meta_pgno;
00488 void *info;
00489 u_int32_t id, opcode;
00490 {
00491 DB *dbp;
00492 u_int32_t cstat, ret_stat;
00493 int ret;
00494 char *dname, *fname;
00495
00496 cstat = TXN_EXPECTED;
00497 fname = name;
00498 dname = NULL;
00499 if ((ret = db_create(&dbp, lp->dbenv, 0)) != 0)
00500 return (ret);
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516 F_SET(dbp, DB_AM_RECOVER);
00517 if (meta_pgno != PGNO_BASE_MD) {
00518 memcpy(dbp->fileid, uid, DB_FILE_ID_LEN);
00519 dbp->meta_pgno = meta_pgno;
00520 }
00521 if (opcode == DBREG_PREOPEN) {
00522 dbp->type = ftype;
00523 if ((ret = __dbreg_setup(dbp, name, id)) != 0)
00524 goto err;
00525 MAKE_INMEM(dbp);
00526 goto skip_open;
00527 }
00528
00529 if (opcode == DBREG_REOPEN) {
00530 MAKE_INMEM(dbp);
00531 fname = NULL;
00532 dname = name;
00533 }
00534
00535 if ((ret = __db_open(dbp, txn, fname, dname, ftype,
00536 DB_DURABLE_UNKNOWN | DB_ODDFILESIZE,
00537 __db_omode(OWNER_RW), meta_pgno)) == 0) {
00538 skip_open:
00539
00540
00541
00542
00543 if ((meta_pgno != PGNO_BASE_MD &&
00544 __dbreg_check_master(dbenv, uid, name) != 0) ||
00545 memcmp(uid, dbp->fileid, DB_FILE_ID_LEN) != 0)
00546 cstat = TXN_UNEXPECTED;
00547 else
00548 cstat = TXN_EXPECTED;
00549
00550
00551 if ((ret = __dbreg_assign_id(dbp, ndx)) != 0)
00552 goto err;
00553
00554
00555
00556
00557
00558
00559
00560 if (id != TXN_INVALID)
00561 ret = __db_txnlist_update(dbenv,
00562 info, id, cstat, NULL, &ret_stat, 1);
00563
00564 err: if (cstat == TXN_UNEXPECTED)
00565 goto not_right;
00566 return (ret);
00567 } else if (ret == ENOENT) {
00568
00569 if (id != TXN_INVALID)
00570 ret = __db_txnlist_update(dbenv, info,
00571 id, TXN_UNEXPECTED, NULL, &ret_stat, 1);
00572 }
00573 not_right:
00574 (void)__db_close(dbp, NULL, DB_NOSYNC);
00575
00576 (void)__dbreg_add_dbentry(dbenv, lp, NULL, ndx);
00577 return (ret);
00578 }
00579
00580 static int
00581 __dbreg_check_master(dbenv, uid, name)
00582 DB_ENV *dbenv;
00583 u_int8_t *uid;
00584 char *name;
00585 {
00586 DB *dbp;
00587 int ret;
00588
00589 ret = 0;
00590 if ((ret = db_create(&dbp, dbenv, 0)) != 0)
00591 return (ret);
00592 F_SET(dbp, DB_AM_RECOVER);
00593 ret = __db_open(dbp, NULL,
00594 name, NULL, DB_BTREE, 0, __db_omode(OWNER_RW), PGNO_BASE_MD);
00595
00596 if (ret == 0 && memcmp(uid, dbp->fileid, DB_FILE_ID_LEN) != 0)
00597 ret = EINVAL;
00598
00599 (void)__db_close(dbp, NULL, 0);
00600 return (ret);
00601 }
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617 int
00618 __dbreg_lazy_id(dbp)
00619 DB *dbp;
00620 {
00621 DB_ENV *dbenv;
00622 DB_LOG *dblp;
00623 DB_TXN *txn;
00624 FNAME *fnp;
00625 LOG *lp;
00626 int32_t id;
00627 int ret;
00628
00629 dbenv = dbp->dbenv;
00630
00631 DB_ASSERT(IS_REP_MASTER(dbenv));
00632
00633 dbenv = dbp->dbenv;
00634 dblp = dbenv->lg_handle;
00635 lp = dblp->reginfo.primary;
00636 fnp = dbp->log_filename;
00637
00638
00639 MUTEX_LOCK(dbenv, lp->mtx_filelist);
00640 if (fnp->id != DB_LOGFILEID_INVALID) {
00641 MUTEX_UNLOCK(dbenv, lp->mtx_filelist);
00642 return (0);
00643 }
00644 id = DB_LOGFILEID_INVALID;
00645 if ((ret = __txn_begin(dbenv, NULL, &txn, 0)) != 0)
00646 goto err;
00647
00648 if ((ret = __dbreg_get_id(dbp, txn, &id)) != 0) {
00649 (void)__txn_abort(txn);
00650 goto err;
00651 }
00652
00653 if ((ret = __txn_commit(txn, DB_TXN_NOSYNC)) != 0)
00654 goto err;
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666 fnp->id = id;
00667 err:
00668 if (ret != 0 && id != DB_LOGFILEID_INVALID)
00669 (void)__dbreg_revoke_id(dbp, 1, id);
00670 MUTEX_UNLOCK(dbenv, lp->mtx_filelist);
00671 return (ret);
00672 }