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 #include "config.h"
00041
00042 #ifndef lint
00043 static const char revid[] = "$Id: db_8c-source.html,v 1.1 2008/06/08 10:16:30 sebdiaz Exp $";
00044 #endif
00045
00046 #ifndef NO_SYSTEM_INCLUDES
00047 #include <sys/types.h>
00048
00049 #include <errno.h>
00050 #include <stddef.h>
00051 #include <stdlib.h>
00052 #include <string.h>
00053 #endif
00054
00055 #include "db_int.h"
00056 #include "db_page.h"
00057 #include "db_shash.h"
00058 #include "db_swap.h"
00059 #include "btree.h"
00060 #include "db_am.h"
00061 #include "hash.h"
00062 #include "lock.h"
00063 #include "log.h"
00064 #include "mp.h"
00065 #include "qam.h"
00066 #include "common_ext.h"
00067
00068
00069 typedef enum { MU_REMOVE, MU_RENAME, MU_OPEN } mu_action;
00070
00071
00072 #define DB_FILE_SETUP_CREATE 0x01
00073 #define DB_FILE_SETUP_ZERO 0x02
00074
00075 static int __db_file_setup __P((DB *,
00076 const char *, u_int32_t, int, db_pgno_t, int *));
00077 static int __db_master_update __P((DB *,
00078 const char *, u_int32_t,
00079 db_pgno_t *, mu_action, const char *, u_int32_t));
00080 static int __db_metabegin __P((DB *, DB_LOCK *));
00081 static int __db_metaend __P((DB *,
00082 DB_LOCK *, int, int (*)(DB *, void *), void *));
00083 static int __db_refresh __P((DB *));
00084 static int __db_remove_callback __P((DB *, void *));
00085 static int __db_set_pgsize __P((DB *, DB_FH *, char *));
00086 static int __db_subdb_remove __P((DB *, const char *, const char *));
00087 static int __db_subdb_rename __P(( DB *,
00088 const char *, const char *, const char *));
00089 #if CONFIG_TEST
00090 static void __db_makecopy __P((const char *, const char *));
00091 #endif
00092
00093
00094
00095
00096
00097
00098
00099
00100 int
00101 CDB___db_open(dbp, name, subdb, type, flags, mode)
00102 DB *dbp;
00103 const char *name, *subdb;
00104 DBTYPE type;
00105 u_int32_t flags;
00106 int mode;
00107 {
00108 DB_ENV *dbenv;
00109 DB_LOCK open_lock;
00110 DB *mdbp;
00111 db_pgno_t meta_pgno;
00112 u_int32_t ok_flags;
00113 int ret, t_ret;
00114
00115 dbenv = dbp->dbenv;
00116 mdbp = NULL;
00117
00118
00119 #define OKFLAGS \
00120 (DB_CREATE | DB_EXCL | DB_FCNTL_LOCKING | DB_COMPRESS | \
00121 DB_NOMMAP | DB_RDONLY | DB_RDWRMASTER | DB_THREAD | DB_TRUNCATE)
00122 if ((ret = CDB___db_fchk(dbenv, "DB->open", flags, OKFLAGS)) != 0)
00123 return (ret);
00124 if (LF_ISSET(DB_EXCL) && !LF_ISSET(DB_CREATE))
00125 return (CDB___db_ferr(dbenv, "DB->open", 1));
00126 if (LF_ISSET(DB_RDONLY) && LF_ISSET(DB_CREATE))
00127 return (CDB___db_ferr(dbenv, "DB->open", 1));
00128 #ifdef HAVE_VXWORKS
00129 if (LF_ISSET(DB_TRUNCATE)) {
00130 CDB___db_err(dbenv, "DB_TRUNCATE unsupported in VxWorks");
00131 return (CDB___db_eopnotsup(dbenv));
00132 }
00133 #endif
00134 switch (type) {
00135 case DB_UNKNOWN:
00136 if (LF_ISSET(DB_CREATE)) {
00137 CDB___db_err(dbenv,
00138 "%s: DB_UNKNOWN type specified with DB_CREATE",
00139 name);
00140 return (EINVAL);
00141 }
00142 ok_flags = 0;
00143 break;
00144 case DB_BTREE:
00145 ok_flags = DB_OK_BTREE;
00146 break;
00147 case DB_HASH:
00148 ok_flags = DB_OK_HASH;
00149 break;
00150 case DB_QUEUE:
00151 ok_flags = DB_OK_QUEUE;
00152 break;
00153 case DB_RECNO:
00154 ok_flags = DB_OK_RECNO;
00155 break;
00156 default:
00157 CDB___db_err(dbenv, "unknown type: %lu", type);
00158 return (EINVAL);
00159 }
00160 if (ok_flags)
00161 DB_ILLEGAL_METHOD(dbp, ok_flags);
00162
00163
00164 if (!F_ISSET(dbenv, DB_ENV_DBLOCAL | DB_ENV_OPEN_CALLED)) {
00165 CDB___db_err(dbenv, "environment not yet opened");
00166 return (EINVAL);
00167 }
00168
00169
00170
00171
00172
00173
00174 if (!F_ISSET(dbenv, DB_ENV_DBLOCAL) && !MPOOL_ON(dbenv)) {
00175 CDB___db_err(dbenv, "environment did not include a memory pool.");
00176 return (EINVAL);
00177 }
00178
00179
00180
00181
00182
00183 if (LF_ISSET(DB_THREAD) &&
00184 !F_ISSET(dbenv, DB_ENV_DBLOCAL | DB_ENV_THREAD)) {
00185 CDB___db_err(dbenv, "environment not created using DB_THREAD");
00186 return (EINVAL);
00187 }
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197 if (F_ISSET(dbenv, DB_ENV_THREAD))
00198 LF_SET(DB_THREAD);
00199
00200
00201 if (LF_ISSET(DB_TRUNCATE) && TXN_ON(dbenv)) {
00202 CDB___db_err(dbenv,
00203 "DB_TRUNCATE illegal in a transaction protected environment");
00204 return (EINVAL);
00205 }
00206
00207
00208 if (subdb != NULL) {
00209
00210 if (name == NULL) {
00211 CDB___db_err(dbenv,
00212 "multiple databases cannot be created in temporary files");
00213 return (EINVAL);
00214 }
00215
00216
00217 if (type == DB_QUEUE) {
00218 CDB___db_err(dbenv, "Queue databases must be one-per-file");
00219 return (EINVAL);
00220 }
00221 }
00222
00223
00224 if (LF_ISSET(DB_RDONLY))
00225 F_SET(dbp, DB_AM_RDONLY);
00226 if (LF_ISSET(DB_COMPRESS))
00227 F_SET(dbp, DB_AM_CMPR);
00228
00229
00230 dbp->type = type;
00231
00232
00233
00234
00235
00236 if (TXN_ON(dbenv) && LF_ISSET(DB_CREATE))
00237 if ((ret = __db_metabegin(dbp, &open_lock)) != 0)
00238 return (ret);
00239
00240
00241
00242
00243
00244
00245
00246 if (subdb == NULL)
00247 meta_pgno = PGNO_BASE_MD;
00248 else {
00249
00250
00251
00252
00253 if ((ret =
00254 CDB___db_master_open(dbp, name, flags, mode, &mdbp)) != 0)
00255 goto err;
00256
00257
00258 dbp->pgsize = mdbp->pgsize;
00259 F_SET(dbp, DB_AM_SUBDB);
00260 memcpy(dbp->fileid, mdbp->fileid, DB_FILE_ID_LEN);
00261
00262 if ((ret = __db_master_update(mdbp,
00263 subdb, type, &meta_pgno, MU_OPEN, NULL, flags)) != 0)
00264 goto err;
00265
00266
00267
00268
00269
00270 LF_CLR(DB_EXCL | DB_TRUNCATE);
00271 }
00272
00273 ret = CDB___db_dbopen(dbp, name, flags, mode, meta_pgno);
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285 if (subdb == NULL && !IS_RECOVERING(dbenv) && !LF_ISSET(DB_RDONLY) &&
00286 !LF_ISSET(DB_RDWRMASTER) && F_ISSET(dbp, DB_AM_SUBDB)) {
00287 CDB___db_err(dbenv,
00288 "files containing multiple databases may only be opened read-only");
00289 ret = EINVAL;
00290 goto err;
00291 }
00292
00293 err:
00294
00295
00296
00297 if (TXN_ON(dbenv) && LF_ISSET(DB_CREATE))
00298 if ((t_ret = __db_metaend(dbp,
00299 &open_lock, ret == 0, NULL, NULL)) != 0 && ret == 0)
00300 ret = t_ret;
00301
00302
00303 if (ret == 0)
00304 F_CLR(dbp, DB_AM_DISCARD);
00305
00306
00307 if (ret != 0) {
00308
00309 if (IS_RECOVERING(dbenv))
00310 dbp->log_fileid = DB_LOGFILEID_INVALID;
00311 __db_refresh(dbp);
00312 }
00313
00314 if (mdbp != NULL) {
00315
00316 if (ret == 0)
00317 F_CLR(mdbp, DB_AM_DISCARD);
00318 if ((t_ret = mdbp->close(mdbp, 0)) != 0 && ret == 0)
00319 ret = t_ret;
00320 }
00321
00322 return (ret);
00323 }
00324
00325
00326
00327
00328
00329
00330 int
00331 CDB___db_dbopen(dbp, name, flags, mode, meta_pgno)
00332 DB *dbp;
00333 const char *name;
00334 u_int32_t flags;
00335 int mode;
00336 db_pgno_t meta_pgno;
00337 {
00338 DB_ENV *dbenv;
00339 int ret, retinfo;
00340
00341 dbenv = dbp->dbenv;
00342
00343
00344 if ((ret = __db_file_setup(dbp,
00345 name, flags, mode, meta_pgno, &retinfo)) != 0)
00346 return (ret);
00347
00348
00349
00350
00351
00352
00353
00354 if (retinfo & DB_FILE_SETUP_CREATE)
00355 flags |= DB_TRUNCATE;
00356
00357
00358 if ((ret = CDB___db_dbenv_setup(dbp, name, flags)) != 0)
00359 return (ret);
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369 F_SET(dbp, DB_OPEN_CALLED);
00370
00371 if (retinfo & DB_FILE_SETUP_ZERO)
00372 return (0);
00373
00374 switch (dbp->type) {
00375 case DB_BTREE:
00376 ret = CDB___bam_open(dbp, name, meta_pgno, flags);
00377 break;
00378 case DB_HASH:
00379 ret = CDB___ham_open(dbp, name, meta_pgno, flags);
00380 break;
00381 case DB_RECNO:
00382 ret = CDB___ram_open(dbp, name, meta_pgno, flags);
00383 break;
00384 case DB_QUEUE:
00385 ret = CDB___qam_open(dbp, name, meta_pgno, flags);
00386 break;
00387 case DB_UNKNOWN:
00388 return (CDB___db_unknown_type(dbp->dbenv,
00389 "CDB___db_dbopen", dbp->type));
00390 break;
00391 }
00392 return (ret);
00393 }
00394
00395
00396
00397
00398
00399
00400
00401
00402 int
00403 CDB___db_master_open(subdbp, name, flags, mode, dbpp)
00404 DB *subdbp;
00405 const char *name;
00406 u_int32_t flags;
00407 int mode;
00408 DB **dbpp;
00409 {
00410 DB *dbp;
00411 int ret;
00412
00413
00414 if ((ret = CDB_db_create(&dbp, subdbp->dbenv, 0)) != 0)
00415 return (ret);
00416
00417
00418
00419
00420
00421
00422
00423 dbp->type = DB_BTREE;
00424 dbp->open_txn = subdbp->open_txn;
00425 dbp->pgsize = subdbp->pgsize;
00426 F_SET(dbp, DB_AM_SUBDB);
00427 if (LF_ISSET(DB_COMPRESS)) F_SET(dbp, DB_AM_CMPR);
00428
00429 if ((ret = CDB___db_dbopen(dbp, name, flags, mode, PGNO_BASE_MD)) != 0) {
00430 if (!F_ISSET(dbp, DB_AM_DISCARD))
00431 dbp->close(dbp, 0);
00432 return (ret);
00433 }
00434
00435 *dbpp = dbp;
00436 return (0);
00437 }
00438
00439
00440
00441
00442
00443 static int
00444 __db_master_update(mdbp, subdb, type, meta_pgnop, action, newname, flags)
00445 DB *mdbp;
00446 const char *subdb;
00447 u_int32_t type;
00448 db_pgno_t *meta_pgnop;
00449 mu_action action;
00450 const char *newname;
00451 u_int32_t flags;
00452 {
00453 DB_ENV *dbenv;
00454 DBC *dbc, *ndbc;
00455 DBT key, data, ndata;
00456 PAGE *p;
00457 db_pgno_t t_pgno;
00458 int ret, t_ret;
00459
00460 dbenv = mdbp->dbenv;
00461 dbc = ndbc = NULL;
00462 p = NULL;
00463
00464 memset(&key, 0, sizeof(key));
00465 memset(&data, 0, sizeof(data));
00466
00467
00468 if ((ret = mdbp->cursor(mdbp, mdbp->open_txn, &dbc, 0)) != 0)
00469 goto err;
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480 key.data = (char *)subdb;
00481 key.size = strlen(subdb);
00482
00483 F_SET(&data, DB_DBT_MALLOC);
00484 ret = dbc->c_get(dbc, &key, &data,
00485 DB_SET | (STD_LOCKING(dbc) &&
00486 (action == MU_RENAME || LF_ISSET(DB_CREATE)) ? DB_RMW : 0));
00487
00488
00489
00490
00491
00492
00493 switch (action) {
00494 case MU_REMOVE:
00495
00496
00497
00498
00499
00500
00501 if (ret != 0)
00502 goto err;
00503
00504
00505
00506
00507
00508 if ((ret = dbc->c_del(dbc, 0)) != 0)
00509 goto err;
00510
00511
00512
00513
00514
00515
00516 memcpy(meta_pgnop, data.data, sizeof(db_pgno_t));
00517 DB_NTOHL(meta_pgnop);
00518 if ((ret = CDB_memp_fget(mdbp->mpf, meta_pgnop, 0, &p)) != 0)
00519 goto err;
00520
00521
00522 if ((ret = CDB___db_free(dbc, p)) != 0)
00523 goto err;
00524 p = NULL;
00525 break;
00526 case MU_RENAME:
00527
00528 if (ret != 0)
00529 goto err;
00530
00531
00532
00533
00534
00535
00536
00537
00538 if ((ret = mdbp->cursor(mdbp, mdbp->open_txn, &ndbc, 0)) != 0)
00539 goto err;
00540 DB_ASSERT(newname != NULL);
00541 key.data = (void *) newname;
00542 key.size = strlen(newname);
00543
00544
00545
00546
00547
00548 memset(&ndata, 0, sizeof(ndata));
00549 F_SET(&ndata, DB_DBT_USERMEM | DB_DBT_PARTIAL);
00550
00551 if ((ret = ndbc->c_get(ndbc, &key, &ndata, DB_SET)) == 0) {
00552
00553 ret = EEXIST;
00554 CDB___db_err(dbenv, "rename: database %s exists", newname);
00555 goto err;
00556 } else if (ret != DB_NOTFOUND)
00557 goto err;
00558
00559
00560
00561
00562
00563
00564 if ((ret = ndbc->c_put(ndbc, &key, &data, DB_KEYFIRST)) != 0)
00565 goto err;
00566 if ((ret = dbc->c_del(dbc, 0)) != 0) {
00567
00568
00569
00570
00571 (void)ndbc->c_del(ndbc, 0);
00572 goto err;
00573 }
00574
00575 break;
00576 case MU_OPEN:
00577
00578
00579
00580
00581 switch (ret) {
00582 case 0:
00583 memcpy(meta_pgnop, data.data, sizeof(db_pgno_t));
00584 DB_NTOHL(meta_pgnop);
00585 goto done;
00586 case DB_NOTFOUND:
00587 if (LF_ISSET(DB_CREATE))
00588 break;
00589
00590
00591
00592
00593 ret = ENOENT;
00594 goto err;
00595 default:
00596 goto err;
00597 }
00598
00599 if ((ret = CDB___db_new(dbc,
00600 type == DB_HASH ? P_HASHMETA : P_BTREEMETA, &p)) != 0)
00601 goto err;
00602 *meta_pgnop = PGNO(p);
00603
00604
00605
00606
00607
00608
00609
00610 t_pgno = PGNO(p);
00611 DB_HTONL(&t_pgno);
00612 memset(&ndata, 0, sizeof(ndata));
00613 ndata.data = &t_pgno;
00614 ndata.size = sizeof(db_pgno_t);
00615 if ((ret = dbc->c_put(dbc, &key, &ndata, DB_KEYLAST)) != 0)
00616 goto err;
00617 break;
00618 }
00619
00620 err:
00621 done:
00622
00623
00624
00625 if (p != NULL) {
00626 if (ret == 0) {
00627 if ((t_ret =
00628 CDB_memp_fput(mdbp->mpf, p, DB_MPOOL_DIRTY)) != 0)
00629 ret = t_ret;
00630
00631
00632
00633
00634
00635
00636 if ((t_ret = mdbp->sync(mdbp, 0)) != 0 && ret == 0)
00637 ret = t_ret;
00638 } else
00639 (void)CDB___db_free(dbc, p);
00640 }
00641
00642
00643 if (data.data != NULL)
00644 CDB___os_free(data.data, data.size);
00645 if (dbc != NULL && (t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
00646 ret = t_ret;
00647 if (ndbc != NULL && (t_ret = ndbc->c_close(ndbc)) != 0 && ret == 0)
00648 ret = t_ret;
00649
00650 return (ret);
00651 }
00652
00653
00654
00655
00656
00657
00658
00659 int
00660 CDB___db_dbenv_setup(dbp, name, flags)
00661 DB *dbp;
00662 const char *name;
00663 u_int32_t flags;
00664 {
00665 DB_ENV *dbenv;
00666 DBT pgcookie;
00667 DB_MPOOL_FINFO finfo;
00668 DB_PGINFO pginfo;
00669 int ret;
00670
00671 dbenv = dbp->dbenv;
00672
00673
00674 if (!F_ISSET(dbenv, DB_ENV_OPEN_CALLED)) {
00675
00676 if (dbenv->mp_gbytes == 0 &&
00677 dbenv->mp_bytes < dbp->pgsize * DB_MINPAGECACHE &&
00678 (ret = dbenv->set_cachesize(
00679 dbenv, 0, dbp->pgsize * DB_MINPAGECACHE, 0)) != 0)
00680 return (ret);
00681
00682 if ((ret = dbenv->open(dbenv, NULL, DB_CREATE |
00683 DB_INIT_MPOOL | DB_PRIVATE | LF_ISSET(DB_THREAD), 0)) != 0)
00684 return (ret);
00685 }
00686
00687
00688 if ((ret =
00689 CDB_memp_register(dbenv, DB_FTYPE_SET, CDB___db_pgin, CDB___db_pgout)) != 0)
00690 return (ret);
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702 memset(&finfo, 0, sizeof(finfo));
00703 switch (dbp->type) {
00704 case DB_BTREE:
00705 case DB_RECNO:
00706 finfo.ftype =
00707 F_ISSET(dbp, DB_AM_SWAP) ? DB_FTYPE_SET : DB_FTYPE_NOTSET;
00708 finfo.clear_len = DB_PAGE_DB_LEN;
00709 break;
00710 case DB_HASH:
00711 finfo.ftype = DB_FTYPE_SET;
00712 finfo.clear_len = DB_PAGE_DB_LEN;
00713 break;
00714 case DB_QUEUE:
00715 finfo.ftype =
00716 F_ISSET(dbp, DB_AM_SWAP) ? DB_FTYPE_SET : DB_FTYPE_NOTSET;
00717 finfo.clear_len = DB_PAGE_QUEUE_LEN;
00718 break;
00719 case DB_UNKNOWN:
00720 return (CDB___db_unknown_type(dbp->dbenv,
00721 "CDB___db_dbenv_setup", dbp->type));
00722 }
00723 finfo.pgcookie = &pgcookie;
00724 finfo.fileid = dbp->fileid;
00725 finfo.lsn_offset = 0;
00726
00727 pginfo.db_pagesize = dbp->pgsize;
00728 pginfo.needswap = F_ISSET(dbp, DB_AM_SWAP);
00729 pgcookie.data = &pginfo;
00730 pgcookie.size = sizeof(DB_PGINFO);
00731
00732 if ((ret = CDB_memp_fopen(dbenv, name,
00733 LF_ISSET(DB_RDONLY | DB_NOMMAP | DB_ODDFILESIZE | DB_TRUNCATE | DB_COMPRESS),
00734 0, dbp->pgsize, &finfo, &dbp->mpf)) != 0)
00735 return (ret);
00736
00737
00738
00739
00740
00741 if (LF_ISSET(DB_THREAD)) {
00742 if ((ret = CDB___db_mutex_alloc(
00743 dbenv, dbenv->reginfo, (MUTEX **)&dbp->mutexp)) != 0)
00744 return (ret);
00745 if ((ret = __db_mutex_init(
00746 dbenv, dbp->mutexp, 0, MUTEX_THREAD)) != 0)
00747 return (ret);
00748 }
00749
00750
00751 if (LOGGING_ON(dbenv) && !IS_RECOVERING(dbenv) &&
00752 #if !defined(DEBUG_ROP)
00753 !F_ISSET(dbp, DB_AM_RDONLY) &&
00754 #endif
00755 (ret = CDB_log_register(dbenv, dbp, name)) != 0)
00756 return (ret);
00757
00758 return (0);
00759 }
00760
00761
00762
00763
00764
00765
00766 static int
00767 __db_file_setup(dbp, name, flags, mode, meta_pgno, retflags)
00768 DB *dbp;
00769 const char *name;
00770 u_int32_t flags;
00771 int mode;
00772 db_pgno_t meta_pgno;
00773 int *retflags;
00774 {
00775 DB *mdb;
00776 DBT namedbt;
00777 DB_ENV *dbenv;
00778 DB_FH *fhp, fh;
00779 DB_LSN lsn;
00780 DB_TXN *txn;
00781 size_t nr;
00782 u_int32_t magic, oflags;
00783 int ret, retry_cnt, t_ret;
00784 char *real_name, mbuf[DBMETASIZE];
00785 size_t disk_pagesize;
00786
00787 #define IS_SUBDB_SETUP (meta_pgno != PGNO_BASE_MD)
00788
00789 dbenv = dbp->dbenv;
00790 dbp->meta_pgno = meta_pgno;
00791 txn = NULL;
00792 *retflags = 0;
00793
00794
00795
00796
00797
00798
00799 if (LF_ISSET(DB_FCNTL_LOCKING)) {
00800 if ((ret = CDB___os_malloc(dbenv, sizeof(*fhp), NULL, &fhp)) != 0)
00801 return (ret);
00802 } else
00803 fhp = &fh;
00804 memset(fhp, 0, sizeof(*fhp));
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840 if (name == NULL) {
00841 F_SET(dbp, DB_AM_INMEM);
00842
00843 if (dbp->type == DB_UNKNOWN) {
00844 CDB___db_err(dbenv,
00845 "DBTYPE of unknown without existing file");
00846 return (EINVAL);
00847 }
00848 real_name = NULL;
00849
00850
00851 if (dbp->pgsize == 0)
00852 dbp->pgsize = DB_DEF_IOSIZE;
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869 if (LOCKING_ON(dbenv) &&
00870 (ret = CDB_lock_id(dbenv, (u_int32_t *)dbp->fileid)) != 0)
00871 return (ret);
00872
00873 return (0);
00874 }
00875
00876
00877 if ((ret = CDB___db_appname(dbenv,
00878 DB_APP_DATA, NULL, name, 0, NULL, &real_name)) != 0)
00879 return (ret);
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892 if (mode == 0)
00893 mode = CDB___db_omode("rwrw--");
00894
00895 oflags = 0;
00896 if (LF_ISSET(DB_RDONLY))
00897 oflags |= DB_OSO_RDONLY;
00898 if (LF_ISSET(DB_TRUNCATE))
00899 oflags |= DB_OSO_TRUNC;
00900
00901 retry_cnt = 0;
00902 open_retry:
00903 *retflags = 0;
00904 ret = 0;
00905 if (!IS_SUBDB_SETUP && LF_ISSET(DB_CREATE)) {
00906 if (dbp->open_txn != NULL) {
00907
00908
00909
00910
00911 if ((ret =
00912 CDB_txn_begin(dbenv, dbp->open_txn, &txn, 0)) != 0)
00913 goto err_msg;
00914
00915 memset(&namedbt, 0, sizeof(namedbt));
00916 namedbt.data = (char *)name;
00917 namedbt.size = strlen(name) + 1;
00918 if ((ret = CDB___crdel_fileopen_log(dbenv, txn,
00919 &lsn, DB_FLUSH, &namedbt, mode)) != 0)
00920 goto err_msg;
00921 }
00922 DB_TEST_RECOVERY(dbp, DB_TEST_PREOPEN, ret, name);
00923 if ((ret = CDB___os_open(dbenv, real_name,
00924 oflags | DB_OSO_CREATE | DB_OSO_EXCL, mode, fhp)) == 0) {
00925 DB_TEST_RECOVERY(dbp, DB_TEST_POSTOPEN, ret, name);
00926
00927
00928 if (dbp->open_txn != NULL) {
00929 if ((ret = CDB_txn_commit(txn, DB_TXN_SYNC)) != 0)
00930 goto err_msg;
00931 txn = NULL;
00932 }
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942 F_SET(dbp, DB_AM_DISCARD);
00943 *retflags |= DB_FILE_SETUP_CREATE;
00944 } else {
00945
00946
00947
00948
00949
00950 if (dbp->open_txn != NULL) {
00951 if ((t_ret = CDB_txn_abort(txn)) != 0) {
00952 ret = t_ret;
00953 goto err_msg;
00954 }
00955 txn = NULL;
00956 }
00957
00958
00959
00960
00961
00962 if (ret == EEXIST && !LF_ISSET(DB_EXCL)) {
00963 LF_CLR(DB_CREATE);
00964 DB_TEST_RECOVERY(dbp,
00965 DB_TEST_POSTOPEN, ret, name);
00966 goto open_retry;
00967 }
00968 }
00969 } else
00970 ret = CDB___os_open(dbenv, real_name, oflags, mode, fhp);
00971
00972
00973
00974
00975
00976
00977
00978 if (ret != 0) {
00979 if (ret == EACCES || ret == ENOENT)
00980 goto err;
00981 goto err_msg;
00982 }
00983
00984
00985 if (dbp->pgsize == 0) {
00986 if (IS_SUBDB_SETUP) {
00987 if ((ret = CDB___db_master_open(dbp,
00988 name, flags, mode, &mdb)) != 0)
00989 goto err;
00990 dbp->pgsize = mdb->pgsize;
00991 (void) mdb->close(mdb, 0);
00992 } else if ((ret = __db_set_pgsize(dbp, fhp, real_name)) != 0)
00993 goto err;
00994 }
00995
00996 disk_pagesize = F_ISSET(dbp, DB_AM_CMPR) ? DB_CMPR_DIVIDE(dbenv, dbp->pgsize) : dbp->pgsize;
00997 if(meta_pgno == PGNO_BASE_MD || !F_ISSET(dbp, DB_AM_CMPR)) {
00998
00999
01000
01001
01002
01003 if ((ret = CDB___os_seek(dbenv, fhp,
01004 disk_pagesize, meta_pgno, 0, 0, DB_OS_SEEK_SET)) != 0)
01005 goto err_msg;
01006
01007
01008
01009
01010
01011
01012 if ((ret = CDB___os_read(dbenv, fhp, mbuf, sizeof(mbuf), &nr)) != 0)
01013 goto err_msg;
01014 } else {
01015 if ((ret = CDB___os_seek(dbenv, fhp, disk_pagesize,
01016 meta_pgno, 0, 0, DB_OS_SEEK_SET)) != 0)
01017 goto err_msg;
01018 if ((ret = CDB___memp_cmpr_read_meta(dbenv, fhp, mbuf, sizeof(mbuf), &nr)) != 0)
01019 goto err_msg;
01020 }
01021
01022 if (nr == sizeof(mbuf)) {
01023
01024
01025
01026
01027
01028
01029
01030
01031 F_CLR(dbp, DB_AM_SWAP);
01032 magic = ((DBMETA *)mbuf)->magic;
01033
01034 swap_retry: switch (magic) {
01035 case DB_BTREEMAGIC:
01036 if ((ret =
01037 CDB___bam_metachk(dbp, name, (BTMETA *)mbuf)) != 0)
01038 goto err;
01039 break;
01040 case DB_HASHMAGIC:
01041 if ((ret =
01042 CDB___ham_metachk(dbp, name, (HMETA *)mbuf)) != 0)
01043 goto err;
01044 break;
01045 case DB_QAMMAGIC:
01046 if ((ret =
01047 CDB___qam_metachk(dbp, name, (QMETA *)mbuf)) != 0)
01048 goto err;
01049 break;
01050 case 0:
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065 if (IS_SUBDB_SETUP) {
01066 if ((IS_RECOVERING(dbenv)
01067 && F_ISSET((DB_LOG *)
01068 dbenv->lg_handle, DBLOG_FORCE_OPEN))
01069 || ((DBMETA *)mbuf)->pgno != PGNO_INVALID)
01070 goto empty;
01071
01072 ret = EINVAL;
01073 goto err;
01074 }
01075
01076 if (IS_RECOVERING(dbenv)) {
01077 *retflags |= DB_FILE_SETUP_ZERO;
01078 goto empty;
01079 }
01080 goto bad_format;
01081 default:
01082 if (F_ISSET(dbp, DB_AM_SWAP))
01083 goto bad_format;
01084
01085 M_32_SWAP(magic);
01086 F_SET(dbp, DB_AM_SWAP);
01087 goto swap_retry;
01088 }
01089 } else {
01090
01091
01092
01093
01094 if (nr != 0 || (!IS_RECOVERING(dbenv) && IS_SUBDB_SETUP))
01095 goto bad_format;
01096
01097
01098 if (!LF_ISSET(DB_CREATE | DB_TRUNCATE))
01099 *retflags = DB_FILE_SETUP_ZERO;
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116 if (!LF_ISSET(DB_CREATE | DB_TRUNCATE) &&
01117 !IS_RECOVERING(dbenv)) {
01118 if (retry_cnt++ < 3) {
01119 CDB___os_sleep(dbenv, 1, 0);
01120 goto open_retry;
01121 }
01122 bad_format: CDB___db_err(dbenv,
01123 "%s: unexpected file type or format", name);
01124 ret = EINVAL;
01125 goto err;
01126 }
01127
01128 DB_ASSERT (dbp->type != DB_UNKNOWN);
01129
01130 empty:
01131
01132
01133
01134
01135
01136
01137 if (!IS_SUBDB_SETUP) {
01138 if (*retflags & DB_FILE_SETUP_ZERO)
01139 memset(dbp->fileid, 0, DB_FILE_ID_LEN);
01140 else {
01141 if ((ret = CDB___os_fileid(dbenv,
01142 real_name, 1, dbp->fileid)) != 0)
01143 goto err_msg;
01144 CDB___memp_cmpr_create(dbenv, fhp, disk_pagesize, F_ISSET(dbp, DB_AM_CMPR) ? MP_CMPR : 0);
01145 }
01146 }
01147 }
01148
01149 if (0) {
01150 err_msg: CDB___db_err(dbenv, "%s: %s", name, CDB_db_strerror(ret));
01151 }
01152
01153
01154
01155
01156
01157 err: if (txn != NULL)
01158 (void)CDB_txn_abort(txn);
01159
01160 DB_TEST_RECOVERY_LABEL
01161
01162
01163
01164
01165
01166 if (F_ISSET(fhp, DB_FH_VALID)) {
01167 if (ret == 0 && LF_ISSET(DB_FCNTL_LOCKING))
01168 dbp->saved_open_fhp = fhp;
01169 else
01170 if ((t_ret = CDB___os_closehandle(fhp)) != 0 && ret == 0)
01171 ret = t_ret;
01172 }
01173
01174 if (real_name != NULL)
01175 CDB___os_freestr(real_name);
01176
01177 return (ret);
01178 }
01179
01180
01181
01182
01183
01184 static int
01185 __db_set_pgsize(dbp, fhp, name)
01186 DB *dbp;
01187 DB_FH *fhp;
01188 char *name;
01189 {
01190 DB_ENV *dbenv;
01191 u_int32_t iopsize;
01192 int ret;
01193
01194 dbenv = dbp->dbenv;
01195
01196
01197
01198
01199
01200
01201
01202 if ((ret = CDB___os_ioinfo(dbenv, name, fhp, NULL, NULL, &iopsize)) != 0) {
01203 CDB___db_err(dbenv, "%s: %s", name, CDB_db_strerror(ret));
01204 return (ret);
01205 }
01206 if (iopsize < 512)
01207 iopsize = 512;
01208 if (iopsize > 16 * 1024)
01209 iopsize = 16 * 1024;
01210
01211
01212
01213
01214
01215 if(F_ISSET(dbp, DB_AM_CMPR)) {
01216 if(iopsize < DB_CMPR_MULTIPLY(dbenv, DB_MIN_PGSIZE))
01217 iopsize = DB_CMPR_MULTIPLY(dbenv, DB_MIN_PGSIZE);
01218 }
01219
01220
01221
01222
01223
01224
01225 OS_ROUNDOFF(iopsize, 512);
01226
01227 dbp->pgsize = iopsize;
01228 F_SET(dbp, DB_AM_PGDEF);
01229
01230 return (0);
01231 }
01232
01233
01234
01235
01236
01237
01238
01239 int
01240 CDB___db_close(dbp, flags)
01241 DB *dbp;
01242 u_int32_t flags;
01243 {
01244 DB_ENV *dbenv;
01245 DBC *dbc;
01246 int ret, t_ret;
01247
01248 ret = 0;
01249
01250 PANIC_CHECK(dbp->dbenv);
01251
01252
01253 if ((ret = CDB___db_closechk(dbp, flags)) != 0)
01254 return (ret);
01255
01256
01257 if (!F_ISSET(dbp, DB_OPEN_CALLED))
01258 goto never_opened;
01259
01260
01261 if (!LF_ISSET(DB_NOSYNC) && !F_ISSET(dbp, DB_AM_DISCARD) &&
01262 (t_ret = dbp->sync(dbp, 0)) != 0 && ret == 0)
01263 ret = t_ret;
01264
01265
01266
01267
01268
01269
01270
01271 while ((dbc = TAILQ_FIRST(&dbp->active_queue)) != NULL)
01272 if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
01273 ret = t_ret;
01274 while ((dbc = TAILQ_FIRST(&dbp->free_queue)) != NULL)
01275 if ((t_ret = CDB___db_c_destroy(dbc)) != 0 && ret == 0)
01276 ret = t_ret;
01277
01278
01279
01280
01281
01282 while ((dbc = TAILQ_FIRST(&dbp->join_queue)) != NULL)
01283 if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
01284 ret = t_ret;
01285
01286
01287 if (!LF_ISSET(DB_NOSYNC) && !F_ISSET(dbp, DB_AM_DISCARD) &&
01288 (t_ret = CDB_memp_fsync(dbp->mpf)) != 0 &&
01289 t_ret != DB_INCOMPLETE && ret == 0)
01290 ret = t_ret;
01291
01292
01293 if (dbp->saved_open_fhp != NULL &&
01294 F_ISSET(dbp->saved_open_fhp, DB_FH_VALID) &&
01295 (t_ret = CDB___os_closehandle(dbp->saved_open_fhp)) != 0 && ret == 0)
01296 ret = t_ret;
01297
01298 never_opened:
01299
01300
01301
01302
01303
01304
01305
01306
01307 if ((t_ret = CDB___ham_db_close(dbp)) != 0 && ret == 0)
01308 ret = t_ret;
01309 if ((t_ret = CDB___bam_db_close(dbp)) != 0 && ret == 0)
01310 ret = t_ret;
01311 if ((t_ret = CDB___qam_db_close(dbp)) != 0 && ret == 0)
01312 ret = t_ret;
01313
01314
01315 dbenv = dbp->dbenv;
01316 if ((t_ret = __db_refresh(dbp)) != 0 && ret == 0)
01317 ret = t_ret;
01318 if (F_ISSET(dbenv, DB_ENV_DBLOCAL) &&
01319 --dbenv->dblocal_ref == 0 &&
01320 (t_ret = dbenv->close(dbenv, 0)) != 0 && ret == 0)
01321 ret = t_ret;
01322
01323 memset(dbp, CLEAR_BYTE, sizeof(*dbp));
01324 CDB___os_free(dbp, sizeof(*dbp));
01325
01326 return (ret);
01327 }
01328
01329
01330
01331
01332
01333 static int
01334 __db_refresh(dbp)
01335 DB *dbp;
01336 {
01337 DB_ENV *dbenv;
01338 DBC *dbc;
01339 int ret, t_ret;
01340
01341 ret = 0;
01342
01343 dbenv = dbp->dbenv;
01344
01345
01346
01347
01348
01349
01350
01351 while ((dbc = TAILQ_FIRST(&dbp->active_queue)) != NULL)
01352 if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
01353 ret = t_ret;
01354 while ((dbc = TAILQ_FIRST(&dbp->free_queue)) != NULL)
01355 if ((t_ret = CDB___db_c_destroy(dbc)) != 0 && ret == 0)
01356 ret = t_ret;
01357
01358 dbp->type = 0;
01359
01360
01361 if (dbp->mpf != NULL) {
01362 if (F_ISSET(dbp, DB_AM_DISCARD))
01363 (void)CDB___memp_fremove(dbp->mpf);
01364 if ((t_ret = CDB_memp_fclose(dbp->mpf)) != 0 && ret == 0)
01365 ret = t_ret;
01366 dbp->mpf = NULL;
01367 }
01368
01369
01370 if (dbp->mutexp != NULL) {
01371 CDB___db_mutex_free(dbenv, dbenv->reginfo, dbp->mutexp);
01372 dbp->mutexp = NULL;
01373 }
01374
01375
01376 if (!IS_RECOVERING(dbenv)
01377 && dbp->log_fileid != DB_LOGFILEID_INVALID)
01378 (void)CDB_log_unregister(dbenv, dbp);
01379
01380 TAILQ_INIT(&dbp->free_queue);
01381 TAILQ_INIT(&dbp->active_queue);
01382 TAILQ_INIT(&dbp->join_queue);
01383
01384 F_CLR(dbp, DB_AM_DISCARD);
01385 F_CLR(dbp, DB_AM_INMEM);
01386 F_CLR(dbp, DB_AM_RDONLY);
01387 F_CLR(dbp, DB_AM_SWAP);
01388 F_CLR(dbp, DB_DBM_ERROR);
01389 F_CLR(dbp, DB_OPEN_CALLED);
01390
01391 return (ret);
01392 }
01393
01394
01395
01396
01397
01398
01399
01400 int
01401 CDB___db_remove(dbp, name, subdb, flags)
01402 DB *dbp;
01403 const char *name, *subdb;
01404 u_int32_t flags;
01405 {
01406 DBT namedbt;
01407 DB_ENV *dbenv;
01408 DB_LOCK remove_lock;
01409 DB_LSN newlsn;
01410 int ret, t_ret;
01411 char *backup, *real_back, *real_name;
01412
01413 dbenv = dbp->dbenv;
01414 ret = 0;
01415 backup = real_back = real_name = NULL;
01416
01417 PANIC_CHECK(dbenv);
01418 DB_ILLEGAL_AFTER_OPEN(dbp, "remove");
01419
01420
01421 if ((ret = CDB___db_removechk(dbp, flags)) != 0)
01422 return (ret);
01423
01424
01425
01426
01427 if (subdb != NULL) {
01428
01429 if (name == NULL) {
01430 CDB___db_err(dbenv,
01431 "multiple databases cannot be created in temporary files");
01432 return (EINVAL);
01433 }
01434 return (__db_subdb_remove(dbp, name, subdb));
01435 }
01436
01437 if ((ret = dbp->open(dbp,
01438 name, NULL, DB_UNKNOWN, DB_RDWRMASTER, 0)) != 0)
01439 return (ret);
01440
01441 if (LOGGING_ON(dbenv) && (ret = CDB___log_file_lock(dbp)) != 0)
01442 goto err_close;
01443
01444 if ((ret = dbp->sync(dbp, 0)) != 0)
01445 goto err_close;
01446
01447
01448
01449
01450
01451
01452 (void)CDB___memp_fremove(dbp->mpf);
01453 if ((ret = CDB_memp_fclose(dbp->mpf)) != 0)
01454 goto err_close;
01455 dbp->mpf = NULL;
01456
01457
01458 if (TXN_ON(dbenv) && (ret = __db_metabegin(dbp, &remove_lock)) != 0)
01459 goto err_close;
01460
01461 if (LOGGING_ON(dbenv)) {
01462 memset(&namedbt, 0, sizeof(namedbt));
01463 namedbt.data = (char *)name;
01464 namedbt.size = strlen(name) + 1;
01465
01466 if ((ret = CDB___crdel_delete_log(dbenv,
01467 dbp->open_txn, &newlsn, DB_FLUSH,
01468 dbp->log_fileid, &namedbt)) != 0) {
01469 CDB___db_err(dbenv,
01470 "%s: %s", name, CDB_db_strerror(ret));
01471 goto err;
01472 }
01473 }
01474
01475
01476 if ((ret = CDB___db_appname(dbenv,
01477 DB_APP_DATA, NULL, name, 0, NULL, &real_name)) != 0)
01478 goto err;
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492 if (TXN_ON(dbenv)) {
01493 if ((ret =
01494 CDB___db_backup_name(dbenv, name, &backup, &newlsn)) != 0)
01495 goto err;
01496 if ((ret = CDB___db_appname(dbenv,
01497 DB_APP_DATA, NULL, backup, 0, NULL, &real_back)) != 0)
01498 goto err;
01499 }
01500
01501 DB_TEST_RECOVERY(dbp, DB_TEST_PRERENAME, ret, name);
01502 if (TXN_ON(dbenv))
01503 ret = CDB___os_rename(dbenv, real_name, real_back);
01504 else
01505 ret = CDB___os_unlink(dbenv, real_name);
01506 DB_TEST_RECOVERY(dbp, DB_TEST_POSTRENAME, ret, name);
01507
01508 err:
01509 DB_TEST_RECOVERY_LABEL
01510
01511
01512
01513
01514 if (dbp->open_txn != NULL && (t_ret = __db_metaend(dbp, &remove_lock,
01515 ret == 0, __db_remove_callback, real_back)) != 0 && ret == 0)
01516 ret = t_ret;
01517
01518
01519
01520 err_close:
01521 if (real_name != NULL)
01522 CDB___os_freestr(real_name);
01523 if (backup != NULL)
01524 CDB___os_freestr(backup);
01525
01526
01527 if ((t_ret = dbp->close(dbp, DB_NOSYNC)) != 0 && ret == 0)
01528 ret = t_ret;
01529
01530 return (ret);
01531 }
01532
01533
01534
01535
01536
01537 static int
01538 __db_subdb_remove(dbp, name, subdb)
01539 DB *dbp;
01540 const char *name, *subdb;
01541 {
01542 DB *mdbp;
01543 DBC *dbc;
01544 DB_ENV *dbenv;
01545 DB_LOCK remove_lock;
01546 db_pgno_t meta_pgno;
01547 int ret, t_ret;
01548
01549 mdbp = NULL;
01550 dbc = NULL;
01551 dbenv = dbp->dbenv;
01552
01553
01554 if (TXN_ON(dbenv) && (ret = __db_metabegin(dbp, &remove_lock)) != 0)
01555 return (ret);
01556
01557
01558
01559
01560
01561 if ((ret = CDB___db_open(dbp, name, subdb, DB_UNKNOWN, ((dbenv->flags & DB_ENV_CMPR) ? DB_COMPRESS : 0), 0)) != 0)
01562 goto err;
01563
01564
01565 switch (dbp->type) {
01566 case DB_BTREE:
01567 case DB_RECNO:
01568 if ((ret = CDB___bam_reclaim(dbp, dbp->open_txn)) != 0)
01569 goto err;
01570 break;
01571 case DB_HASH:
01572 if ((ret = CDB___ham_reclaim(dbp, dbp->open_txn)) != 0)
01573 goto err;
01574 break;
01575 default:
01576 ret = CDB___db_unknown_type(dbp->dbenv,
01577 "__db_subdb_remove", dbp->type);
01578 goto err;
01579 }
01580
01581
01582
01583
01584
01585 if ((ret = CDB___db_master_open(dbp, name, ((dbenv->flags & DB_ENV_CMPR) ? DB_COMPRESS : 0), 0, &mdbp)) != 0)
01586 goto err;
01587
01588 if ((ret = __db_master_update(mdbp,
01589 subdb, dbp->type, &meta_pgno, MU_REMOVE, NULL, 0)) != 0)
01590 goto err;
01591
01592 err:
01593
01594
01595
01596 if (dbp->open_txn != NULL && (t_ret = __db_metaend(dbp,
01597 &remove_lock, ret == 0, NULL, NULL)) != 0 && ret == 0)
01598 ret = t_ret;
01599
01600
01601
01602
01603
01604 if ((t_ret = dbp->close(dbp, 0)) != 0 && ret == 0)
01605 ret = t_ret;
01606
01607 if (mdbp != NULL && (t_ret = mdbp->close(mdbp, 0)) != 0 && ret == 0)
01608 ret = t_ret;
01609
01610 return (ret);
01611 }
01612
01613
01614
01615
01616
01617
01618
01619
01620 int
01621 CDB___db_rename(dbp, filename, subdb, newname, flags)
01622 DB *dbp;
01623 const char *filename, *subdb, *newname;
01624 u_int32_t flags;
01625 {
01626 DBT namedbt, newnamedbt;
01627 DB_ENV *dbenv;
01628 DB_LOCK remove_lock;
01629 DB_LSN newlsn;
01630 char *real_name, *real_newname;
01631 int ret, t_ret;
01632
01633 dbenv = dbp->dbenv;
01634 ret = 0;
01635 real_name = real_newname = NULL;
01636
01637 PANIC_CHECK(dbenv);
01638 DB_ILLEGAL_AFTER_OPEN(dbp, "rename");
01639
01640
01641 if ((ret = CDB___db_removechk(dbp, flags)) != 0)
01642 return (ret);
01643
01644
01645
01646
01647 if (subdb != NULL) {
01648 if (filename == NULL) {
01649 CDB___db_err(dbenv,
01650 "multiple databases cannot be created in temporary files");
01651 return (EINVAL);
01652 }
01653 return (__db_subdb_rename(dbp, filename, subdb, newname));
01654 }
01655
01656 if ((ret = dbp->open(dbp,
01657 filename, NULL, DB_UNKNOWN, DB_RDWRMASTER, 0)) != 0)
01658 return (ret);
01659
01660 if (LOGGING_ON(dbenv) && (ret = CDB___log_file_lock(dbp)) != 0)
01661 goto err_close;
01662
01663 if ((ret = dbp->sync(dbp, 0)) != 0)
01664 goto err_close;
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675 if ((ret = CDB___memp_fremove(dbp->mpf)) != 0)
01676 goto err_close;
01677
01678
01679
01680
01681
01682
01683 if ((ret = CDB_memp_fclose(dbp->mpf)) != 0)
01684 goto err_close;
01685 dbp->mpf = NULL;
01686
01687
01688 if (TXN_ON(dbenv) && (ret = __db_metabegin(dbp, &remove_lock)) != 0)
01689 goto err_close;
01690
01691 if (LOGGING_ON(dbenv)) {
01692 memset(&namedbt, 0, sizeof(namedbt));
01693 namedbt.data = (char *)filename;
01694 namedbt.size = strlen(filename) + 1;
01695
01696 memset(&newnamedbt, 0, sizeof(namedbt));
01697 newnamedbt.data = (char *)newname;
01698 newnamedbt.size = strlen(newname) + 1;
01699
01700 if ((ret = CDB___crdel_rename_log(dbenv, dbp->open_txn,
01701 &newlsn, 0, dbp->log_fileid, &namedbt, &newnamedbt)) != 0) {
01702 CDB___db_err(dbenv, "%s: %s", filename, CDB_db_strerror(ret));
01703 goto err;
01704 }
01705
01706 if ((ret = CDB___log_filelist_update(dbenv, dbp,
01707 dbp->log_fileid, newname, NULL)) != 0)
01708 goto err;
01709 }
01710
01711
01712 if ((ret = CDB___db_appname(dbenv,
01713 DB_APP_DATA, NULL, filename, 0, NULL, &real_name)) != 0)
01714 goto err;
01715
01716
01717 if ((ret = CDB___db_appname(dbenv,
01718 DB_APP_DATA, NULL, newname, 0, NULL, &real_newname)) != 0)
01719 goto err;
01720
01721
01722
01723
01724
01725 if (CDB___os_exists(real_newname, NULL) == 0) {
01726 ret = EEXIST;
01727 CDB___db_err(dbenv, "rename: file %s exists", real_newname);
01728 goto err;
01729 }
01730
01731 DB_TEST_RECOVERY(dbp, DB_TEST_PRERENAME, ret, filename);
01732 ret = CDB___os_rename(dbenv, real_name, real_newname);
01733 DB_TEST_RECOVERY(dbp, DB_TEST_POSTRENAME, ret, newname);
01734
01735 DB_TEST_RECOVERY_LABEL
01736 err: if (dbp->open_txn != NULL && (t_ret = __db_metaend(dbp,
01737 &remove_lock, ret == 0, NULL, NULL)) != 0 && ret == 0)
01738 ret = t_ret;
01739
01740 err_close:
01741
01742 dbp->close(dbp, DB_NOSYNC);
01743 if (real_name != NULL)
01744 CDB___os_freestr(real_name);
01745 if (real_newname != NULL)
01746 CDB___os_freestr(real_newname);
01747
01748 return (ret);
01749 }
01750
01751
01752
01753
01754
01755 static int
01756 __db_subdb_rename(dbp, name, subdb, newname)
01757 DB *dbp;
01758 const char *name, *subdb, *newname;
01759 {
01760 DB *mdbp;
01761 DBC *dbc;
01762 DB_ENV *dbenv;
01763 DB_LOCK remove_lock;
01764 int ret, t_ret;
01765
01766 mdbp = NULL;
01767 dbc = NULL;
01768 dbenv = dbp->dbenv;
01769
01770
01771 if (TXN_ON(dbenv) && (ret = __db_metabegin(dbp, &remove_lock)) != 0)
01772 return (ret);
01773
01774
01775
01776
01777
01778 if ((ret = CDB___db_open(dbp, name, subdb, DB_UNKNOWN, 0, 0)) != 0)
01779 goto err;
01780
01781
01782
01783
01784 if ((ret = CDB___db_master_open(dbp, name, 0, 0, &mdbp)) != 0)
01785 goto err;
01786
01787 if ((ret = __db_master_update(mdbp,
01788 subdb, dbp->type, NULL, MU_RENAME, newname, 0)) != 0)
01789 goto err;
01790
01791 err:
01792
01793
01794
01795 if (dbp->open_txn != NULL && (t_ret = __db_metaend(dbp,
01796 &remove_lock, ret == 0, NULL, NULL)) != 0 && ret == 0)
01797 ret = t_ret;
01798
01799
01800
01801
01802
01803 if ((t_ret = dbp->close(dbp, 0)) != 0 && ret == 0)
01804 ret = t_ret;
01805
01806 if (mdbp != NULL && (t_ret = mdbp->close(mdbp, 0)) != 0 && ret == 0)
01807 ret = t_ret;
01808
01809 return (ret);
01810 }
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822
01823 static int
01824 __db_metabegin(dbp, lockp)
01825 DB *dbp;
01826 DB_LOCK *lockp;
01827 {
01828 DB_ENV *dbenv;
01829 DBT dbplock;
01830 u_int32_t locker, lockval;
01831 int ret;
01832
01833 dbenv = dbp->dbenv;
01834
01835 lockp->off = LOCK_INVALID;
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851 if (LOCKING_ON(dbenv)) {
01852 if ((ret = CDB_lock_id(dbenv, &locker)) != 0)
01853 return (ret);
01854 lockval = 0;
01855 dbplock.data = &lockval;
01856 dbplock.size = sizeof(lockval);
01857 if ((ret = CDB_lock_get(dbenv,
01858 locker, 0, &dbplock, DB_LOCK_WRITE, lockp)) != 0)
01859 return(ret);
01860 }
01861
01862 return (CDB_txn_begin(dbenv, NULL, &dbp->open_txn, 0));
01863 }
01864
01865
01866
01867
01868
01869 static int
01870 __db_metaend(dbp, lockp, commit, callback, cookie)
01871 DB *dbp;
01872 DB_LOCK *lockp;
01873 int commit, (*callback) __P((DB *, void *));
01874 void *cookie;
01875 {
01876 DB_ENV *dbenv;
01877 int ret, t_ret;
01878
01879 ret = 0;
01880 dbenv = dbp->dbenv;
01881
01882
01883 if (commit) {
01884 if ((ret = CDB_txn_commit(dbp->open_txn, DB_TXN_SYNC)) == 0) {
01885
01886
01887
01888
01889 if (callback != NULL)
01890 ret = callback(dbp, cookie);
01891 }
01892 } else if ((t_ret = CDB_txn_abort(dbp->open_txn)) && ret == 0)
01893 ret = t_ret;
01894
01895
01896 if (lockp->off != LOCK_INVALID &&
01897 (t_ret = CDB_lock_put(dbenv, lockp)) != 0 && ret == 0)
01898 ret = t_ret;
01899
01900 return (ret);
01901 }
01902
01903
01904
01905
01906
01907
01908
01909
01910 int
01911 CDB___db_log_page(dbp, name, lsn, pgno, page)
01912 DB *dbp;
01913 const char *name;
01914 DB_LSN *lsn;
01915 db_pgno_t pgno;
01916 PAGE *page;
01917 {
01918 DBT name_dbt, page_dbt;
01919 DB_LSN new_lsn;
01920 int ret;
01921
01922 if (dbp->open_txn == NULL)
01923 return (0);
01924
01925 memset(&page_dbt, 0, sizeof(page_dbt));
01926 page_dbt.size = dbp->pgsize;
01927 page_dbt.data = page;
01928 if (pgno == PGNO_BASE_MD) {
01929
01930
01931
01932
01933
01934
01935
01936 memset(&name_dbt, 0, sizeof(name_dbt));
01937 name_dbt.data = (char *)name;
01938 if (name == NULL || *name == '\0')
01939 name_dbt.size = 0;
01940 else
01941 name_dbt.size = strlen(name) + 1;
01942
01943 ret = CDB___crdel_metapage_log(dbp->dbenv,
01944 dbp->open_txn, &new_lsn, DB_FLUSH,
01945 dbp->log_fileid, &name_dbt, pgno, &page_dbt);
01946 } else
01947 ret = CDB___crdel_metasub_log(dbp->dbenv, dbp->open_txn,
01948 &new_lsn, 0, dbp->log_fileid, pgno, &page_dbt, lsn);
01949
01950 if (ret == 0)
01951 page->lsn = new_lsn;
01952 return (ret);
01953 }
01954
01955
01956
01957
01958
01959
01960
01961
01962 #undef BACKUP_PREFIX
01963 #define BACKUP_PREFIX "__db."
01964
01965 #undef MAX_LSN_TO_TEXT
01966 #define MAX_LSN_TO_TEXT 21
01967 int
01968 CDB___db_backup_name(dbenv, name, backup, lsn)
01969 DB_ENV *dbenv;
01970 const char *name;
01971 char **backup;
01972 DB_LSN *lsn;
01973 {
01974 size_t len;
01975 int plen, ret;
01976 char *p, *retp;
01977
01978 len = strlen(name) + strlen(BACKUP_PREFIX) + MAX_LSN_TO_TEXT + 1;
01979
01980 if ((ret = CDB___os_malloc(dbenv, len, NULL, &retp)) != 0)
01981 return (ret);
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994 if ((p = CDB___db_rpath(name)) == NULL)
01995 snprintf(retp, len,
01996 "%s%s.0x%x0x%x", BACKUP_PREFIX, name,
01997 lsn->file, lsn->offset);
01998 else {
01999 plen = p - name + 1;
02000 p++;
02001 snprintf(retp, len,
02002 "%.*s%s%s.0x%x0x%x", plen, name, BACKUP_PREFIX, p,
02003 lsn->file, lsn->offset);
02004 }
02005
02006 *backup = retp;
02007 return (0);
02008 }
02009
02010
02011
02012
02013
02014
02015 static int
02016 __db_remove_callback(dbp, cookie)
02017 DB *dbp;
02018 void *cookie;
02019 {
02020 return (CDB___os_unlink(dbp->dbenv, cookie));
02021 }
02022
02023 #if CONFIG_TEST
02024
02025
02026
02027
02028
02029
02030 int
02031 __db_testcopy(dbp, name)
02032 DB *dbp;
02033 const char *name;
02034 {
02035 size_t len;
02036 int dircnt, i, ret;
02037 char **namesp, *backup, *copy, *dir, *p, *real_name;
02038
02039 real_name = NULL;
02040
02041 if ((ret = CDB___db_appname(dbp->dbenv,
02042 DB_APP_DATA, NULL, name, 0, NULL, &real_name)) != 0)
02043 return (ret);
02044
02045
02046
02047
02048 len = strlen(real_name) + strlen(BACKUP_PREFIX) + MAX_LSN_TO_TEXT + 9;
02049
02050 if ((ret = CDB___os_malloc(dbp->dbenv, len, NULL, ©)) != 0)
02051 goto out;
02052
02053 if ((ret = CDB___os_malloc(dbp->dbenv, len, NULL, &backup)) != 0)
02054 goto out;
02055
02056
02057
02058
02059 snprintf(copy, len, "%s.afterop", real_name);
02060 __db_makecopy(real_name, copy);
02061
02062 if ((ret = CDB___os_strdup(dbp->dbenv, real_name, &dir)) != 0)
02063 goto out;
02064 CDB___os_freestr(real_name);
02065 real_name = NULL;
02066
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076 snprintf(backup, len, "%s%s.0x", BACKUP_PREFIX, name);
02077
02078
02079
02080
02081 p = CDB___db_rpath(dir);
02082 if (p != NULL)
02083 *p = '\0';
02084 ret = CDB___os_dirlist(dbp->dbenv, dir, &namesp, &dircnt);
02085 #if DIAGNOSTIC
02086
02087
02088
02089
02090
02091
02092
02093 *p = '/';
02094 #endif
02095 CDB___os_freestr(dir);
02096 if (ret != 0)
02097 goto out;
02098 for (i = 0; i < dircnt; i++) {
02099
02100
02101
02102
02103
02104
02105
02106
02107 if (strncmp(namesp[i], backup, strlen(backup)) == 0) {
02108 if ((ret = CDB___db_appname(dbp->dbenv, DB_APP_DATA,
02109 NULL, namesp[i], 0, NULL, &real_name)) != 0)
02110 goto out;
02111
02112
02113
02114
02115
02116
02117 if (strstr(real_name, ".afterop") != NULL) {
02118 CDB___os_freestr(real_name);
02119 real_name = NULL;
02120 continue;
02121 }
02122 snprintf(copy, len, "%s.afterop", real_name);
02123 __db_makecopy(real_name, copy);
02124 CDB___os_freestr(real_name);
02125 real_name = NULL;
02126 }
02127 }
02128 out:
02129 if (real_name)
02130 CDB___os_freestr(real_name);
02131 return (ret);
02132 }
02133
02134 static void
02135 __db_makecopy(src, dest)
02136 const char *src, *dest;
02137 {
02138 DB_FH rfh, wfh;
02139 size_t rcnt, wcnt;
02140 char *buf;
02141
02142 memset(&rfh, 0, sizeof(rfh));
02143 memset(&wfh, 0, sizeof(wfh));
02144
02145 if (CDB___os_malloc(NULL, 1024, NULL, &buf) != 0)
02146 return;
02147
02148 if (CDB___os_open(NULL,
02149 src, DB_OSO_RDONLY, CDB___db_omode("rw----"), &rfh) != 0)
02150 goto err;
02151 if (CDB___os_open(NULL, dest,
02152 DB_OSO_CREATE | DB_OSO_TRUNC, CDB___db_omode("rw----"), &wfh) != 0)
02153 goto err;
02154
02155 for (;;)
02156 if (CDB___os_read(NULL, &rfh, buf, 1024, &rcnt) < 0 || rcnt == 0 ||
02157 CDB___os_write(NULL, &wfh, buf, rcnt, &wcnt) < 0 || wcnt != rcnt)
02158 break;
02159
02160 err: CDB___os_free(buf, 1024);
02161 if (F_ISSET(&rfh, DB_FH_VALID))
02162 CDB___os_closehandle(&rfh);
02163 if (F_ISSET(&wfh, DB_FH_VALID))
02164 CDB___os_closehandle(&wfh);
02165 }
02166 #endif