Mercurial > hg > openjdk > jigsaw > bdb
view src/db/db_truncate.c @ 0:a1985f14b030
Initial load
author | chegar |
---|---|
date | Fri, 11 May 2012 10:42:02 +0100 |
parents | |
children |
line wrap: on
line source
/*- * See the file LICENSE for redistribution information. * * Copyright (c) 2001, 2012 Oracle and/or its affiliates. All rights reserved. * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. * * $Id$ */ #include "db_config.h" #include "db_int.h" #include "dbinc/db_page.h" #include "dbinc/btree.h" #include "dbinc/hash.h" #include "dbinc/heap.h" #include "dbinc/qam.h" #include "dbinc/lock.h" #include "dbinc/partition.h" #include "dbinc/txn.h" static int __db_cursor_check_func __P((DBC *, DBC *, u_int32_t *, db_pgno_t, u_int32_t, void *)); static int __db_cursor_check __P((DB *)); /* * __db_truncate_pp * DB->truncate pre/post processing. * * PUBLIC: int __db_truncate_pp __P((DB *, DB_TXN *, u_int32_t *, u_int32_t)); */ int __db_truncate_pp(dbp, txn, countp, flags) DB *dbp; DB_TXN *txn; u_int32_t *countp, flags; { DB_THREAD_INFO *ip; ENV *env; int handle_check, ret, t_ret, txn_local; env = dbp->env; handle_check = txn_local = 0; STRIP_AUTO_COMMIT(flags); /* Check for invalid flags. */ if (F_ISSET(dbp, DB_AM_SECONDARY)) { __db_errx(env, DB_STR("0685", "DB->truncate forbidden on secondary indices")); return (EINVAL); } if ((ret = __db_fchk(env, "DB->truncate", flags, 0)) != 0) return (ret); ENV_ENTER(env, ip); XA_CHECK_TXN(ip, txn); /* * Make sure there are no active cursors on this db. Since we drop * pages we cannot really adjust cursors. */ if ((ret = __db_cursor_check(dbp)) != 0) { __db_errx(env, DB_STR("0686", "DB->truncate not permitted with active cursors")); goto err; } #ifdef CONFIG_TEST if (IS_REP_MASTER(env)) DB_TEST_WAIT(env, env->test_check); #endif /* Check for replication block. */ handle_check = IS_ENV_REPLICATED(env); if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, IS_REAL_TXN(txn))) != 0) { handle_check = 0; goto err; } /* * Check for changes to a read-only database. This must be after the * replication block so that we cannot race master/client state changes. */ if (DB_IS_READONLY(dbp)) { ret = __db_rdonly(env, "DB->truncate"); goto err; } /* * Create local transaction as necessary, check for consistent * transaction usage. */ if (IS_DB_AUTO_COMMIT(dbp, txn)) { if ((ret = __txn_begin(env, ip, NULL, &txn, 0)) != 0) goto err; txn_local = 1; } /* Check for consistent transaction usage. */ if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 0)) != 0) goto err; ret = __db_truncate(dbp, ip, txn, countp); err: if (txn_local && (t_ret = __db_txn_auto_resolve(env, txn, 0, ret)) && ret == 0) ret = t_ret; /* Release replication block. */ if (handle_check && (t_ret = __env_db_rep_exit(env)) != 0 && ret == 0) ret = t_ret; ENV_LEAVE(env, ip); return (ret); } /* * __db_truncate * DB->truncate. * * PUBLIC: int __db_truncate __P((DB *, DB_THREAD_INFO *, DB_TXN *, * PUBLIC: u_int32_t *)); */ int __db_truncate(dbp, ip, txn, countp) DB *dbp; DB_THREAD_INFO *ip; DB_TXN *txn; u_int32_t *countp; { DB *sdbp; DBC *dbc; ENV *env; u_int32_t scount; int ret, t_ret; env = dbp->env; dbc = NULL; ret = 0; /* * Run through all secondaries and truncate them first. The count * returned is the count of the primary only. QUEUE uses normal * processing to truncate so it will update the secondaries normally. */ if (dbp->type != DB_QUEUE && DB_IS_PRIMARY(dbp)) { if ((ret = __db_s_first(dbp, &sdbp)) != 0) return (ret); for (; sdbp != NULL && ret == 0; ret = __db_s_next(&sdbp, txn)) if ((ret = __db_truncate(sdbp, ip, txn, &scount)) != 0) break; if (sdbp != NULL) (void)__db_s_done(sdbp, txn); if (ret != 0) return (ret); } DB_TEST_RECOVERY(dbp, DB_TEST_PREDESTROY, ret, NULL); /* Acquire a cursor. */ if ((ret = __db_cursor(dbp, ip, txn, &dbc, 0)) != 0) return (ret); DEBUG_LWRITE(dbc, txn, "DB->truncate", NULL, NULL, 0); #ifdef HAVE_PARTITION if (DB_IS_PARTITIONED(dbp)) ret = __part_truncate(dbc, countp); else #endif switch (dbp->type) { case DB_BTREE: case DB_RECNO: ret = __bam_truncate(dbc, countp); break; case DB_HASH: ret = __ham_truncate(dbc, countp); break; case DB_HEAP: ret = __heap_truncate(dbc, countp); break; case DB_QUEUE: ret = __qam_truncate(dbc, countp); break; case DB_UNKNOWN: default: ret = __db_unknown_type(env, "DB->truncate", dbp->type); break; } /* Discard the cursor. */ if (dbc != NULL && (t_ret = __dbc_close(dbc)) != 0 && ret == 0) ret = t_ret; DB_TEST_RECOVERY(dbp, DB_TEST_POSTDESTROY, ret, NULL); DB_TEST_RECOVERY_LABEL return (ret); } static int __db_cursor_check_func(dbc, my_dbc, foundp, pgno, indx, args) DBC *dbc, *my_dbc; u_int32_t *foundp; db_pgno_t pgno; u_int32_t indx; void *args; { COMPQUIET(my_dbc, NULL); COMPQUIET(args, NULL); COMPQUIET(pgno, 0); COMPQUIET(indx, 0); if (IS_INITIALIZED(dbc)) { *foundp = 1; return (EEXIST); } return (0); } /* * __db_cursor_check -- * See if there are any active cursors on this db. */ static int __db_cursor_check(dbp) DB *dbp; { int ret; u_int32_t found; ret = __db_walk_cursors(dbp, NULL, __db_cursor_check_func, &found, 0, 0, NULL); return (ret == EEXIST ? EINVAL : ret); }