2 ctdb control tool - database vacuum
4 Copyright (C) Andrew Tridgell 2008
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include "system/filesys.h"
22 #include "system/network.h"
23 #include "../include/ctdb_client.h"
24 #include "../include/ctdb_private.h"
25 #include "../common/rb_tree.h"
28 /* should be tunable */
29 #define TIMELIMIT() timeval_current_ofs(10, 0)
33 vacuum all our databases
35 int ctdb_vacuum(struct ctdb_context *ctdb, int argc, const char **argv)
37 printf("\"ctdb vacuum\" is not implemented any more.\n");
41 struct vacuum_traverse_state {
43 struct tdb_context *dest_db;
47 traverse function for repacking
49 static int repack_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *private)
51 struct vacuum_traverse_state *state = (struct vacuum_traverse_state *)private;
52 if (tdb_store(state->dest_db, key, data, TDB_INSERT) != 0) {
62 static int ctdb_repack_tdb(struct tdb_context *tdb)
64 struct tdb_context *tmp_db;
65 struct vacuum_traverse_state state;
67 if (tdb_transaction_start(tdb) != 0) {
68 DEBUG(DEBUG_ERR,(__location__ " Failed to start transaction\n"));
72 tmp_db = tdb_open("tmpdb", tdb_hash_size(tdb),
73 TDB_INTERNAL|TDB_DISALLOW_NESTING,
76 DEBUG(DEBUG_ERR,(__location__ " Failed to create tmp_db\n"));
77 tdb_transaction_cancel(tdb);
82 state.dest_db = tmp_db;
84 if (tdb_traverse_read(tdb, repack_traverse, &state) == -1) {
85 DEBUG(DEBUG_ERR,(__location__ " Failed to traverse copying out\n"));
86 tdb_transaction_cancel(tdb);
92 DEBUG(DEBUG_ERR,(__location__ " Error during traversal\n"));
93 tdb_transaction_cancel(tdb);
98 if (tdb_wipe_all(tdb) != 0) {
99 DEBUG(DEBUG_ERR,(__location__ " Failed to wipe database\n"));
100 tdb_transaction_cancel(tdb);
108 if (tdb_traverse_read(tmp_db, repack_traverse, &state) == -1) {
109 DEBUG(DEBUG_ERR,(__location__ " Failed to traverse copying back\n"));
110 tdb_transaction_cancel(tdb);
116 DEBUG(DEBUG_ERR,(__location__ " Error during second traversal\n"));
117 tdb_transaction_cancel(tdb);
124 if (tdb_transaction_commit(tdb) != 0) {
125 DEBUG(DEBUG_ERR,(__location__ " Failed to commit\n"));
133 /* repack one database */
134 static int ctdb_repack_db(struct ctdb_context *ctdb, uint32_t db_id,
135 bool persistent, uint32_t repack_limit)
137 struct ctdb_db_context *ctdb_db;
141 if (ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, db_id, ctdb, &name) != 0) {
142 DEBUG(DEBUG_ERR,(__location__ " Failed to get name of db 0x%x\n", db_id));
146 ctdb_db = ctdb_attach(ctdb, TIMELIMIT(), name, persistent, 0);
147 if (ctdb_db == NULL) {
148 DEBUG(DEBUG_ERR,(__location__ " Failed to attach to database '%s'\n", name));
152 size = tdb_freelist_size(ctdb_db->ltdb->tdb);
154 DEBUG(DEBUG_ERR,(__location__ " Failed to get freelist size for '%s'\n", name));
158 if (size <= repack_limit) {
162 printf("Repacking %s with %u freelist entries\n", name, size);
164 if (ctdb_repack_tdb(ctdb_db->ltdb->tdb) != 0) {
165 DEBUG(DEBUG_ERR,(__location__ " Failed to repack '%s'\n", name));
174 repack all our databases
176 int ctdb_repack(struct ctdb_context *ctdb, int argc, const char **argv)
178 struct ctdb_dbid_map *dbmap=NULL;
180 /* a reasonable default limit to prevent us using too much memory */
181 uint32_t repack_limit = 10000;
184 repack_limit = atoi(argv[0]);
187 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &dbmap);
189 DEBUG(DEBUG_ERR, ("Unable to get dbids from local node\n"));
193 for (i=0;i<dbmap->num;i++) {
194 if (ctdb_repack_db(ctdb, dbmap->dbs[i].dbid,
195 dbmap->dbs[i].flags & CTDB_DB_FLAGS_PERSISTENT, repack_limit) != 0) {
196 DEBUG(DEBUG_ERR,("Failed to repack db 0x%x\n", dbmap->dbs[i].dbid));