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 ;
} ;
2007-04-29 12:48:46 +04:00
static int traverse_cleardb ( struct tdb_context * tdb , TDB_DATA key , TDB_DATA data , void * p )
{
int ret ;
ret = tdb_delete ( tdb , key ) ;
if ( ret ) {
DEBUG ( 0 , ( __location__ " failed to delete tdb record \n " ) ) ;
return ret ;
}
return 0 ;
}
2007-04-29 12:34:11 +04:00
static int traverse_setdmaster ( struct tdb_context * tdb , TDB_DATA key , TDB_DATA data , void * p )
{
uint32_t * dmaster = ( uint32_t * ) p ;
struct ctdb_ltdb_header * header = ( struct ctdb_ltdb_header * ) data . dptr ;
int ret ;
header - > dmaster = * dmaster ;
ret = tdb_store ( tdb , key , data , TDB_REPLACE ) ;
if ( ret ) {
DEBUG ( 0 , ( __location__ " failed to write tdb data back ret:%d \n " , ret ) ) ;
return ret ;
}
return 0 ;
}
2007-04-28 23:47:13 +04:00
struct getkeys_params {
struct ctdb_db_context * ctdb_db ;
TDB_DATA * outdata ;
2007-05-02 04:20:34 +04:00
uint32_t lmaster ;
2007-04-28 23:47:13 +04:00
} ;
static int traverse_getkeys ( struct tdb_context * tdb , TDB_DATA key , TDB_DATA data , void * p )
{
struct getkeys_params * params = ( struct getkeys_params * ) p ;
TDB_DATA * outdata = talloc_get_type ( params - > outdata , TDB_DATA ) ;
struct ctdb_db_context * ctdb_db = talloc_get_type ( params - > ctdb_db , struct ctdb_db_context ) ;
unsigned char * ptr ;
2007-04-29 12:34:11 +04:00
int len ;
2007-05-02 04:20:34 +04:00
uint32_t lmaster ;
lmaster = ctdb_lmaster ( ctdb_db - > ctdb , & key ) ;
/* only include this record if the lmaster matches or if
the wildcard lmaster ( - 1 ) was specified .
*/
2007-05-02 15:00:02 +04:00
if ( ( params - > lmaster ! = CTDB_LMASTER_ANY )
& & ( params - > lmaster ! = lmaster ) ) {
2007-05-02 04:20:34 +04:00
return 0 ;
}
2007-04-28 23:47:13 +04:00
len = outdata - > dsize ;
len + = 4 ; /*lmaster*/
len + = 4 ; /*key len*/
2007-05-02 15:00:02 +04:00
len + = 4 ; /*data len */
2007-04-28 23:47:13 +04:00
len + = key . dsize ;
len = ( len + CTDB_DS_ALIGNMENT - 1 ) & ~ ( CTDB_DS_ALIGNMENT - 1 ) ;
len + = sizeof ( struct ctdb_ltdb_header ) ;
len = ( len + CTDB_DS_ALIGNMENT - 1 ) & ~ ( CTDB_DS_ALIGNMENT - 1 ) ;
2007-05-02 15:00:02 +04:00
len + = ( data . dsize - sizeof ( struct ctdb_ltdb_header ) ) ;
2007-04-28 23:47:13 +04:00
len = ( len + CTDB_DS_ALIGNMENT - 1 ) & ~ ( CTDB_DS_ALIGNMENT - 1 ) ;
ptr = outdata - > dptr = talloc_realloc_size ( outdata , outdata - > dptr , len ) ;
ptr + = outdata - > dsize ;
outdata - > dsize = len ;
2007-04-29 18:58:27 +04:00
/* number of records is stored as the second 4 bytes */
( ( uint32_t * ) ( & outdata - > dptr [ 0 ] ) ) [ 1 ] + + ;
2007-04-28 23:47:13 +04:00
2007-05-02 04:20:34 +04:00
* ( ( uint32_t * ) ptr ) = lmaster ;
2007-04-28 23:47:13 +04:00
ptr + = 4 ;
* ( ( uint32_t * ) ptr ) = key . dsize ;
ptr + = 4 ;
2007-05-02 15:00:02 +04:00
* ( ( uint32_t * ) ptr ) = data . dsize - sizeof ( struct ctdb_ltdb_header ) ;
ptr + = 4 ;
ptr = outdata - > dptr + ( ( ( ptr - outdata - > dptr ) + CTDB_DS_ALIGNMENT - 1 ) & ~ ( CTDB_DS_ALIGNMENT - 1 ) ) ;
2007-04-28 23:47:13 +04:00
memcpy ( ptr , key . dptr , key . dsize ) ;
2007-05-02 15:00:02 +04:00
ptr + = key . dsize ;
2007-04-28 23:47:13 +04:00
2007-05-02 15:00:02 +04:00
ptr = outdata - > dptr + ( ( ( ptr - outdata - > dptr ) + CTDB_DS_ALIGNMENT - 1 ) & ~ ( CTDB_DS_ALIGNMENT - 1 ) ) ;
2007-04-28 23:47:13 +04:00
memcpy ( ptr , data . dptr , sizeof ( struct ctdb_ltdb_header ) ) ;
2007-05-02 15:00:02 +04:00
ptr + = sizeof ( struct ctdb_ltdb_header ) ;
2007-04-28 23:47:13 +04:00
2007-05-02 15:00:02 +04:00
ptr = outdata - > dptr + ( ( ( ptr - outdata - > dptr ) + CTDB_DS_ALIGNMENT - 1 ) & ~ ( CTDB_DS_ALIGNMENT - 1 ) ) ;
2007-04-28 23:47:13 +04:00
memcpy ( ptr , data . dptr + sizeof ( struct ctdb_ltdb_header ) , data . dsize - sizeof ( struct ctdb_ltdb_header ) ) ;
return 0 ;
}
2007-04-26 16:27:49 +04:00
/*
process a control request
*/
static int32_t ctdb_control_dispatch ( struct ctdb_context * ctdb ,
2007-05-04 05:41:29 +04:00
uint32_t opcode ,
uint64_t srvid , uint32_t client_id ,
TDB_DATA indata ,
2007-05-03 11:12:23 +04:00
TDB_DATA * outdata , uint32_t srcnode )
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-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-04-29 18:58:27 +04:00
case CTDB_CONTROL_PULL_DB : {
2007-05-02 04:20:34 +04:00
uint32_t dbid , lmaster ;
2007-04-28 23:47:13 +04:00
struct ctdb_db_context * ctdb_db ;
struct getkeys_params params ;
2007-05-02 04:20:34 +04:00
dbid = ( ( uint32_t * ) ( & indata . dptr [ 0 ] ) ) [ 0 ] ;
2007-04-28 23:47:13 +04:00
ctdb_db = find_ctdb_db ( ctdb , dbid ) ;
if ( ! ctdb_db ) {
DEBUG ( 0 , ( __location__ " Unknown db \n " ) ) ;
return - 1 ;
}
2007-05-02 04:20:34 +04:00
lmaster = ( ( uint32_t * ) ( & indata . dptr [ 0 ] ) ) [ 1 ] ;
2007-04-29 18:58:27 +04:00
outdata - > dsize = 2 * sizeof ( uint32_t ) ;
outdata - > dptr = ( unsigned char * ) talloc_array ( outdata , uint32_t , 2 ) ;
( ( uint32_t * ) ( & outdata - > dptr [ 0 ] ) ) [ 0 ] = dbid ;
( ( uint32_t * ) ( & outdata - > dptr [ 0 ] ) ) [ 1 ] = 0 ;
2007-04-28 23:47:13 +04:00
params . ctdb_db = ctdb_db ;
params . outdata = outdata ;
2007-05-02 04:20:34 +04:00
params . lmaster = lmaster ;
2007-04-29 12:48:46 +04:00
tdb_traverse_read ( ctdb_db - > ltdb - > tdb , traverse_getkeys , & params ) ;
2007-04-28 23:47:13 +04:00
return 0 ;
}
2007-04-29 12:34:11 +04:00
case CTDB_CONTROL_SET_DMASTER : {
uint32_t dbid , dmaster ;
struct ctdb_db_context * ctdb_db ;
dbid = ( ( uint32_t * ) ( & indata . dptr [ 0 ] ) ) [ 0 ] ;
ctdb_db = find_ctdb_db ( ctdb , dbid ) ;
if ( ! ctdb_db ) {
DEBUG ( 0 , ( __location__ " Unknown db 0x%08x \n " , dbid ) ) ;
return - 1 ;
}
dmaster = ( ( uint32_t * ) ( & indata . dptr [ 0 ] ) ) [ 1 ] ;
outdata - > dsize = 0 ;
outdata - > dptr = NULL ;
2007-04-29 12:48:46 +04:00
tdb_traverse ( ctdb_db - > ltdb - > tdb , traverse_setdmaster , & dmaster ) ;
return 0 ;
}
case CTDB_CONTROL_CLEAR_DB : {
uint32_t dbid ;
struct ctdb_db_context * ctdb_db ;
dbid = ( ( uint32_t * ) ( & indata . dptr [ 0 ] ) ) [ 0 ] ;
ctdb_db = find_ctdb_db ( ctdb , dbid ) ;
if ( ! ctdb_db ) {
DEBUG ( 0 , ( __location__ " Unknown db 0x%08x \n " , dbid ) ) ;
2007-04-29 12:34:11 +04:00
return - 1 ;
}
2007-04-29 12:48:46 +04:00
outdata - > dsize = 0 ;
outdata - > dptr = NULL ;
2007-04-29 12:34:11 +04:00
2007-04-29 12:48:46 +04:00
tdb_traverse ( ctdb_db - > ltdb - > tdb , traverse_cleardb , NULL ) ;
2007-04-29 12:34:11 +04:00
return 0 ;
}
2007-04-29 18:58:27 +04:00
case CTDB_CONTROL_PUSH_DB : {
uint32_t dbid , num ;
2007-04-29 16:14:51 +04:00
struct ctdb_db_context * ctdb_db ;
2007-04-29 18:58:27 +04:00
unsigned char * ptr ;
2007-04-29 16:14:51 +04:00
int i , ret ;
2007-04-29 18:58:27 +04:00
TDB_DATA key , data ;
2007-05-02 04:20:34 +04:00
struct ctdb_ltdb_header * hdr , header ;
2007-04-29 18:58:27 +04:00
outdata - > dsize = 0 ;
outdata - > dptr = NULL ;
2007-04-29 16:14:51 +04:00
dbid = ( ( uint32_t * ) ( & indata . dptr [ 0 ] ) ) [ 0 ] ;
ctdb_db = find_ctdb_db ( ctdb , dbid ) ;
if ( ! ctdb_db ) {
DEBUG ( 0 , ( __location__ " Unknown db 0x%08x \n " , dbid ) ) ;
return - 1 ;
}
2007-04-29 18:58:27 +04:00
num = ( ( uint32_t * ) ( & indata . dptr [ 0 ] ) ) [ 1 ] ;
ptr = & indata . dptr [ 8 ] ;
for ( i = 0 ; i < num ; i + + ) {
/* skip the lmaster*/
2007-05-02 15:00:02 +04:00
ptr + = 4 ;
2007-04-29 18:58:27 +04:00
2007-05-02 15:00:02 +04:00
/* keylength */
key . dsize = * ( ( uint32_t * ) ptr ) ;
ptr + = 4 ;
2007-04-29 18:58:27 +04:00
2007-05-02 15:00:02 +04:00
/* data length */
data . dsize = * ( ( uint32_t * ) ptr ) ;
ptr + = 4 ;
/* key */
ptr = indata . dptr + ( ( ( ptr - indata . dptr ) + CTDB_DS_ALIGNMENT - 1 ) & ~ ( CTDB_DS_ALIGNMENT - 1 ) ) ;
key . dptr = ptr ;
ptr + = key . dsize ;
2007-04-29 18:58:27 +04:00
/* header */
2007-05-02 15:00:02 +04:00
ptr = indata . dptr + ( ( ( ptr - indata . dptr ) + CTDB_DS_ALIGNMENT - 1 ) & ~ ( CTDB_DS_ALIGNMENT - 1 ) ) ;
2007-05-02 04:20:34 +04:00
hdr = ( struct ctdb_ltdb_header * ) ptr ;
2007-05-02 15:00:02 +04:00
ptr + = sizeof ( struct ctdb_ltdb_header ) ;
2007-04-29 18:58:27 +04:00
/* data */
2007-05-02 15:00:02 +04:00
ptr = indata . dptr + ( ( ( ptr - indata . dptr ) + CTDB_DS_ALIGNMENT - 1 ) & ~ ( CTDB_DS_ALIGNMENT - 1 ) ) ;
2007-04-29 18:58:27 +04:00
data . dptr = ptr ;
2007-05-02 15:00:02 +04:00
ptr + = data . dsize ;
ptr = indata . dptr + ( ( ( ptr - indata . dptr ) + CTDB_DS_ALIGNMENT - 1 ) & ~ ( CTDB_DS_ALIGNMENT - 1 ) ) ;
2007-04-29 18:58:27 +04:00
ret = ctdb_ltdb_lock ( ctdb_db , key ) ;
2007-04-29 16:14:51 +04:00
if ( ret ! = 0 ) {
DEBUG ( 0 , ( __location__ " Unable to lock db \n " ) ) ;
return - 1 ;
}
2007-05-02 04:20:34 +04:00
ret = ctdb_ltdb_fetch ( ctdb_db , key , & header , outdata , NULL ) ;
2007-04-29 16:14:51 +04:00
if ( ret ! = 0 ) {
2007-05-02 04:20:34 +04:00
DEBUG ( 0 , ( __location__ " Unable to fetch record \n " ) ) ;
2007-04-29 18:58:27 +04:00
ctdb_ltdb_unlock ( ctdb_db , key ) ;
2007-04-29 16:14:51 +04:00
return - 1 ;
}
2007-05-02 04:25:14 +04:00
if ( header . rsn < hdr - > rsn ) {
2007-05-02 04:20:34 +04:00
ret = ctdb_ltdb_store ( ctdb_db , key , hdr , data ) ;
if ( ret ! = 0 ) {
DEBUG ( 0 , ( __location__ " Unable to store record \n " ) ) ;
ctdb_ltdb_unlock ( ctdb_db , key ) ;
return - 1 ;
}
}
2007-04-29 18:58:27 +04:00
ctdb_ltdb_unlock ( ctdb_db , key ) ;
2007-04-29 16:14:51 +04:00
}
return 0 ;
}
2007-05-03 10:18:03 +04:00
case CTDB_CONTROL_WRITE_RECORD :
return ctdb_control_writerecord ( ctdb , opcode , indata , outdata ) ;
2007-05-02 15:00:02 +04:00
2007-04-29 16:51:56 +04:00
case CTDB_CONTROL_SET_RECMODE : {
ctdb - > recovery_mode = ( ( uint32_t * ) ( & indata . dptr [ 0 ] ) ) [ 0 ] ;
return 0 ;
}
case CTDB_CONTROL_GET_RECMODE : {
outdata - > dsize = sizeof ( uint32_t ) ;
2007-05-06 01:52:20 +04:00
outdata - > dptr = ( unsigned char * ) & ctdb - > recovery_mode ;
2007-04-29 16:51:56 +04:00
return 0 ;
}
2007-05-05 22:31:22 +04:00
case CTDB_CONTROL_GET_PID : {
2007-05-06 01:52:20 +04:00
static uint32_t pid ;
pid = getpid ( ) ;
2007-05-05 22:31:22 +04:00
outdata - > dsize = sizeof ( uint32_t ) ;
2007-05-06 01:52:20 +04:00
outdata - > dptr = ( unsigned char * ) & pid ;
2007-05-05 22:31:22 +04:00
return 0 ;
}
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-04-26 16:27:49 +04:00
default :
DEBUG ( 0 , ( __location__ " Unknown CTDB control opcode %u \n " , opcode ) ) ;
return - 1 ;
}
}
/*
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 ;
2007-04-27 14:56:10 +04:00
TDB_DATA data , * outdata ;
2007-04-26 16:27:49 +04:00
struct ctdb_reply_control * r ;
int32_t status ;
size_t len ;
data . dptr = & c - > data [ 0 ] ;
data . dsize = c - > datalen ;
2007-04-27 14:56:10 +04:00
outdata = talloc_zero ( c , TDB_DATA ) ;
2007-05-04 05:41:29 +04:00
status = ctdb_control_dispatch ( ctdb , c - > opcode , c - > srvid , c - > client_id ,
data , outdata , hdr - > srcnode ) ;
2007-04-26 16:27:49 +04:00
2007-04-30 17:31:40 +04:00
/* some controls send no reply */
if ( c - > flags & CTDB_CTRL_FLAG_NOREPLY ) {
return ;
}
2007-04-27 14:56:10 +04:00
len = offsetof ( struct ctdb_reply_control , data ) + outdata - > dsize ;
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 ) ;
r - > hdr . destnode = hdr - > srcnode ;
r - > hdr . reqid = hdr - > reqid ;
r - > status = status ;
2007-04-27 14:56:10 +04:00
r - > datalen = outdata - > dsize ;
if ( outdata - > dsize ) {
memcpy ( & r - > data [ 0 ] , outdata - > dptr , outdata - > dsize ) ;
2007-04-26 16:27:49 +04:00
}
ctdb_queue_packet ( ctdb , & r - > hdr ) ;
talloc_free ( r ) ;
}
/*
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 ;
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-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-04-26 16:27:49 +04:00
state - > callback ( ctdb , c - > status , data , state - > private_data ) ;
}
static int ctdb_control_destructor ( struct ctdb_control_state * state )
{
ctdb_reqid_remove ( state - > ctdb , state - > reqid ) ;
return 0 ;
}
/*
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-04-26 16:27:49 +04:00
# if CTDB_REQ_TIMEOUT
event_add_timed ( ctdb - > ev , state , timeval_current_ofs ( CTDB_REQ_TIMEOUT , 0 ) ,
ctdb_control_timeout , state ) ;
# endif
talloc_free ( c ) ;
return 0 ;
}