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
00039
00040
00041
00042 #include "db_config.h"
00043
00044 #ifndef NO_SYSTEM_INCLUDES
00045 #include <sys/types.h>
00046
00047 #include <string.h>
00048 #endif
00049
00050 #include "db_int.h"
00051 #include "dbinc/db_page.h"
00052 #include "dbinc/db_shash.h"
00053 #include "dbinc/db_swap.h"
00054 #include "dbinc/btree.h"
00055 #include "dbinc/fop.h"
00056 #include "dbinc/hash.h"
00057 #include "dbinc/lock.h"
00058 #include "dbinc/log.h"
00059 #include "dbinc/mp.h"
00060 #include "dbinc/qam.h"
00061 #include "dbinc/txn.h"
00062
00063 static int __db_disassociate __P((DB *));
00064
00065 #ifdef CONFIG_TEST
00066 static void __db_makecopy __P((DB_ENV *, const char *, const char *));
00067 static int __db_testdocopy __P((DB_ENV *, const char *));
00068 static int __qam_testdocopy __P((DB *, const char *));
00069 #endif
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 int
00084 __db_master_open(subdbp, txn, name, flags, mode, dbpp)
00085 DB *subdbp;
00086 DB_TXN *txn;
00087 const char *name;
00088 u_int32_t flags;
00089 int mode;
00090 DB **dbpp;
00091 {
00092 DB *dbp;
00093 int ret;
00094
00095 *dbpp = NULL;
00096
00097
00098 if ((ret = db_create(&dbp, subdbp->dbenv, 0)) != 0)
00099 return (ret);
00100
00101
00102
00103
00104
00105
00106
00107 dbp->pgsize = subdbp->pgsize;
00108 F_SET(dbp, DB_AM_SUBDB);
00109 F_SET(dbp, F_ISSET(subdbp,
00110 DB_AM_RECOVER | DB_AM_SWAP |
00111 DB_AM_ENCRYPT | DB_AM_CHKSUM | DB_AM_NOT_DURABLE));
00112
00113
00114
00115
00116
00117
00118 LF_CLR(DB_EXCL);
00119 LF_SET(DB_RDWRMASTER);
00120 if ((ret = __db_open(dbp,
00121 txn, name, NULL, DB_BTREE, flags, mode, PGNO_BASE_MD)) != 0)
00122 goto err;
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133 if (F_ISSET(dbp, DB_AM_CHKSUM))
00134 F_SET(subdbp, DB_AM_CHKSUM);
00135 if (subdbp->pgsize != 0 && dbp->pgsize != subdbp->pgsize) {
00136 ret = EINVAL;
00137 __db_err(dbp->dbenv,
00138 "Different pagesize specified on existent file");
00139 goto err;
00140 }
00141 err:
00142 if (ret != 0 && !F_ISSET(dbp, DB_AM_DISCARD))
00143 (void)__db_close(dbp, txn, 0);
00144 else
00145 *dbpp = dbp;
00146 return (ret);
00147 }
00148
00149
00150
00151
00152
00153
00154
00155
00156 int
00157 __db_master_update(mdbp, sdbp, txn, subdb, type, action, newname, flags)
00158 DB *mdbp, *sdbp;
00159 DB_TXN *txn;
00160 const char *subdb;
00161 DBTYPE type;
00162 mu_action action;
00163 const char *newname;
00164 u_int32_t flags;
00165 {
00166 DB_ENV *dbenv;
00167 DBC *dbc, *ndbc;
00168 DBT key, data, ndata;
00169 PAGE *p, *r;
00170 db_pgno_t t_pgno;
00171 int modify, ret, t_ret;
00172
00173 dbenv = mdbp->dbenv;
00174 dbc = ndbc = NULL;
00175 p = NULL;
00176
00177 memset(&key, 0, sizeof(key));
00178 memset(&data, 0, sizeof(data));
00179
00180
00181 modify = (action != MU_OPEN || LF_ISSET(DB_CREATE)) ? 1 : 0;
00182
00183
00184
00185
00186
00187 if ((ret = __db_cursor(mdbp, txn, &dbc,
00188 (CDB_LOCKING(dbenv) && modify) ? DB_WRITECURSOR : 0)) != 0)
00189 goto err;
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204 key.data = (void *)subdb;
00205 key.size = (u_int32_t)strlen(subdb);
00206 F_SET(&data, DB_DBT_MALLOC);
00207
00208 ret = __db_c_get(dbc, &key, &data,
00209 DB_SET | ((STD_LOCKING(dbc) && modify) ? DB_RMW : 0));
00210
00211
00212
00213
00214
00215
00216 switch (action) {
00217 case MU_REMOVE:
00218
00219
00220
00221
00222
00223
00224 if (ret != 0)
00225 goto err;
00226
00227
00228
00229
00230
00231 if ((ret = __db_c_del(dbc, 0)) != 0)
00232 goto err;
00233
00234
00235
00236
00237
00238
00239 memcpy(&sdbp->meta_pgno, data.data, sizeof(db_pgno_t));
00240 DB_NTOHL(&sdbp->meta_pgno);
00241 if ((ret =
00242 __memp_fget(mdbp->mpf, &sdbp->meta_pgno, 0, &p)) != 0)
00243 goto err;
00244
00245
00246 if (TYPE(p) == P_BTREEMETA &&
00247 ((BTMETA *)p)->root != PGNO_INVALID) {
00248 if ((ret = __memp_fget(mdbp->mpf,
00249 &((BTMETA *)p)->root, 0, &r)) != 0)
00250 goto err;
00251
00252
00253 if ((ret = __db_free(dbc, r)) != 0) {
00254 r = NULL;
00255 goto err;
00256 }
00257 }
00258
00259 if ((ret = __db_free(dbc, p)) != 0) {
00260 p = NULL;
00261 goto err;
00262 }
00263 p = NULL;
00264 break;
00265 case MU_RENAME:
00266
00267 if (ret != 0)
00268 goto err;
00269
00270
00271
00272
00273
00274
00275
00276
00277 if ((ret = __db_cursor(mdbp, txn, &ndbc, 0)) != 0)
00278 goto err;
00279 key.data = (void *)newname;
00280 key.size = (u_int32_t)strlen(newname);
00281
00282
00283
00284
00285
00286 memset(&ndata, 0, sizeof(ndata));
00287 F_SET(&ndata, DB_DBT_USERMEM | DB_DBT_PARTIAL);
00288
00289 if ((ret = __db_c_get(ndbc, &key, &ndata, DB_SET)) == 0) {
00290
00291 ret = EEXIST;
00292 __db_err(dbenv, "rename: database %s exists", newname);
00293 goto err;
00294 } else if (ret != DB_NOTFOUND)
00295 goto err;
00296
00297
00298
00299
00300
00301
00302 if ((ret = __db_c_put(ndbc, &key, &data, DB_KEYFIRST)) != 0)
00303 goto err;
00304 if ((ret = __db_c_del(dbc, 0)) != 0) {
00305
00306
00307
00308
00309 (void)__db_c_del(ndbc, 0);
00310 goto err;
00311 }
00312
00313 break;
00314 case MU_OPEN:
00315
00316
00317
00318
00319 switch (ret) {
00320 case 0:
00321 if (LF_ISSET(DB_CREATE) && LF_ISSET(DB_EXCL)) {
00322 ret = EEXIST;
00323 goto err;
00324 }
00325 memcpy(&sdbp->meta_pgno, data.data, sizeof(db_pgno_t));
00326 DB_NTOHL(&sdbp->meta_pgno);
00327 goto done;
00328 case DB_NOTFOUND:
00329 if (LF_ISSET(DB_CREATE))
00330 break;
00331
00332
00333
00334
00335 ret = ENOENT;
00336 goto err;
00337 default:
00338 goto err;
00339 }
00340
00341
00342 if ((ret = __db_new(dbc,
00343 type == DB_HASH ? P_HASHMETA : P_BTREEMETA, &p)) != 0)
00344 goto err;
00345 sdbp->meta_pgno = PGNO(p);
00346
00347
00348
00349
00350
00351
00352
00353 t_pgno = PGNO(p);
00354 DB_HTONL(&t_pgno);
00355 memset(&ndata, 0, sizeof(ndata));
00356 ndata.data = &t_pgno;
00357 ndata.size = sizeof(db_pgno_t);
00358 if ((ret = __db_c_put(dbc, &key, &ndata, DB_KEYLAST)) != 0)
00359 goto err;
00360 F_SET(sdbp, DB_AM_CREATED);
00361 break;
00362 }
00363
00364 err:
00365 done:
00366
00367
00368
00369 if (p != NULL) {
00370 if (ret == 0) {
00371 if ((t_ret =
00372 __memp_fput(mdbp->mpf, p, DB_MPOOL_DIRTY)) != 0)
00373 ret = t_ret;
00374 } else
00375 (void)__memp_fput(mdbp->mpf, p, 0);
00376 }
00377
00378
00379 if (data.data != NULL)
00380 __os_ufree(dbenv, data.data);
00381 if (dbc != NULL && (t_ret = __db_c_close(dbc)) != 0 && ret == 0)
00382 ret = t_ret;
00383 if (ndbc != NULL && (t_ret = __db_c_close(ndbc)) != 0 && ret == 0)
00384 ret = t_ret;
00385
00386 return (ret);
00387 }
00388
00389
00390
00391
00392
00393
00394
00395
00396 int
00397 __db_dbenv_setup(dbp, txn, fname, dname, id, flags)
00398 DB *dbp;
00399 DB_TXN *txn;
00400 const char *fname, *dname;
00401 u_int32_t id, flags;
00402 {
00403 DB *ldbp;
00404 DB_ENV *dbenv;
00405 u_int32_t maxid;
00406 int ret;
00407
00408 dbenv = dbp->dbenv;
00409
00410
00411 if (!F_ISSET(dbenv, DB_ENV_OPEN_CALLED)) {
00412
00413 if (dbenv->mp_gbytes == 0 &&
00414 dbenv->mp_bytes < dbp->pgsize * DB_MINPAGECACHE &&
00415 (ret = __memp_set_cachesize(
00416 dbenv, 0, dbp->pgsize * DB_MINPAGECACHE, 0)) != 0)
00417 return (ret);
00418
00419 if ((ret = __env_open(dbenv, NULL, DB_CREATE |
00420 DB_INIT_MPOOL | DB_PRIVATE | LF_ISSET(DB_THREAD), 0)) != 0)
00421 return (ret);
00422 }
00423
00424
00425 if ((!F_ISSET(dbp, DB_AM_INMEM) || dname == NULL) &&
00426 (ret = __db_dbenv_mpool(dbp, fname, flags)) != 0)
00427 return (ret);
00428
00429
00430 if (LF_ISSET(DB_THREAD) && (ret = __mutex_alloc(
00431 dbenv, MTX_DB_HANDLE, DB_MUTEX_THREAD, &dbp->mutex)) != 0)
00432 return (ret);
00433
00434
00435
00436
00437
00438
00439
00440 if (LOGGING_ON(dbenv) && dbp->log_filename == NULL &&
00441 (ret = __dbreg_setup(dbp,
00442 F_ISSET(dbp, DB_AM_INMEM) ? dname : fname, id)) != 0)
00443 return (ret);
00444
00445
00446
00447
00448
00449 if (DBENV_LOGGING(dbenv) && !F_ISSET(dbp, DB_AM_RECOVER) &&
00450 #if !defined(DEBUG_ROP)
00451 !F_ISSET(dbp, DB_AM_RDONLY) &&
00452 #endif
00453 (ret = __dbreg_new_id(dbp, txn)) != 0)
00454 return (ret);
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465 MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
00466 for (maxid = 0, ldbp = LIST_FIRST(&dbenv->dblist);
00467 ldbp != NULL; ldbp = LIST_NEXT(ldbp, dblistlinks)) {
00468 if (!F_ISSET(dbp, DB_AM_INMEM)) {
00469 if (memcmp(ldbp->fileid, dbp->fileid, DB_FILE_ID_LEN)
00470 == 0 && ldbp->meta_pgno == dbp->meta_pgno)
00471 break;
00472 } else if (dname != NULL) {
00473 if (F_ISSET(ldbp, DB_AM_INMEM) &&
00474 strcmp(ldbp->dname, dname) == 0)
00475 break;
00476 }
00477 if (ldbp->adj_fileid > maxid)
00478 maxid = ldbp->adj_fileid;
00479 }
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491 if (ldbp == NULL) {
00492 dbp->adj_fileid = maxid + 1;
00493 LIST_INSERT_HEAD(&dbenv->dblist, dbp, dblistlinks);
00494 } else {
00495 dbp->adj_fileid = ldbp->adj_fileid;
00496 LIST_INSERT_AFTER(ldbp, dbp, dblistlinks);
00497 }
00498 MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
00499
00500 return (0);
00501 }
00502
00503
00504
00505
00506
00507
00508
00509 int
00510 __db_dbenv_mpool(dbp, fname, flags)
00511 DB *dbp;
00512 const char *fname;
00513 u_int32_t flags;
00514 {
00515 DB_ENV *dbenv;
00516 DBT pgcookie;
00517 DB_MPOOLFILE *mpf;
00518 DB_PGINFO pginfo;
00519 int fidset, ftype, ret;
00520 int32_t lsn_off;
00521 u_int8_t nullfid[DB_FILE_ID_LEN];
00522 u_int32_t clear_len;
00523
00524 COMPQUIET(mpf, NULL);
00525
00526 dbenv = dbp->dbenv;
00527 lsn_off = 0;
00528
00529
00530 if (F_ISSET(dbp, DB_AM_OPEN_CALLED))
00531 return (0);
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541 switch (dbp->type) {
00542 case DB_BTREE:
00543 case DB_RECNO:
00544 ftype = F_ISSET(dbp, DB_AM_SWAP | DB_AM_ENCRYPT | DB_AM_CHKSUM)
00545 ? DB_FTYPE_SET : DB_FTYPE_NOTSET;
00546 clear_len = CRYPTO_ON(dbenv) ?
00547 (dbp->pgsize != 0 ? dbp->pgsize : DB_CLEARLEN_NOTSET) :
00548 DB_PAGE_DB_LEN;
00549 break;
00550 case DB_HASH:
00551 ftype = DB_FTYPE_SET;
00552 clear_len = CRYPTO_ON(dbenv) ?
00553 (dbp->pgsize != 0 ? dbp->pgsize : DB_CLEARLEN_NOTSET) :
00554 DB_PAGE_DB_LEN;
00555 break;
00556 case DB_QUEUE:
00557 ftype = F_ISSET(dbp,
00558 DB_AM_SWAP | DB_AM_ENCRYPT | DB_AM_CHKSUM) ?
00559 DB_FTYPE_SET : DB_FTYPE_NOTSET;
00560
00561
00562
00563
00564
00565
00566
00567 clear_len = dbp->pgsize != 0 ? dbp->pgsize : DB_CLEARLEN_NOTSET;
00568 break;
00569 case DB_UNKNOWN:
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582 if (F_ISSET(dbp, DB_AM_VERIFYING)) {
00583 ftype = DB_FTYPE_NOTSET;
00584 clear_len = DB_PAGE_DB_LEN;
00585 break;
00586 }
00587
00588
00589
00590
00591
00592
00593 if (F_ISSET(dbp, DB_AM_INMEM)) {
00594 clear_len = DB_CLEARLEN_NOTSET;
00595 ftype = DB_FTYPE_NOTSET;
00596 lsn_off = DB_LSN_OFF_NOTSET;
00597 break;
00598 }
00599
00600 default:
00601 return (__db_unknown_type(dbenv, "DB->open", dbp->type));
00602 }
00603
00604 mpf = dbp->mpf;
00605
00606 memset(nullfid, 0, DB_FILE_ID_LEN);
00607 fidset = memcmp(nullfid, dbp->fileid, DB_FILE_ID_LEN);
00608 if (fidset)
00609 (void)__memp_set_fileid(mpf, dbp->fileid);
00610
00611 (void)__memp_set_clear_len(mpf, clear_len);
00612 (void)__memp_set_ftype(mpf, ftype);
00613 (void)__memp_set_lsn_offset(mpf, lsn_off);
00614
00615 pginfo.db_pagesize = dbp->pgsize;
00616 pginfo.flags =
00617 F_ISSET(dbp, (DB_AM_CHKSUM | DB_AM_ENCRYPT | DB_AM_SWAP));
00618 pginfo.type = dbp->type;
00619 pgcookie.data = &pginfo;
00620 pgcookie.size = sizeof(DB_PGINFO);
00621 (void)__memp_set_pgcookie(mpf, &pgcookie);
00622
00623 if ((ret = __memp_fopen(mpf, NULL, fname,
00624 LF_ISSET(DB_CREATE | DB_DURABLE_UNKNOWN |
00625 DB_NOMMAP | DB_ODDFILESIZE | DB_RDONLY | DB_TRUNCATE) |
00626 (F_ISSET(dbenv, DB_ENV_DIRECT_DB) ? DB_DIRECT : 0) |
00627 (F_ISSET(dbp, DB_AM_NOT_DURABLE) ? DB_TXN_NOT_DURABLE : 0),
00628 0, dbp->pgsize)) != 0) {
00629
00630
00631
00632
00633 (void)__memp_fclose(dbp->mpf, 0);
00634 (void)__memp_fcreate(dbenv, &dbp->mpf);
00635 if (F_ISSET(dbp, DB_AM_INMEM))
00636 MAKE_INMEM(dbp);
00637 return (ret);
00638 }
00639
00640
00641
00642
00643
00644
00645
00646
00647 F_SET(dbp, DB_AM_OPEN_CALLED);
00648 if (!fidset && fname != NULL) {
00649 (void)__memp_get_fileid(dbp->mpf, dbp->fileid);
00650 dbp->preserve_fid = 1;
00651 }
00652
00653 return (0);
00654 }
00655
00656
00657
00658
00659
00660
00661
00662 int
00663 __db_close(dbp, txn, flags)
00664 DB *dbp;
00665 DB_TXN *txn;
00666 u_int32_t flags;
00667 {
00668 DB_ENV *dbenv;
00669 int db_ref, deferred_close, ret, t_ret;
00670
00671 dbenv = dbp->dbenv;
00672 deferred_close = ret = 0;
00673
00674
00675
00676
00677
00678
00679
00680
00681 if (txn != NULL)
00682 (void)__db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 0);
00683
00684
00685 ret = __db_refresh(dbp, txn, flags, &deferred_close, 0);
00686
00687
00688
00689
00690
00691 if (deferred_close)
00692 return (ret);
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705 MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
00706 db_ref = --dbenv->db_ref;
00707 MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
00708 if (F_ISSET(dbenv, DB_ENV_DBLOCAL) && db_ref == 0 &&
00709 (t_ret = __env_close(dbenv, 0)) != 0 && ret == 0)
00710 ret = t_ret;
00711
00712
00713 memset(dbp, CLEAR_BYTE, sizeof(*dbp));
00714 __os_free(dbenv, dbp);
00715
00716 return (ret);
00717 }
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729 int
00730 __db_refresh(dbp, txn, flags, deferred_closep, reuse)
00731 DB *dbp;
00732 DB_TXN *txn;
00733 u_int32_t flags;
00734 int *deferred_closep, reuse;
00735 {
00736 DB *sdbp;
00737 DBC *dbc;
00738 DB_ENV *dbenv;
00739 DB_LOCKREQ lreq;
00740 REGENV *renv;
00741 REGINFO *infop;
00742 u_int32_t save_flags;
00743 int resync, ret, t_ret;
00744
00745 ret = 0;
00746
00747 dbenv = dbp->dbenv;
00748 infop = dbenv->reginfo;
00749 if (infop != NULL)
00750 renv = infop->primary;
00751 else
00752 renv = NULL;
00753
00754
00755 if (!F_ISSET(dbp, DB_AM_OPEN_CALLED))
00756 goto never_opened;
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767 for (sdbp = LIST_FIRST(&dbp->s_secondaries);
00768 sdbp != NULL; sdbp = LIST_NEXT(sdbp, s_links)) {
00769 LIST_REMOVE(sdbp, s_links);
00770 if ((t_ret = __db_disassociate(sdbp)) != 0 && ret == 0)
00771 ret = t_ret;
00772 }
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783 if (!LF_ISSET(DB_NOSYNC) &&
00784 !F_ISSET(dbp, DB_AM_DISCARD | DB_AM_RECOVER) &&
00785 (t_ret = __db_sync(dbp)) != 0 && ret == 0)
00786 ret = t_ret;
00787
00788
00789
00790
00791
00792
00793
00794
00795 resync = TAILQ_FIRST(&dbp->active_queue) == NULL ? 0 : 1;
00796 while ((dbc = TAILQ_FIRST(&dbp->active_queue)) != NULL)
00797 if ((t_ret = __db_c_close(dbc)) != 0) {
00798 if (ret == 0)
00799 ret = t_ret;
00800 break;
00801 }
00802
00803 while ((dbc = TAILQ_FIRST(&dbp->free_queue)) != NULL)
00804 if ((t_ret = __db_c_destroy(dbc)) != 0) {
00805 if (ret == 0)
00806 ret = t_ret;
00807 break;
00808 }
00809
00810
00811
00812
00813
00814
00815 while ((dbc = TAILQ_FIRST(&dbp->join_queue)) != NULL)
00816 if ((t_ret = __db_join_close(dbc)) != 0) {
00817 if (ret == 0)
00818 ret = t_ret;
00819 break;
00820 }
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831 if (resync && !LF_ISSET(DB_NOSYNC) &&
00832 !F_ISSET(dbp, DB_AM_DISCARD | DB_AM_RECOVER) &&
00833 (t_ret = __memp_fsync(dbp->mpf)) != 0 && ret == 0)
00834 ret = t_ret;
00835
00836 never_opened:
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848 if (!reuse && LOGGING_ON(dbp->dbenv)) {
00849
00850
00851
00852
00853
00854 DB_ASSERT(renv != NULL);
00855 if (F_ISSET(dbp, DB_AM_RECOVER) || IS_REP_CLIENT(dbenv) ||
00856 dbp->timestamp != renv->rep_timestamp)
00857 t_ret = __dbreg_revoke_id(dbp, 0, DB_LOGFILEID_INVALID);
00858 else {
00859 if ((t_ret = __dbreg_close_id(dbp,
00860 txn, DBREG_CLOSE)) != 0 && txn != NULL) {
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873 if ((ret =
00874 __txn_closeevent(dbenv, txn, dbp)) != 0)
00875 return (__db_panic(dbenv, ret));
00876 if (deferred_closep != NULL)
00877 *deferred_closep = 1;
00878 return (t_ret);
00879 }
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891 }
00892
00893 if (ret == 0)
00894 ret = t_ret;
00895
00896
00897 if ((t_ret = __dbreg_teardown(dbp)) != 0 && ret == 0)
00898 ret = t_ret;
00899 }
00900
00901
00902 if (dbp->saved_open_fhp != NULL &&
00903 (t_ret = __os_closehandle(dbenv, dbp->saved_open_fhp)) != 0 &&
00904 ret == 0)
00905 ret = t_ret;
00906
00907
00908
00909
00910
00911
00912
00913
00914 MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
00915 if (!reuse && dbp->dblistlinks.le_prev != NULL) {
00916 LIST_REMOVE(dbp, dblistlinks);
00917 dbp->dblistlinks.le_prev = NULL;
00918 }
00919
00920
00921 if (dbp->mpf != NULL) {
00922 if ((t_ret = __memp_fclose(dbp->mpf,
00923 F_ISSET(dbp, DB_AM_DISCARD) ? DB_MPOOL_DISCARD : 0)) != 0 &&
00924 ret == 0)
00925 ret = t_ret;
00926 dbp->mpf = NULL;
00927 if (reuse &&
00928 (t_ret = __memp_fcreate(dbenv, &dbp->mpf)) != 0 &&
00929 ret == 0)
00930 ret = t_ret;
00931 }
00932
00933 MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955 if ((t_ret = __bam_db_close(dbp)) != 0 && ret == 0)
00956 ret = t_ret;
00957 if ((t_ret = __ham_db_close(dbp)) != 0 && ret == 0)
00958 ret = t_ret;
00959 if ((t_ret = __qam_db_close(dbp, dbp->flags)) != 0 && ret == 0)
00960 ret = t_ret;
00961
00962
00963
00964
00965
00966
00967
00968
00969 if (!reuse && dbp->lid != DB_LOCK_INVALIDID) {
00970
00971 if (txn != NULL)
00972 __txn_remlock(dbenv, txn, &dbp->handle_lock, dbp->lid);
00973
00974
00975 lreq.op = DB_LOCK_PUT_ALL;
00976 lreq.obj = NULL;
00977 if ((t_ret = __lock_vec(dbenv,
00978 dbp->lid, 0, &lreq, 1, NULL)) != 0 && ret == 0)
00979 ret = t_ret;
00980
00981 if ((t_ret = __lock_id_free(dbenv, dbp->lid)) != 0 && ret == 0)
00982 ret = t_ret;
00983 dbp->lid = DB_LOCK_INVALIDID;
00984 LOCK_INIT(dbp->handle_lock);
00985 }
00986
00987
00988
00989
00990
00991 if (LOCKING_ON(dbenv) &&
00992 F_ISSET(dbp, DB_AM_INMEM) && !dbp->preserve_fid &&
00993 *(u_int32_t *)dbp->fileid != DB_LOCK_INVALIDID &&
00994 (t_ret = __lock_id_free(dbenv, *(u_int32_t *)dbp->fileid)) != 0 &&
00995 ret == 0)
00996 ret = t_ret;
00997
00998 if (reuse) {
00999
01000
01001
01002
01003
01004
01005 save_flags = F_ISSET(dbp, DB_AM_INMEM | DB_AM_TXN);
01006
01007
01008
01009
01010
01011 if ((ret = __bam_db_create(dbp)) != 0)
01012 return (ret);
01013 if ((ret = __ham_db_create(dbp)) != 0)
01014 return (ret);
01015 if ((ret = __qam_db_create(dbp)) != 0)
01016 return (ret);
01017
01018
01019 dbp->flags = dbp->orig_flags | save_flags;
01020
01021 if (FLD_ISSET(save_flags, DB_AM_INMEM)) {
01022
01023
01024
01025
01026
01027 memset(dbp->fileid, 0, sizeof(dbp->fileid));
01028 MAKE_INMEM(dbp);
01029 }
01030 return (ret);
01031 }
01032
01033 dbp->type = DB_UNKNOWN;
01034
01035
01036 if ((t_ret = __mutex_free(dbenv, &dbp->mutex)) != 0 && ret == 0)
01037 ret = t_ret;
01038
01039
01040 if (dbp->fname != NULL) {
01041 __os_free(dbp->dbenv, dbp->fname);
01042 dbp->fname = NULL;
01043 }
01044 if (dbp->dname != NULL) {
01045 __os_free(dbp->dbenv, dbp->dname);
01046 dbp->dname = NULL;
01047 }
01048
01049
01050 if (dbp->my_rskey.data != NULL)
01051 __os_free(dbp->dbenv, dbp->my_rskey.data);
01052 if (dbp->my_rkey.data != NULL)
01053 __os_free(dbp->dbenv, dbp->my_rkey.data);
01054 if (dbp->my_rdata.data != NULL)
01055 __os_free(dbp->dbenv, dbp->my_rdata.data);
01056
01057
01058 memset(&dbp->my_rskey, 0, sizeof(DBT));
01059 memset(&dbp->my_rkey, 0, sizeof(DBT));
01060 memset(&dbp->my_rdata, 0, sizeof(DBT));
01061
01062
01063 memset(dbp->fileid, 0, sizeof(dbp->fileid));
01064 dbp->adj_fileid = 0;
01065 dbp->meta_pgno = 0;
01066 dbp->cur_lid = DB_LOCK_INVALIDID;
01067 dbp->associate_lid = DB_LOCK_INVALIDID;
01068 dbp->cl_id = 0;
01069 dbp->open_flags = 0;
01070
01071
01072
01073
01074
01075
01076
01077
01078 if (txn != NULL)
01079 LOCK_INIT(dbp->handle_lock);
01080
01081
01082 dbp->flags = dbp->orig_flags;
01083
01084 return (ret);
01085 }
01086
01087
01088
01089
01090
01091
01092
01093 int
01094 __db_log_page(dbp, txn, lsn, pgno, page)
01095 DB *dbp;
01096 DB_TXN *txn;
01097 DB_LSN *lsn;
01098 db_pgno_t pgno;
01099 PAGE *page;
01100 {
01101 DBT page_dbt;
01102 DB_LSN new_lsn;
01103 int ret;
01104
01105 if (!LOGGING_ON(dbp->dbenv) || txn == NULL)
01106 return (0);
01107
01108 memset(&page_dbt, 0, sizeof(page_dbt));
01109 page_dbt.size = dbp->pgsize;
01110 page_dbt.data = page;
01111
01112 ret = __crdel_metasub_log(dbp, txn, &new_lsn, 0, pgno, &page_dbt, lsn);
01113
01114 if (ret == 0)
01115 page->lsn = new_lsn;
01116 return (ret);
01117 }
01118
01119
01120
01121
01122
01123
01124
01125
01126 #undef BACKUP_PREFIX
01127 #define BACKUP_PREFIX "__db"
01128
01129 #undef MAX_LSN_TO_TEXT
01130 #define MAX_LSN_TO_TEXT 17
01131
01132 int
01133 __db_backup_name(dbenv, name, txn, backup)
01134 DB_ENV *dbenv;
01135 const char *name;
01136 DB_TXN *txn;
01137 char **backup;
01138 {
01139 DB_LSN lsn;
01140 size_t len;
01141 int ret;
01142 char *p, *retp;
01143
01144
01145
01146
01147
01148
01149 len = strlen(name) + strlen(BACKUP_PREFIX) + 1 + MAX_LSN_TO_TEXT;
01150 if ((ret = __os_malloc(dbenv, len, &retp)) != 0)
01151 return (ret);
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175 p = __db_rpath(name);
01176 if (txn == NULL) {
01177 #ifdef HAVE_VXWORKS
01178 { int i, n;
01179
01180 if (p == NULL)
01181 n = snprintf(retp,
01182 len, "%s%.4s.tmp", BACKUP_PREFIX, name);
01183 else
01184 n = snprintf(retp, len, "%.*s%s%.4s.tmp",
01185 (int)(p - name) + 1, name, BACKUP_PREFIX, p + 1);
01186
01187
01188
01189
01190
01191
01192
01193 for (i = 0, p = (retp + n) - 8; i < 4; p++, i++)
01194 if (*p == '.')
01195 *p = '_';
01196 }
01197 #else
01198 if (p == NULL)
01199 snprintf(retp, len, "%s.%s", BACKUP_PREFIX, name);
01200 else
01201 snprintf(retp, len, "%.*s%s.%s",
01202 (int)(p - name) + 1, name, BACKUP_PREFIX, p + 1);
01203 #endif
01204 } else {
01205 lsn = ((TXN_DETAIL *)txn->td)->last_lsn;
01206 if (IS_ZERO_LSN(lsn)) {
01207
01208
01209
01210
01211
01212
01213
01214 if ((ret = __db_debug_log(dbenv,
01215 txn, &lsn, 0, NULL, 0, NULL, NULL, 0)) != 0) {
01216 __os_free(dbenv, retp);
01217 return (ret);
01218 }
01219 }
01220
01221 if (p == NULL)
01222 snprintf(retp, len,
01223 "%s.%x.%x", BACKUP_PREFIX, lsn.file, lsn.offset);
01224 else
01225 snprintf(retp, len, "%.*s%x.%x",
01226 (int)(p - name) + 1, name, lsn.file, lsn.offset);
01227 }
01228
01229 *backup = retp;
01230 return (0);
01231 }
01232
01233
01234
01235
01236
01237
01238
01239
01240 DB *
01241 __dblist_get(dbenv, adjid)
01242 DB_ENV *dbenv;
01243 u_int32_t adjid;
01244 {
01245 DB *dbp;
01246
01247 for (dbp = LIST_FIRST(&dbenv->dblist);
01248 dbp != NULL && dbp->adj_fileid != adjid;
01249 dbp = LIST_NEXT(dbp, dblistlinks))
01250 ;
01251
01252 return (dbp);
01253 }
01254
01255
01256
01257
01258
01259 static int
01260 __db_disassociate(sdbp)
01261 DB *sdbp;
01262 {
01263 DBC *dbc;
01264 int ret, t_ret;
01265
01266 ret = 0;
01267
01268 sdbp->s_callback = NULL;
01269 sdbp->s_primary = NULL;
01270 sdbp->get = sdbp->stored_get;
01271 sdbp->close = sdbp->stored_close;
01272
01273
01274
01275
01276
01277 if (sdbp->s_refcnt != 1 ||
01278 TAILQ_FIRST(&sdbp->active_queue) != NULL ||
01279 TAILQ_FIRST(&sdbp->join_queue) != NULL) {
01280 __db_err(sdbp->dbenv,
01281 "Closing a primary DB while a secondary DB has active cursors is unsafe");
01282 ret = EINVAL;
01283 }
01284 sdbp->s_refcnt = 0;
01285
01286 while ((dbc = TAILQ_FIRST(&sdbp->free_queue)) != NULL)
01287 if ((t_ret = __db_c_destroy(dbc)) != 0 && ret == 0)
01288 ret = t_ret;
01289
01290 F_CLR(sdbp, DB_AM_SECONDARY);
01291 return (ret);
01292 }
01293
01294 #ifdef CONFIG_TEST
01295
01296
01297
01298
01299
01300
01301
01302
01303 int
01304 __db_testcopy(dbenv, dbp, name)
01305 DB_ENV *dbenv;
01306 DB *dbp;
01307 const char *name;
01308 {
01309 DB_MPOOL *dbmp;
01310 DB_MPOOLFILE *mpf;
01311
01312 DB_ASSERT(dbp != NULL || name != NULL);
01313
01314 if (name == NULL) {
01315 dbmp = dbenv->mp_handle;
01316 mpf = dbp->mpf;
01317 name = R_ADDR(dbmp->reginfo, mpf->mfp->path_off);
01318 }
01319
01320 if (dbp != NULL && dbp->type == DB_QUEUE)
01321 return (__qam_testdocopy(dbp, name));
01322 else
01323 return (__db_testdocopy(dbenv, name));
01324 }
01325
01326 static int
01327 __qam_testdocopy(dbp, name)
01328 DB *dbp;
01329 const char *name;
01330 {
01331 QUEUE_FILELIST *filelist, *fp;
01332 char buf[256], *dir;
01333 int ret;
01334
01335 filelist = NULL;
01336 if ((ret = __db_testdocopy(dbp->dbenv, name)) != 0)
01337 return (ret);
01338 if (dbp->mpf != NULL &&
01339 (ret = __qam_gen_filelist(dbp, &filelist)) != 0)
01340 return (ret);
01341
01342 if (filelist == NULL)
01343 return (0);
01344 dir = ((QUEUE *)dbp->q_internal)->dir;
01345 for (fp = filelist; fp->mpf != NULL; fp++) {
01346 snprintf(buf, sizeof(buf),
01347 QUEUE_EXTENT, dir, PATH_SEPARATOR[0], name, fp->id);
01348 if ((ret = __db_testdocopy(dbp->dbenv, buf)) != 0)
01349 return (ret);
01350 }
01351
01352 __os_free(dbp->dbenv, filelist);
01353 return (0);
01354 }
01355
01356
01357
01358
01359
01360
01361 static int
01362 __db_testdocopy(dbenv, name)
01363 DB_ENV *dbenv;
01364 const char *name;
01365 {
01366 size_t len;
01367 int dircnt, i, ret;
01368 char *backup, *copy, *dir, **namesp, *p, *real_name;
01369
01370 dircnt = 0;
01371 copy = backup = NULL;
01372 namesp = NULL;
01373
01374
01375 if ((ret = __db_appname(dbenv,
01376 DB_APP_DATA, name, 0, NULL, &real_name)) != 0)
01377 return (ret);
01378
01379
01380
01381
01382 len = strlen(real_name) +
01383 strlen(BACKUP_PREFIX) + 1 + MAX_LSN_TO_TEXT + 9;
01384
01385 if ((ret = __os_malloc(dbenv, len, ©)) != 0)
01386 goto err;
01387
01388 if ((ret = __os_malloc(dbenv, len, &backup)) != 0)
01389 goto err;
01390
01391
01392
01393
01394 snprintf(copy, len, "%s.afterop", real_name);
01395 __db_makecopy(dbenv, real_name, copy);
01396
01397 if ((ret = __os_strdup(dbenv, real_name, &dir)) != 0)
01398 goto err;
01399 __os_free(dbenv, real_name);
01400 real_name = NULL;
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412 snprintf(backup, len, "%s.%s.0x", BACKUP_PREFIX, name);
01413
01414
01415
01416
01417 p = __db_rpath(dir);
01418 if (p != NULL)
01419 *p = '\0';
01420 ret = __os_dirlist(dbenv, dir, &namesp, &dircnt);
01421 #if DIAGNOSTIC
01422
01423
01424
01425
01426
01427
01428
01429 *p = '/';
01430 #endif
01431 __os_free(dbenv, dir);
01432 if (ret != 0)
01433 goto err;
01434 for (i = 0; i < dircnt; i++) {
01435
01436
01437
01438
01439
01440
01441
01442
01443 if (strncmp(namesp[i], backup, strlen(backup)) == 0) {
01444 if ((ret = __db_appname(dbenv, DB_APP_DATA,
01445 namesp[i], 0, NULL, &real_name)) != 0)
01446 goto err;
01447
01448
01449
01450
01451
01452
01453 if (strstr(real_name, ".afterop") != NULL) {
01454 __os_free(dbenv, real_name);
01455 real_name = NULL;
01456 continue;
01457 }
01458 snprintf(copy, len, "%s.afterop", real_name);
01459 __db_makecopy(dbenv, real_name, copy);
01460 __os_free(dbenv, real_name);
01461 real_name = NULL;
01462 }
01463 }
01464
01465 err: if (backup != NULL)
01466 __os_free(dbenv, backup);
01467 if (copy != NULL)
01468 __os_free(dbenv, copy);
01469 if (namesp != NULL)
01470 __os_dirfree(dbenv, namesp, dircnt);
01471 if (real_name != NULL)
01472 __os_free(dbenv, real_name);
01473 return (ret);
01474 }
01475
01476 static void
01477 __db_makecopy(dbenv, src, dest)
01478 DB_ENV *dbenv;
01479 const char *src, *dest;
01480 {
01481 DB_FH *rfhp, *wfhp;
01482 size_t rcnt, wcnt;
01483 char *buf;
01484
01485 rfhp = wfhp = NULL;
01486
01487 if (__os_malloc(dbenv, 1024, &buf) != 0)
01488 return;
01489
01490 if (__os_open(dbenv,
01491 src, DB_OSO_RDONLY, __db_omode(OWNER_RW), &rfhp) != 0)
01492 goto err;
01493 if (__os_open(dbenv, dest,
01494 DB_OSO_CREATE | DB_OSO_TRUNC, __db_omode(OWNER_RW), &wfhp) != 0)
01495 goto err;
01496
01497 for (;;)
01498 if (__os_read(dbenv, rfhp, buf, 1024, &rcnt) < 0 || rcnt == 0 ||
01499 __os_write(dbenv, wfhp, buf, rcnt, &wcnt) < 0)
01500 break;
01501
01502 err: if (buf != NULL)
01503 __os_free(dbenv, buf);
01504 if (rfhp != NULL)
01505 (void)__os_closehandle(dbenv, rfhp);
01506 if (wfhp != NULL)
01507 (void)__os_closehandle(dbenv, wfhp);
01508 }
01509 #endif