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"
26 #include "lib/tdb_wrap/tdb_wrap.h"
28 /* should be tunable */
29 #define TIMELIMIT() timeval_current_ofs(10, 0)
32 struct vacuum_traverse_state
{
34 struct tdb_context
*dest_db
;
38 traverse function for repacking
40 static int repack_traverse(struct tdb_context
*tdb
, TDB_DATA key
, TDB_DATA data
, void *private)
42 struct vacuum_traverse_state
*state
= (struct vacuum_traverse_state
*)private;
43 if (tdb_store(state
->dest_db
, key
, data
, TDB_INSERT
) != 0) {
53 static int ctdb_repack_tdb(struct tdb_context
*tdb
)
55 struct tdb_context
*tmp_db
;
56 struct vacuum_traverse_state state
;
58 if (tdb_transaction_start(tdb
) != 0) {
59 DEBUG(DEBUG_ERR
,(__location__
" Failed to start transaction\n"));
63 tmp_db
= tdb_open("tmpdb", tdb_hash_size(tdb
),
64 TDB_INTERNAL
|TDB_DISALLOW_NESTING
,
67 DEBUG(DEBUG_ERR
,(__location__
" Failed to create tmp_db\n"));
68 tdb_transaction_cancel(tdb
);
73 state
.dest_db
= tmp_db
;
75 if (tdb_traverse_read(tdb
, repack_traverse
, &state
) == -1) {
76 DEBUG(DEBUG_ERR
,(__location__
" Failed to traverse copying out\n"));
77 tdb_transaction_cancel(tdb
);
83 DEBUG(DEBUG_ERR
,(__location__
" Error during traversal\n"));
84 tdb_transaction_cancel(tdb
);
89 if (tdb_wipe_all(tdb
) != 0) {
90 DEBUG(DEBUG_ERR
,(__location__
" Failed to wipe database\n"));
91 tdb_transaction_cancel(tdb
);
99 if (tdb_traverse_read(tmp_db
, repack_traverse
, &state
) == -1) {
100 DEBUG(DEBUG_ERR
,(__location__
" Failed to traverse copying back\n"));
101 tdb_transaction_cancel(tdb
);
107 DEBUG(DEBUG_ERR
,(__location__
" Error during second traversal\n"));
108 tdb_transaction_cancel(tdb
);
115 if (tdb_transaction_commit(tdb
) != 0) {
116 DEBUG(DEBUG_ERR
,(__location__
" Failed to commit\n"));
124 /* repack one database */
125 static int ctdb_repack_db(struct ctdb_context
*ctdb
, uint32_t db_id
,
126 bool persistent
, uint32_t repack_limit
)
128 struct ctdb_db_context
*ctdb_db
;
132 if (ctdb_ctrl_getdbname(ctdb
, TIMELIMIT(), CTDB_CURRENT_NODE
, db_id
, ctdb
, &name
) != 0) {
133 DEBUG(DEBUG_ERR
,(__location__
" Failed to get name of db 0x%x\n", db_id
));
137 ctdb_db
= ctdb_attach(ctdb
, TIMELIMIT(), name
, persistent
, 0);
138 if (ctdb_db
== NULL
) {
139 DEBUG(DEBUG_ERR
,(__location__
" Failed to attach to database '%s'\n", name
));
143 size
= tdb_freelist_size(ctdb_db
->ltdb
->tdb
);
145 DEBUG(DEBUG_ERR
,(__location__
" Failed to get freelist size for '%s'\n", name
));
149 if (size
<= repack_limit
) {
153 printf("Repacking %s with %u freelist entries\n", name
, size
);
155 if (ctdb_repack_tdb(ctdb_db
->ltdb
->tdb
) != 0) {
156 DEBUG(DEBUG_ERR
,(__location__
" Failed to repack '%s'\n", name
));
165 repack all our databases
167 int ctdb_repack(struct ctdb_context
*ctdb
, int argc
, const char **argv
)
169 struct ctdb_dbid_map
*dbmap
=NULL
;
171 /* a reasonable default limit to prevent us using too much memory */
172 uint32_t repack_limit
= 10000;
175 repack_limit
= atoi(argv
[0]);
178 ret
= ctdb_ctrl_getdbmap(ctdb
, TIMELIMIT(), CTDB_CURRENT_NODE
, ctdb
, &dbmap
);
180 DEBUG(DEBUG_ERR
, ("Unable to get dbids from local node\n"));
184 for (i
=0;i
<dbmap
->num
;i
++) {
185 if (ctdb_repack_db(ctdb
, dbmap
->dbs
[i
].dbid
,
186 dbmap
->dbs
[i
].flags
& CTDB_DB_FLAGS_PERSISTENT
, repack_limit
) != 0) {
187 DEBUG(DEBUG_ERR
,("Failed to repack db 0x%x\n", dbmap
->dbs
[i
].dbid
));