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
2007-05-10 10:42:13 +00:00
/*
Unix SMB / CIFS implementation .
Database interface wrapper around tdb
Copyright ( C ) Volker Lendecke 2005 - 2007
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 19:25:36 +00: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
2007-05-10 10:42:13 +00: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
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
struct db_tdb_ctx {
2007-06-03 06:54:51 +00:00
struct tdb_wrap * wtdb ;
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
2007-05-10 10:42:13 +00:00
} ;
static NTSTATUS db_tdb_store ( struct db_record * rec , TDB_DATA data , int flag ) ;
static NTSTATUS db_tdb_delete ( struct db_record * rec ) ;
static int db_tdb_record_destr ( struct db_record * data )
{
struct db_tdb_ctx * ctx =
talloc_get_type_abort ( data - > private_data , struct db_tdb_ctx ) ;
DEBUG ( 10 , ( " Unlocking key %s \n " ,
hex_encode ( data , ( unsigned char * ) data - > key . dptr ,
data - > key . dsize ) ) ) ;
2007-06-03 06:54:51 +00:00
if ( tdb_chainunlock ( ctx - > wtdb - > tdb , data - > key ) ! = 0 ) {
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
2007-05-10 10:42:13 +00:00
DEBUG ( 0 , ( " tdb_chainunlock failed \n " ) ) ;
return - 1 ;
}
return 0 ;
}
static struct db_record * db_tdb_fetch_locked ( struct db_context * db ,
TALLOC_CTX * mem_ctx , TDB_DATA key )
{
struct db_tdb_ctx * ctx = talloc_get_type_abort ( db - > private_data ,
struct db_tdb_ctx ) ;
struct db_record * result ;
TDB_DATA value ;
result = TALLOC_P ( mem_ctx , struct db_record ) ;
if ( result = = NULL ) {
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
return NULL ;
}
result - > key . dsize = key . dsize ;
result - > key . dptr = ( uint8 * ) talloc_memdup ( result , key . dptr , key . dsize ) ;
if ( result - > key . dptr = = NULL ) {
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
TALLOC_FREE ( result ) ;
return NULL ;
}
result - > value . dptr = NULL ;
result - > value . dsize = 0 ;
result - > private_data = talloc_reference ( result , ctx ) ;
result - > store = db_tdb_store ;
result - > delete_rec = db_tdb_delete ;
{
char * keystr = hex_encode ( NULL , ( unsigned char * ) key . dptr ,
key . dsize ) ;
DEBUG ( 10 , ( " Locking key %s \n " , keystr ) ) ;
TALLOC_FREE ( keystr ) ;
}
2007-06-03 06:54:51 +00:00
if ( tdb_chainlock ( ctx - > wtdb - > tdb , key ) ! = 0 ) {
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
2007-05-10 10:42:13 +00:00
DEBUG ( 3 , ( " tdb_chainlock failed \n " ) ) ;
TALLOC_FREE ( result ) ;
return NULL ;
}
talloc_set_destructor ( result , db_tdb_record_destr ) ;
2007-06-03 06:54:51 +00:00
value = tdb_fetch ( ctx - > wtdb - > tdb , key ) ;
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
2007-05-10 10:42:13 +00:00
if ( value . dptr = = NULL ) {
return result ;
}
result - > value . dsize = value . dsize ;
result - > value . dptr = ( uint8 * ) talloc_memdup ( result , value . dptr ,
value . dsize ) ;
if ( result - > value . dptr = = NULL ) {
DEBUG ( 3 , ( " talloc failed \n " ) ) ;
TALLOC_FREE ( result ) ;
return NULL ;
}
SAFE_FREE ( value . dptr ) ;
DEBUG ( 10 , ( " Allocated locked data 0x%p \n " , result ) ) ;
return result ;
}
static NTSTATUS db_tdb_store ( struct db_record * rec , TDB_DATA data , int flag )
{
struct db_tdb_ctx * ctx = talloc_get_type_abort ( rec - > private_data ,
struct db_tdb_ctx ) ;
/*
* This has a bug : We need to replace rec - > value for correct
* operation , but right now brlock and locking don ' t use the value
* anymore after it was stored .
*/
2007-06-03 06:54:51 +00:00
return ( tdb_store ( ctx - > wtdb - > tdb , rec - > key , data , flag ) = = 0 ) ?
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
2007-05-10 10:42:13 +00:00
NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ;
}
static NTSTATUS db_tdb_delete ( struct db_record * rec )
{
struct db_tdb_ctx * ctx = talloc_get_type_abort ( rec - > private_data ,
struct db_tdb_ctx ) ;
2007-05-28 11:08:58 +00:00
int res ;
2007-06-03 06:54:51 +00:00
res = tdb_delete ( ctx - > wtdb - > tdb , rec - > key ) ;
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
2007-05-10 10:42:13 +00:00
2007-05-28 11:08:58 +00:00
if ( res = = 0 ) {
return NT_STATUS_OK ;
}
2007-06-03 06:54:51 +00:00
return map_nt_error_from_tdb ( tdb_error ( ctx - > wtdb - > tdb ) ) ;
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
2007-05-10 10:42:13 +00:00
}
struct db_tdb_traverse_ctx {
struct db_context * db ;
int ( * f ) ( struct db_record * rec , void * private_data ) ;
void * private_data ;
} ;
static int db_tdb_traverse_func ( TDB_CONTEXT * tdb , TDB_DATA kbuf , TDB_DATA dbuf ,
void * private_data )
{
struct db_tdb_traverse_ctx * ctx =
( struct db_tdb_traverse_ctx * ) private_data ;
struct db_record rec ;
rec . key = kbuf ;
rec . value = dbuf ;
rec . store = db_tdb_store ;
rec . delete_rec = db_tdb_delete ;
rec . private_data = ctx - > db - > private_data ;
return ctx - > f ( & rec , ctx - > private_data ) ;
}
static int db_tdb_traverse ( struct db_context * db ,
int ( * f ) ( struct db_record * rec , void * private_data ) ,
void * private_data )
{
struct db_tdb_ctx * db_ctx =
talloc_get_type_abort ( db - > private_data , struct db_tdb_ctx ) ;
struct db_tdb_traverse_ctx ctx ;
ctx . db = db ;
ctx . f = f ;
ctx . private_data = private_data ;
2007-06-03 06:54:51 +00:00
return tdb_traverse ( db_ctx - > wtdb - > tdb , db_tdb_traverse_func , & ctx ) ;
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
2007-05-10 10:42:13 +00:00
}
2007-05-29 18:04:38 +00:00
static NTSTATUS db_tdb_store_deny ( struct db_record * rec , TDB_DATA data , int flag )
{
return NT_STATUS_MEDIA_WRITE_PROTECTED ;
}
static NTSTATUS db_tdb_delete_deny ( struct db_record * rec )
{
return NT_STATUS_MEDIA_WRITE_PROTECTED ;
}
static int db_tdb_traverse_read_func ( TDB_CONTEXT * tdb , TDB_DATA kbuf , TDB_DATA dbuf ,
void * private_data )
{
struct db_tdb_traverse_ctx * ctx =
( struct db_tdb_traverse_ctx * ) private_data ;
struct db_record rec ;
rec . key = kbuf ;
rec . value = dbuf ;
rec . store = db_tdb_store_deny ;
rec . delete_rec = db_tdb_delete_deny ;
rec . private_data = ctx - > db - > private_data ;
return ctx - > f ( & rec , ctx - > private_data ) ;
}
static int db_tdb_traverse_read ( struct db_context * db ,
int ( * f ) ( struct db_record * rec , void * private_data ) ,
void * private_data )
{
struct db_tdb_ctx * db_ctx =
talloc_get_type_abort ( db - > private_data , struct db_tdb_ctx ) ;
struct db_tdb_traverse_ctx ctx ;
ctx . db = db ;
ctx . f = f ;
ctx . private_data = private_data ;
2007-06-03 06:54:51 +00:00
return tdb_traverse_read ( db_ctx - > wtdb - > tdb , db_tdb_traverse_read_func , & ctx ) ;
2007-05-29 18:04:38 +00: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
2007-05-10 10:42:13 +00:00
static int db_tdb_get_seqnum ( struct db_context * db )
{
struct db_tdb_ctx * db_ctx =
talloc_get_type_abort ( db - > private_data , struct db_tdb_ctx ) ;
2007-06-03 06:54:51 +00:00
return tdb_get_seqnum ( db_ctx - > wtdb - > tdb ) ;
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
2007-05-10 10:42:13 +00:00
}
struct db_context * db_open_tdb ( TALLOC_CTX * mem_ctx ,
const char * name ,
int hash_size , int tdb_flags ,
int open_flags , mode_t mode )
{
struct db_context * result = NULL ;
struct db_tdb_ctx * db_tdb ;
result = TALLOC_ZERO_P ( mem_ctx , struct db_context ) ;
if ( result = = NULL ) {
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
goto fail ;
}
result - > private_data = db_tdb = TALLOC_P ( result , struct db_tdb_ctx ) ;
if ( db_tdb = = NULL ) {
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
goto fail ;
}
2007-06-03 06:54:51 +00:00
db_tdb - > wtdb = tdb_wrap_open ( db_tdb , name , hash_size , tdb_flags ,
open_flags , mode ) ;
if ( db_tdb - > wtdb = = NULL ) {
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
2007-05-10 10:42:13 +00:00
DEBUG ( 3 , ( " Could not open tdb: %s \n " , strerror ( errno ) ) ) ;
goto fail ;
}
result - > fetch_locked = db_tdb_fetch_locked ;
result - > traverse = db_tdb_traverse ;
2007-05-29 18:04:38 +00:00
result - > traverse_read = db_tdb_traverse_read ;
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
2007-05-10 10:42:13 +00:00
result - > get_seqnum = db_tdb_get_seqnum ;
return result ;
fail :
if ( result ! = NULL ) {
TALLOC_FREE ( result ) ;
}
return NULL ;
}