2007-04-26 16:27:49 +04:00
/*
ctdb_control protocol code
Copyright ( C ) Andrew Tridgell 2007
2007-05-31 07:50:53 +04: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 09:29:31 +04:00
the Free Software Foundation ; either version 3 of the License , or
2007-05-31 07:50:53 +04:00
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
2007-04-26 16:27:49 +04:00
but WITHOUT ANY WARRANTY ; without even the implied warranty of
2007-05-31 07:50:53 +04: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 09:29:31 +04:00
along with this program ; if not , see < http : //www.gnu.org/licenses/>.
2007-04-26 16:27:49 +04:00
*/
# 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
2007-08-24 09:53:41 +04:00
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 ;
2007-05-17 08:10:38 +04:00
unsigned flags ;
2007-04-26 16:27:49 +04:00
} ;
2007-08-24 09:53:41 +04:00
2007-04-26 16:27:49 +04:00
/*
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 ) ) ;
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-05-29 06:16:59 +04:00
case CTDB_CONTROL_STATISTICS : {
2007-04-27 16:49:44 +04:00
CHECK_CONTROL_DATA_SIZE ( 0 ) ;
2007-05-29 06:16:59 +04:00
ctdb - > statistics . memory_used = talloc_total_size ( ctdb ) ;
ctdb - > statistics . frozen = ( ctdb - > freeze_mode = = CTDB_FREEZE_FROZEN ) ;
ctdb - > statistics . recovering = ( ctdb - > recovery_mode = = CTDB_RECOVERY_ACTIVE ) ;
outdata - > dptr = ( uint8_t * ) & ctdb - > statistics ;
outdata - > dsize = sizeof ( ctdb - > statistics ) ;
2007-04-26 16:51:41 +04:00
return 0 ;
}
2007-04-26 21:27:07 +04:00
2007-06-07 12:05:25 +04:00
case CTDB_CONTROL_GET_ALL_TUNABLES : {
CHECK_CONTROL_DATA_SIZE ( 0 ) ;
outdata - > dptr = ( uint8_t * ) & ctdb - > tunable ;
outdata - > dsize = sizeof ( ctdb - > tunable ) ;
return 0 ;
}
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-05-29 06:16:59 +04:00
case CTDB_CONTROL_STATISTICS_RESET : {
2007-04-28 21:13:36 +04:00
CHECK_CONTROL_DATA_SIZE ( 0 ) ;
2007-05-29 06:16:59 +04:00
ZERO_STRUCT ( ctdb - > statistics ) ;
2007-04-28 21:13:36 +04:00
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_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 :
2007-09-04 04:06:36 +04:00
return ctdb - > pnn ;
2007-05-05 22:31:22 +04:00
2007-04-26 21:27:07 +04:00
case CTDB_CONTROL_PING :
2007-04-27 16:49:44 +04:00
CHECK_CONTROL_DATA_SIZE ( 0 ) ;
2007-05-29 06:16:59 +04:00
return ctdb - > statistics . 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 :
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 ;
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 ) ) ;
return ctdb_control_traverse_start ( ctdb , indata , outdata , srcnode ) ;
case CTDB_CONTROL_TRAVERSE_ALL :
return ctdb_control_traverse_all ( ctdb , indata , outdata ) ;
case CTDB_CONTROL_TRAVERSE_DATA :
return ctdb_control_traverse_data ( ctdb , indata , outdata ) ;
2007-05-04 05:41:29 +04:00
case CTDB_CONTROL_REGISTER_SRVID :
return daemon_register_message_handler ( ctdb , client_id , srvid ) ;
case CTDB_CONTROL_DEREGISTER_SRVID :
return daemon_deregister_message_handler ( ctdb , client_id , srvid ) ;
2007-05-04 16:18:00 +04:00
case CTDB_CONTROL_ENABLE_SEQNUM :
CHECK_CONTROL_DATA_SIZE ( sizeof ( uint32_t ) ) ;
return ctdb_ltdb_enable_seqnum ( ctdb , * ( uint32_t * ) indata . dptr ) ;
case CTDB_CONTROL_UPDATE_SEQNUM :
CHECK_CONTROL_DATA_SIZE ( sizeof ( uint32_t ) ) ;
return ctdb_ltdb_update_seqnum ( ctdb , * ( uint32_t * ) indata . dptr , srcnode ) ;
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-06-02 02:41:19 +04:00
return ctdb_control_set_recmode ( ctdb , c , indata , async_reply , errormsg ) ;
2007-05-12 09:15:27 +04:00
2007-05-21 03:24:34 +04:00
case CTDB_CONTROL_SET_MONMODE :
CHECK_CONTROL_DATA_SIZE ( sizeof ( uint32_t ) ) ;
ctdb - > monitoring_mode = * ( uint32_t * ) indata . dptr ;
return 0 ;
case CTDB_CONTROL_GET_MONMODE :
return ctdb - > monitoring_mode ;
2007-05-17 04:45:31 +04:00
case CTDB_CONTROL_SHUTDOWN :
2007-05-29 07:33:59 +04:00
ctdb_release_all_ips ( ctdb ) ;
2007-06-02 02:41:19 +04:00
ctdb - > methods - > shutdown ( ctdb ) ;
2007-05-29 07:33:59 +04:00
ctdb_event_script ( ctdb , " shutdown " ) ;
2007-08-21 03:46:27 +04:00
DEBUG ( 0 , ( " Received SHUTDOWN command. Stopping CTDB daemon. \n " ) ) ;
2007-05-29 07:33:59 +04:00
exit ( 0 ) ;
2007-05-17 04:45:31 +04:00
2007-05-23 11:21:14 +04:00
case CTDB_CONTROL_MAX_RSN :
CHECK_CONTROL_DATA_SIZE ( sizeof ( uint32_t ) ) ;
return ctdb_control_max_rsn ( ctdb , indata , outdata ) ;
case CTDB_CONTROL_SET_RSN_NONEMPTY :
CHECK_CONTROL_DATA_SIZE ( sizeof ( struct ctdb_control_set_rsn_nonempty ) ) ;
return ctdb_control_set_rsn_nonempty ( ctdb , indata , outdata ) ;
2007-05-25 07:05:25 +04:00
case CTDB_CONTROL_TAKEOVER_IP :
2007-06-04 14:07:37 +04:00
CHECK_CONTROL_DATA_SIZE ( sizeof ( struct ctdb_public_ip ) ) ;
2007-06-01 13:05:41 +04:00
return ctdb_control_takeover_ip ( ctdb , c , indata , async_reply ) ;
2007-05-25 07:05:25 +04:00
case CTDB_CONTROL_RELEASE_IP :
2007-06-04 14:07:37 +04:00
CHECK_CONTROL_DATA_SIZE ( sizeof ( struct ctdb_public_ip ) ) ;
2007-06-01 13:05:41 +04:00
return ctdb_control_release_ip ( ctdb , c , indata , async_reply ) ;
2007-05-25 07:05:25 +04:00
2007-06-04 15:11:51 +04:00
case CTDB_CONTROL_GET_PUBLIC_IPS :
CHECK_CONTROL_DATA_SIZE ( 0 ) ;
return ctdb_control_get_public_ips ( ctdb , c , outdata ) ;
2007-05-23 11:21:14 +04:00
case CTDB_CONTROL_DELETE_LOW_RSN :
CHECK_CONTROL_DATA_SIZE ( sizeof ( struct ctdb_control_delete_low_rsn ) ) ;
return ctdb_control_delete_low_rsn ( ctdb , indata , outdata ) ;
2007-05-27 09:26:29 +04:00
case CTDB_CONTROL_TCP_CLIENT :
CHECK_CONTROL_DATA_SIZE ( sizeof ( struct ctdb_control_tcp ) ) ;
2007-07-20 04:06:41 +04:00
return ctdb_control_tcp_client ( ctdb , client_id , indata ) ;
2007-05-27 18:34:40 +04:00
case CTDB_CONTROL_STARTUP :
CHECK_CONTROL_DATA_SIZE ( 0 ) ;
return ctdb_control_startup ( ctdb , srcnode ) ;
2007-05-27 09:26:29 +04:00
case CTDB_CONTROL_TCP_ADD :
2007-05-27 18:34:40 +04:00
CHECK_CONTROL_DATA_SIZE ( sizeof ( struct ctdb_control_tcp_vnn ) ) ;
2007-05-27 09:26:29 +04:00
return ctdb_control_tcp_add ( ctdb , indata ) ;
2007-06-04 13:53:19 +04:00
case CTDB_CONTROL_SET_TUNABLE :
return ctdb_control_set_tunable ( ctdb , indata ) ;
case CTDB_CONTROL_GET_TUNABLE :
return ctdb_control_get_tunable ( ctdb , indata , outdata ) ;
case CTDB_CONTROL_LIST_TUNABLES :
return ctdb_control_list_tunables ( ctdb , outdata ) ;
2007-06-07 09:18:55 +04:00
case CTDB_CONTROL_MODIFY_FLAGS :
CHECK_CONTROL_DATA_SIZE ( sizeof ( struct ctdb_node_modflags ) ) ;
return ctdb_control_modflags ( ctdb , indata ) ;
2007-06-07 03:16:17 +04:00
2007-07-11 12:24:25 +04:00
case CTDB_CONTROL_KILL_TCP :
2007-07-12 02:30:04 +04:00
CHECK_CONTROL_DATA_SIZE ( sizeof ( struct ctdb_control_killtcp ) ) ;
2007-07-11 12:24:25 +04:00
return ctdb_control_kill_tcp ( ctdb , indata ) ;
2007-07-20 09:05:55 +04:00
case CTDB_CONTROL_GET_TCP_TICKLE_LIST :
2007-09-04 03:50:07 +04:00
CHECK_CONTROL_DATA_SIZE ( sizeof ( struct sockaddr_in ) ) ;
2007-07-20 09:05:55 +04:00
return ctdb_control_get_tcp_tickle_list ( ctdb , indata , outdata ) ;
case CTDB_CONTROL_SET_TCP_TICKLE_LIST :
2007-07-20 04:06:41 +04:00
/* data size is verified in the called function */
2007-07-20 09:05:55 +04:00
return ctdb_control_set_tcp_tickle_list ( ctdb , indata ) ;
2007-07-20 04:06:41 +04:00
2007-08-24 09:53:41 +04:00
case CTDB_CONTROL_REGISTER_SERVER_ID :
CHECK_CONTROL_DATA_SIZE ( sizeof ( struct ctdb_server_id ) ) ;
return ctdb_control_register_server_id ( ctdb , client_id , indata ) ;
case CTDB_CONTROL_UNREGISTER_SERVER_ID :
CHECK_CONTROL_DATA_SIZE ( sizeof ( struct ctdb_server_id ) ) ;
return ctdb_control_unregister_server_id ( ctdb , indata ) ;
case CTDB_CONTROL_CHECK_SERVER_ID :
CHECK_CONTROL_DATA_SIZE ( sizeof ( struct ctdb_server_id ) ) ;
return ctdb_control_check_server_id ( ctdb , indata ) ;
2007-08-26 04:57:02 +04:00
case CTDB_CONTROL_GET_SERVER_ID_LIST :
CHECK_CONTROL_DATA_SIZE ( 0 ) ;
return ctdb_control_get_server_id_list ( ctdb , outdata ) ;
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 " ,
2007-09-04 04:06:36 +04:00
ctdb - > pnn , 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 */
2007-05-23 14:15:09 +04:00
DEBUG ( 0 , ( " Dropped orphaned control reply with reqid:%u \n " , hdr - > reqid ) ) ;
2007-04-26 16:27:49 +04:00
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-12 08:34:21 +04:00
TALLOC_CTX * tmp_ctx = talloc_new ( ev ) ;
2007-05-10 08:06:48 +04:00
2007-05-29 06:16:59 +04:00
state - > ctdb - > statistics . timeouts . control + + ;
2007-05-10 08:06:48 +04:00
2007-05-12 08:34:21 +04:00
talloc_steal ( tmp_ctx , state ) ;
2007-05-17 08:10:38 +04:00
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-06-09 15:58:50 +04:00
if ( ( ( destnode = = CTDB_BROADCAST_VNNMAP ) | |
( destnode = = CTDB_BROADCAST_ALL ) | |
( destnode = = CTDB_BROADCAST_CONNECTED ) ) & &
! ( 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-06-09 15:58:50 +04:00
if ( destnode ! = CTDB_BROADCAST_VNNMAP & &
destnode ! = CTDB_BROADCAST_ALL & &
destnode ! = CTDB_BROADCAST_CONNECTED & &
2007-09-04 04:09:58 +04:00
( ! ctdb_validate_pnn ( ctdb , destnode ) | |
2007-06-07 09:18:55 +04:00
( ctdb - > nodes [ destnode ] - > flags & NODE_FLAGS_DISCONNECTED ) ) ) {
2007-05-17 17:23:41 +04:00
if ( ! ( flags & CTDB_CTRL_FLAG_NOREPLY ) ) {
callback ( ctdb , - 1 , tdb_null , " ctdb_control to disconnected node " , private_data ) ;
}
return 0 ;
}
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 ;
2007-05-17 08:10:38 +04:00
state - > flags = flags ;
2007-04-26 16:27:49 +04:00
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-06-04 11:46:37 +04:00
if ( ctdb - > tunable . control_timeout ) {
event_add_timed ( ctdb - > ev , state ,
timeval_current_ofs ( ctdb - > tunable . control_timeout , 0 ) ,
ctdb_control_timeout , state ) ;
}
2007-04-26 16:27:49 +04:00
talloc_free ( c ) ;
return 0 ;
}