2006-11-28 09:56:10 +03:00
/*
ctdb ltdb code
Copyright ( C ) Andrew Tridgell 2006
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 ,
2006-11-28 09:56:10 +03: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/>.
2006-11-28 09:56:10 +03:00
*/
# 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
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
{
2007-04-27 12:43:52 +04:00
uint32_t idx , lmaster ;
idx = ctdb_hash ( key ) % ctdb - > vnn_map - > size ;
lmaster = ctdb - > vnn_map - > map [ idx ] ;
return lmaster ;
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 ) ) {
2007-04-19 12:31:49 +04:00
TDB_DATA d2 ;
2006-12-18 05:24:02 +03:00
/* return an initial header */
2007-04-19 12:31:49 +04:00
if ( rec . dptr ) free ( rec . dptr ) ;
2007-06-02 07:16:11 +04:00
if ( ctdb - > vnn_map = = NULL ) {
/* called from the client */
ZERO_STRUCTP ( data ) ;
header - > dmaster = ( uint32_t ) - 1 ;
return - 1 ;
}
2007-04-03 13:41:00 +04:00
ltdb_initial_header ( ctdb_db , key , header ) ;
2007-04-19 12:31:49 +04:00
ZERO_STRUCT ( d2 ) ;
2007-04-04 15:15:56 +04:00
if ( data ) {
2007-04-19 12:31:49 +04:00
* data = d2 ;
2007-04-04 15:15:56 +04:00
}
2007-04-19 12:31:49 +04:00
ctdb_ltdb_store ( ctdb_db , key , header , d2 ) ;
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 ;
2007-05-11 04:33:43 +04:00
if ( ctdb - > flags & CTDB_FLAG_TORTURE ) {
struct ctdb_ltdb_header * h2 ;
rec = tdb_fetch ( ctdb_db - > ltdb - > tdb , key ) ;
h2 = ( struct ctdb_ltdb_header * ) rec . dptr ;
if ( rec . dptr & & rec . dsize > = sizeof ( h2 ) & & h2 - > rsn > header - > rsn ) {
DEBUG ( 0 , ( " RSN regression! %llu %llu \n " ,
( unsigned long long ) h2 - > rsn , ( unsigned long long ) header - > rsn ) ) ;
}
if ( rec . dptr ) free ( rec . dptr ) ;
}
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 ;
}
2007-04-11 05:01:42 +04:00
/*
lock a record in the ltdb , given a key
*/
int ctdb_ltdb_lock ( struct ctdb_db_context * ctdb_db , TDB_DATA key )
{
return tdb_chainlock ( ctdb_db - > ltdb - > tdb , key ) ;
}
/*
unlock a record in the ltdb , given a key
*/
int ctdb_ltdb_unlock ( struct ctdb_db_context * ctdb_db , TDB_DATA key )
{
2007-04-22 20:19:49 +04:00
int ret = tdb_chainunlock ( ctdb_db - > ltdb - > tdb , key ) ;
if ( ret ! = 0 ) {
DEBUG ( 0 , ( " tdb_chainunlock failed \n " ) ) ;
}
return ret ;
2007-04-11 05:01:42 +04:00
}