+/** Add all the DB's pages to the free list.
+ * @param[in] mc Cursor on the DB to free.
+ * @param[in] subs non-Zero to check for sub-DBs in this DB.
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+mdb_drop0(MDB_cursor *mc, int subs)
+{
+ int rc;
+
+ rc = mdb_page_search(mc, NULL, 0);
+ if (rc == MDB_SUCCESS) {
+ MDB_node *ni;
+ MDB_cursor mx;
+ unsigned int i;
+
+ /* LEAF2 pages have no nodes, cannot have sub-DBs */
+ if (!subs || IS_LEAF2(mc->mc_pg[mc->mc_top]))
+ mdb_cursor_pop(mc);
+
+ mdb_cursor_copy(mc, &mx);
+ while (mc->mc_snum > 0) {
+ if (IS_LEAF(mc->mc_pg[mc->mc_top])) {
+ for (i=0; i<NUMKEYS(mc->mc_pg[mc->mc_top]); i++) {
+ ni = NODEPTR(mc->mc_pg[mc->mc_top], i);
+ if (ni->mn_flags & F_SUBDATA) {
+ mdb_xcursor_init1(mc, ni);
+ rc = mdb_drop0(&mc->mc_xcursor->mx_cursor, 0);
+ if (rc)
+ return rc;
+ }
+ }
+ } else {
+ for (i=0; i<NUMKEYS(mc->mc_pg[mc->mc_top]); i++) {
+ pgno_t pg;
+ ni = NODEPTR(mc->mc_pg[mc->mc_top], i);
+ pg = NODEPGNO(ni);
+ /* free it */
+ mdb_midl_append(&mc->mc_txn->mt_free_pgs, pg);
+ }
+ }
+ if (!mc->mc_top)
+ break;
+ rc = mdb_cursor_sibling(mc, 1);
+ if (rc) {
+ /* no more siblings, go back to beginning
+ * of previous level. (stack was already popped
+ * by mdb_cursor_sibling)
+ */
+ for (i=1; i<mc->mc_top; i++)
+ mc->mc_pg[i] = mx.mc_pg[i];
+ }
+ }
+ /* free it */
+ mdb_midl_append(&mc->mc_txn->mt_free_pgs,
+ mc->mc_db->md_root);
+ }
+ return 0;
+}
+
+int mdb_drop(MDB_txn *txn, MDB_dbi dbi, int del)
+{
+ MDB_cursor *mc;
+ int rc;
+
+ if (!txn || !dbi || dbi >= txn->mt_numdbs)
+ return EINVAL;
+
+ if (F_ISSET(txn->mt_flags, MDB_TXN_RDONLY))
+ return EACCES;
+
+ rc = mdb_cursor_open(txn, dbi, &mc);
+ if (rc)
+ return rc;
+
+ rc = mdb_drop0(mc, mc->mc_db->md_flags & MDB_DUPSORT);
+ if (rc)
+ goto leave;
+
+ /* Can't delete the main DB */
+ if (del && dbi > MAIN_DBI) {
+ rc = mdb_del(txn, MAIN_DBI, &mc->mc_dbx->md_name, NULL);
+ if (!rc)
+ mdb_close(txn->mt_env, dbi);
+ } else {
+ txn->mt_dbflags[dbi] |= DB_DIRTY;
+ txn->mt_dbs[dbi].md_depth = 0;
+ txn->mt_dbs[dbi].md_branch_pages = 0;
+ txn->mt_dbs[dbi].md_leaf_pages = 0;
+ txn->mt_dbs[dbi].md_overflow_pages = 0;
+ txn->mt_dbs[dbi].md_entries = 0;
+ txn->mt_dbs[dbi].md_root = P_INVALID;
+ }
+leave:
+ mdb_cursor_close(mc);
+ return rc;
+}
+