2007-04-26 16:27:49 +04:00
/*
ctdb_control protocol code
Copyright ( C ) Andrew Tridgell 2007
This library is free software ; you can redistribute it and / or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation ; either
version 2 of the License , or ( at your option ) any later version .
This library is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
Lesser General Public License for more details .
You should have received a copy of the GNU Lesser General Public
License along with this library ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
# include "includes.h"
# include "lib/events/events.h"
# 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"
2007-04-28 23:47:13 +04:00
# include "db_wrap.h"
2007-04-26 16:27:49 +04:00
struct ctdb_control_state {
struct ctdb_context * ctdb ;
uint32_t reqid ;
ctdb_control_callback_fn_t callback ;
void * private_data ;
} ;
/*
process a control request
*/
static int32_t ctdb_control_dispatch ( struct ctdb_context * ctdb ,
2007-05-12 09:15:27 +04:00
struct ctdb_req_control * c ,
2007-05-04 05:41:29 +04:00
TDB_DATA indata ,
2007-05-12 09:15:27 +04:00
TDB_DATA * outdata , uint32_t srcnode ,
2007-05-12 15:25:26 +04:00
const char * * errormsg ,
2007-05-12 09:15:27 +04:00
bool * async_reply )
2007-04-26 16:27:49 +04:00
{
2007-05-12 09:15:27 +04:00
uint32_t opcode = c - > opcode ;
uint64_t srvid = c - > srvid ;
uint32_t client_id = c - > client_id ;
2007-04-26 16:27:49 +04:00
switch ( opcode ) {
case CTDB_CONTROL_PROCESS_EXISTS : {
2007-05-05 02:11:54 +04:00
CHECK_CONTROL_DATA_SIZE ( sizeof ( pid_t ) ) ;
ctdb - > status . controls . process_exists + + ;
return kill ( * ( pid_t * ) indata . dptr , 0 ) ;
2007-04-26 16:27:49 +04:00
}
2007-04-26 21:27:07 +04:00
2007-04-27 17:14:36 +04:00
case CTDB_CONTROL_SET_DEBUG : {
CHECK_CONTROL_DATA_SIZE ( sizeof ( uint32_t ) ) ;
LogLevel = * ( uint32_t * ) indata . dptr ;
return 0 ;
}
case CTDB_CONTROL_GET_DEBUG : {
CHECK_CONTROL_DATA_SIZE ( 0 ) ;
outdata - > dptr = ( uint8_t * ) & LogLevel ;
outdata - > dsize = sizeof ( LogLevel ) ;
return 0 ;
}
2007-04-26 16:51:41 +04:00
case CTDB_CONTROL_STATUS : {
2007-04-27 16:49:44 +04:00
CHECK_CONTROL_DATA_SIZE ( 0 ) ;
2007-05-05 02:11:54 +04:00
ctdb - > status . controls . status + + ;
2007-05-05 02:33:35 +04:00
ctdb - > status . memory_used = talloc_total_size ( ctdb ) ;
2007-05-12 09:51:08 +04:00
ctdb - > status . frozen = ( ctdb - > freeze_mode = = CTDB_FREEZE_FROZEN ) ;
ctdb - > status . recovering = ( ctdb - > recovery_mode = = CTDB_RECOVERY_ACTIVE ) ;
2007-04-26 16:51:41 +04:00
outdata - > dptr = ( uint8_t * ) & ctdb - > status ;
outdata - > dsize = sizeof ( ctdb - > status ) ;
return 0 ;
}
2007-04-26 21:27:07 +04:00
2007-05-05 05:03:10 +04:00
case CTDB_CONTROL_DUMP_MEMORY : {
CHECK_CONTROL_DATA_SIZE ( 0 ) ;
talloc_report_full ( ctdb , stdout ) ;
return 0 ;
}
2007-04-28 21:13:36 +04:00
case CTDB_CONTROL_STATUS_RESET : {
CHECK_CONTROL_DATA_SIZE ( 0 ) ;
ZERO_STRUCT ( ctdb - > status ) ;
return 0 ;
}
2007-05-03 05:06:24 +04:00
case CTDB_CONTROL_GETVNNMAP :
return ctdb_control_getvnnmap ( ctdb , opcode , indata , outdata ) ;
2007-04-27 14:56:10 +04:00
2007-05-03 07:07:34 +04:00
case CTDB_CONTROL_GET_DBMAP :
return ctdb_control_getdbmap ( ctdb , opcode , indata , outdata ) ;
2007-04-28 14:00:50 +04:00
2007-05-03 07:30:38 +04:00
case CTDB_CONTROL_GET_NODEMAP :
return ctdb_control_getnodemap ( ctdb , opcode , indata , outdata ) ;
2007-04-28 14:40:26 +04:00
2007-05-03 05:06:24 +04:00
case CTDB_CONTROL_SETVNNMAP :
return ctdb_control_setvnnmap ( ctdb , opcode , indata , outdata ) ;
2007-04-27 16:08:12 +04:00
2007-05-10 11:43:45 +04:00
case CTDB_CONTROL_PULL_DB :
CHECK_CONTROL_DATA_SIZE ( sizeof ( struct ctdb_control_pulldb ) ) ;
return ctdb_control_pull_db ( ctdb , indata , outdata ) ;
2007-04-28 23:47:13 +04:00
2007-05-10 11:43:45 +04:00
case CTDB_CONTROL_SET_DMASTER :
CHECK_CONTROL_DATA_SIZE ( sizeof ( struct ctdb_control_set_dmaster ) ) ;
return ctdb_control_set_dmaster ( ctdb , indata ) ;
2007-04-28 23:47:13 +04:00
2007-05-10 11:43:45 +04:00
case CTDB_CONTROL_CLEAR_DB :
CHECK_CONTROL_DATA_SIZE ( sizeof ( uint32_t ) ) ;
return ctdb_control_clear_db ( ctdb , indata ) ;
2007-04-28 23:47:13 +04:00
2007-05-10 11:43:45 +04:00
case CTDB_CONTROL_PUSH_DB :
return ctdb_control_push_db ( ctdb , indata ) ;
2007-05-02 15:00:02 +04:00
2007-04-29 16:51:56 +04:00
case CTDB_CONTROL_GET_RECMODE : {
2007-05-06 02:05:22 +04:00
return ctdb - > recovery_mode ;
2007-04-29 16:51:56 +04:00
}
2007-05-06 23:02:48 +04:00
case CTDB_CONTROL_SET_RECMASTER : {
2007-05-14 07:48:14 +04:00
CHECK_CONTROL_DATA_SIZE ( sizeof ( uint32_t ) ) ;
if ( ctdb - > freeze_mode ! = CTDB_FREEZE_FROZEN ) {
DEBUG ( 0 , ( " Attempt to set recmaster when not frozen \n " ) ) ;
return - 1 ;
}
2007-05-06 23:02:48 +04:00
ctdb - > recovery_master = ( ( uint32_t * ) ( & indata . dptr [ 0 ] ) ) [ 0 ] ;
return 0 ;
}
2007-05-15 04:17:16 +04:00
case CTDB_CONTROL_GET_RECMASTER :
2007-05-06 23:02:48 +04:00
return ctdb - > recovery_master ;
2007-05-15 04:17:16 +04:00
case CTDB_CONTROL_GET_PID :
2007-05-06 02:05:22 +04:00
return getpid ( ) ;
2007-05-15 04:17:16 +04:00
case CTDB_CONTROL_GET_VNN :
return ctdb - > vnn ;
2007-05-05 22:31:22 +04:00
2007-04-26 21:27:07 +04:00
case CTDB_CONTROL_CONFIG : {
2007-04-27 16:49:44 +04:00
CHECK_CONTROL_DATA_SIZE ( 0 ) ;
2007-05-05 02:11:54 +04:00
ctdb - > status . controls . get_config + + ;
2007-04-26 21:27:07 +04:00
outdata - > dptr = ( uint8_t * ) ctdb ;
outdata - > dsize = sizeof ( * ctdb ) ;
return 0 ;
}
case CTDB_CONTROL_PING :
2007-04-27 16:49:44 +04:00
CHECK_CONTROL_DATA_SIZE ( 0 ) ;
2007-05-05 02:11:54 +04:00
ctdb - > status . controls . ping + + ;
2007-05-05 08:09:46 +04:00
return ctdb - > status . num_clients ;
2007-04-26 21:27:07 +04:00
2007-05-04 09:21:40 +04:00
case CTDB_CONTROL_GET_DBNAME : {
uint32_t db_id ;
struct ctdb_db_context * ctdb_db ;
CHECK_CONTROL_DATA_SIZE ( sizeof ( db_id ) ) ;
db_id = * ( uint32_t * ) indata . dptr ;
ctdb_db = find_ctdb_db ( ctdb , db_id ) ;
if ( ctdb_db = = NULL ) return - 1 ;
outdata - > dptr = discard_const ( ctdb_db - > db_name ) ;
outdata - > dsize = strlen ( ctdb_db - > db_name ) + 1 ;
return 0 ;
}
2007-04-27 01:10:35 +04:00
case CTDB_CONTROL_GETDBPATH : {
uint32_t db_id ;
struct ctdb_db_context * ctdb_db ;
2007-04-27 17:14:36 +04:00
CHECK_CONTROL_DATA_SIZE ( sizeof ( db_id ) ) ;
2007-04-27 01:10:35 +04:00
db_id = * ( uint32_t * ) indata . dptr ;
ctdb_db = find_ctdb_db ( ctdb , db_id ) ;
if ( ctdb_db = = NULL ) return - 1 ;
outdata - > dptr = discard_const ( ctdb_db - > db_path ) ;
2007-04-27 01:29:26 +04:00
outdata - > dsize = strlen ( ctdb_db - > db_path ) + 1 ;
2007-04-27 01:10:35 +04:00
return 0 ;
}
2007-04-30 17:31:40 +04:00
case CTDB_CONTROL_DB_ATTACH :
2007-05-05 02:11:54 +04:00
ctdb - > status . controls . attach + + ;
2007-04-30 17:31:40 +04:00
return ctdb_control_db_attach ( ctdb , indata , outdata ) ;
case CTDB_CONTROL_SET_CALL : {
2007-05-02 15:00:02 +04:00
struct ctdb_control_set_call * sc =
2007-04-30 17:31:40 +04:00
( struct ctdb_control_set_call * ) indata . dptr ;
2007-05-05 02:11:54 +04:00
ctdb - > status . controls . set_call + + ;
2007-04-30 17:31:40 +04:00
CHECK_CONTROL_DATA_SIZE ( sizeof ( struct ctdb_control_set_call ) ) ;
2007-05-02 15:00:02 +04:00
return ctdb_daemon_set_call ( ctdb , sc - > db_id , sc - > fn , sc - > id ) ;
2007-04-30 17:31:40 +04:00
}
2007-05-03 11:12:23 +04:00
case CTDB_CONTROL_TRAVERSE_START :
CHECK_CONTROL_DATA_SIZE ( sizeof ( struct ctdb_traverse_start ) ) ;
2007-05-05 02:11:54 +04:00
ctdb - > status . controls . traverse_start + + ;
2007-05-03 11:12:23 +04:00
return ctdb_control_traverse_start ( ctdb , indata , outdata , srcnode ) ;
case CTDB_CONTROL_TRAVERSE_ALL :
2007-05-05 02:11:54 +04:00
ctdb - > status . controls . traverse_all + + ;
2007-05-03 11:12:23 +04:00
return ctdb_control_traverse_all ( ctdb , indata , outdata ) ;
case CTDB_CONTROL_TRAVERSE_DATA :
2007-05-05 02:11:54 +04:00
ctdb - > status . controls . traverse_data + + ;
2007-05-03 11:12:23 +04:00
return ctdb_control_traverse_data ( ctdb , indata , outdata ) ;
2007-05-04 05:41:29 +04:00
case CTDB_CONTROL_REGISTER_SRVID :
2007-05-05 02:11:54 +04:00
ctdb - > status . controls . register_srvid + + ;
2007-05-04 05:41:29 +04:00
return daemon_register_message_handler ( ctdb , client_id , srvid ) ;
case CTDB_CONTROL_DEREGISTER_SRVID :
2007-05-05 02:11:54 +04:00
ctdb - > status . controls . deregister_srvid + + ;
2007-05-04 05:41:29 +04:00
return daemon_deregister_message_handler ( ctdb , client_id , srvid ) ;
2007-05-04 16:18:00 +04:00
case CTDB_CONTROL_ENABLE_SEQNUM :
2007-05-05 02:11:54 +04:00
ctdb - > status . controls . enable_seqnum + + ;
2007-05-04 16:18:00 +04:00
CHECK_CONTROL_DATA_SIZE ( sizeof ( uint32_t ) ) ;
return ctdb_ltdb_enable_seqnum ( ctdb , * ( uint32_t * ) indata . dptr ) ;
case CTDB_CONTROL_UPDATE_SEQNUM :
2007-05-05 02:11:54 +04:00
ctdb - > status . controls . update_seqnum + + ;
2007-05-04 16:18:00 +04:00
CHECK_CONTROL_DATA_SIZE ( sizeof ( uint32_t ) ) ;
return ctdb_ltdb_update_seqnum ( ctdb , * ( uint32_t * ) indata . dptr , srcnode ) ;
case CTDB_CONTROL_SET_SEQNUM_FREQUENCY :
2007-05-05 02:11:54 +04:00
ctdb - > status . controls . set_seqnum_frequency + + ;
2007-05-04 16:18:00 +04:00
CHECK_CONTROL_DATA_SIZE ( sizeof ( uint32_t ) ) ;
return ctdb_ltdb_set_seqnum_frequency ( ctdb , * ( uint32_t * ) indata . dptr ) ;
2007-05-04 09:33:28 +04:00
2007-05-12 09:15:27 +04:00
case CTDB_CONTROL_FREEZE :
CHECK_CONTROL_DATA_SIZE ( 0 ) ;
return ctdb_control_freeze ( ctdb , c , async_reply ) ;
case CTDB_CONTROL_THAW :
CHECK_CONTROL_DATA_SIZE ( 0 ) ;
return ctdb_control_thaw ( ctdb ) ;
case CTDB_CONTROL_SET_RECMODE :
CHECK_CONTROL_DATA_SIZE ( sizeof ( uint32_t ) ) ;
2007-05-12 15:25:26 +04:00
return ctdb_control_set_recmode ( ctdb , indata , errormsg ) ;
2007-05-12 09:15:27 +04:00
2007-05-17 04:45:31 +04:00
case CTDB_CONTROL_SHUTDOWN :
exit ( 10 ) ;
2007-04-26 16:27:49 +04:00
default :
DEBUG ( 0 , ( __location__ " Unknown CTDB control opcode %u \n " , opcode ) ) ;
return - 1 ;
}
}
2007-05-12 08:34:21 +04:00
2007-04-26 16:27:49 +04:00
/*
2007-05-12 08:34:21 +04:00
send a reply for a ctdb control
*/
void ctdb_request_control_reply ( struct ctdb_context * ctdb , struct ctdb_req_control * c ,
2007-05-12 15:25:26 +04:00
TDB_DATA * outdata , int32_t status , const char * errormsg )
2007-04-26 16:27:49 +04:00
{
struct ctdb_reply_control * r ;
size_t len ;
2007-05-12 15:25:26 +04:00
2007-04-30 17:31:40 +04:00
/* some controls send no reply */
if ( c - > flags & CTDB_CTRL_FLAG_NOREPLY ) {
return ;
}
2007-05-12 08:34:21 +04:00
len = offsetof ( struct ctdb_reply_control , data ) + ( outdata ? outdata - > dsize : 0 ) ;
2007-05-12 15:25:26 +04:00
if ( errormsg ) {
len + = strlen ( errormsg ) ;
}
2007-04-28 12:50:32 +04:00
r = ctdb_transport_allocate ( ctdb , ctdb , CTDB_REPLY_CONTROL , len , struct ctdb_reply_control ) ;
2007-04-26 16:27:49 +04:00
CTDB_NO_MEMORY_VOID ( ctdb , r ) ;
2007-05-12 08:34:21 +04:00
r - > hdr . destnode = c - > hdr . srcnode ;
r - > hdr . reqid = c - > hdr . reqid ;
2007-04-26 16:27:49 +04:00
r - > status = status ;
2007-05-12 08:34:21 +04:00
r - > datalen = outdata ? outdata - > dsize : 0 ;
if ( outdata & & outdata - > dsize ) {
2007-04-27 14:56:10 +04:00
memcpy ( & r - > data [ 0 ] , outdata - > dptr , outdata - > dsize ) ;
2007-04-26 16:27:49 +04:00
}
2007-05-12 15:25:26 +04:00
if ( errormsg ) {
r - > errorlen = strlen ( errormsg ) ;
memcpy ( & r - > data [ r - > datalen ] , errormsg , r - > errorlen ) ;
}
2007-04-26 16:27:49 +04:00
ctdb_queue_packet ( ctdb , & r - > hdr ) ;
talloc_free ( r ) ;
}
2007-05-12 08:34:21 +04:00
/*
called when a CTDB_REQ_CONTROL packet comes in
*/
void ctdb_request_control ( struct ctdb_context * ctdb , struct ctdb_req_header * hdr )
{
struct ctdb_req_control * c = ( struct ctdb_req_control * ) hdr ;
TDB_DATA data , * outdata ;
int32_t status ;
2007-05-12 09:15:27 +04:00
bool async_reply = False ;
2007-05-12 15:25:26 +04:00
const char * errormsg = NULL ;
2007-05-12 08:34:21 +04:00
data . dptr = & c - > data [ 0 ] ;
data . dsize = c - > datalen ;
outdata = talloc_zero ( c , TDB_DATA ) ;
2007-05-12 15:25:26 +04:00
status = ctdb_control_dispatch ( ctdb , c , data , outdata , hdr - > srcnode ,
& errormsg , & async_reply ) ;
2007-05-12 08:34:21 +04:00
2007-05-12 09:15:27 +04:00
if ( ! async_reply ) {
2007-05-12 15:25:26 +04:00
ctdb_request_control_reply ( ctdb , c , outdata , status , errormsg ) ;
2007-05-12 09:15:27 +04:00
}
2007-05-12 08:34:21 +04:00
}
2007-04-26 16:27:49 +04:00
/*
called when a CTDB_REPLY_CONTROL packet comes in
*/
void ctdb_reply_control ( struct ctdb_context * ctdb , struct ctdb_req_header * hdr )
{
struct ctdb_reply_control * c = ( struct ctdb_reply_control * ) hdr ;
TDB_DATA data ;
struct ctdb_control_state * state ;
2007-05-12 15:25:26 +04:00
const char * errormsg = NULL ;
2007-04-26 16:27:49 +04:00
state = ctdb_reqid_find ( ctdb , hdr - > reqid , struct ctdb_control_state ) ;
if ( state = = NULL ) {
2007-04-29 18:19:40 +04:00
DEBUG ( 0 , ( " vnn %u Invalid reqid %u in ctdb_reply_control \n " ,
ctdb - > vnn , hdr - > reqid ) ) ;
2007-04-26 16:27:49 +04:00
return ;
}
if ( hdr - > reqid ! = state - > reqid ) {
/* we found a record but it was the wrong one */
DEBUG ( 0 , ( " Dropped orphaned control reply with reqid:%d \n " , hdr - > reqid ) ) ;
return ;
}
data . dptr = & c - > data [ 0 ] ;
data . dsize = c - > datalen ;
2007-05-12 15:25:26 +04:00
if ( c - > errorlen ) {
errormsg = talloc_strndup ( state ,
( char * ) & c - > data [ c - > datalen ] , c - > errorlen ) ;
}
2007-04-26 16:27:49 +04:00
2007-05-05 02:33:35 +04:00
/* make state a child of the packet, so it goes away when the packet
is freed . */
talloc_steal ( hdr , state ) ;
2007-05-12 15:25:26 +04:00
state - > callback ( ctdb , c - > status , data , errormsg , state - > private_data ) ;
2007-04-26 16:27:49 +04:00
}
static int ctdb_control_destructor ( struct ctdb_control_state * state )
{
ctdb_reqid_remove ( state - > ctdb , state - > reqid ) ;
return 0 ;
}
2007-05-10 08:06:48 +04:00
/*
handle a timeout of a control
*/
static void ctdb_control_timeout ( struct event_context * ev , struct timed_event * te ,
struct timeval t , void * private_data )
{
struct ctdb_control_state * state = talloc_get_type ( private_data , struct ctdb_control_state ) ;
2007-05-16 06:34:30 +04:00
struct ctdb_req_control * c = ( struct ctdb_req_control * ) state - > private_data ;
2007-05-12 08:34:21 +04:00
TALLOC_CTX * tmp_ctx = talloc_new ( ev ) ;
2007-05-10 08:06:48 +04:00
state - > ctdb - > status . timeouts . control + + ;
2007-05-12 08:34:21 +04:00
talloc_steal ( tmp_ctx , state ) ;
2007-05-16 06:34:30 +04:00
/* Dont retry the control if the caller asked for NOREQUEUE */
if ( ! ( c - > flags & CTDB_CTRL_FLAG_NOREQUEUE ) ) {
state - > callback ( state - > ctdb , - 1 , tdb_null ,
" ctdb_control timed out " ,
state - > private_data ) ;
}
2007-05-12 08:34:21 +04:00
talloc_free ( tmp_ctx ) ;
2007-05-10 08:06:48 +04:00
}
2007-04-26 16:27:49 +04:00
/*
send a control message to a node
*/
int ctdb_daemon_send_control ( struct ctdb_context * ctdb , uint32_t destnode ,
2007-05-04 05:41:29 +04:00
uint64_t srvid , uint32_t opcode , uint32_t client_id ,
uint32_t flags ,
2007-04-30 17:31:40 +04:00
TDB_DATA data ,
2007-04-26 16:27:49 +04:00
ctdb_control_callback_fn_t callback ,
void * private_data )
{
struct ctdb_req_control * c ;
struct ctdb_control_state * state ;
size_t len ;
2007-05-05 07:17:26 +04:00
if ( ( ( destnode = = CTDB_BROADCAST_VNNMAP ) | | ( destnode = = CTDB_BROADCAST_VNNMAP ) ) & & ! ( flags & CTDB_CTRL_FLAG_NOREPLY ) ) {
2007-04-30 17:31:40 +04:00
DEBUG ( 0 , ( " Attempt to broadcast control without NOREPLY \n " ) ) ;
return - 1 ;
}
2007-05-05 02:33:35 +04:00
/* the state is made a child of private_data if possible. This means any reply
will be discarded if the private_data goes away */
state = talloc ( private_data ? private_data : ctdb , struct ctdb_control_state ) ;
2007-04-26 16:27:49 +04:00
CTDB_NO_MEMORY ( ctdb , state ) ;
state - > reqid = ctdb_reqid_new ( ctdb , state ) ;
state - > callback = callback ;
state - > private_data = private_data ;
state - > ctdb = ctdb ;
talloc_set_destructor ( state , ctdb_control_destructor ) ;
len = offsetof ( struct ctdb_req_control , data ) + data . dsize ;
2007-04-28 12:50:32 +04:00
c = ctdb_transport_allocate ( ctdb , state , CTDB_REQ_CONTROL , len ,
struct ctdb_req_control ) ;
2007-04-26 16:27:49 +04:00
CTDB_NO_MEMORY ( ctdb , c ) ;
talloc_set_name_const ( c , " ctdb_req_control packet " ) ;
c - > hdr . destnode = destnode ;
c - > hdr . reqid = state - > reqid ;
c - > opcode = opcode ;
2007-05-04 05:41:29 +04:00
c - > client_id = client_id ;
2007-04-30 17:31:40 +04:00
c - > flags = flags ;
2007-04-26 16:27:49 +04:00
c - > srvid = srvid ;
c - > datalen = data . dsize ;
if ( data . dsize ) {
memcpy ( & c - > data [ 0 ] , data . dptr , data . dsize ) ;
}
2007-04-30 17:31:40 +04:00
2007-04-26 16:27:49 +04:00
ctdb_queue_packet ( ctdb , & c - > hdr ) ;
2007-04-30 17:31:40 +04:00
if ( flags & CTDB_CTRL_FLAG_NOREPLY ) {
talloc_free ( state ) ;
return 0 ;
}
2007-05-10 08:06:48 +04:00
# if CTDB_CONTROL_TIMEOUT
event_add_timed ( ctdb - > ev , state , timeval_current_ofs ( CTDB_CONTROL_TIMEOUT , 0 ) ,
2007-04-26 16:27:49 +04:00
ctdb_control_timeout , state ) ;
# endif
talloc_free ( c ) ;
return 0 ;
}