2007-04-10 00:03:39 +04:00
/*
ctdb daemon code
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"
# include "db_wrap.h"
# include "lib/tdb/include/tdb.h"
# include "lib/events/events.h"
# include "lib/util/dlinklist.h"
# include "system/network.h"
# include "system/filesys.h"
2007-04-17 09:33:20 +04:00
# include "system/wait.h"
2007-04-10 00:03:39 +04:00
# include "../include/ctdb.h"
# include "../include/ctdb_private.h"
static void ctdb_main_loop ( struct ctdb_context * ctdb )
{
ctdb - > methods - > start ( ctdb ) ;
/* go into a wait loop to allow other nodes to complete */
event_loop_wait ( ctdb - > ev ) ;
2007-04-17 16:27:17 +04:00
DEBUG ( 0 , ( " event_loop_wait() returned. this should not happen \n " ) ) ;
2007-04-10 00:03:39 +04:00
exit ( 1 ) ;
}
static void set_non_blocking ( int fd )
{
unsigned v ;
v = fcntl ( fd , F_GETFL , 0 ) ;
fcntl ( fd , F_SETFL , v | O_NONBLOCK ) ;
}
2007-04-17 09:33:20 +04:00
static void block_signal ( int signum )
{
struct sigaction act ;
memset ( & act , 0 , sizeof ( act ) ) ;
act . sa_handler = SIG_IGN ;
sigemptyset ( & act . sa_mask ) ;
sigaddset ( & act . sa_mask , signum ) ;
sigaction ( signum , & act , NULL ) ;
}
2007-04-10 00:03:39 +04:00
2007-04-10 13:33:21 +04:00
/*
structure describing a connected client in the daemon
*/
2007-04-10 00:03:39 +04:00
struct ctdb_client {
struct ctdb_context * ctdb ;
int fd ;
2007-04-10 13:33:21 +04:00
struct ctdb_queue * queue ;
2007-04-10 00:03:39 +04:00
} ;
2007-04-11 05:58:28 +04:00
/*
message handler for when we are in daemon mode . This redirects the message
to the right client
*/
static void daemon_message_handler ( struct ctdb_context * ctdb , uint32_t srvid ,
2007-04-13 14:38:24 +04:00
TDB_DATA data , void * private_data )
2007-04-11 05:58:28 +04:00
{
2007-04-13 14:38:24 +04:00
struct ctdb_client * client = talloc_get_type ( private_data , struct ctdb_client ) ;
2007-04-11 05:58:28 +04:00
struct ctdb_req_message * r ;
int len ;
/* construct a message to send to the client containing the data */
len = offsetof ( struct ctdb_req_message , data ) + data . dsize ;
r = ctdbd_allocate_pkt ( ctdb , len ) ;
2007-04-11 07:43:15 +04:00
/*XXX cant use this since it returns an int CTDB_NO_MEMORY(ctdb, r);*/
2007-04-11 05:58:28 +04:00
talloc_set_name_const ( r , " req_message packet " ) ;
2007-04-17 11:36:53 +04:00
memset ( r , 0 , offsetof ( struct ctdb_req_message , data ) ) ;
2007-04-11 08:54:47 +04:00
2007-04-11 05:58:28 +04:00
r - > hdr . length = len ;
r - > hdr . ctdb_magic = CTDB_MAGIC ;
r - > hdr . ctdb_version = CTDB_VERSION ;
r - > hdr . operation = CTDB_REQ_MESSAGE ;
r - > srvid = srvid ;
r - > datalen = data . dsize ;
memcpy ( & r - > data [ 0 ] , data . dptr , data . dsize ) ;
2007-04-17 04:15:44 +04:00
2007-04-11 05:58:28 +04:00
ctdb_queue_send ( client - > queue , ( uint8_t * ) & r - > hdr , len ) ;
talloc_free ( r ) ;
2007-04-11 07:43:15 +04:00
return ;
2007-04-11 05:58:28 +04:00
}
/*
this is called when the ctdb daemon received a ctdb request to
set the srvid from the client
*/
static void daemon_request_register_message_handler ( struct ctdb_client * client ,
struct ctdb_req_register * c )
{
int res ;
res = ctdb_register_message_handler ( client - > ctdb , client ,
c - > srvid , daemon_message_handler ,
client ) ;
if ( res ! = 0 ) {
2007-04-17 16:27:17 +04:00
DEBUG ( 0 , ( __location__ " Failed to register handler %u in daemon \n " ,
c - > srvid ) ) ;
2007-04-11 05:58:28 +04:00
}
}
2007-04-17 08:52:51 +04:00
static struct ctdb_call_state * ctdb_daemon_fetch_lock_send ( struct ctdb_db_context * ctdb_db ,
TALLOC_CTX * mem_ctx ,
2007-04-17 10:20:32 +04:00
TDB_DATA key , struct ctdb_ltdb_header * header ,
TDB_DATA * data )
2007-04-12 09:46:50 +04:00
{
struct ctdb_call * call ;
struct ctdb_record_handle * rec ;
struct ctdb_call_state * state ;
rec = talloc ( mem_ctx , struct ctdb_record_handle ) ;
CTDB_NO_MEMORY_NULL ( ctdb_db - > ctdb , rec ) ;
call = talloc ( rec , struct ctdb_call ) ;
ZERO_STRUCT ( * call ) ;
call - > call_id = CTDB_FETCH_FUNC ;
call - > key = key ;
call - > flags = CTDB_IMMEDIATE_MIGRATION ;
rec - > ctdb_db = ctdb_db ;
rec - > key = key ;
rec - > key . dptr = talloc_memdup ( rec , key . dptr , key . dsize ) ;
rec - > data = data ;
2007-04-17 10:20:32 +04:00
state = ctdb_daemon_call_send_remote ( ctdb_db , call , header ) ;
2007-04-12 09:46:50 +04:00
state - > fetch_private = rec ;
return state ;
}
2007-04-12 15:14:41 +04:00
struct client_fetch_lock_data {
struct ctdb_client * client ;
uint32_t reqid ;
} ;
2007-04-17 08:52:51 +04:00
2007-04-12 09:46:50 +04:00
static void daemon_fetch_lock_complete ( struct ctdb_call_state * state )
{
struct ctdb_reply_fetch_lock * r ;
2007-04-13 14:38:24 +04:00
struct client_fetch_lock_data * data = talloc_get_type ( state - > async . private_data , struct client_fetch_lock_data ) ;
2007-04-12 15:14:41 +04:00
struct ctdb_client * client = talloc_get_type ( data - > client , struct ctdb_client ) ;
2007-04-12 09:46:50 +04:00
int length , res ;
length = offsetof ( struct ctdb_reply_fetch_lock , data ) + state - > call . reply_data . dsize ;
r = ctdbd_allocate_pkt ( client - > ctdb , length ) ;
if ( r = = NULL ) {
2007-04-17 16:27:17 +04:00
DEBUG ( 0 , ( __location__ " Failed to allocate reply_call in ctdb daemon \n " ) ) ;
2007-04-12 09:46:50 +04:00
return ;
}
2007-04-17 11:36:53 +04:00
memset ( r , 0 , offsetof ( struct ctdb_reply_fetch_lock , data ) ) ;
2007-04-12 09:46:50 +04:00
r - > hdr . length = length ;
r - > hdr . ctdb_magic = CTDB_MAGIC ;
r - > hdr . ctdb_version = CTDB_VERSION ;
r - > hdr . operation = CTDB_REPLY_FETCH_LOCK ;
2007-04-12 15:14:41 +04:00
r - > hdr . reqid = data - > reqid ;
2007-04-12 09:46:50 +04:00
r - > state = state - > state ;
r - > datalen = state - > call . reply_data . dsize ;
memcpy ( & r - > data [ 0 ] , state - > call . reply_data . dptr , r - > datalen ) ;
res = ctdb_queue_send ( client - > queue , ( uint8_t * ) & r - > hdr , r - > hdr . length ) ;
if ( res ! = 0 ) {
2007-04-17 16:27:17 +04:00
DEBUG ( 0 , ( __location__ " Failed to queue packet from daemon to client \n " ) ) ;
2007-04-12 09:46:50 +04:00
}
talloc_free ( r ) ;
}
/*
called when the daemon gets a fetch lock request from a client
*/
static void daemon_request_fetch_lock ( struct ctdb_client * client ,
2007-04-17 10:20:32 +04:00
struct ctdb_req_fetch_lock * f )
2007-04-12 09:46:50 +04:00
{
struct ctdb_call_state * state ;
TDB_DATA key , * data ;
struct ctdb_db_context * ctdb_db ;
2007-04-12 15:14:41 +04:00
struct client_fetch_lock_data * fl_data ;
2007-04-12 09:46:50 +04:00
ctdb_db = find_ctdb_db ( client - > ctdb , f - > db_id ) ;
2007-04-17 05:26:59 +04:00
if ( ctdb_db = = NULL ) {
struct ctdb_reply_fetch_lock r ;
ZERO_STRUCT ( r ) ;
r . hdr . length = sizeof ( r ) ;
r . hdr . ctdb_magic = CTDB_MAGIC ;
r . hdr . ctdb_version = CTDB_VERSION ;
r . hdr . operation = CTDB_REPLY_FETCH_LOCK ;
r . hdr . reqid = f - > hdr . reqid ;
r . state = - 1 ;
/*
* Ignore the result , there ' s not much we can do anyway .
*/
ctdb_queue_send ( client - > queue , ( uint8_t * ) & r . hdr ,
r . hdr . length ) ;
return ;
}
2007-04-12 09:46:50 +04:00
key . dsize = f - > keylen ;
key . dptr = & f - > key [ 0 ] ;
data = talloc ( client , TDB_DATA ) ;
data - > dptr = NULL ;
data - > dsize = 0 ;
2007-04-17 10:20:32 +04:00
state = ctdb_daemon_fetch_lock_send ( ctdb_db , client , key , & f - > header , data ) ;
2007-04-12 09:46:50 +04:00
talloc_steal ( state , data ) ;
2007-04-12 15:14:41 +04:00
fl_data = talloc ( state , struct client_fetch_lock_data ) ;
fl_data - > client = client ;
fl_data - > reqid = f - > hdr . reqid ;
2007-04-12 09:46:50 +04:00
state - > async . fn = daemon_fetch_lock_complete ;
2007-04-13 14:38:24 +04:00
state - > async . private_data = fl_data ;
2007-04-12 09:46:50 +04:00
}
2007-04-11 08:54:47 +04:00
/*
called when the daemon gets a connect wait request from a client
*/
static void daemon_request_connect_wait ( struct ctdb_client * client ,
struct ctdb_req_connect_wait * c )
{
struct ctdb_reply_connect_wait r ;
int res ;
/* first wait - in the daemon */
ctdb_daemon_connect_wait ( client - > ctdb ) ;
/* now send the reply */
ZERO_STRUCT ( r ) ;
r . hdr . length = sizeof ( r ) ;
r . hdr . ctdb_magic = CTDB_MAGIC ;
r . hdr . ctdb_version = CTDB_VERSION ;
r . hdr . operation = CTDB_REPLY_CONNECT_WAIT ;
2007-04-11 13:04:09 +04:00
r . vnn = ctdb_get_vnn ( client - > ctdb ) ;
2007-04-11 08:54:47 +04:00
r . num_connected = client - > ctdb - > num_connected ;
res = ctdb_queue_send ( client - > queue , ( uint8_t * ) & r . hdr , r . hdr . length ) ;
if ( res ! = 0 ) {
2007-04-17 16:27:17 +04:00
DEBUG ( 0 , ( __location__ " Failed to queue a connect wait response \n " ) ) ;
2007-04-11 08:54:47 +04:00
return ;
}
}
2007-04-10 00:03:39 +04:00
/*
destroy a ctdb_client
*/
static int ctdb_client_destructor ( struct ctdb_client * client )
{
close ( client - > fd ) ;
client - > fd = - 1 ;
return 0 ;
}
2007-04-11 07:43:15 +04:00
/*
this is called when the ctdb daemon received a ctdb request message
from a local client over the unix domain socket
*/
static void daemon_request_message_from_client ( struct ctdb_client * client ,
2007-04-11 08:05:01 +04:00
struct ctdb_req_message * c )
2007-04-11 07:43:15 +04:00
{
2007-04-11 08:05:01 +04:00
TDB_DATA data ;
int res ;
/* maybe the message is for another client on this node */
2007-04-11 07:43:15 +04:00
if ( ctdb_get_vnn ( client - > ctdb ) = = c - > hdr . destnode ) {
ctdb_request_message ( client - > ctdb , ( struct ctdb_req_header * ) c ) ;
2007-04-11 08:05:01 +04:00
return ;
}
/* its for a remote node */
data . dptr = & c - > data [ 0 ] ;
data . dsize = c - > datalen ;
res = ctdb_daemon_send_message ( client - > ctdb , c - > hdr . destnode ,
c - > srvid , data ) ;
if ( res ! = 0 ) {
2007-04-17 16:27:17 +04:00
DEBUG ( 0 , ( __location__ " Failed to send message to remote node %u \n " ,
c - > hdr . destnode ) ) ;
2007-04-11 07:43:15 +04:00
}
}
2007-04-10 13:33:21 +04:00
/*
this is called when the ctdb daemon received a ctdb request call
from a local client over the unix domain socket
*/
2007-04-11 05:01:42 +04:00
static void daemon_request_call_from_client ( struct ctdb_client * client ,
struct ctdb_req_call * c )
2007-04-10 00:03:39 +04:00
{
struct ctdb_call_state * state ;
struct ctdb_db_context * ctdb_db ;
struct ctdb_call call ;
2007-04-11 05:01:42 +04:00
struct ctdb_reply_call * r ;
2007-04-10 00:03:39 +04:00
int res ;
2007-04-11 05:01:42 +04:00
uint32_t length ;
2007-04-10 00:03:39 +04:00
2007-04-12 09:46:50 +04:00
ctdb_db = find_ctdb_db ( client - > ctdb , c - > db_id ) ;
2007-04-10 00:03:39 +04:00
if ( ! ctdb_db ) {
2007-04-17 16:27:17 +04:00
DEBUG ( 0 , ( __location__ " Unknown database in request. db_id==0x%08x " ,
c - > db_id ) ) ;
2007-04-10 00:03:39 +04:00
return ;
}
ZERO_STRUCT ( call ) ;
call . call_id = c - > callid ;
call . key . dptr = c - > data ;
call . key . dsize = c - > keylen ;
call . call_data . dptr = c - > data + c - > keylen ;
call . call_data . dsize = c - > calldatalen ;
2007-04-17 08:52:51 +04:00
state = ctdb_daemon_call_send ( ctdb_db , & call ) ;
// state->async.fn = daemon_call_from_client_callback;
// state->async.private_data = state;
2007-04-10 00:03:39 +04:00
/* XXX this must be converted to fully async */
2007-04-17 08:52:51 +04:00
res = ctdb_daemon_call_recv ( state , & call ) ;
2007-04-10 00:03:39 +04:00
if ( res ! = 0 ) {
2007-04-17 16:27:17 +04:00
DEBUG ( 0 , ( __location__ " ctdbd_call_recv() returned error \n " ) ) ;
2007-04-10 00:03:39 +04:00
exit ( 1 ) ;
}
2007-04-11 05:01:42 +04:00
length = offsetof ( struct ctdb_reply_call , data ) + call . reply_data . dsize ;
r = ctdbd_allocate_pkt ( client - > ctdb , length ) ;
if ( r = = NULL ) {
2007-04-17 16:27:17 +04:00
DEBUG ( 0 , ( __location__ " Failed to allocate reply_call in ctdb daemon \n " ) ) ;
2007-04-11 05:01:42 +04:00
return ;
}
2007-04-17 11:36:53 +04:00
memset ( r , 0 , offsetof ( struct ctdb_reply_call , data ) ) ;
2007-04-11 05:01:42 +04:00
r - > hdr . length = length ;
r - > hdr . ctdb_magic = CTDB_MAGIC ;
r - > hdr . ctdb_version = CTDB_VERSION ;
r - > hdr . operation = CTDB_REPLY_CALL ;
r - > hdr . reqid = c - > hdr . reqid ;
r - > datalen = call . reply_data . dsize ;
memcpy ( & r - > data [ 0 ] , call . reply_data . dptr , r - > datalen ) ;
2007-04-17 08:52:51 +04:00
res = ctdb_queue_send ( client - > queue , ( uint8_t * ) & r - > hdr , r - > hdr . length ) ;
2007-04-11 05:01:42 +04:00
if ( res ! = 0 ) {
2007-04-17 16:27:17 +04:00
DEBUG ( 0 , ( __location__ " Failed to queue packet from daemon to client \n " ) ) ;
2007-04-10 00:03:39 +04:00
}
2007-04-11 05:01:42 +04:00
talloc_free ( r ) ;
2007-04-10 00:03:39 +04:00
}
/* data contains a packet from the client */
2007-04-17 08:52:51 +04:00
static void daemon_incoming_packet ( struct ctdb_client * client , void * data , size_t nread )
2007-04-10 00:03:39 +04:00
{
struct ctdb_req_header * hdr = data ;
if ( hdr - > ctdb_magic ! = CTDB_MAGIC ) {
2007-04-17 04:15:44 +04:00
ctdb_set_error ( client - > ctdb , " Non CTDB packet rejected in daemon \n " ) ;
2007-04-11 08:05:01 +04:00
goto done ;
2007-04-10 00:03:39 +04:00
}
if ( hdr - > ctdb_version ! = CTDB_VERSION ) {
2007-04-17 04:15:44 +04:00
ctdb_set_error ( client - > ctdb , " Bad CTDB version 0x%x rejected in daemon \n " , hdr - > ctdb_version ) ;
2007-04-11 08:05:01 +04:00
goto done ;
2007-04-10 00:03:39 +04:00
}
switch ( hdr - > operation ) {
case CTDB_REQ_CALL :
2007-04-11 05:01:42 +04:00
daemon_request_call_from_client ( client , ( struct ctdb_req_call * ) hdr ) ;
2007-04-10 00:03:39 +04:00
break ;
2007-04-11 05:58:28 +04:00
case CTDB_REQ_REGISTER :
daemon_request_register_message_handler ( client ,
( struct ctdb_req_register * ) hdr ) ;
break ;
2007-04-11 07:43:15 +04:00
case CTDB_REQ_MESSAGE :
daemon_request_message_from_client ( client , ( struct ctdb_req_message * ) hdr ) ;
break ;
2007-04-11 08:54:47 +04:00
case CTDB_REQ_CONNECT_WAIT :
daemon_request_connect_wait ( client , ( struct ctdb_req_connect_wait * ) hdr ) ;
break ;
2007-04-12 09:46:50 +04:00
case CTDB_REQ_FETCH_LOCK :
daemon_request_fetch_lock ( client , ( struct ctdb_req_fetch_lock * ) hdr ) ;
break ;
2007-04-13 03:41:15 +04:00
default :
2007-04-17 16:27:17 +04:00
DEBUG ( 0 , ( __location__ " daemon: unrecognized operation %d \n " ,
hdr - > operation ) ) ;
2007-04-10 00:03:39 +04:00
}
2007-04-11 08:05:01 +04:00
done :
2007-04-10 00:03:39 +04:00
talloc_free ( data ) ;
}
2007-04-17 08:52:51 +04:00
static void ctdb_daemon_read_cb ( uint8_t * data , size_t cnt , void * args )
2007-04-10 00:03:39 +04:00
{
2007-04-10 02:38:29 +04:00
struct ctdb_client * client = talloc_get_type ( args , struct ctdb_client ) ;
struct ctdb_req_header * hdr ;
2007-04-11 15:17:36 +04:00
if ( cnt = = 0 ) {
talloc_free ( client ) ;
return ;
}
2007-04-10 02:38:29 +04:00
if ( cnt < sizeof ( * hdr ) ) {
2007-04-17 04:15:44 +04:00
ctdb_set_error ( client - > ctdb , " Bad packet length %d in daemon \n " , cnt ) ;
2007-04-10 00:03:39 +04:00
return ;
}
2007-04-10 02:38:29 +04:00
hdr = ( struct ctdb_req_header * ) data ;
if ( cnt ! = hdr - > length ) {
2007-04-17 04:15:44 +04:00
ctdb_set_error ( client - > ctdb , " Bad header length %d expected %d \n in daemon " ,
2007-04-10 02:38:29 +04:00
hdr - > length , cnt ) ;
2007-04-10 00:03:39 +04:00
return ;
}
2007-04-10 02:38:29 +04:00
if ( hdr - > ctdb_magic ! = CTDB_MAGIC ) {
ctdb_set_error ( client - > ctdb , " Non CTDB packet rejected \n " ) ;
2007-04-10 00:03:39 +04:00
return ;
}
2007-04-10 02:38:29 +04:00
if ( hdr - > ctdb_version ! = CTDB_VERSION ) {
2007-04-17 04:15:44 +04:00
ctdb_set_error ( client - > ctdb , " Bad CTDB version 0x%x rejected in daemon \n " , hdr - > ctdb_version ) ;
2007-04-10 00:03:39 +04:00
return ;
}
2007-04-10 02:38:29 +04:00
/* it is the responsibility of the incoming packet function to free 'data' */
2007-04-17 08:52:51 +04:00
daemon_incoming_packet ( client , data , cnt ) ;
2007-04-10 02:38:29 +04:00
}
2007-04-10 00:03:39 +04:00
static void ctdb_accept_client ( struct event_context * ev , struct fd_event * fde ,
2007-04-13 14:38:24 +04:00
uint16_t flags , void * private_data )
2007-04-10 00:03:39 +04:00
{
struct sockaddr_in addr ;
socklen_t len ;
int fd ;
2007-04-13 14:38:24 +04:00
struct ctdb_context * ctdb = talloc_get_type ( private_data , struct ctdb_context ) ;
2007-04-10 00:03:39 +04:00
struct ctdb_client * client ;
memset ( & addr , 0 , sizeof ( addr ) ) ;
len = sizeof ( addr ) ;
fd = accept ( ctdb - > daemon . sd , ( struct sockaddr * ) & addr , & len ) ;
if ( fd = = - 1 ) {
return ;
}
set_non_blocking ( fd ) ;
client = talloc_zero ( ctdb , struct ctdb_client ) ;
client - > ctdb = ctdb ;
client - > fd = fd ;
2007-04-10 13:33:21 +04:00
client - > queue = ctdb_queue_setup ( ctdb , client , fd , CTDB_DS_ALIGNMENT ,
2007-04-17 08:52:51 +04:00
ctdb_daemon_read_cb , client ) ;
2007-04-10 00:03:39 +04:00
talloc_set_destructor ( client , ctdb_client_destructor ) ;
}
static void ctdb_read_from_parent ( struct event_context * ev , struct fd_event * fde ,
2007-04-13 14:38:24 +04:00
uint16_t flags , void * private_data )
2007-04-10 00:03:39 +04:00
{
2007-04-13 14:38:24 +04:00
int * fd = private_data ;
2007-04-10 00:03:39 +04:00
int cnt ;
char buf ;
/* XXX this is a good place to try doing some cleaning up before exiting */
cnt = read ( * fd , & buf , 1 ) ;
if ( cnt = = 0 ) {
2007-04-17 16:27:17 +04:00
DEBUG ( 0 , ( __location__ " parent process exited. filedescriptor dissappeared \n " ) ) ;
2007-04-10 00:03:39 +04:00
exit ( 1 ) ;
} else {
2007-04-17 16:27:17 +04:00
DEBUG ( 0 , ( __location__ " ctdb: did not expect data from parent process \n " ) ) ;
2007-04-10 00:03:39 +04:00
exit ( 1 ) ;
}
}
/*
create a unix domain socket and bind it
return a file descriptor open on the socket
*/
static int ux_socket_bind ( struct ctdb_context * ctdb )
{
struct sockaddr_un addr ;
ctdb - > daemon . sd = socket ( AF_UNIX , SOCK_STREAM , 0 ) ;
if ( ctdb - > daemon . sd = = - 1 ) {
ctdb - > daemon . sd = - 1 ;
return - 1 ;
}
set_non_blocking ( ctdb - > daemon . sd ) ;
memset ( & addr , 0 , sizeof ( addr ) ) ;
addr . sun_family = AF_UNIX ;
strncpy ( addr . sun_path , ctdb - > daemon . name , sizeof ( addr . sun_path ) ) ;
if ( bind ( ctdb - > daemon . sd , ( struct sockaddr * ) & addr , sizeof ( addr ) ) = = - 1 ) {
close ( ctdb - > daemon . sd ) ;
ctdb - > daemon . sd = - 1 ;
return - 1 ;
}
listen ( ctdb - > daemon . sd , 1 ) ;
return 0 ;
}
2007-04-11 05:01:42 +04:00
/*
delete the socket on exit - called on destruction of autofree context
*/
static int unlink_destructor ( const char * name )
2007-04-10 02:47:39 +04:00
{
2007-04-11 05:01:42 +04:00
unlink ( name ) ;
return 0 ;
2007-04-10 02:47:39 +04:00
}
2007-04-10 00:03:39 +04:00
/*
start the protocol going
*/
2007-04-17 08:52:51 +04:00
int ctdb_start ( struct ctdb_context * ctdb )
2007-04-10 00:03:39 +04:00
{
pid_t pid ;
static int fd [ 2 ] ;
int res ;
struct fd_event * fde ;
2007-04-11 05:01:42 +04:00
const char * domain_socket_name ;
2007-04-10 00:03:39 +04:00
/* generate a name to use for our local socket */
ctdb - > daemon . name = talloc_asprintf ( ctdb , " %s.%s " , CTDB_PATH , ctdb - > address . address ) ;
/* get rid of any old sockets */
unlink ( ctdb - > daemon . name ) ;
/* create a unix domain stream socket to listen to */
res = ux_socket_bind ( ctdb ) ;
if ( res ! = 0 ) {
2007-04-17 16:27:17 +04:00
DEBUG ( 0 , ( __location__ " Failed to open CTDB unix domain socket \n " ) ) ;
2007-04-10 00:03:39 +04:00
exit ( 10 ) ;
}
res = pipe ( & fd [ 0 ] ) ;
if ( res ) {
2007-04-17 16:27:17 +04:00
DEBUG ( 0 , ( __location__ " Failed to open pipe for CTDB \n " ) ) ;
2007-04-10 00:03:39 +04:00
exit ( 1 ) ;
}
pid = fork ( ) ;
if ( pid = = - 1 ) {
2007-04-17 16:27:17 +04:00
DEBUG ( 0 , ( __location__ " Failed to fork CTDB daemon \n " ) ) ;
2007-04-10 00:03:39 +04:00
exit ( 1 ) ;
}
if ( pid ) {
close ( fd [ 0 ] ) ;
close ( ctdb - > daemon . sd ) ;
ctdb - > daemon . sd = - 1 ;
return 0 ;
}
2007-04-17 09:33:20 +04:00
block_signal ( SIGPIPE ) ;
2007-04-11 05:01:42 +04:00
/* ensure the socket is deleted on exit of the daemon */
domain_socket_name = talloc_strdup ( talloc_autofree_context ( ) , ctdb - > daemon . name ) ;
talloc_set_destructor ( domain_socket_name , unlink_destructor ) ;
2007-04-10 00:03:39 +04:00
close ( fd [ 1 ] ) ;
2007-04-17 08:52:51 +04:00
2007-04-10 00:03:39 +04:00
ctdb - > ev = event_context_init ( NULL ) ;
fde = event_add_fd ( ctdb - > ev , ctdb , fd [ 0 ] , EVENT_FD_READ , ctdb_read_from_parent , & fd [ 0 ] ) ;
fde = event_add_fd ( ctdb - > ev , ctdb , ctdb - > daemon . sd , EVENT_FD_READ , ctdb_accept_client , ctdb ) ;
ctdb_main_loop ( ctdb ) ;
return 0 ;
}
/*
2007-04-11 05:01:42 +04:00
allocate a packet for use in client < - > daemon communication
*/
void * ctdbd_allocate_pkt ( struct ctdb_context * ctdb , size_t len )
2007-04-10 00:03:39 +04:00
{
int size ;
size = ( len + ( CTDB_DS_ALIGNMENT - 1 ) ) & ~ ( CTDB_DS_ALIGNMENT - 1 ) ;
return talloc_size ( ctdb , size ) ;
}