r22775: For the cluster code I've developed a wrapper around tdb to put different
database backends in place dynamically.
The main abstractions are db_context and db_record, it should be mainly
self-describing, see include/dbwrap.h. You open the db just as you would open
a tdb, this time with db_open(). If you want to fetch a record, just do the
db->fetch() call, if you want to do operations on it, you need to get it with
fetch_locked().
I added dbwrap_file.c (not heavily tested lately) as an example for what can
be done with that abstraction, uses a file per key. So if anybody is willing
to shape that up, we might have a chance on reiserfs again.... :-)
This abstraction works fine for brlock.tdb, locking.tdb, connections.tdb and
sessionid.tdb. It should work fine for the others as well, I just did not yet
get around to convert them.
If nobody loudly screams NO, then I will import the code that uses this soon.
Volker
(This used to be commit e9d7484ca246cfca4a1fd23be35edc2783136ebe)
2007-05-10 14:42:13 +04:00
/*
Unix SMB / CIFS implementation .
Database interface wrapper
Copyright ( C ) Jim McDonough < jmcd @ us . ibm . com > 2006
Major code contributions from Aleksey Fedoseev ( fedoseev @ ru . ibm . com )
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-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
r22775: For the cluster code I've developed a wrapper around tdb to put different
database backends in place dynamically.
The main abstractions are db_context and db_record, it should be mainly
self-describing, see include/dbwrap.h. You open the db just as you would open
a tdb, this time with db_open(). If you want to fetch a record, just do the
db->fetch() call, if you want to do operations on it, you need to get it with
fetch_locked().
I added dbwrap_file.c (not heavily tested lately) as an example for what can
be done with that abstraction, uses a file per key. So if anybody is willing
to shape that up, we might have a chance on reiserfs again.... :-)
This abstraction works fine for brlock.tdb, locking.tdb, connections.tdb and
sessionid.tdb. It should work fine for the others as well, I just did not yet
get around to convert them.
If nobody loudly screams NO, then I will import the code that uses this soon.
Volker
(This used to be commit e9d7484ca246cfca4a1fd23be35edc2783136ebe)
2007-05-10 14:42:13 +04:00
( at your option ) any later version .
This program 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 General Public License for more details .
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
r22775: For the cluster code I've developed a wrapper around tdb to put different
database backends in place dynamically.
The main abstractions are db_context and db_record, it should be mainly
self-describing, see include/dbwrap.h. You open the db just as you would open
a tdb, this time with db_open(). If you want to fetch a record, just do the
db->fetch() call, if you want to do operations on it, you need to get it with
fetch_locked().
I added dbwrap_file.c (not heavily tested lately) as an example for what can
be done with that abstraction, uses a file per key. So if anybody is willing
to shape that up, we might have a chance on reiserfs again.... :-)
This abstraction works fine for brlock.tdb, locking.tdb, connections.tdb and
sessionid.tdb. It should work fine for the others as well, I just did not yet
get around to convert them.
If nobody loudly screams NO, then I will import the code that uses this soon.
Volker
(This used to be commit e9d7484ca246cfca4a1fd23be35edc2783136ebe)
2007-05-10 14:42:13 +04:00
*/
# include "includes.h"
2008-01-16 12:09:48 +03:00
# ifdef CLUSTER_SUPPORT
# include "ctdb_private.h"
# endif
r22775: For the cluster code I've developed a wrapper around tdb to put different
database backends in place dynamically.
The main abstractions are db_context and db_record, it should be mainly
self-describing, see include/dbwrap.h. You open the db just as you would open
a tdb, this time with db_open(). If you want to fetch a record, just do the
db->fetch() call, if you want to do operations on it, you need to get it with
fetch_locked().
I added dbwrap_file.c (not heavily tested lately) as an example for what can
be done with that abstraction, uses a file per key. So if anybody is willing
to shape that up, we might have a chance on reiserfs again.... :-)
This abstraction works fine for brlock.tdb, locking.tdb, connections.tdb and
sessionid.tdb. It should work fine for the others as well, I just did not yet
get around to convert them.
If nobody loudly screams NO, then I will import the code that uses this soon.
Volker
(This used to be commit e9d7484ca246cfca4a1fd23be35edc2783136ebe)
2007-05-10 14:42:13 +04:00
/*
* Fall back using fetch_locked if no genuine fetch operation is provided
*/
static int dbwrap_fallback_fetch ( struct db_context * db , TALLOC_CTX * mem_ctx ,
TDB_DATA key , TDB_DATA * data )
{
struct db_record * rec ;
if ( ! ( rec = db - > fetch_locked ( db , mem_ctx , key ) ) ) {
return - 1 ;
}
data - > dsize = rec - > value . dsize ;
data - > dptr = talloc_move ( mem_ctx , & rec - > value . dptr ) ;
TALLOC_FREE ( rec ) ;
return 0 ;
}
2009-02-22 02:18:05 +03:00
/*
* Fall back using fetch if no genuine parse operation is provided
*/
static int dbwrap_fallback_parse_record ( struct db_context * db , TDB_DATA key ,
int ( * parser ) ( TDB_DATA key ,
TDB_DATA data ,
void * private_data ) ,
void * private_data )
{
TDB_DATA data ;
int res ;
res = db - > fetch ( db , talloc_tos ( ) , key , & data ) ;
if ( res ! = 0 ) {
return res ;
}
res = parser ( key , data , private_data ) ;
TALLOC_FREE ( data . dptr ) ;
return res ;
}
2009-03-27 22:12:30 +03:00
bool db_is_local ( const char * name )
{
# ifdef CLUSTER_SUPPORT
const char * sockname = lp_ctdbd_socket ( ) ;
if ( ! sockname | | ! * sockname ) {
sockname = CTDB_PATH ;
}
if ( lp_clustering ( ) & & socket_exist ( sockname ) ) {
const char * partname ;
/* ctdb only wants the file part of the name */
partname = strrchr ( name , ' / ' ) ;
if ( partname ) {
partname + + ;
} else {
partname = name ;
}
/* allow ctdb for individual databases to be disabled */
if ( lp_parm_bool ( - 1 , " ctdb " , partname , True ) ) {
return false ;
}
}
# endif
return true ;
}
2008-03-27 18:08:21 +03:00
/**
2008-08-07 10:20:05 +04:00
* open a database
2008-03-27 18:08:21 +03:00
*/
r22775: For the cluster code I've developed a wrapper around tdb to put different
database backends in place dynamically.
The main abstractions are db_context and db_record, it should be mainly
self-describing, see include/dbwrap.h. You open the db just as you would open
a tdb, this time with db_open(). If you want to fetch a record, just do the
db->fetch() call, if you want to do operations on it, you need to get it with
fetch_locked().
I added dbwrap_file.c (not heavily tested lately) as an example for what can
be done with that abstraction, uses a file per key. So if anybody is willing
to shape that up, we might have a chance on reiserfs again.... :-)
This abstraction works fine for brlock.tdb, locking.tdb, connections.tdb and
sessionid.tdb. It should work fine for the others as well, I just did not yet
get around to convert them.
If nobody loudly screams NO, then I will import the code that uses this soon.
Volker
(This used to be commit e9d7484ca246cfca4a1fd23be35edc2783136ebe)
2007-05-10 14:42:13 +04:00
struct db_context * db_open ( TALLOC_CTX * mem_ctx ,
const char * name ,
int hash_size , int tdb_flags ,
int open_flags , mode_t mode )
{
struct db_context * result = NULL ;
2008-01-16 12:09:48 +03:00
# ifdef CLUSTER_SUPPORT
const char * sockname = lp_ctdbd_socket ( ) ;
r22775: For the cluster code I've developed a wrapper around tdb to put different
database backends in place dynamically.
The main abstractions are db_context and db_record, it should be mainly
self-describing, see include/dbwrap.h. You open the db just as you would open
a tdb, this time with db_open(). If you want to fetch a record, just do the
db->fetch() call, if you want to do operations on it, you need to get it with
fetch_locked().
I added dbwrap_file.c (not heavily tested lately) as an example for what can
be done with that abstraction, uses a file per key. So if anybody is willing
to shape that up, we might have a chance on reiserfs again.... :-)
This abstraction works fine for brlock.tdb, locking.tdb, connections.tdb and
sessionid.tdb. It should work fine for the others as well, I just did not yet
get around to convert them.
If nobody loudly screams NO, then I will import the code that uses this soon.
Volker
(This used to be commit e9d7484ca246cfca4a1fd23be35edc2783136ebe)
2007-05-10 14:42:13 +04:00
2008-01-16 12:09:48 +03:00
if ( ! sockname | | ! * sockname ) {
sockname = CTDB_PATH ;
}
2007-06-10 21:02:09 +04:00
2008-07-14 12:43:28 +04:00
if ( lp_clustering ( ) ) {
2007-06-10 21:02:09 +04:00
const char * partname ;
2008-07-14 12:43:28 +04:00
if ( ! socket_exist ( sockname ) ) {
DEBUG ( 1 , ( " ctdb socket does not exist - is ctdb not "
" running? \n " ) ) ;
return NULL ;
}
2007-06-10 21:02:09 +04:00
/* ctdb only wants the file part of the name */
partname = strrchr ( name , ' / ' ) ;
if ( partname ) {
partname + + ;
} else {
partname = name ;
}
/* allow ctdb for individual databases to be disabled */
if ( lp_parm_bool ( - 1 , " ctdb " , partname , True ) ) {
result = db_open_ctdb ( mem_ctx , partname , hash_size ,
tdb_flags , open_flags , mode ) ;
if ( result = = NULL ) {
DEBUG ( 0 , ( " failed to attach to ctdb %s \n " ,
partname ) ) ;
2008-08-11 11:21:11 +04:00
if ( errno = = 0 ) {
errno = EIO ;
}
2008-07-15 17:27:14 +04:00
return NULL ;
2007-06-10 21:02:09 +04:00
}
}
}
# endif
r22775: For the cluster code I've developed a wrapper around tdb to put different
database backends in place dynamically.
The main abstractions are db_context and db_record, it should be mainly
self-describing, see include/dbwrap.h. You open the db just as you would open
a tdb, this time with db_open(). If you want to fetch a record, just do the
db->fetch() call, if you want to do operations on it, you need to get it with
fetch_locked().
I added dbwrap_file.c (not heavily tested lately) as an example for what can
be done with that abstraction, uses a file per key. So if anybody is willing
to shape that up, we might have a chance on reiserfs again.... :-)
This abstraction works fine for brlock.tdb, locking.tdb, connections.tdb and
sessionid.tdb. It should work fine for the others as well, I just did not yet
get around to convert them.
If nobody loudly screams NO, then I will import the code that uses this soon.
Volker
(This used to be commit e9d7484ca246cfca4a1fd23be35edc2783136ebe)
2007-05-10 14:42:13 +04:00
if ( result = = NULL ) {
result = db_open_tdb ( mem_ctx , name , hash_size ,
tdb_flags , open_flags , mode ) ;
}
if ( ( result ! = NULL ) & & ( result - > fetch = = NULL ) ) {
result - > fetch = dbwrap_fallback_fetch ;
}
2009-02-22 02:18:05 +03:00
if ( ( result ! = NULL ) & & ( result - > parse_record = = NULL ) ) {
result - > parse_record = dbwrap_fallback_parse_record ;
}
r22775: For the cluster code I've developed a wrapper around tdb to put different
database backends in place dynamically.
The main abstractions are db_context and db_record, it should be mainly
self-describing, see include/dbwrap.h. You open the db just as you would open
a tdb, this time with db_open(). If you want to fetch a record, just do the
db->fetch() call, if you want to do operations on it, you need to get it with
fetch_locked().
I added dbwrap_file.c (not heavily tested lately) as an example for what can
be done with that abstraction, uses a file per key. So if anybody is willing
to shape that up, we might have a chance on reiserfs again.... :-)
This abstraction works fine for brlock.tdb, locking.tdb, connections.tdb and
sessionid.tdb. It should work fine for the others as well, I just did not yet
get around to convert them.
If nobody loudly screams NO, then I will import the code that uses this soon.
Volker
(This used to be commit e9d7484ca246cfca4a1fd23be35edc2783136ebe)
2007-05-10 14:42:13 +04:00
return result ;
}
2007-11-24 21:56:16 +03:00
2008-12-17 10:53:31 +03:00
NTSTATUS dbwrap_delete ( struct db_context * db , TDB_DATA key )
2007-11-24 21:56:16 +03:00
{
struct db_record * rec ;
NTSTATUS status ;
2008-12-17 10:53:31 +03:00
rec = db - > fetch_locked ( db , talloc_tos ( ) , key ) ;
2007-11-24 21:56:16 +03:00
if ( rec = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
status = rec - > delete_rec ( rec ) ;
TALLOC_FREE ( rec ) ;
return status ;
}
2008-12-17 10:53:31 +03:00
NTSTATUS dbwrap_store ( struct db_context * db , TDB_DATA key ,
TDB_DATA data , int flags )
2007-11-24 21:56:16 +03:00
{
struct db_record * rec ;
NTSTATUS status ;
2008-12-17 10:53:31 +03:00
rec = db - > fetch_locked ( db , talloc_tos ( ) , key ) ;
2007-11-24 21:56:16 +03:00
if ( rec = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
status = rec - > store ( rec , data , flags ) ;
TALLOC_FREE ( rec ) ;
return status ;
}
2008-12-17 10:53:31 +03:00
TDB_DATA dbwrap_fetch ( struct db_context * db , TALLOC_CTX * mem_ctx ,
TDB_DATA key )
2007-11-24 21:56:16 +03:00
{
TDB_DATA result ;
2008-12-17 10:53:31 +03:00
if ( db - > fetch ( db , mem_ctx , key , & result ) = = - 1 ) {
2007-11-24 21:56:16 +03:00
return make_tdb_data ( NULL , 0 ) ;
}
return result ;
}
2008-12-17 10:53:31 +03:00
NTSTATUS dbwrap_delete_bystring ( struct db_context * db , const char * key )
{
return dbwrap_delete ( db , string_term_tdb_data ( key ) ) ;
}
NTSTATUS dbwrap_store_bystring ( struct db_context * db , const char * key ,
TDB_DATA data , int flags )
{
return dbwrap_store ( db , string_term_tdb_data ( key ) , data , flags ) ;
}
TDB_DATA dbwrap_fetch_bystring ( struct db_context * db , TALLOC_CTX * mem_ctx ,
const char * key )
{
return dbwrap_fetch ( db , mem_ctx , string_term_tdb_data ( key ) ) ;
}