4 Copyright (C) Andrew Tridgell 2007
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/network.h"
22 #include "system/filesys.h"
23 #include "system/wait.h"
24 #include "../include/ctdb_private.h"
25 #include "lib/util/dlinklist.h"
26 #include "lib/tdb_wrap/tdb_wrap.h"
27 #include "../common/rb_tree.h"
31 * Cancel a transaction on database
33 static int db_transaction_cancel_handler(struct ctdb_db_context *ctdb_db,
38 tdb_add_flags(ctdb_db->ltdb->tdb, TDB_NOLOCK);
39 ret = tdb_transaction_cancel(ctdb_db->ltdb->tdb);
41 DEBUG(DEBUG_ERR, ("Failed to cancel transaction for db %s\n",
44 tdb_remove_flags(ctdb_db->ltdb->tdb, TDB_NOLOCK);
49 * Start a transaction on database
51 static int db_transaction_start_handler(struct ctdb_db_context *ctdb_db,
54 bool freeze_transaction_started = *(bool *)private_data;
57 tdb_add_flags(ctdb_db->ltdb->tdb, TDB_NOLOCK);
58 if (freeze_transaction_started) {
59 ret = tdb_transaction_cancel(ctdb_db->ltdb->tdb);
62 ("Failed to cancel transaction for db %s\n",
66 ret = tdb_transaction_start(ctdb_db->ltdb->tdb);
67 tdb_remove_flags(ctdb_db->ltdb->tdb, TDB_NOLOCK);
69 DEBUG(DEBUG_ERR, ("Failed to start transaction for db %s\n",
77 * Commit a transaction on database
79 static int db_transaction_commit_handler(struct ctdb_db_context *ctdb_db,
82 int healthy_nodes = *(int *)private_data;
85 tdb_add_flags(ctdb_db->ltdb->tdb, TDB_NOLOCK);
86 ret = tdb_transaction_commit(ctdb_db->ltdb->tdb);
87 tdb_remove_flags(ctdb_db->ltdb->tdb, TDB_NOLOCK);
89 DEBUG(DEBUG_ERR, ("Failed to commit transaction for db %s\n",
94 ret = ctdb_update_persistent_health(ctdb_db->ctdb, ctdb_db, NULL,
97 DEBUG(DEBUG_ERR, ("Failed to update persistent health for db %s\n",
104 /* a list of control requests waiting for db freeze */
105 struct ctdb_db_freeze_waiter {
106 struct ctdb_db_freeze_waiter *next, *prev;
107 struct ctdb_context *ctdb;
112 /* a handle to a db freeze lock child process */
113 struct ctdb_db_freeze_handle {
114 struct ctdb_db_context *ctdb_db;
115 struct lock_request *lreq;
116 struct ctdb_db_freeze_waiter *waiters;
120 * Called when freeing database freeze handle
122 static int ctdb_db_freeze_handle_destructor(struct ctdb_db_freeze_handle *h)
124 struct ctdb_db_context *ctdb_db = h->ctdb_db;
126 DEBUG(DEBUG_ERR, ("Release freeze handle for db %s\n",
129 /* Cancel any pending transactions */
130 if (ctdb_db->freeze_transaction_started) {
131 db_transaction_cancel_handler(ctdb_db, NULL);
132 ctdb_db->freeze_transaction_started = false;
134 ctdb_db->freeze_mode = CTDB_FREEZE_NONE;
135 ctdb_db->freeze_handle = NULL;
137 talloc_free(h->lreq);
142 * Called when a database is frozen
144 static void ctdb_db_freeze_handler(void *private_data, bool locked)
146 struct ctdb_db_freeze_handle *h = talloc_get_type_abort(
147 private_data, struct ctdb_db_freeze_handle);
148 struct ctdb_db_freeze_waiter *w;
150 if (h->ctdb_db->freeze_mode == CTDB_FREEZE_FROZEN) {
151 DEBUG(DEBUG_ERR, ("Freeze db child died - unfreezing\n"));
152 h->ctdb_db->freeze_mode = CTDB_FREEZE_NONE;
158 DEBUG(DEBUG_ERR, ("Failed to get db lock for %s\n",
159 h->ctdb_db->db_name));
160 h->ctdb_db->freeze_mode = CTDB_FREEZE_NONE;
165 h->ctdb_db->freeze_mode = CTDB_FREEZE_FROZEN;
167 /* notify the waiters */
168 while ((w = h->waiters) != NULL) {
170 DLIST_REMOVE(h->waiters, w);
176 * Start freeze process for a database
178 static void ctdb_start_db_freeze(struct ctdb_db_context *ctdb_db)
180 struct ctdb_db_freeze_handle *h;
182 if (ctdb_db->freeze_mode == CTDB_FREEZE_FROZEN) {
186 if (ctdb_db->freeze_handle != NULL) {
190 DEBUG(DEBUG_ERR, ("Freeze db: %s\n", ctdb_db->db_name));
192 ctdb_stop_vacuuming(ctdb_db->ctdb);
194 h = talloc_zero(ctdb_db, struct ctdb_db_freeze_handle);
195 CTDB_NO_MEMORY_FATAL(ctdb_db->ctdb, h);
197 h->ctdb_db = ctdb_db;
198 h->lreq = ctdb_lock_db(h, ctdb_db, false, ctdb_db_freeze_handler, h);
199 CTDB_NO_MEMORY_FATAL(ctdb_db->ctdb, h->lreq);
200 talloc_set_destructor(h, ctdb_db_freeze_handle_destructor);
202 ctdb_db->freeze_handle = h;
203 ctdb_db->freeze_mode = CTDB_FREEZE_PENDING;
207 * Reply to a waiter for db freeze
209 static int ctdb_db_freeze_waiter_destructor(struct ctdb_db_freeze_waiter *w)
211 /* 'c' pointer is talloc_memdup(), so cannot use talloc_get_type */
212 struct ctdb_req_control *c =
213 (struct ctdb_req_control *)w->private_data;
215 ctdb_request_control_reply(w->ctdb, c, NULL, w->status, NULL);
222 int32_t ctdb_control_db_freeze(struct ctdb_context *ctdb,
223 struct ctdb_req_control *c,
227 struct ctdb_db_context *ctdb_db;
228 struct ctdb_db_freeze_waiter *w;
230 ctdb_db = find_ctdb_db(ctdb, db_id);
231 if (ctdb_db == NULL) {
232 DEBUG(DEBUG_ERR, ("Freeze db for unknown dbid 0x%08x\n", db_id));
236 if (ctdb_db->freeze_mode == CTDB_FREEZE_FROZEN) {
237 DEBUG(DEBUG_ERR, ("Freeze db: %s frozen\n", ctdb_db->db_name));
241 ctdb_start_db_freeze(ctdb_db);
243 /* add ourselves to the list of waiters */
244 w = talloc(ctdb_db->freeze_handle, struct ctdb_db_freeze_waiter);
245 CTDB_NO_MEMORY(ctdb, w);
247 w->private_data = talloc_steal(w, c);
249 talloc_set_destructor(w, ctdb_db_freeze_waiter_destructor);
250 DLIST_ADD(ctdb_db->freeze_handle->waiters, w);
259 int32_t ctdb_control_db_thaw(struct ctdb_context *ctdb, uint32_t db_id)
261 struct ctdb_db_context *ctdb_db;
263 ctdb_db = find_ctdb_db(ctdb, db_id);
264 if (ctdb_db == NULL) {
265 DEBUG(DEBUG_ERR, ("Thaw db for unknown dbid 0x%08x\n", db_id));
269 DEBUG(DEBUG_ERR, ("Thaw db: %s\n", ctdb_db->db_name));
271 TALLOC_FREE(ctdb_db->freeze_handle);
272 ctdb_call_resend_db(ctdb_db);
278 a list of control requests waiting for a freeze lock child to get
281 struct ctdb_freeze_waiter {
282 struct ctdb_freeze_waiter *next, *prev;
283 struct ctdb_context *ctdb;
284 struct ctdb_req_control *c;
289 /* a handle to a freeze lock child process */
290 struct ctdb_freeze_handle {
291 struct ctdb_context *ctdb;
293 unsigned int num_total, num_locked, num_failed;
294 struct ctdb_freeze_waiter *waiters;
297 static int db_thaw(struct ctdb_db_context *ctdb_db, void *private_data)
299 talloc_free(ctdb_db->freeze_handle);
304 destroy a freeze handle
306 static int ctdb_freeze_handle_destructor(struct ctdb_freeze_handle *h)
308 struct ctdb_context *ctdb = h->ctdb;
310 DEBUG(DEBUG_ERR,("Release freeze handler for prio %u\n", h->priority));
312 /* cancel any pending transactions */
313 if (ctdb->freeze_transaction_started) {
314 ctdb_db_prio_iterator(ctdb, h->priority,
315 db_transaction_cancel_handler, NULL);
316 ctdb->freeze_transaction_started = false;
319 ctdb_db_prio_iterator(ctdb, h->priority, db_thaw, NULL);
321 ctdb->freeze_mode[h->priority] = CTDB_FREEZE_NONE;
322 ctdb->freeze_handles[h->priority] = NULL;
328 called when the child writes its status to us
330 static void ctdb_freeze_lock_handler(void *private_data, bool locked)
332 struct ctdb_freeze_handle *h = talloc_get_type_abort(private_data,
333 struct ctdb_freeze_handle);
334 struct ctdb_freeze_waiter *w;
336 if (h->ctdb->freeze_mode[h->priority] == CTDB_FREEZE_FROZEN) {
337 DEBUG(DEBUG_INFO,("freeze child died - unfreezing\n"));
343 DEBUG(DEBUG_ERR,("Failed to get locks in ctdb_freeze_child\n"));
344 /* we didn't get the locks - destroy the handle */
349 h->ctdb->freeze_mode[h->priority] = CTDB_FREEZE_FROZEN;
351 /* notify the waiters */
352 if (h != h->ctdb->freeze_handles[h->priority]) {
353 DEBUG(DEBUG_ERR,("lockwait finished but h is not linked\n"));
355 while ((w = h->waiters)) {
357 DLIST_REMOVE(h->waiters, w);
363 * When single database is frozen
365 static int db_freeze_waiter_destructor(struct ctdb_db_freeze_waiter *w)
367 struct ctdb_freeze_handle *h = talloc_get_type_abort(
368 w->private_data, struct ctdb_freeze_handle);
370 if (w->status == 0) {
376 /* Call ctdb_freeze_lock_handler() only when the status of all
377 * databases is known.
379 if (h->num_locked + h->num_failed == h->num_total) {
382 if (h->num_locked == h->num_total) {
387 ctdb_freeze_lock_handler(h, locked);
393 * Count the number of databases
395 static int db_count(struct ctdb_db_context *ctdb_db, void *private_data)
397 int *count = (int *)private_data;
405 * Freeze a single database
407 static int db_freeze(struct ctdb_db_context *ctdb_db, void *private_data)
409 struct ctdb_freeze_handle *h = talloc_get_type_abort(
410 private_data, struct ctdb_freeze_handle);
411 struct ctdb_db_freeze_waiter *w;
413 ctdb_start_db_freeze(ctdb_db);
415 w = talloc(ctdb_db->freeze_handle, struct ctdb_db_freeze_waiter);
416 CTDB_NO_MEMORY(h->ctdb, w);
420 talloc_set_destructor(w, db_freeze_waiter_destructor);
422 if (ctdb_db->freeze_mode == CTDB_FREEZE_FROZEN) {
423 /* Early return if already frozen */
429 DLIST_ADD(ctdb_db->freeze_handle->waiters, w);
435 start the freeze process for a certain priority
437 void ctdb_start_freeze(struct ctdb_context *ctdb, uint32_t priority)
439 struct ctdb_freeze_handle *h;
442 if ((priority < 1) || (priority > NUM_DB_PRIORITIES)) {
443 DEBUG(DEBUG_ERR,(__location__ " Invalid db priority : %u\n", priority));
444 ctdb_fatal(ctdb, "Internal error");
447 if (ctdb->freeze_mode[priority] == CTDB_FREEZE_FROZEN) {
448 /* we're already frozen */
452 if (ctdb->freeze_handles[priority] != NULL) {
453 /* already trying to freeze */
457 DEBUG(DEBUG_ERR, ("Freeze priority %u\n", priority));
459 /* Stop any vacuuming going on: we don't want to wait. */
460 ctdb_stop_vacuuming(ctdb);
462 /* create freeze lock children for each database */
463 h = talloc_zero(ctdb, struct ctdb_freeze_handle);
464 CTDB_NO_MEMORY_FATAL(ctdb, h);
466 h->priority = priority;
467 talloc_set_destructor(h, ctdb_freeze_handle_destructor);
469 ret = ctdb_db_prio_iterator(ctdb, priority, db_count, &h->num_total);
475 ctdb->freeze_mode[priority] = CTDB_FREEZE_PENDING;
477 ret = ctdb_db_prio_iterator(ctdb, priority, db_freeze, h);
483 ctdb->freeze_handles[priority] = h;
484 if (h->num_total == 0) {
485 ctdb->freeze_mode[priority] = CTDB_FREEZE_FROZEN;
490 destroy a waiter for a freeze mode change
492 static int ctdb_freeze_waiter_destructor(struct ctdb_freeze_waiter *w)
494 ctdb_request_control_reply(w->ctdb, w->c, NULL, w->status, NULL);
501 int32_t ctdb_control_freeze(struct ctdb_context *ctdb, struct ctdb_req_control *c, bool *async_reply)
503 struct ctdb_freeze_waiter *w;
506 priority = (uint32_t)c->srvid;
509 DEBUG(DEBUG_ERR,("Freeze priority 0 requested, remapping to priority 1\n"));
513 if ((priority < 1) || (priority > NUM_DB_PRIORITIES)) {
514 DEBUG(DEBUG_ERR,(__location__ " Invalid db priority : %u\n", priority));
518 if (ctdb->freeze_mode[priority] == CTDB_FREEZE_FROZEN) {
519 DEBUG(DEBUG_ERR, ("Freeze priority %u: frozen\n", priority));
520 /* we're already frozen */
524 ctdb_start_freeze(ctdb, priority);
526 if (ctdb->freeze_handles[priority] == NULL) {
527 DEBUG(DEBUG_ERR,("No freeze lock handle when adding a waiter\n"));
531 /* If there are no databases, we are done. */
532 if (ctdb->freeze_handles[priority]->num_total == 0) {
536 /* add ourselves to list of waiters */
537 w = talloc(ctdb->freeze_handles[priority], struct ctdb_freeze_waiter);
538 CTDB_NO_MEMORY(ctdb, w);
540 w->c = talloc_steal(w, c);
541 w->priority = priority;
543 talloc_set_destructor(w, ctdb_freeze_waiter_destructor);
544 DLIST_ADD(ctdb->freeze_handles[priority]->waiters, w);
546 /* we won't reply till later */
553 block until we are frozen, used during daemon startup
555 bool ctdb_blocking_freeze(struct ctdb_context *ctdb)
559 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
560 ctdb_start_freeze(ctdb, i);
562 /* block until frozen */
563 while (ctdb->freeze_mode[i] == CTDB_FREEZE_PENDING) {
564 event_loop_once(ctdb->ev);
572 static void thaw_priority(struct ctdb_context *ctdb, uint32_t priority)
574 DEBUG(DEBUG_ERR,("Thawing priority %u\n", priority));
576 /* cancel any pending transactions */
577 if (ctdb->freeze_transaction_started) {
578 ctdb_db_prio_iterator(ctdb, priority,
579 db_transaction_cancel_handler, NULL);
580 ctdb->freeze_transaction_started = false;
583 ctdb_db_prio_iterator(ctdb, priority, db_thaw, NULL);
584 if (ctdb->freeze_handles[priority] != NULL) {
585 talloc_free(ctdb->freeze_handles[priority]);
586 ctdb->freeze_handles[priority] = NULL;
593 int32_t ctdb_control_thaw(struct ctdb_context *ctdb, uint32_t priority,
596 if (priority > NUM_DB_PRIORITIES) {
597 DEBUG(DEBUG_ERR,(__location__ " Invalid db priority : %u\n",
602 if (check_recmode && ctdb->recovery_mode == CTDB_RECOVERY_ACTIVE) {
603 DEBUG(DEBUG_ERR, ("Failing to thaw databases while "
604 "recovery is active\n"));
610 for (i=1;i<=NUM_DB_PRIORITIES; i++) {
611 thaw_priority(ctdb, i);
614 thaw_priority(ctdb, priority);
617 ctdb_call_resend_all(ctdb);
623 start a transaction on all databases - used for recovery
625 int32_t ctdb_control_transaction_start(struct ctdb_context *ctdb, uint32_t id)
629 if (!ctdb_db_all_frozen(ctdb)) {
630 DEBUG(DEBUG_ERR, (__location__
631 " failing transaction start while not frozen\n"));
635 ret = ctdb_db_iterator(ctdb, db_transaction_start_handler,
636 &ctdb->freeze_transaction_started);
641 ctdb->freeze_transaction_started = true;
642 ctdb->freeze_transaction_id = id;
648 cancel a transaction for all databases - used for recovery
650 int32_t ctdb_control_transaction_cancel(struct ctdb_context *ctdb)
652 DEBUG(DEBUG_ERR,(__location__ " recovery transaction cancelled called\n"));
654 ctdb_db_iterator(ctdb, db_transaction_cancel_handler, NULL);
655 ctdb->freeze_transaction_started = false;
661 commit transactions on all databases
663 int32_t ctdb_control_transaction_commit(struct ctdb_context *ctdb, uint32_t id)
666 int healthy_nodes = 0;
669 if (!ctdb_db_all_frozen(ctdb)) {
670 DEBUG(DEBUG_ERR, (__location__
671 " failing transaction commit while not frozen\n"));
675 if (!ctdb->freeze_transaction_started) {
676 DEBUG(DEBUG_ERR,(__location__ " transaction not started\n"));
680 if (id != ctdb->freeze_transaction_id) {
681 DEBUG(DEBUG_ERR,(__location__ " incorrect transaction id 0x%x in commit\n", id));
685 DEBUG(DEBUG_DEBUG,(__location__ " num_nodes[%d]\n", ctdb->num_nodes));
686 for (i=0; i < ctdb->num_nodes; i++) {
687 DEBUG(DEBUG_DEBUG,(__location__ " node[%d].flags[0x%X]\n",
688 i, ctdb->nodes[i]->flags));
689 if (ctdb->nodes[i]->flags == 0) {
693 DEBUG(DEBUG_INFO,(__location__ " healthy_nodes[%d]\n", healthy_nodes));
695 ret = ctdb_db_iterator(ctdb, db_transaction_commit_handler,
698 DEBUG(DEBUG_ERR, ("Cancel all transactions\n"));
702 ctdb->freeze_transaction_started = false;
703 ctdb->freeze_transaction_id = 0;
708 /* cancel any pending transactions */
709 ctdb_db_iterator(ctdb, db_transaction_cancel_handler, NULL);
710 ctdb->freeze_transaction_started = false;
716 wipe a database - only possible when in a frozen transaction
718 int32_t ctdb_control_wipe_database(struct ctdb_context *ctdb, TDB_DATA indata)
720 struct ctdb_control_wipe_database w = *(struct ctdb_control_wipe_database *)indata.dptr;
721 struct ctdb_db_context *ctdb_db;
723 ctdb_db = find_ctdb_db(ctdb, w.db_id);
725 DEBUG(DEBUG_ERR,(__location__ " Unknown db 0x%x\n", w.db_id));
729 if (ctdb->freeze_mode[ctdb_db->priority] != CTDB_FREEZE_FROZEN) {
730 DEBUG(DEBUG_ERR,(__location__ " Failed transaction_start while not frozen\n"));
734 if (!ctdb->freeze_transaction_started) {
735 DEBUG(DEBUG_ERR,(__location__ " transaction not started\n"));
739 if (w.transaction_id != ctdb->freeze_transaction_id) {
740 DEBUG(DEBUG_ERR,(__location__ " incorrect transaction id 0x%x in commit\n", w.transaction_id));
744 if (tdb_wipe_all(ctdb_db->ltdb->tdb) != 0) {
745 DEBUG(DEBUG_ERR,(__location__ " Failed to wipe database for db '%s'\n",
750 if (!ctdb_db->persistent) {
751 talloc_free(ctdb_db->delete_queue);
752 ctdb_db->delete_queue = trbt_create(ctdb_db, 0);
753 if (ctdb_db->delete_queue == NULL) {
754 DEBUG(DEBUG_ERR, (__location__ " Failed to re-create "
755 "the vacuum tree.\n"));
763 bool ctdb_db_frozen(struct ctdb_db_context *ctdb_db)
765 if (ctdb_db->freeze_mode != CTDB_FREEZE_FROZEN) {
772 bool ctdb_db_prio_frozen(struct ctdb_context *ctdb, uint32_t priority)
777 if (priority > NUM_DB_PRIORITIES) {
778 DEBUG(DEBUG_ERR, ("Invalid DB priority specified\n"));
782 if (ctdb->freeze_mode[priority] != CTDB_FREEZE_FROZEN) {
789 bool ctdb_db_all_frozen(struct ctdb_context *ctdb)
793 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
794 if (ctdb->freeze_mode[i] != CTDB_FREEZE_FROZEN) {