2007-05-12 15:15:27 +10:00
/*
ctdb freeze handling
Copyright ( C ) Andrew Tridgell 2007
2007-05-31 13:50:53 +10:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-10 15:29:31 +10:00
the Free Software Foundation ; either version 3 of the License , or
2007-05-31 13:50:53 +10:00
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
2007-05-12 15:15:27 +10:00
but WITHOUT ANY WARRANTY ; without even the implied warranty of
2007-05-31 13:50:53 +10:00
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
2007-07-10 15:29:31 +10:00
along with this program ; if not , see < http : //www.gnu.org/licenses/>.
2007-05-12 15:15:27 +10:00
*/
# include "includes.h"
2010-08-18 09:16:31 +09:30
# include "lib/tevent/tevent.h"
2007-05-12 15:15:27 +10:00
# include "lib/tdb/include/tdb.h"
# include "system/network.h"
# include "system/filesys.h"
# include "system/wait.h"
# include "../include/ctdb_private.h"
# include "lib/util/dlinklist.h"
# include "db_wrap.h"
2010-12-17 02:22:02 +01:00
# include "../common/rb_tree.h"
2007-05-12 15:15:27 +10:00
2010-07-01 21:46:55 +10:00
static bool later_db ( const char * name )
{
return ( strstr ( name , " notify " ) | | strstr ( name , " serverid " ) ) ;
}
2007-05-12 15:15:27 +10:00
/*
lock all databases
*/
2009-10-12 12:08:39 +11:00
static int ctdb_lock_all_databases ( struct ctdb_context * ctdb , uint32_t priority )
2007-05-12 15:15:27 +10:00
{
struct ctdb_db_context * ctdb_db ;
2009-10-14 08:17:49 +11:00
/* REMOVE later */
/* This double loop is for backward compatibility and deadlock
avoidance for old samba versions that not yet support
the set prio call .
This code shall be removed later
*/
2007-05-12 15:15:27 +10:00
for ( ctdb_db = ctdb - > db_list ; ctdb_db ; ctdb_db = ctdb_db - > next ) {
2009-10-12 12:08:39 +11:00
if ( ctdb_db - > priority ! = priority ) {
continue ;
}
2010-07-01 21:46:55 +10:00
if ( later_db ( ctdb_db - > db_name ) ) {
2009-10-14 08:17:49 +11:00
continue ;
}
DEBUG ( DEBUG_INFO , ( " locking database 0x%08x priority:%u %s \n " , ctdb_db - > db_id , ctdb_db - > priority , ctdb_db - > db_name ) ) ;
if ( tdb_lockall ( ctdb_db - > ltdb - > tdb ) ! = 0 ) {
2010-06-08 12:09:19 +10:00
DEBUG ( DEBUG_ERR , ( __location__ " Failed to lock database %s \n " , ctdb_db - > db_name ) ) ;
2009-10-14 08:17:49 +11:00
return - 1 ;
}
}
for ( ctdb_db = ctdb - > db_list ; ctdb_db ; ctdb_db = ctdb_db - > next ) {
if ( ctdb_db - > priority ! = priority ) {
continue ;
}
2010-07-01 21:46:55 +10:00
if ( ! later_db ( ctdb_db - > db_name ) ) {
2009-10-14 08:17:49 +11:00
continue ;
}
2009-10-10 14:26:09 +11:00
DEBUG ( DEBUG_INFO , ( " locking database 0x%08x priority:%u %s \n " , ctdb_db - > db_id , ctdb_db - > priority , ctdb_db - > db_name ) ) ;
2007-05-12 15:15:27 +10:00
if ( tdb_lockall ( ctdb_db - > ltdb - > tdb ) ! = 0 ) {
2010-06-08 12:09:19 +10:00
DEBUG ( DEBUG_ERR , ( __location__ " Failed to lock database %s \n " , ctdb_db - > db_name ) ) ;
2007-05-12 15:15:27 +10:00
return - 1 ;
}
}
return 0 ;
}
/*
a list of control requests waiting for a freeze lock child to get
the database locks
*/
struct ctdb_freeze_waiter {
struct ctdb_freeze_waiter * next , * prev ;
struct ctdb_context * ctdb ;
struct ctdb_req_control * c ;
2009-10-12 12:08:39 +11:00
uint32_t priority ;
2007-05-12 15:15:27 +10:00
int32_t status ;
} ;
/* a handle to a freeze lock child process */
struct ctdb_freeze_handle {
struct ctdb_context * ctdb ;
2009-10-12 12:08:39 +11:00
uint32_t priority ;
2007-05-12 15:15:27 +10:00
pid_t child ;
int fd ;
struct ctdb_freeze_waiter * waiters ;
} ;
/*
destroy a freeze handle
*/
static int ctdb_freeze_handle_destructor ( struct ctdb_freeze_handle * h )
{
2008-07-07 08:50:12 +10:00
struct ctdb_context * ctdb = h - > ctdb ;
struct ctdb_db_context * ctdb_db ;
2009-10-12 12:08:39 +11:00
DEBUG ( DEBUG_ERR , ( " Release freeze handler for prio %u \n " , h - > priority ) ) ;
2008-07-07 08:50:12 +10:00
/* cancel any pending transactions */
2009-10-12 12:08:39 +11:00
if ( ctdb - > freeze_transaction_started ) {
2008-07-07 08:50:12 +10:00
for ( ctdb_db = ctdb - > db_list ; ctdb_db ; ctdb_db = ctdb_db - > next ) {
2009-10-12 12:08:39 +11:00
if ( ctdb_db - > priority ! = h - > priority ) {
continue ;
}
2008-07-07 08:50:12 +10:00
tdb_add_flags ( ctdb_db - > ltdb - > tdb , TDB_NOLOCK ) ;
if ( tdb_transaction_cancel ( ctdb_db - > ltdb - > tdb ) ! = 0 ) {
DEBUG ( DEBUG_ERR , ( __location__ " Failed to cancel transaction for db '%s' \n " ,
ctdb_db - > db_name ) ) ;
}
tdb_remove_flags ( ctdb_db - > ltdb - > tdb , TDB_NOLOCK ) ;
}
2009-10-12 12:08:39 +11:00
ctdb - > freeze_transaction_started = false ;
2008-07-07 08:50:12 +10:00
}
2009-10-12 12:08:39 +11:00
ctdb - > freeze_mode [ h - > priority ] = CTDB_FREEZE_NONE ;
ctdb - > freeze_handles [ h - > priority ] = NULL ;
2008-07-07 08:50:12 +10:00
2007-05-12 15:15:27 +10:00
kill ( h - > child , SIGKILL ) ;
return 0 ;
}
/*
called when the child writes its status to us
*/
static void ctdb_freeze_lock_handler ( struct event_context * ev , struct fd_event * fde ,
uint16_t flags , void * private_data )
{
struct ctdb_freeze_handle * h = talloc_get_type ( private_data , struct ctdb_freeze_handle ) ;
int32_t status ;
struct ctdb_freeze_waiter * w ;
2009-10-12 12:08:39 +11:00
if ( h - > ctdb - > freeze_mode [ h - > priority ] = = CTDB_FREEZE_FROZEN ) {
2008-02-04 20:07:15 +11:00
DEBUG ( DEBUG_INFO , ( " freeze child died - unfreezing \n " ) ) ;
2007-05-12 15:59:49 +10:00
talloc_free ( h ) ;
return ;
}
2007-05-12 15:15:27 +10:00
if ( read ( h - > fd , & status , sizeof ( status ) ) ! = sizeof ( status ) ) {
2008-02-04 20:07:15 +11:00
DEBUG ( DEBUG_ERR , ( " read error from freeze lock child \n " ) ) ;
2007-05-12 15:15:27 +10:00
status = - 1 ;
}
if ( status = = - 1 ) {
2008-02-04 20:07:15 +11:00
DEBUG ( DEBUG_ERR , ( " Failed to get locks in ctdb_freeze_child \n " ) ) ;
2007-05-12 15:15:27 +10:00
/* we didn't get the locks - destroy the handle */
talloc_free ( h ) ;
return ;
}
2009-10-12 12:08:39 +11:00
h - > ctdb - > freeze_mode [ h - > priority ] = CTDB_FREEZE_FROZEN ;
2007-05-12 15:15:27 +10:00
/* notify the waiters */
2009-10-22 13:41:28 +11:00
if ( h ! = h - > ctdb - > freeze_handles [ h - > priority ] ) {
DEBUG ( DEBUG_ERR , ( " lockwait finished but h is not linked \n " ) ) ;
}
while ( ( w = h - > waiters ) ) {
2007-05-12 15:15:27 +10:00
w - > status = status ;
2009-10-22 13:41:28 +11:00
DLIST_REMOVE ( h - > waiters , w ) ;
2007-05-12 15:15:27 +10:00
talloc_free ( w ) ;
}
}
/*
create a child which gets locks on all the open databases , then calls the callback telling the parent
that it is done
*/
2009-10-12 12:08:39 +11:00
static struct ctdb_freeze_handle * ctdb_freeze_lock ( struct ctdb_context * ctdb , uint32_t priority )
2007-05-12 15:15:27 +10:00
{
struct ctdb_freeze_handle * h ;
int fd [ 2 ] ;
struct fd_event * fde ;
h = talloc_zero ( ctdb , struct ctdb_freeze_handle ) ;
2008-07-04 17:04:26 +10:00
CTDB_NO_MEMORY_NULL ( ctdb , h ) ;
2007-05-12 15:15:27 +10:00
2009-10-12 12:08:39 +11:00
h - > ctdb = ctdb ;
h - > priority = priority ;
2007-05-12 15:15:27 +10:00
2009-11-26 12:08:35 +11:00
if ( pipe ( fd ) = = - 1 ) {
2008-02-04 20:07:15 +11:00
DEBUG ( DEBUG_ERR , ( " Failed to create pipe for ctdb_freeze_lock \n " ) ) ;
2007-05-12 15:15:27 +10:00
talloc_free ( h ) ;
return NULL ;
}
h - > child = fork ( ) ;
if ( h - > child = = - 1 ) {
2008-02-04 20:07:15 +11:00
DEBUG ( DEBUG_ERR , ( " Failed to fork child for ctdb_freeze_lock \n " ) ) ;
2007-05-12 15:15:27 +10:00
talloc_free ( h ) ;
return NULL ;
}
if ( h - > child = = 0 ) {
int ret ;
2009-11-26 12:08:35 +11:00
2007-05-12 15:15:27 +10:00
/* in the child */
close ( fd [ 0 ] ) ;
2009-11-26 12:08:35 +11:00
2010-07-19 19:29:09 +09:30
debug_extra = talloc_asprintf ( NULL , " freeze_lock-%u: " , priority ) ;
2009-10-12 12:08:39 +11:00
ret = ctdb_lock_all_databases ( ctdb , priority ) ;
2007-05-12 15:15:27 +10:00
if ( ret ! = 0 ) {
_exit ( 0 ) ;
}
2008-06-26 11:02:08 +10:00
2009-11-26 12:08:35 +11:00
ret = write ( fd [ 1 ] , & ret , sizeof ( ret ) ) ;
if ( ret ! = sizeof ( ret ) ) {
2008-06-26 14:00:36 +10:00
DEBUG ( DEBUG_ERR , ( __location__ " Failed to write to socket from freeze child. ret:%d errno:%u \n " , ret , errno ) ) ;
2009-11-26 12:08:35 +11:00
_exit ( 1 ) ;
2008-06-26 09:54:27 +10:00
}
2009-11-26 12:08:35 +11:00
while ( 1 ) {
sleep ( 1 ) ;
if ( kill ( ctdb - > ctdbd_pid , 0 ) ! = 0 ) {
DEBUG ( DEBUG_ERR , ( " Parent died. Exiting lock wait child \n " ) ) ;
_exit ( 0 ) ;
}
}
2007-05-12 15:15:27 +10:00
}
talloc_set_destructor ( h , ctdb_freeze_handle_destructor ) ;
close ( fd [ 1 ] ) ;
2009-11-26 12:08:35 +11:00
set_close_on_exec ( fd [ 0 ] ) ;
2007-05-12 15:15:27 +10:00
h - > fd = fd [ 0 ] ;
2009-11-26 12:08:35 +11:00
2010-08-18 09:16:31 +09:30
fde = event_add_fd ( ctdb - > ev , h , h - > fd , EVENT_FD_READ ,
2007-05-12 15:15:27 +10:00
ctdb_freeze_lock_handler , h ) ;
if ( fde = = NULL ) {
2008-02-04 20:07:15 +11:00
DEBUG ( DEBUG_ERR , ( " Failed to setup fd event for ctdb_freeze_lock \n " ) ) ;
2007-05-12 15:15:27 +10:00
close ( fd [ 0 ] ) ;
talloc_free ( h ) ;
return NULL ;
}
2010-08-18 09:16:31 +09:30
tevent_fd_set_auto_close ( fde ) ;
2007-05-12 15:15:27 +10:00
return h ;
}
/*
destroy a waiter for a freeze mode change
*/
static int ctdb_freeze_waiter_destructor ( struct ctdb_freeze_waiter * w )
{
2007-05-12 21:25:26 +10:00
ctdb_request_control_reply ( w - > ctdb , w - > c , NULL , w - > status , NULL ) ;
2007-05-12 15:15:27 +10:00
return 0 ;
}
/*
2009-10-12 12:08:39 +11:00
start the freeze process for a certain priority
2007-05-12 15:15:27 +10:00
*/
2009-10-12 12:08:39 +11:00
int ctdb_start_freeze ( struct ctdb_context * ctdb , uint32_t priority )
2007-05-12 15:15:27 +10:00
{
2009-10-14 10:14:03 +11:00
if ( priority = = 0 ) {
DEBUG ( DEBUG_ERR , ( " Freeze priority 0 requested, remapping to priority 1 \n " ) ) ;
priority = 1 ;
}
2009-10-12 12:08:39 +11:00
if ( ( priority < 1 ) | | ( priority > NUM_DB_PRIORITIES ) ) {
DEBUG ( DEBUG_ERR , ( __location__ " Invalid db priority : %u \n " , priority ) ) ;
return - 1 ;
}
if ( ctdb - > freeze_mode [ priority ] = = CTDB_FREEZE_FROZEN ) {
2007-05-12 15:15:27 +10:00
/* we're already frozen */
2009-10-12 12:08:39 +11:00
return 0 ;
2007-05-12 15:15:27 +10:00
}
2010-07-21 12:29:55 +09:30
/* Stop any vacuuming going on: we don't want to wait. */
ctdb_stop_vacuuming ( ctdb ) ;
2007-05-12 15:15:27 +10:00
/* if there isn't a freeze lock child then create one */
2009-10-22 13:41:28 +11:00
if ( ctdb - > freeze_handles [ priority ] = = NULL ) {
2009-10-12 12:08:39 +11:00
ctdb - > freeze_handles [ priority ] = ctdb_freeze_lock ( ctdb , priority ) ;
CTDB_NO_MEMORY ( ctdb , ctdb - > freeze_handles [ priority ] ) ;
ctdb - > freeze_mode [ priority ] = CTDB_FREEZE_PENDING ;
2007-05-12 15:15:27 +10:00
}
2009-10-12 12:08:39 +11:00
return 0 ;
2007-06-10 08:46:33 +10:00
}
/*
freeze the databases
*/
int32_t ctdb_control_freeze ( struct ctdb_context * ctdb , struct ctdb_req_control * c , bool * async_reply )
{
struct ctdb_freeze_waiter * w ;
2009-10-12 09:22:17 +11:00
uint32_t priority ;
priority = ( uint32_t ) c - > srvid ;
2007-06-10 08:46:33 +10:00
2009-10-12 12:08:39 +11:00
DEBUG ( DEBUG_ERR , ( " Freeze priority %u \n " , priority ) ) ;
2009-10-14 10:14:03 +11:00
if ( priority = = 0 ) {
DEBUG ( DEBUG_ERR , ( " Freeze priority 0 requested, remapping to priority 1 \n " ) ) ;
priority = 1 ;
}
2009-10-12 12:08:39 +11:00
if ( ( priority < 1 ) | | ( priority > NUM_DB_PRIORITIES ) ) {
DEBUG ( DEBUG_ERR , ( __location__ " Invalid db priority : %u \n " , priority ) ) ;
return - 1 ;
}
if ( ctdb - > freeze_mode [ priority ] = = CTDB_FREEZE_FROZEN ) {
2007-06-10 08:46:33 +10:00
/* we're already frozen */
return 0 ;
}
2009-10-12 12:08:39 +11:00
if ( ctdb_start_freeze ( ctdb , priority ) ! = 0 ) {
DEBUG ( DEBUG_ERR , ( __location__ " Failed to start freezing databases with priority %u \n " , priority ) ) ;
return - 1 ;
}
2007-05-12 15:15:27 +10:00
/* add ourselves to list of waiters */
2009-10-22 13:41:28 +11:00
if ( ctdb - > freeze_handles [ priority ] = = NULL ) {
DEBUG ( DEBUG_ERR , ( " No freeze lock handle when adding a waiter \n " ) ) ;
return - 1 ;
}
2009-10-12 12:08:39 +11:00
w = talloc ( ctdb - > freeze_handles [ priority ] , struct ctdb_freeze_waiter ) ;
2007-05-12 15:15:27 +10:00
CTDB_NO_MEMORY ( ctdb , w ) ;
2009-10-12 12:08:39 +11:00
w - > ctdb = ctdb ;
w - > c = talloc_steal ( w , c ) ;
w - > priority = priority ;
w - > status = - 1 ;
2007-05-12 15:15:27 +10:00
talloc_set_destructor ( w , ctdb_freeze_waiter_destructor ) ;
2009-10-12 12:08:39 +11:00
DLIST_ADD ( ctdb - > freeze_handles [ priority ] - > waiters , w ) ;
2007-05-12 15:15:27 +10:00
/* we won't reply till later */
* async_reply = True ;
return 0 ;
}
2007-05-23 12:23:07 +10:00
/*
block until we are frozen , used during daemon startup
*/
bool ctdb_blocking_freeze ( struct ctdb_context * ctdb )
{
2009-10-12 12:08:39 +11:00
int i ;
for ( i = 1 ; i < = NUM_DB_PRIORITIES ; i + + ) {
if ( ctdb_start_freeze ( ctdb , i ) ) {
DEBUG ( DEBUG_ERR , ( __location__ " Failed to freeze databases of prio %u \n " , i ) ) ;
continue ;
}
2007-05-23 12:23:07 +10:00
2009-10-12 12:08:39 +11:00
/* block until frozen */
while ( ctdb - > freeze_mode [ i ] = = CTDB_FREEZE_PENDING ) {
event_loop_once ( ctdb - > ev ) ;
}
2007-05-23 12:23:07 +10:00
}
2009-10-12 12:08:39 +11:00
return 0 ;
2007-05-23 12:23:07 +10:00
}
2009-10-12 12:08:39 +11:00
static void thaw_priority ( struct ctdb_context * ctdb , uint32_t priority )
2007-05-12 15:15:27 +10:00
{
2009-10-12 12:08:39 +11:00
DEBUG ( DEBUG_ERR , ( " Thawing priority %u \n " , priority ) ) ;
2009-10-12 09:22:17 +11:00
2008-01-06 12:38:01 +11:00
/* cancel any pending transactions */
2009-10-12 12:08:39 +11:00
if ( ctdb - > freeze_transaction_started ) {
2008-01-06 12:38:01 +11:00
struct ctdb_db_context * ctdb_db ;
for ( ctdb_db = ctdb - > db_list ; ctdb_db ; ctdb_db = ctdb_db - > next ) {
tdb_add_flags ( ctdb_db - > ltdb - > tdb , TDB_NOLOCK ) ;
if ( tdb_transaction_cancel ( ctdb_db - > ltdb - > tdb ) ! = 0 ) {
2008-02-04 20:07:15 +11:00
DEBUG ( DEBUG_ERR , ( __location__ " Failed to cancel transaction for db '%s' \n " ,
2008-01-06 12:38:01 +11:00
ctdb_db - > db_name ) ) ;
}
tdb_remove_flags ( ctdb_db - > ltdb - > tdb , TDB_NOLOCK ) ;
}
}
2009-10-12 12:08:39 +11:00
ctdb - > freeze_transaction_started = false ;
2008-01-06 12:38:01 +11:00
2008-01-05 09:36:21 +11:00
#if 0
/* this hack can be used to get a copy of the databases at the end of a recovery */
system ( " mkdir -p /var/ctdb.saved; /usr/bin/rsync --delete -a /var/ctdb/ /var/ctdb.saved/$$ 2>&1 > /dev/null " ) ;
# endif
2008-01-06 12:38:01 +11:00
#if 0
/* and this one for local testing */
system ( " mkdir -p test.db.saved; /usr/bin/rsync --delete -a test.db/ test.db.saved/$$ 2>&1 > /dev/null " ) ;
# endif
2009-10-22 13:41:28 +11:00
if ( ctdb - > freeze_handles [ priority ] ! = NULL ) {
talloc_free ( ctdb - > freeze_handles [ priority ] ) ;
ctdb - > freeze_handles [ priority ] = NULL ;
}
2009-10-12 12:08:39 +11:00
}
/*
thaw the databases
*/
int32_t ctdb_control_thaw ( struct ctdb_context * ctdb , uint32_t priority )
{
if ( priority > NUM_DB_PRIORITIES ) {
DEBUG ( DEBUG_ERR , ( __location__ " Invalid db priority : %u \n " , priority ) ) ;
return - 1 ;
}
if ( priority = = 0 ) {
int i ;
for ( i = 1 ; i < = NUM_DB_PRIORITIES ; i + + ) {
thaw_priority ( ctdb , i ) ;
}
} else {
thaw_priority ( ctdb , priority ) ;
}
2008-01-06 12:38:01 +11:00
2007-05-19 00:56:49 +10:00
ctdb_call_resend_all ( ctdb ) ;
2007-05-12 15:15:27 +10:00
return 0 ;
}
2008-01-06 12:38:01 +11:00
/*
start a transaction on all databases - used for recovery
*/
2008-01-06 13:24:55 +11:00
int32_t ctdb_control_transaction_start ( struct ctdb_context * ctdb , uint32_t id )
2008-01-06 12:38:01 +11:00
{
struct ctdb_db_context * ctdb_db ;
2009-10-12 12:08:39 +11:00
int i ;
2008-01-06 12:38:01 +11:00
2009-10-12 12:08:39 +11:00
for ( i = 1 ; i < = NUM_DB_PRIORITIES ; i + + ) {
if ( ctdb - > freeze_mode [ i ] ! = CTDB_FREEZE_FROZEN ) {
DEBUG ( DEBUG_ERR , ( __location__ " Failed transaction_start while not frozen \n " ) ) ;
return - 1 ;
}
2008-01-06 12:38:01 +11:00
}
for ( ctdb_db = ctdb - > db_list ; ctdb_db ; ctdb_db = ctdb_db - > next ) {
int ret ;
tdb_add_flags ( ctdb_db - > ltdb - > tdb , TDB_NOLOCK ) ;
2009-10-12 12:08:39 +11:00
if ( ctdb - > freeze_transaction_started ) {
2008-01-06 12:38:01 +11:00
if ( tdb_transaction_cancel ( ctdb_db - > ltdb - > tdb ) ! = 0 ) {
2008-02-04 20:07:15 +11:00
DEBUG ( DEBUG_ERR , ( __location__ " Failed to cancel transaction for db '%s' \n " ,
2008-01-06 12:38:01 +11:00
ctdb_db - > db_name ) ) ;
/* not a fatal error */
}
}
ret = tdb_transaction_start ( ctdb_db - > ltdb - > tdb ) ;
tdb_remove_flags ( ctdb_db - > ltdb - > tdb , TDB_NOLOCK ) ;
if ( ret ! = 0 ) {
2008-02-04 20:07:15 +11:00
DEBUG ( DEBUG_ERR , ( __location__ " Failed to start transaction for db '%s' \n " ,
2008-01-06 12:38:01 +11:00
ctdb_db - > db_name ) ) ;
return - 1 ;
}
}
2009-10-12 12:08:39 +11:00
ctdb - > freeze_transaction_started = true ;
ctdb - > freeze_transaction_id = id ;
2008-01-06 12:38:01 +11:00
return 0 ;
}
2009-10-12 16:48:05 +11:00
/*
cancel a transaction for all databases - used for recovery
*/
int32_t ctdb_control_transaction_cancel ( struct ctdb_context * ctdb )
{
struct ctdb_db_context * ctdb_db ;
DEBUG ( DEBUG_ERR , ( __location__ " recovery transaction cancelled called \n " ) ) ;
for ( ctdb_db = ctdb - > db_list ; ctdb_db ; ctdb_db = ctdb_db - > next ) {
tdb_add_flags ( ctdb_db - > ltdb - > tdb , TDB_NOLOCK ) ;
if ( tdb_transaction_cancel ( ctdb_db - > ltdb - > tdb ) ! = 0 ) {
DEBUG ( DEBUG_ERR , ( __location__ " Failed to cancel transaction for db '%s' \n " , ctdb_db - > db_name ) ) ;
/* not a fatal error */
}
tdb_remove_flags ( ctdb_db - > ltdb - > tdb , TDB_NOLOCK ) ;
}
ctdb - > freeze_transaction_started = false ;
return 0 ;
}
2008-01-06 12:38:01 +11:00
/*
commit transactions on all databases
*/
2008-01-06 13:24:55 +11:00
int32_t ctdb_control_transaction_commit ( struct ctdb_context * ctdb , uint32_t id )
2008-01-06 12:38:01 +11:00
{
struct ctdb_db_context * ctdb_db ;
2009-10-12 12:08:39 +11:00
int i ;
2009-12-07 13:28:11 +01:00
int healthy_nodes = 0 ;
2009-10-12 12:08:39 +11:00
for ( i = 1 ; i < = NUM_DB_PRIORITIES ; i + + ) {
if ( ctdb - > freeze_mode [ i ] ! = CTDB_FREEZE_FROZEN ) {
DEBUG ( DEBUG_ERR , ( __location__ " Failed transaction_start while not frozen \n " ) ) ;
return - 1 ;
}
2008-01-06 12:38:01 +11:00
}
2009-10-12 12:08:39 +11:00
if ( ! ctdb - > freeze_transaction_started ) {
2008-02-04 20:07:15 +11:00
DEBUG ( DEBUG_ERR , ( __location__ " transaction not started \n " ) ) ;
2008-01-06 12:38:01 +11:00
return - 1 ;
}
2009-10-12 12:08:39 +11:00
if ( id ! = ctdb - > freeze_transaction_id ) {
2008-02-04 20:07:15 +11:00
DEBUG ( DEBUG_ERR , ( __location__ " incorrect transaction id 0x%x in commit \n " , id ) ) ;
2008-01-06 13:24:55 +11:00
return - 1 ;
}
2009-12-07 13:28:11 +01:00
DEBUG ( DEBUG_DEBUG , ( __location__ " num_nodes[%d] \n " , ctdb - > num_nodes ) ) ;
for ( i = 0 ; i < ctdb - > num_nodes ; i + + ) {
DEBUG ( DEBUG_DEBUG , ( __location__ " node[%d].flags[0x%X] \n " ,
i , ctdb - > nodes [ i ] - > flags ) ) ;
if ( ctdb - > nodes [ i ] - > flags = = 0 ) {
healthy_nodes + + ;
}
}
DEBUG ( DEBUG_INFO , ( __location__ " healthy_nodes[%d] \n " , healthy_nodes ) ) ;
2008-01-06 12:38:01 +11:00
for ( ctdb_db = ctdb - > db_list ; ctdb_db ; ctdb_db = ctdb_db - > next ) {
2009-12-07 13:19:33 +01:00
int ret ;
2008-01-06 12:38:01 +11:00
tdb_add_flags ( ctdb_db - > ltdb - > tdb , TDB_NOLOCK ) ;
2009-12-07 13:19:33 +01:00
ret = tdb_transaction_commit ( ctdb_db - > ltdb - > tdb ) ;
if ( ret ! = 0 ) {
2008-07-07 08:51:05 +10:00
DEBUG ( DEBUG_ERR , ( __location__ " Failed to commit transaction for db '%s'. Cancel all transactions and resetting transaction_started to false. \n " ,
2008-01-06 12:38:01 +11:00
ctdb_db - > db_name ) ) ;
2009-12-07 13:19:33 +01:00
goto fail ;
2008-01-06 12:38:01 +11:00
}
tdb_remove_flags ( ctdb_db - > ltdb - > tdb , TDB_NOLOCK ) ;
2009-12-07 13:28:11 +01:00
ret = ctdb_update_persistent_health ( ctdb , ctdb_db , NULL , healthy_nodes ) ;
if ( ret ! = 0 ) {
DEBUG ( DEBUG_CRIT , ( __location__ " Failed to update persistent health for db '%s'. "
" Cancel all remaining transactions and resetting transaction_started to false. \n " ,
ctdb_db - > db_name ) ) ;
goto fail ;
}
2008-01-06 12:38:01 +11:00
}
2009-10-12 12:08:39 +11:00
ctdb - > freeze_transaction_started = false ;
ctdb - > freeze_transaction_id = 0 ;
2008-01-06 12:38:01 +11:00
return 0 ;
2009-12-07 13:19:33 +01:00
fail :
/* cancel any pending transactions */
for ( ctdb_db = ctdb - > db_list ; ctdb_db ; ctdb_db = ctdb_db - > next ) {
tdb_add_flags ( ctdb_db - > ltdb - > tdb , TDB_NOLOCK ) ;
if ( tdb_transaction_cancel ( ctdb_db - > ltdb - > tdb ) ! = 0 ) {
DEBUG ( DEBUG_ERR , ( __location__ " Failed to cancel transaction for db '%s' \n " ,
ctdb_db - > db_name ) ) ;
}
tdb_remove_flags ( ctdb_db - > ltdb - > tdb , TDB_NOLOCK ) ;
}
ctdb - > freeze_transaction_started = false ;
return - 1 ;
2008-01-06 12:38:01 +11:00
}
/*
wipe a database - only possible when in a frozen transaction
*/
int32_t ctdb_control_wipe_database ( struct ctdb_context * ctdb , TDB_DATA indata )
{
2008-01-06 13:24:55 +11:00
struct ctdb_control_wipe_database w = * ( struct ctdb_control_wipe_database * ) indata . dptr ;
2008-01-06 12:38:01 +11:00
struct ctdb_db_context * ctdb_db ;
2009-10-12 12:08:39 +11:00
ctdb_db = find_ctdb_db ( ctdb , w . db_id ) ;
if ( ! ctdb_db ) {
DEBUG ( DEBUG_ERR , ( __location__ " Unknown db 0x%x \n " , w . db_id ) ) ;
2008-01-06 12:38:01 +11:00
return - 1 ;
}
2009-10-12 12:08:39 +11:00
if ( ctdb - > freeze_mode [ ctdb_db - > priority ] ! = CTDB_FREEZE_FROZEN ) {
DEBUG ( DEBUG_ERR , ( __location__ " Failed transaction_start while not frozen \n " ) ) ;
2008-01-06 12:38:01 +11:00
return - 1 ;
}
2009-10-12 12:08:39 +11:00
if ( ! ctdb - > freeze_transaction_started ) {
DEBUG ( DEBUG_ERR , ( __location__ " transaction not started \n " ) ) ;
2008-01-06 13:24:55 +11:00
return - 1 ;
}
2009-10-12 12:08:39 +11:00
if ( w . transaction_id ! = ctdb - > freeze_transaction_id ) {
DEBUG ( DEBUG_ERR , ( __location__ " incorrect transaction id 0x%x in commit \n " , w . transaction_id ) ) ;
2008-01-06 12:38:01 +11:00
return - 1 ;
}
if ( tdb_wipe_all ( ctdb_db - > ltdb - > tdb ) ! = 0 ) {
2008-02-04 20:07:15 +11:00
DEBUG ( DEBUG_ERR , ( __location__ " Failed to wipe database for db '%s' \n " ,
2008-01-06 12:38:01 +11:00
ctdb_db - > db_name ) ) ;
return - 1 ;
}
2010-12-17 02:22:02 +01:00
if ( ! ctdb_db - > persistent ) {
talloc_free ( ctdb_db - > delete_queue ) ;
ctdb_db - > delete_queue = trbt_create ( ctdb_db , 0 ) ;
if ( ctdb_db - > delete_queue = = NULL ) {
DEBUG ( DEBUG_ERR , ( __location__ " Failed to re-create "
" the vacuum tree. \n " ) ) ;
return - 1 ;
}
}
2008-01-06 12:38:01 +11:00
return 0 ;
}