2006-11-27 13:38:13 +03:00
/*
2006-11-28 09:56:10 +03:00
ctdb main protocol code
2006-11-27 13:38:13 +03:00
Copyright ( C ) Andrew Tridgell 2006
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"
2007-01-23 03:38:45 +03:00
# include "lib/tdb/include/tdb.h"
2006-11-27 13:38:13 +03:00
# include "lib/events/events.h"
2007-01-23 03:38:45 +03:00
# include "lib/util/dlinklist.h"
2006-11-27 13:38:13 +03:00
# include "system/network.h"
# include "system/filesys.h"
2007-01-23 03:38:45 +03:00
# include "../include/ctdb_private.h"
2006-11-27 13:38:13 +03:00
/*
choose the transport we will use
*/
int ctdb_set_transport ( struct ctdb_context * ctdb , const char * transport )
{
int ctdb_tcp_init ( struct ctdb_context * ctdb ) ;
if ( strcmp ( transport , " tcp " ) = = 0 ) {
return ctdb_tcp_init ( ctdb ) ;
}
ctdb_set_error ( ctdb , " Unknown transport '%s' \n " , transport ) ;
return - 1 ;
}
2006-12-01 07:45:24 +03:00
/*
set some ctdb flags
*/
void ctdb_set_flags ( struct ctdb_context * ctdb , unsigned flags )
{
ctdb - > flags | = flags ;
}
2007-01-23 03:38:45 +03:00
/*
set max acess count before a dmaster migration
*/
void ctdb_set_max_lacount ( struct ctdb_context * ctdb , unsigned count )
{
ctdb - > max_lacount = count ;
}
2006-11-27 13:38:13 +03:00
/*
add a node to the list of active nodes
*/
static int ctdb_add_node ( struct ctdb_context * ctdb , char * nstr )
{
2006-11-28 09:56:10 +03:00
struct ctdb_node * node , * * nodep ;
nodep = talloc_realloc ( ctdb , ctdb - > nodes , struct ctdb_node * , ctdb - > num_nodes + 1 ) ;
CTDB_NO_MEMORY ( ctdb , nodep ) ;
ctdb - > nodes = nodep ;
nodep = & ctdb - > nodes [ ctdb - > num_nodes ] ;
( * nodep ) = talloc_zero ( ctdb - > nodes , struct ctdb_node ) ;
CTDB_NO_MEMORY ( ctdb , * nodep ) ;
node = * nodep ;
2006-11-27 13:38:13 +03:00
if ( ctdb_parse_address ( ctdb , node , nstr , & node - > address ) ! = 0 ) {
return - 1 ;
}
node - > ctdb = ctdb ;
2006-11-28 06:15:46 +03:00
node - > name = talloc_asprintf ( node , " %s:%u " ,
node - > address . address ,
node - > address . port ) ;
2006-11-28 09:56:10 +03:00
/* for now we just set the vnn to the line in the file - this
will change ! */
node - > vnn = ctdb - > num_nodes ;
2006-11-27 13:38:13 +03:00
if ( ctdb - > methods - > add_node ( node ) ! = 0 ) {
talloc_free ( node ) ;
return - 1 ;
}
2006-11-28 09:56:10 +03:00
if ( ctdb_same_address ( & ctdb - > address , & node - > address ) ) {
ctdb - > vnn = node - > vnn ;
}
ctdb - > num_nodes + + ;
2006-11-27 13:38:13 +03:00
return 0 ;
}
/*
setup the node list from a file
*/
int ctdb_set_nlist ( struct ctdb_context * ctdb , const char * nlist )
{
char * * lines ;
int nlines ;
int i ;
lines = file_lines_load ( nlist , & nlines , ctdb ) ;
if ( lines = = NULL ) {
ctdb_set_error ( ctdb , " Failed to load nlist '%s' \n " , nlist ) ;
return - 1 ;
}
for ( i = 0 ; i < nlines ; i + + ) {
if ( ctdb_add_node ( ctdb , lines [ i ] ) ! = 0 ) {
talloc_free ( lines ) ;
return - 1 ;
}
}
talloc_free ( lines ) ;
return 0 ;
}
/*
setup the local node address
*/
int ctdb_set_address ( struct ctdb_context * ctdb , const char * address )
{
2006-11-28 09:56:10 +03:00
if ( ctdb_parse_address ( ctdb , ctdb , address , & ctdb - > address ) ! = 0 ) {
return - 1 ;
}
ctdb - > name = talloc_asprintf ( ctdb , " %s:%u " ,
ctdb - > address . address ,
ctdb - > address . port ) ;
return 0 ;
2006-11-27 13:38:13 +03:00
}
/*
add a node to the list of active nodes
*/
int ctdb_set_call ( struct ctdb_context * ctdb , ctdb_fn_t fn , int id )
{
struct ctdb_registered_call * call ;
call = talloc ( ctdb , struct ctdb_registered_call ) ;
call - > fn = fn ;
call - > id = id ;
DLIST_ADD ( ctdb - > calls , call ) ;
return 0 ;
}
2007-01-23 03:38:45 +03:00
/*
return the vnn of this node
*/
uint32_t ctdb_get_vnn ( struct ctdb_context * ctdb )
{
return ctdb - > vnn ;
}
2006-11-27 13:38:13 +03:00
/*
start the protocol going
*/
int ctdb_start ( struct ctdb_context * ctdb )
{
return ctdb - > methods - > start ( ctdb ) ;
}
/*
2006-11-28 09:56:10 +03:00
called by the transport layer when a packet comes in
2006-11-27 13:38:13 +03:00
*/
2006-11-28 09:56:10 +03:00
static void ctdb_recv_pkt ( struct ctdb_context * ctdb , uint8_t * data , uint32_t length )
2006-11-27 13:38:13 +03:00
{
2006-12-01 07:45:24 +03:00
struct ctdb_req_header * hdr ;
2007-02-07 05:26:07 +03:00
2006-12-01 07:45:24 +03:00
if ( length < sizeof ( * hdr ) ) {
ctdb_set_error ( ctdb , " Bad packet length %d \n " , length ) ;
return ;
}
hdr = ( struct ctdb_req_header * ) data ;
if ( length ! = hdr - > length ) {
ctdb_set_error ( ctdb , " Bad header length %d expected %d \n " ,
hdr - > length , length ) ;
return ;
}
2007-01-23 03:38:45 +03:00
2006-12-01 07:45:24 +03:00
switch ( hdr - > operation ) {
case CTDB_REQ_CALL :
ctdb_request_call ( ctdb , hdr ) ;
break ;
case CTDB_REPLY_CALL :
ctdb_reply_call ( ctdb , hdr ) ;
break ;
2006-12-18 06:27:20 +03:00
case CTDB_REPLY_ERROR :
ctdb_reply_error ( ctdb , hdr ) ;
break ;
2006-12-18 06:44:06 +03:00
case CTDB_REPLY_REDIRECT :
ctdb_reply_redirect ( ctdb , hdr ) ;
break ;
2006-12-18 08:01:11 +03:00
case CTDB_REQ_DMASTER :
ctdb_request_dmaster ( ctdb , hdr ) ;
break ;
case CTDB_REPLY_DMASTER :
ctdb_reply_dmaster ( ctdb , hdr ) ;
break ;
2006-12-01 07:45:24 +03:00
default :
printf ( " Packet with unknown operation %d \n " , hdr - > operation ) ;
talloc_free ( hdr ) ;
break ;
}
2006-11-27 13:38:13 +03:00
}
2006-11-28 03:51:33 +03:00
/*
2006-11-28 09:56:10 +03:00
called by the transport layer when a node is dead
2006-11-28 03:51:33 +03:00
*/
2006-11-28 09:56:10 +03:00
static void ctdb_node_dead ( struct ctdb_node * node )
2006-11-28 03:51:33 +03:00
{
2006-12-01 00:58:08 +03:00
node - > ctdb - > num_connected - - ;
printf ( " %s: node %s is dead: %d connected \n " ,
node - > ctdb - > name , node - > name , node - > ctdb - > num_connected ) ;
2006-11-28 03:51:33 +03:00
}
2006-11-28 06:15:46 +03:00
/*
2007-02-07 05:26:07 +03:00
called by the transport layer when a node is connected
2006-11-28 06:15:46 +03:00
*/
2006-11-28 09:56:10 +03:00
static void ctdb_node_connected ( struct ctdb_node * node )
2006-11-28 06:15:46 +03:00
{
2006-12-01 00:58:08 +03:00
node - > ctdb - > num_connected + + ;
printf ( " %s: connected to %s - %d connected \n " ,
node - > ctdb - > name , node - > name , node - > ctdb - > num_connected ) ;
}
/*
wait for all nodes to be connected
*/
void ctdb_connect_wait ( struct ctdb_context * ctdb )
{
2006-12-01 07:45:24 +03:00
int expected = ctdb - > num_nodes - 1 ;
if ( ctdb - > flags & CTDB_FLAG_SELF_CONNECT ) {
expected + + ;
}
while ( ctdb - > num_connected ! = expected ) {
event_loop_once ( ctdb - > ev ) ;
}
}
/*
wait until we ' re the only node left
*/
void ctdb_wait_loop ( struct ctdb_context * ctdb )
{
int expected = 0 ;
if ( ctdb - > flags & CTDB_FLAG_SELF_CONNECT ) {
expected + + ;
}
while ( ctdb - > num_connected > expected ) {
2006-12-01 00:58:08 +03:00
event_loop_once ( ctdb - > ev ) ;
}
2006-11-28 06:15:46 +03:00
}
2006-11-28 03:51:33 +03:00
static const struct ctdb_upcalls ctdb_upcalls = {
2006-11-28 09:56:10 +03:00
. recv_pkt = ctdb_recv_pkt ,
. node_dead = ctdb_node_dead ,
. node_connected = ctdb_node_connected
2006-11-28 03:51:33 +03:00
} ;
/*
initialise the ctdb daemon .
NOTE : In current code the daemon does not fork . This is for testing purposes only
and to simplify the code .
*/
struct ctdb_context * ctdb_init ( struct event_context * ev )
{
struct ctdb_context * ctdb ;
ctdb = talloc_zero ( ev , struct ctdb_context ) ;
ctdb - > ev = ev ;
ctdb - > upcalls = & ctdb_upcalls ;
2006-11-28 12:48:34 +03:00
ctdb - > idr = idr_init ( ctdb ) ;
2007-01-23 03:38:45 +03:00
ctdb - > max_lacount = CTDB_DEFAULT_MAX_LACOUNT ;
2006-11-28 03:51:33 +03:00
return ctdb ;
}