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/db_shash.h"
00021 #include "dbinc/btree.h"
00022 #include "dbinc/hash.h"
00023 #include "dbinc/qam.h"
00024 #include "dbinc/lock.h"
00025 #include "dbinc/log.h"
00026 #include "dbinc/txn.h"
00027
00028 static int __db_cursor_check __P((DB *));
00029
00030
00031
00032
00033
00034
00035
00036 int
00037 __db_truncate_pp(dbp, txn, countp, flags)
00038 DB *dbp;
00039 DB_TXN *txn;
00040 u_int32_t *countp, flags;
00041 {
00042 DB_ENV *dbenv;
00043 DB_THREAD_INFO *ip;
00044 int handle_check, ret, t_ret, txn_local;
00045
00046 dbenv = dbp->dbenv;
00047 txn_local = 0;
00048 handle_check = 0;
00049
00050 PANIC_CHECK(dbenv);
00051 STRIP_AUTO_COMMIT(flags);
00052
00053
00054 if (F_ISSET(dbp, DB_AM_SECONDARY)) {
00055 __db_err(dbenv,
00056 "DB->truncate forbidden on secondary indices");
00057 return (EINVAL);
00058 }
00059 if ((ret = __db_fchk(dbenv, "DB->truncate", flags, 0)) != 0)
00060 return (ret);
00061
00062 ENV_ENTER(dbenv, ip);
00063
00064
00065
00066
00067
00068 if (__db_cursor_check(dbp) != 0) {
00069 __db_err(dbenv,
00070 "DB->truncate not permitted with active cursors");
00071 goto err;
00072 }
00073
00074 #if CONFIG_TEST
00075 if (IS_REP_MASTER(dbenv))
00076 DB_TEST_WAIT(dbenv, dbenv->test_check);
00077 #endif
00078
00079 handle_check = IS_ENV_REPLICATED(dbenv);
00080 if (handle_check &&
00081 (ret = __db_rep_enter(dbp, 1, 0, txn != NULL)) != 0) {
00082 handle_check = 0;
00083 goto err;
00084 }
00085
00086
00087
00088
00089
00090
00091 if (DB_IS_READONLY(dbp)) {
00092 ret = __db_rdonly(dbenv, "DB->truncate");
00093 goto err;
00094 }
00095
00096
00097
00098
00099
00100 if (IS_DB_AUTO_COMMIT(dbp, txn)) {
00101 if ((ret = __txn_begin(dbenv, NULL, &txn, 0)) != 0)
00102 goto err;
00103 txn_local = 1;
00104 }
00105
00106
00107 if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 0)) != 0)
00108 goto err;
00109
00110 ret = __db_truncate(dbp, txn, countp);
00111
00112 err: if (txn_local &&
00113 (t_ret = __db_txn_auto_resolve(dbenv, txn, 0, ret)) && ret == 0)
00114 ret = t_ret;
00115
00116
00117 if (handle_check && (t_ret = __env_db_rep_exit(dbenv)) != 0 && ret == 0)
00118 ret = t_ret;
00119
00120 ENV_LEAVE(dbenv, ip);
00121 return (ret);
00122 }
00123
00124
00125
00126
00127
00128
00129
00130 int
00131 __db_truncate(dbp, txn, countp)
00132 DB *dbp;
00133 DB_TXN *txn;
00134 u_int32_t *countp;
00135 {
00136 DB *sdbp;
00137 DBC *dbc;
00138 DB_ENV *dbenv;
00139 u_int32_t scount;
00140 int ret, t_ret;
00141
00142 dbenv = dbp->dbenv;
00143 dbc = NULL;
00144 ret = 0;
00145
00146
00147
00148
00149
00150
00151 if (dbp->type != DB_QUEUE && LIST_FIRST(&dbp->s_secondaries) != NULL) {
00152 if ((ret = __db_s_first(dbp, &sdbp)) != 0)
00153 return (ret);
00154 for (; sdbp != NULL && ret == 0; ret = __db_s_next(&sdbp))
00155 if ((ret = __db_truncate(sdbp, txn, &scount)) != 0)
00156 break;
00157 if (sdbp != NULL)
00158 (void)__db_s_done(sdbp);
00159 if (ret != 0)
00160 return (ret);
00161 }
00162
00163 DB_TEST_RECOVERY(dbp, DB_TEST_PREDESTROY, ret, NULL);
00164
00165
00166 if ((ret = __db_cursor(dbp, txn, &dbc, 0)) != 0)
00167 return (ret);
00168
00169 DEBUG_LWRITE(dbc, txn, "DB->truncate", NULL, NULL, 0);
00170
00171 switch (dbp->type) {
00172 case DB_BTREE:
00173 case DB_RECNO:
00174 ret = __bam_truncate(dbc, countp);
00175 break;
00176 case DB_HASH:
00177 ret = __ham_truncate(dbc, countp);
00178 break;
00179 case DB_QUEUE:
00180 ret = __qam_truncate(dbc, countp);
00181 break;
00182 case DB_UNKNOWN:
00183 default:
00184 ret = __db_unknown_type(dbenv, "DB->truncate", dbp->type);
00185 break;
00186 }
00187
00188
00189 if (dbc != NULL && (t_ret = __db_c_close(dbc)) != 0 && ret == 0)
00190 ret = t_ret;
00191
00192 DB_TEST_RECOVERY(dbp, DB_TEST_POSTDESTROY, ret, NULL);
00193
00194 DB_TEST_RECOVERY_LABEL
00195
00196 return (ret);
00197 }
00198
00199
00200
00201
00202
00203 static int
00204 __db_cursor_check(dbp)
00205 DB *dbp;
00206 {
00207 DB *ldbp;
00208 DBC *dbc;
00209 DB_ENV *dbenv;
00210 int found;
00211
00212 dbenv = dbp->dbenv;
00213
00214 MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
00215 for (found = 0, ldbp = __dblist_get(dbenv, dbp->adj_fileid);
00216 ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
00217 ldbp = LIST_NEXT(ldbp, dblistlinks)) {
00218 MUTEX_LOCK(dbenv, dbp->mutex);
00219 for (dbc = TAILQ_FIRST(&ldbp->active_queue);
00220 dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
00221 if (IS_INITIALIZED(dbc)) {
00222 found = 1;
00223 break;
00224 }
00225 }
00226 MUTEX_UNLOCK(dbenv, dbp->mutex);
00227 if (found == 1)
00228 break;
00229 }
00230 MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
00231
00232 return (found);
00233 }