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
00015 #include <string.h>
00016 #endif
00017
00018 #include "db_int.h"
00019 #include "dbinc/db_page.h"
00020 #include "dbinc/fop.h"
00021 #include "dbinc/btree.h"
00022 #include "dbinc/hash.h"
00023 #include "dbinc/db_shash.h"
00024 #include "dbinc/lock.h"
00025 #include "dbinc/mp.h"
00026 #include "dbinc/txn.h"
00027
00028 static int __db_dbtxn_remove __P((DB *, DB_TXN *, const char *, const char *));
00029 static int __db_subdb_remove __P((DB *, DB_TXN *, const char *, const char *));
00030
00031
00032
00033
00034
00035
00036
00037
00038 int
00039 __env_dbremove_pp(dbenv, txn, name, subdb, flags)
00040 DB_ENV *dbenv;
00041 DB_TXN *txn;
00042 const char *name, *subdb;
00043 u_int32_t flags;
00044 {
00045 DB *dbp;
00046 DB_THREAD_INFO *ip;
00047 int handle_check, ret, t_ret, txn_local;
00048
00049 dbp = NULL;
00050 txn_local = 0;
00051
00052 PANIC_CHECK(dbenv);
00053 ENV_ILLEGAL_BEFORE_OPEN(dbenv, "DB_ENV->dbremove");
00054
00055
00056
00057
00058
00059 if ((ret = __db_fchk(dbenv, "DB->remove", flags, DB_AUTO_COMMIT)) != 0)
00060 return (ret);
00061
00062 ENV_ENTER(dbenv, ip);
00063
00064
00065 handle_check = IS_ENV_REPLICATED(dbenv);
00066 if (handle_check && (ret = __env_rep_enter(dbenv, 1)) != 0) {
00067 handle_check = 0;
00068 goto err;
00069 }
00070
00071
00072
00073
00074
00075 if (IS_ENV_AUTO_COMMIT(dbenv, txn, flags)) {
00076 if ((ret = __db_txn_auto_init(dbenv, &txn)) != 0)
00077 goto err;
00078 txn_local = 1;
00079 } else
00080 if (txn != NULL && !TXN_ON(dbenv)) {
00081 ret = __db_not_txn_env(dbenv);
00082 goto err;
00083 }
00084 LF_CLR(DB_AUTO_COMMIT);
00085
00086 if ((ret = db_create(&dbp, dbenv, 0)) != 0)
00087 goto err;
00088
00089 ret = __db_remove_int(dbp, txn, name, subdb, flags);
00090
00091 if (txn_local) {
00092
00093
00094
00095
00096
00097 LOCK_INIT(dbp->handle_lock);
00098 dbp->lid = DB_LOCK_INVALIDID;
00099 } else if (txn != NULL) {
00100
00101
00102
00103
00104
00105
00106
00107 dbp->lid = DB_LOCK_INVALIDID;
00108 }
00109
00110 err: if (txn_local && (t_ret =
00111 __db_txn_auto_resolve(dbenv, txn, 0, ret)) != 0 && ret == 0)
00112 ret = t_ret;
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123 if (dbp != NULL &&
00124 (t_ret = __db_close(dbp, NULL, DB_NOSYNC)) != 0 && ret == 0)
00125 ret = t_ret;
00126
00127 if (handle_check && (t_ret = __env_db_rep_exit(dbenv)) != 0 && ret == 0)
00128 ret = t_ret;
00129
00130 ENV_LEAVE(dbenv, ip);
00131 return (ret);
00132 }
00133
00134
00135
00136
00137
00138
00139
00140
00141 int
00142 __db_remove_pp(dbp, name, subdb, flags)
00143 DB *dbp;
00144 const char *name, *subdb;
00145 u_int32_t flags;
00146 {
00147 DB_ENV *dbenv;
00148 DB_THREAD_INFO *ip;
00149 int handle_check, ret, t_ret;
00150
00151 dbenv = dbp->dbenv;
00152
00153 PANIC_CHECK(dbenv);
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 if (F_ISSET(dbp, DB_AM_OPEN_CALLED)) {
00166 ret = __db_mi_open(dbenv, "DB->remove", 1);
00167 return (ret);
00168 }
00169
00170
00171 if ((ret = __db_fchk(dbenv, "DB->remove", flags, 0)) != 0)
00172 return (ret);
00173
00174
00175 if ((ret = __db_check_txn(dbp, NULL, DB_LOCK_INVALIDID, 0)) != 0)
00176 return (ret);
00177
00178 ENV_ENTER(dbenv, ip);
00179
00180 handle_check = IS_ENV_REPLICATED(dbenv);
00181 if (handle_check && (ret = __db_rep_enter(dbp, 1, 1, 0)) != 0) {
00182 handle_check = 0;
00183 goto err;
00184 }
00185
00186
00187 ret = __db_remove(dbp, NULL, name, subdb, flags);
00188
00189 if (handle_check && (t_ret = __env_db_rep_exit(dbenv)) != 0 && ret == 0)
00190 ret = t_ret;
00191
00192 err: ENV_LEAVE(dbenv, ip);
00193 return (ret);
00194 }
00195
00196
00197
00198
00199
00200
00201
00202
00203 int
00204 __db_remove(dbp, txn, name, subdb, flags)
00205 DB *dbp;
00206 DB_TXN *txn;
00207 const char *name, *subdb;
00208 u_int32_t flags;
00209 {
00210 int ret, t_ret;
00211
00212 ret = __db_remove_int(dbp, txn, name, subdb, flags);
00213
00214 if ((t_ret = __db_close(dbp, txn, DB_NOSYNC)) != 0 && ret == 0)
00215 ret = t_ret;
00216
00217 return (ret);
00218 }
00219
00220
00221
00222
00223
00224
00225
00226
00227 int
00228 __db_remove_int(dbp, txn, name, subdb, flags)
00229 DB *dbp;
00230 DB_TXN *txn;
00231 const char *name, *subdb;
00232 u_int32_t flags;
00233 {
00234 DB_ENV *dbenv;
00235 int ret;
00236 char *real_name, *tmpname;
00237
00238 dbenv = dbp->dbenv;
00239 real_name = tmpname = NULL;
00240
00241 if (name == NULL && subdb == NULL) {
00242 __db_err(dbenv, "Remove on temporary files invalid");
00243 ret = EINVAL;
00244 goto err;
00245 }
00246
00247 if (name == NULL) {
00248 MAKE_INMEM(dbp);
00249 real_name = (char *)subdb;
00250 } else if (subdb != NULL) {
00251 ret = __db_subdb_remove(dbp, txn, name, subdb);
00252 goto err;
00253 }
00254
00255
00256 if (txn != NULL) {
00257 ret = __db_dbtxn_remove(dbp, txn, name, subdb);
00258 goto err;
00259 }
00260
00261
00262
00263
00264
00265
00266 if (!F_ISSET(dbp, DB_AM_INMEM) && (ret =
00267 __db_appname(dbenv, DB_APP_DATA, name, 0, NULL, &real_name)) != 0)
00268 goto err;
00269
00270
00271
00272
00273
00274
00275 if (!F_ISSET(dbp, DB_AM_INMEM) && LF_ISSET(DB_FORCE) &&
00276 (ret = __db_backup_name(dbenv, real_name, NULL, &tmpname)) == 0)
00277 (void)__os_unlink(dbenv, tmpname);
00278
00279 if ((ret = __fop_remove_setup(dbp, NULL, real_name, 0)) != 0)
00280 goto err;
00281
00282 if (dbp->db_am_remove != NULL &&
00283 (ret = dbp->db_am_remove(dbp, NULL, name, subdb)) != 0)
00284 goto err;
00285
00286 ret = F_ISSET(dbp, DB_AM_INMEM) ?
00287 __db_inmem_remove(dbp, NULL, real_name) :
00288 __fop_remove(dbenv, NULL, dbp->fileid, name, DB_APP_DATA,
00289 F_ISSET(dbp, DB_AM_NOT_DURABLE) ? DB_LOG_NOT_DURABLE : 0);
00290
00291 err: if (!F_ISSET(dbp, DB_AM_INMEM) && real_name != NULL)
00292 __os_free(dbenv, real_name);
00293 if (tmpname != NULL)
00294 __os_free(dbenv, tmpname);
00295
00296 return (ret);
00297 }
00298
00299
00300
00301
00302
00303
00304 int
00305 __db_inmem_remove(dbp, txn, name)
00306 DB *dbp;
00307 DB_TXN *txn;
00308 const char *name;
00309 {
00310 DB_ENV *dbenv;
00311 DB_LSN lsn;
00312 DBT fid_dbt, name_dbt;
00313 u_int32_t locker;
00314 int ret;
00315
00316 dbenv = dbp->dbenv;
00317 locker = DB_LOCK_INVALIDID;
00318
00319 DB_ASSERT(name != NULL);
00320
00321
00322 (void)__memp_set_flags(dbp->mpf, DB_MPOOL_NOFILE, 1);
00323 if ((ret = __memp_fopen(dbp->mpf, NULL, name, 0, 0, 0)) != 0)
00324 return (ret);
00325 if ((ret = __memp_get_fileid(dbp->mpf, dbp->fileid)) != 0)
00326 goto err;
00327 dbp->preserve_fid = 1;
00328
00329 if (LOCKING_ON(dbenv)) {
00330 if (dbp->lid == DB_LOCK_INVALIDID &&
00331 (ret = __lock_id(dbenv, &dbp->lid, NULL)) != 0)
00332 goto err;
00333 locker = txn == NULL ? dbp->lid : txn->txnid;
00334 }
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344 if ((ret = __fop_lock_handle(dbenv,
00345 dbp, locker, DB_LOCK_WRITE, NULL, 0)) != 0)
00346 goto err;
00347
00348 if (LOGGING_ON(dbenv)) {
00349 memset(&fid_dbt, 0, sizeof(fid_dbt));
00350 fid_dbt.data = dbp->fileid;
00351 fid_dbt.size = DB_FILE_ID_LEN;
00352 memset(&name_dbt, 0, sizeof(name_dbt));
00353 name_dbt.data = (void *)name;
00354 name_dbt.size = (u_int32_t)strlen(name) + 1;
00355
00356 if (txn != NULL && (ret =
00357 __txn_remevent(dbenv, txn, name, dbp->fileid, 1)) != 0)
00358 goto err;
00359
00360 if ((ret = __crdel_inmem_remove_log(dbenv,
00361 txn, &lsn, 0, &name_dbt, &fid_dbt)) != 0)
00362 goto err;
00363 }
00364
00365 if (txn == NULL)
00366 ret = __memp_nameop(dbenv, dbp->fileid, NULL, name, NULL, 1);
00367
00368 err: return (ret);
00369 }
00370
00371
00372
00373
00374
00375 static int
00376 __db_subdb_remove(dbp, txn, name, subdb)
00377 DB *dbp;
00378 DB_TXN *txn;
00379 const char *name, *subdb;
00380 {
00381 DB *mdbp, *sdbp;
00382 int ret, t_ret;
00383
00384 mdbp = sdbp = NULL;
00385
00386
00387 if ((ret = db_create(&sdbp, dbp->dbenv, 0)) != 0)
00388 goto err;
00389 if ((ret = __db_open(sdbp,
00390 txn, name, subdb, DB_UNKNOWN, DB_WRITEOPEN, 0, PGNO_BASE_MD)) != 0)
00391 goto err;
00392
00393 DB_TEST_RECOVERY(sdbp, DB_TEST_PREDESTROY, ret, name);
00394
00395
00396 switch (sdbp->type) {
00397 case DB_BTREE:
00398 case DB_RECNO:
00399 if ((ret = __bam_reclaim(sdbp, txn)) != 0)
00400 goto err;
00401 break;
00402 case DB_HASH:
00403 if ((ret = __ham_reclaim(sdbp, txn)) != 0)
00404 goto err;
00405 break;
00406 case DB_QUEUE:
00407 case DB_UNKNOWN:
00408 default:
00409 ret = __db_unknown_type(
00410 sdbp->dbenv, "__db_subdb_remove", sdbp->type);
00411 goto err;
00412 }
00413
00414
00415
00416
00417
00418 if ((ret = __db_master_open(sdbp, txn, name, 0, 0, &mdbp)) != 0)
00419 goto err;
00420
00421 if ((ret = __db_master_update(
00422 mdbp, sdbp, txn, subdb, sdbp->type, MU_REMOVE, NULL, 0)) != 0)
00423 goto err;
00424
00425 DB_TEST_RECOVERY(sdbp, DB_TEST_POSTDESTROY, ret, name);
00426
00427 DB_TEST_RECOVERY_LABEL
00428 err:
00429
00430 if ((t_ret = __db_close(sdbp, txn, 0)) != 0 && ret == 0)
00431 ret = t_ret;
00432
00433 if (mdbp != NULL &&
00434 (t_ret = __db_close(mdbp, txn, DB_NOSYNC)) != 0 && ret == 0)
00435 ret = t_ret;
00436
00437 return (ret);
00438 }
00439
00440 static int
00441 __db_dbtxn_remove(dbp, txn, name, subdb)
00442 DB *dbp;
00443 DB_TXN *txn;
00444 const char *name, *subdb;
00445 {
00446 DB_ENV *dbenv;
00447 int ret;
00448 char *tmpname;
00449
00450 dbenv = dbp->dbenv;
00451 tmpname = NULL;
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461 if ((ret = __db_backup_name(dbenv,
00462 F_ISSET(dbp, DB_AM_INMEM) ? subdb : name, txn, &tmpname)) != 0)
00463 return (ret);
00464
00465 DB_TEST_RECOVERY(dbp, DB_TEST_PREDESTROY, ret, name);
00466
00467 if ((ret = __db_rename_int(dbp, txn, name, subdb, tmpname)) != 0)
00468 goto err;
00469
00470
00471
00472
00473 if (dbp->db_am_remove != NULL &&
00474 (ret = dbp->db_am_remove(dbp, txn, tmpname, NULL)) != 0)
00475 goto err;
00476
00477 ret = F_ISSET(dbp, DB_AM_INMEM) ?
00478 __db_inmem_remove(dbp, txn, tmpname) :
00479 __fop_remove(dbenv, txn, dbp->fileid, tmpname, DB_APP_DATA,
00480 F_ISSET(dbp, DB_AM_NOT_DURABLE) ? DB_LOG_NOT_DURABLE : 0);
00481
00482 DB_TEST_RECOVERY(dbp, DB_TEST_POSTDESTROY, ret, name);
00483
00484 err:
00485 DB_TEST_RECOVERY_LABEL
00486 if (tmpname != NULL)
00487 __os_free(dbenv, tmpname);
00488
00489 return (ret);
00490 }