2006-11-28 09:56:10 +03:00
/*
ctdb ltdb 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 "lib/events/events.h"
2007-01-23 03:38:45 +03:00
# include "lib/tdb/include/tdb.h"
2006-11-28 09:56:10 +03:00
# include "system/network.h"
# include "system/filesys.h"
2007-01-23 03:38:45 +03:00
# include "../include/ctdb_private.h"
2007-01-25 07:10:40 +03:00
# include "db_wrap.h"
2007-04-04 09:02:49 +04:00
# include "lib/util/dlinklist.h"
2007-01-25 07:10:40 +03:00
2007-04-04 09:02:49 +04:00
/*
find an attached ctdb_db handle given a name
*/
struct ctdb_db_context * ctdb_db_handle ( struct ctdb_context * ctdb , const char * name )
{
struct ctdb_db_context * tmp_db ;
for ( tmp_db = ctdb - > db_list ; tmp_db ; tmp_db = tmp_db - > next ) {
if ( strcmp ( name , tmp_db - > db_name ) = = 0 ) {
return tmp_db ;
}
}
return NULL ;
}
2006-11-28 09:56:10 +03:00
2007-04-04 15:15:56 +04:00
/*
this is the dummy null procedure that all databases support
*/
static int ctdb_fetch_func ( struct ctdb_call_info * call )
{
call - > reply_data = & call - > record_data ;
return 0 ;
}
2006-11-28 09:56:10 +03:00
/*
attach to a specific database
*/
2007-04-03 13:41:00 +04:00
struct ctdb_db_context * ctdb_attach ( struct ctdb_context * ctdb , const char * name , int tdb_flags ,
int open_flags , mode_t mode )
2006-11-28 09:56:10 +03:00
{
2007-04-03 13:41:00 +04:00
struct ctdb_db_context * ctdb_db , * tmp_db ;
TDB_DATA data ;
2007-04-04 15:15:56 +04:00
int ret ;
2007-04-03 13:41:00 +04:00
ctdb_db = talloc_zero ( ctdb , struct ctdb_db_context ) ;
CTDB_NO_MEMORY_NULL ( ctdb , ctdb_db ) ;
ctdb_db - > ctdb = ctdb ;
ctdb_db - > db_name = talloc_strdup ( ctdb_db , name ) ;
CTDB_NO_MEMORY_NULL ( ctdb , ctdb_db - > db_name ) ;
2007-04-04 09:02:49 +04:00
data . dptr = discard_const ( name ) ;
2007-04-03 13:41:00 +04:00
data . dsize = strlen ( name ) ;
ctdb_db - > db_id = ctdb_hash ( & data ) ;
for ( tmp_db = ctdb - > db_list ; tmp_db ; tmp_db = tmp_db - > next ) {
if ( tmp_db - > db_id = = ctdb_db - > db_id ) {
ctdb_set_error ( ctdb , " CTDB database hash collission '%s' : '%s' " ,
name , tmp_db - > db_name ) ;
talloc_free ( ctdb_db ) ;
return NULL ;
}
}
2006-11-28 09:56:10 +03:00
/* when we have a separate daemon this will need to be a real
file , not a TDB_INTERNAL , so the parent can access it to
for ltdb bypass */
2007-04-03 13:41:00 +04:00
ctdb_db - > ltdb = tdb_wrap_open ( ctdb , name , 0 , TDB_INTERNAL , open_flags , mode ) ;
if ( ctdb_db - > ltdb = = NULL ) {
2006-11-28 09:56:10 +03:00
ctdb_set_error ( ctdb , " Failed to open tdb %s \n " , name ) ;
2007-04-03 13:41:00 +04:00
talloc_free ( ctdb_db ) ;
return NULL ;
2006-11-28 09:56:10 +03:00
}
2007-04-03 13:41:00 +04:00
2007-04-04 15:15:56 +04:00
/*
all databases support the " fetch " function . we need this in order to do forced migration of records
*/
ret = ctdb_set_call ( ctdb_db , ctdb_fetch_func , CTDB_FETCH_FUNC ) ;
if ( ret ! = 0 ) {
talloc_free ( ctdb_db ) ;
return NULL ;
}
2007-04-03 13:41:00 +04:00
DLIST_ADD ( ctdb - > db_list , ctdb_db ) ;
2007-04-04 15:15:56 +04:00
2007-04-03 13:41:00 +04:00
return ctdb_db ;
2006-11-28 09:56:10 +03:00
}
2006-12-18 05:24:02 +03:00
2006-12-18 06:44:06 +03:00
/*
return the lmaster given a key
*/
2006-12-18 08:01:11 +03:00
uint32_t ctdb_lmaster ( struct ctdb_context * ctdb , const TDB_DATA * key )
2006-12-18 06:44:06 +03:00
{
2006-12-18 08:01:11 +03:00
return ctdb_hash ( key ) % ctdb - > num_nodes ;
2006-12-18 06:44:06 +03:00
}
2006-12-18 05:24:02 +03:00
/*
construct an initial header for a record with no ltdb header yet
*/
2007-04-03 13:41:00 +04:00
static void ltdb_initial_header ( struct ctdb_db_context * ctdb_db ,
2006-12-18 05:24:02 +03:00
TDB_DATA key ,
struct ctdb_ltdb_header * header )
{
header - > rsn = 0 ;
2006-12-18 06:05:49 +03:00
/* initial dmaster is the lmaster */
2007-04-03 13:41:00 +04:00
header - > dmaster = ctdb_lmaster ( ctdb_db - > ctdb , & key ) ;
2006-12-18 05:24:02 +03:00
header - > laccessor = header - > dmaster ;
header - > lacount = 0 ;
}
/*
fetch a record from the ltdb , separating out the header information
and returning the body of the record . A valid ( initial ) header is
returned if the record is not present
*/
2007-04-03 13:41:00 +04:00
int ctdb_ltdb_fetch ( struct ctdb_db_context * ctdb_db ,
2007-04-07 04:45:00 +04:00
TDB_DATA key , struct ctdb_ltdb_header * header ,
TALLOC_CTX * mem_ctx , TDB_DATA * data )
2006-12-18 05:24:02 +03:00
{
TDB_DATA rec ;
2007-04-03 13:41:00 +04:00
struct ctdb_context * ctdb = ctdb_db - > ctdb ;
2006-12-18 05:24:02 +03:00
2007-04-03 13:41:00 +04:00
rec = tdb_fetch ( ctdb_db - > ltdb - > tdb , key ) ;
2006-12-18 05:24:02 +03:00
if ( rec . dsize < sizeof ( * header ) ) {
/* return an initial header */
2006-12-20 02:32:31 +03:00
free ( rec . dptr ) ;
2007-04-03 13:41:00 +04:00
ltdb_initial_header ( ctdb_db , key , header ) ;
2007-04-04 15:15:56 +04:00
if ( data ) {
data - > dptr = NULL ;
data - > dsize = 0 ;
}
2006-12-18 05:24:02 +03:00
return 0 ;
}
* header = * ( struct ctdb_ltdb_header * ) rec . dptr ;
2007-04-04 15:15:56 +04:00
if ( data ) {
data - > dsize = rec . dsize - sizeof ( struct ctdb_ltdb_header ) ;
2007-04-07 04:45:00 +04:00
data - > dptr = talloc_memdup ( mem_ctx ,
sizeof ( struct ctdb_ltdb_header ) + rec . dptr ,
2007-04-04 15:15:56 +04:00
data - > dsize ) ;
}
2006-12-20 02:32:31 +03:00
free ( rec . dptr ) ;
2007-04-04 15:15:56 +04:00
if ( data ) {
CTDB_NO_MEMORY ( ctdb , data - > dptr ) ;
}
2006-12-18 05:24:02 +03:00
return 0 ;
}
/*
fetch a record from the ltdb , separating out the header information
and returning the body of the record . A valid ( initial ) header is
returned if the record is not present
*/
2007-04-03 13:41:00 +04:00
int ctdb_ltdb_store ( struct ctdb_db_context * ctdb_db , TDB_DATA key ,
2006-12-18 05:24:02 +03:00
struct ctdb_ltdb_header * header , TDB_DATA data )
{
2007-04-03 13:41:00 +04:00
struct ctdb_context * ctdb = ctdb_db - > ctdb ;
2006-12-18 05:24:02 +03:00
TDB_DATA rec ;
int ret ;
2006-12-18 17:55:48 +03:00
rec . dsize = sizeof ( * header ) + data . dsize ;
2006-12-18 05:24:02 +03:00
rec . dptr = talloc_size ( ctdb , rec . dsize ) ;
CTDB_NO_MEMORY ( ctdb , rec . dptr ) ;
memcpy ( rec . dptr , header , sizeof ( * header ) ) ;
memcpy ( rec . dptr + sizeof ( * header ) , data . dptr , data . dsize ) ;
2007-01-25 07:10:40 +03:00
2007-04-03 13:41:00 +04:00
ret = tdb_store ( ctdb_db - > ltdb - > tdb , key , rec , TDB_REPLACE ) ;
2006-12-18 05:24:02 +03:00
talloc_free ( rec . dptr ) ;
return ret ;
}