Removed TDB code, which we cannot port, because it needs a filesystem.

About multilink support.

Multilink uses Samba TDB (Trivial Database Library), which
we cannot port, for the above reason.

We have to choose between doing a memory-shared TDB-clone,
or dropping multilink support at all.
This commit is contained in:
Sylvain Rochet 2012-05-17 23:21:09 +02:00
parent 1a1deb5d58
commit 1d7efce0dc
6 changed files with 12 additions and 2893 deletions

View File

@ -30,6 +30,17 @@
#include "lwip/opt.h"
/* Multilink support
*
* Multilink uses Samba TDB (Trivial Database Library), which
* we cannot port, because it needs a filesystem.
*
* We have to choose between doing a memory-shared TDB-clone,
* or dropping multilink support at all.
*/
#ifdef HAVE_MULTILINK
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
@ -593,3 +604,4 @@ str_to_epdisc(ep, str)
return 1;
}
#endif /* HAVE_MULTILINK */

View File

@ -109,10 +109,6 @@
#include "ecp.h"
#include "pathnames.h"
#ifdef USE_TDB
#include "tdb.h"
#endif
#if CBCP_SUPPORT
#include "cbcp.h"
#endif
@ -153,10 +149,6 @@ int ppp_session_number; /* Session number, for channels with such a
concept (eg PPPoE) */
int childwait_done; /* have timed out waiting for children */
#ifdef USE_TDB
TDB_CONTEXT *pppdb; /* database for storing status etc. */
#endif
char db_key[32];
int (*holdoff_hook) __P((void)) = NULL;
@ -247,13 +239,6 @@ static void forget_child __P((int pid, int status));
static int reap_kids __P((void));
static void childwait_end __P((void *));
#ifdef USE_TDB
static void update_db_entry __P((void));
static void add_db_key __P((const char *));
static void delete_db_key __P((const char *));
static void cleanup_db __P((void));
#endif
static void handle_events __P((void));
void print_link_stats __P((void));
@ -430,20 +415,6 @@ int ppp_oldmain() {
*/
linux_sys_init();
#ifdef USE_TDB
pppdb = tdb_open(_PATH_PPPDB, 0, 0, O_RDWR|O_CREAT, 0644);
if (pppdb != NULL) {
slprintf(db_key, sizeof(db_key), "pppd%d", getpid());
update_db_entry();
} else {
warn("Warning: couldn't open ppp database %s", _PATH_PPPDB);
if (multilink) {
warn("Warning: disabling multilink");
multilink = 0;
}
}
#endif
/*
* Detach ourselves from the terminal, if required,
* and identify who is running us.
@ -1184,12 +1155,6 @@ cleanup()
if (the_channel->cleanup)
(*the_channel->cleanup)();
remove_pidfiles();
#ifdef USE_TDB
if (pppdb != NULL)
cleanup_db();
#endif
}
void
@ -1566,9 +1531,6 @@ safe_fork(int infd, int outfd, int errfd)
/* Executing in the child */
sys_close();
#ifdef USE_TDB
tdb_close(pppdb);
#endif
/* make sure infd, outfd and errfd won't get tromped on below */
if (infd == 1 || infd == 2)
@ -1864,17 +1826,8 @@ script_setenv(var, value, iskey)
if (script_env != 0) {
for (i = 0; (p = script_env[i]) != 0; ++i) {
if (strncmp(p, var, varl) == 0 && p[varl] == '=') {
#ifdef USE_TDB
if (p[-1] && pppdb != NULL)
delete_db_key(p);
#endif
free(p-1);
script_env[i] = newstring;
#ifdef USE_TDB
if (iskey && pppdb != NULL)
add_db_key(newstring);
update_db_entry();
#endif
return;
}
}
@ -1900,14 +1853,6 @@ script_setenv(var, value, iskey)
script_env[i] = newstring;
script_env[i+1] = 0;
#ifdef USE_TDB
if (pppdb != NULL) {
if (iskey)
add_db_key(newstring);
update_db_entry();
}
#endif
}
/*
@ -1926,138 +1871,10 @@ script_unsetenv(var)
return;
for (i = 0; (p = script_env[i]) != 0; ++i) {
if (strncmp(p, var, vl) == 0 && p[vl] == '=') {
#ifdef USE_TDB
if (p[-1] && pppdb != NULL)
delete_db_key(p);
#endif
free(p-1);
while ((script_env[i] = script_env[i+1]) != 0)
++i;
break;
}
}
#ifdef USE_TDB
if (pppdb != NULL)
update_db_entry();
#endif
}
/*
* Any arbitrary string used as a key for locking the database.
* It doesn't matter what it is as long as all pppds use the same string.
*/
#define PPPD_LOCK_KEY "pppd lock"
/*
* lock_db - get an exclusive lock on the TDB database.
* Used to ensure atomicity of various lookup/modify operations.
*/
void lock_db()
{
#ifdef USE_TDB
TDB_DATA key;
key.dptr = PPPD_LOCK_KEY;
key.dsize = strlen(key.dptr);
tdb_chainlock(pppdb, key);
#endif
}
/*
* unlock_db - remove the exclusive lock obtained by lock_db.
*/
void unlock_db()
{
#ifdef USE_TDB
TDB_DATA key;
key.dptr = PPPD_LOCK_KEY;
key.dsize = strlen(key.dptr);
tdb_chainunlock(pppdb, key);
#endif
}
#ifdef USE_TDB
/*
* update_db_entry - update our entry in the database.
*/
static void
update_db_entry()
{
TDB_DATA key, dbuf;
int vlen, i;
char *p, *q, *vbuf;
if (script_env == NULL)
return;
vlen = 0;
for (i = 0; (p = script_env[i]) != 0; ++i)
vlen += strlen(p) + 1;
vbuf = malloc(vlen + 1);
if (vbuf == 0)
novm("database entry");
q = vbuf;
for (i = 0; (p = script_env[i]) != 0; ++i)
q += slprintf(q, vbuf + vlen - q, "%s;", p);
key.dptr = db_key;
key.dsize = strlen(db_key);
dbuf.dptr = vbuf;
dbuf.dsize = vlen;
if (tdb_store(pppdb, key, dbuf, TDB_REPLACE))
error("tdb_store failed: %s", tdb_errorstr(pppdb));
if (vbuf)
free(vbuf);
}
/*
* add_db_key - add a key that we can use to look up our database entry.
*/
static void
add_db_key(str)
const char *str;
{
TDB_DATA key, dbuf;
key.dptr = (char *) str;
key.dsize = strlen(str);
dbuf.dptr = db_key;
dbuf.dsize = strlen(db_key);
if (tdb_store(pppdb, key, dbuf, TDB_REPLACE))
error("tdb_store key failed: %s", tdb_errorstr(pppdb));
}
/*
* delete_db_key - delete a key for looking up our database entry.
*/
static void
delete_db_key(str)
const char *str;
{
TDB_DATA key;
key.dptr = (char *) str;
key.dsize = strlen(str);
tdb_delete(pppdb, key);
}
/*
* cleanup_db - delete all the entries we put in the database.
*/
static void
cleanup_db()
{
TDB_DATA key;
int i;
char *p;
key.dptr = db_key;
key.dsize = strlen(db_key);
tdb_delete(pppdb, key);
for (i = 0; (p = script_env[i]) != 0; ++i)
if (p[-1])
delete_db_key(p);
}
#endif /* USE_TDB */

View File

@ -1,476 +0,0 @@
/*
Unix SMB/CIFS implementation.
trivial database library
Copyright (C) Anton Blanchard 2001
** NOTE! The following LGPL license applies to the tdb
** library. This does NOT imply that all of Samba is released
** under the LGPL
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 "lwip/opt.h"
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
#include <time.h>
#include <signal.h>
#include "tdb.h"
#include "spinlock.h"
#define DEBUG
#ifdef USE_SPINLOCKS
/*
* ARCH SPECIFIC
*/
#if defined(SPARC_SPINLOCKS)
static inline int __spin_trylock(spinlock_t *lock)
{
unsigned int result;
asm volatile("ldstub [%1], %0"
: "=r" (result)
: "r" (lock)
: "memory");
return (result == 0) ? 0 : EBUSY;
}
static inline void __spin_unlock(spinlock_t *lock)
{
asm volatile("":::"memory");
*lock = 0;
}
static inline void __spin_lock_init(spinlock_t *lock)
{
*lock = 0;
}
static inline int __spin_is_locked(spinlock_t *lock)
{
return (*lock != 0);
}
#elif defined(POWERPC_SPINLOCKS)
static inline int __spin_trylock(spinlock_t *lock)
{
unsigned int result;
__asm__ __volatile__(
"1: lwarx %0,0,%1\n\
cmpwi 0,%0,0\n\
li %0,0\n\
bne- 2f\n\
li %0,1\n\
stwcx. %0,0,%1\n\
bne- 1b\n\
isync\n\
2:" : "=&r"(result)
: "r"(lock)
: "cr0", "memory");
return (result == 1) ? 0 : EBUSY;
}
static inline void __spin_unlock(spinlock_t *lock)
{
asm volatile("eieio":::"memory");
*lock = 0;
}
static inline void __spin_lock_init(spinlock_t *lock)
{
*lock = 0;
}
static inline int __spin_is_locked(spinlock_t *lock)
{
return (*lock != 0);
}
#elif defined(INTEL_SPINLOCKS)
static inline int __spin_trylock(spinlock_t *lock)
{
int oldval;
asm volatile("xchgl %0,%1"
: "=r" (oldval), "=m" (*lock)
: "0" (0)
: "memory");
return oldval > 0 ? 0 : EBUSY;
}
static inline void __spin_unlock(spinlock_t *lock)
{
asm volatile("":::"memory");
*lock = 1;
}
static inline void __spin_lock_init(spinlock_t *lock)
{
*lock = 1;
}
static inline int __spin_is_locked(spinlock_t *lock)
{
return (*lock != 1);
}
#elif defined(MIPS_SPINLOCKS) && defined(sgi) && (_COMPILER_VERSION >= 730)
/* Implement spinlocks on IRIX using the MIPSPro atomic fetch operations. See
* sync(3) for the details of the intrinsic operations.
*
* "sgi" and "_COMPILER_VERSION" are always defined by MIPSPro.
*/
#ifdef STANDALONE
/* MIPSPro 7.3 has "__inline" as an extension, but not "inline. */
#define inline __inline
#endif /* STANDALONE */
/* Returns 0 if the lock is acquired, EBUSY otherwise. */
static inline int __spin_trylock(spinlock_t *lock)
{
unsigned int val;
val = __lock_test_and_set(lock, 1);
return val == 0 ? 0 : EBUSY;
}
static inline void __spin_unlock(spinlock_t *lock)
{
__lock_release(lock);
}
static inline void __spin_lock_init(spinlock_t *lock)
{
__lock_release(lock);
}
/* Returns 1 if the lock is held, 0 otherwise. */
static inline int __spin_is_locked(spinlock_t *lock)
{
unsigned int val;
val = __add_and_fetch(lock, 0);
return val;
}
#elif defined(MIPS_SPINLOCKS)
static inline unsigned int load_linked(unsigned long addr)
{
unsigned int res;
__asm__ __volatile__("ll\t%0,(%1)"
: "=r" (res)
: "r" (addr));
return res;
}
static inline unsigned int store_conditional(unsigned long addr, unsigned int value)
{
unsigned int res;
__asm__ __volatile__("sc\t%0,(%2)"
: "=r" (res)
: "0" (value), "r" (addr));
return res;
}
static inline int __spin_trylock(spinlock_t *lock)
{
unsigned int mw;
do {
mw = load_linked(lock);
if (mw)
return EBUSY;
} while (!store_conditional(lock, 1));
asm volatile("":::"memory");
return 0;
}
static inline void __spin_unlock(spinlock_t *lock)
{
asm volatile("":::"memory");
*lock = 0;
}
static inline void __spin_lock_init(spinlock_t *lock)
{
*lock = 0;
}
static inline int __spin_is_locked(spinlock_t *lock)
{
return (*lock != 0);
}
#else
#error Need to implement spinlock code in spinlock.c
#endif
/*
* OS SPECIFIC
*/
static void yield_cpu(void)
{
struct timespec tm;
#ifdef USE_SCHED_YIELD
sched_yield();
#else
/* Linux will busy loop for delays < 2ms on real time tasks */
tm.tv_sec = 0;
tm.tv_nsec = 2000000L + 1;
nanosleep(&tm, NULL);
#endif
}
static int this_is_smp(void)
{
#if defined(HAVE_SYSCONF) && defined(SYSCONF_SC_NPROC_ONLN)
return (sysconf(_SC_NPROC_ONLN) > 1) ? 1 : 0;
#else
return 0;
#endif
}
/*
* GENERIC
*/
static int smp_machine = 0;
static inline void __spin_lock(spinlock_t *lock)
{
int ntries = 0;
while(__spin_trylock(lock)) {
while(__spin_is_locked(lock)) {
if (smp_machine && ntries++ < MAX_BUSY_LOOPS)
continue;
yield_cpu();
}
}
}
static void __read_lock(tdb_rwlock_t *rwlock)
{
int ntries = 0;
while(1) {
__spin_lock(&rwlock->lock);
if (!(rwlock->count & RWLOCK_BIAS)) {
rwlock->count++;
__spin_unlock(&rwlock->lock);
return;
}
__spin_unlock(&rwlock->lock);
while(rwlock->count & RWLOCK_BIAS) {
if (smp_machine && ntries++ < MAX_BUSY_LOOPS)
continue;
yield_cpu();
}
}
}
static void __write_lock(tdb_rwlock_t *rwlock)
{
int ntries = 0;
while(1) {
__spin_lock(&rwlock->lock);
if (rwlock->count == 0) {
rwlock->count |= RWLOCK_BIAS;
__spin_unlock(&rwlock->lock);
return;
}
__spin_unlock(&rwlock->lock);
while(rwlock->count != 0) {
if (smp_machine && ntries++ < MAX_BUSY_LOOPS)
continue;
yield_cpu();
}
}
}
static void __write_unlock(tdb_rwlock_t *rwlock)
{
__spin_lock(&rwlock->lock);
#ifdef DEBUG
if (!(rwlock->count & RWLOCK_BIAS))
fprintf(stderr, "bug: write_unlock\n");
#endif
rwlock->count &= ~RWLOCK_BIAS;
__spin_unlock(&rwlock->lock);
}
static void __read_unlock(tdb_rwlock_t *rwlock)
{
__spin_lock(&rwlock->lock);
#ifdef DEBUG
if (!rwlock->count)
fprintf(stderr, "bug: read_unlock\n");
if (rwlock->count & RWLOCK_BIAS)
fprintf(stderr, "bug: read_unlock\n");
#endif
rwlock->count--;
__spin_unlock(&rwlock->lock);
}
/* TDB SPECIFIC */
/* lock a list in the database. list -1 is the alloc list */
int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type)
{
tdb_rwlock_t *rwlocks;
if (!tdb->map_ptr) return -1;
rwlocks = (tdb_rwlock_t *)((char *)tdb->map_ptr + tdb->header.rwlocks);
switch(rw_type) {
case F_RDLCK:
__read_lock(&rwlocks[list+1]);
break;
case F_WRLCK:
__write_lock(&rwlocks[list+1]);
break;
default:
return TDB_ERRCODE(TDB_ERR_LOCK, -1);
}
return 0;
}
/* unlock the database. */
int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type)
{
tdb_rwlock_t *rwlocks;
if (!tdb->map_ptr) return -1;
rwlocks = (tdb_rwlock_t *)((char *)tdb->map_ptr + tdb->header.rwlocks);
switch(rw_type) {
case F_RDLCK:
__read_unlock(&rwlocks[list+1]);
break;
case F_WRLCK:
__write_unlock(&rwlocks[list+1]);
break;
default:
return TDB_ERRCODE(TDB_ERR_LOCK, -1);
}
return 0;
}
int tdb_create_rwlocks(int fd, unsigned int hash_size)
{
unsigned size, i;
tdb_rwlock_t *rwlocks;
size = TDB_SPINLOCK_SIZE(hash_size);
rwlocks = malloc(size);
if (!rwlocks)
return -1;
for(i = 0; i < hash_size+1; i++) {
__spin_lock_init(&rwlocks[i].lock);
rwlocks[i].count = 0;
}
/* Write it out (appending to end) */
if (write(fd, rwlocks, size) != size) {
free(rwlocks);
return -1;
}
smp_machine = this_is_smp();
free(rwlocks);
return 0;
}
int tdb_clear_spinlocks(TDB_CONTEXT *tdb)
{
tdb_rwlock_t *rwlocks;
unsigned i;
if (tdb->header.rwlocks == 0) return 0;
if (!tdb->map_ptr) return -1;
/* We're mmapped here */
rwlocks = (tdb_rwlock_t *)((char *)tdb->map_ptr + tdb->header.rwlocks);
for(i = 0; i < tdb->header.hash_size+1; i++) {
__spin_lock_init(&rwlocks[i].lock);
rwlocks[i].count = 0;
}
return 0;
}
#else
int tdb_create_rwlocks(int fd, unsigned int hash_size) { return 0; }
int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type) { return -1; }
int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type) { return -1; }
/* Non-spinlock version: remove spinlock pointer */
int tdb_clear_spinlocks(TDB_CONTEXT *tdb)
{
tdb_off off = (tdb_off)((char *)&tdb->header.rwlocks
- (char *)&tdb->header);
tdb->header.rwlocks = 0;
if (lseek(tdb->fd, off, SEEK_SET) != off
|| write(tdb->fd, (void *)&tdb->header.rwlocks,
sizeof(tdb->header.rwlocks))
!= sizeof(tdb->header.rwlocks))
return -1;
return 0;
}
#endif

View File

@ -1,59 +0,0 @@
#ifndef __SPINLOCK_H__
#define __SPINLOCK_H__
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "tdb.h"
#ifdef USE_SPINLOCKS
#define RWLOCK_BIAS 0x1000UL
/* OS SPECIFIC */
#define MAX_BUSY_LOOPS 1000
#undef USE_SCHED_YIELD
/* ARCH SPECIFIC */
/* We should make sure these are padded to a cache line */
#if defined(SPARC_SPINLOCKS)
typedef volatile char spinlock_t;
#elif defined(POWERPC_SPINLOCKS)
typedef volatile unsigned long spinlock_t;
#elif defined(INTEL_SPINLOCKS)
typedef volatile int spinlock_t;
#elif defined(MIPS_SPINLOCKS)
typedef volatile unsigned long spinlock_t;
#else
#error Need to implement spinlock code in spinlock.h
#endif
typedef struct {
spinlock_t lock;
volatile int count;
} tdb_rwlock_t;
int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type);
int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type);
int tdb_create_rwlocks(int fd, unsigned int hash_size);
int tdb_clear_spinlocks(TDB_CONTEXT *tdb);
#define TDB_SPINLOCK_SIZE(hash_size) (((hash_size) + 1) * sizeof(tdb_rwlock_t))
#else /* !USE_SPINLOCKS */
#if 0
#define tdb_create_rwlocks(fd, hash_size) 0
#define tdb_spinlock(tdb, list, rw_type) (-1)
#define tdb_spinunlock(tdb, list, rw_type) (-1)
#else
int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type);
int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type);
int tdb_create_rwlocks(int fd, unsigned int hash_size);
#endif
int tdb_clear_spinlocks(TDB_CONTEXT *tdb);
#define TDB_SPINLOCK_SIZE(hash_size) 0
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,164 +0,0 @@
#ifndef __TDB_H__
#define __TDB_H__
/*
Unix SMB/CIFS implementation.
trivial database library
Copyright (C) Andrew Tridgell 1999-2004
** NOTE! The following LGPL license applies to the tdb
** library. This does NOT imply that all of Samba is released
** under the LGPL
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
*/
#ifdef __cplusplus
extern "C" {
#endif
#ifndef PRINTF_ATTRIBUTE
/** Use gcc attribute to check printf fns. a1 is the 1-based index of
* the parameter containing the format, and a2 the index of the first
* argument. Note that some gcc 2.x versions don't handle this
* properly **/
#if (__GNUC__ >= 3)
#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
#else
#define PRINTF_ATTRIBUTE(a1, a2)
#endif
#endif
/* flags to tdb_store() */
#define TDB_REPLACE 1
#define TDB_INSERT 2
#define TDB_MODIFY 3
/* flags for tdb_open() */
#define TDB_DEFAULT 0 /* just a readability place holder */
#define TDB_CLEAR_IF_FIRST 1
#define TDB_INTERNAL 2 /* don't store on disk */
#define TDB_NOLOCK 4 /* don't do any locking */
#define TDB_NOMMAP 8 /* don't use mmap */
#define TDB_CONVERT 16 /* convert endian (internal use) */
#define TDB_BIGENDIAN 32 /* header is big-endian (internal use) */
#define TDB_ERRCODE(code, ret) ((tdb->ecode = (code)), ret)
/* error codes */
enum TDB_ERROR {TDB_SUCCESS=0, TDB_ERR_CORRUPT, TDB_ERR_IO, TDB_ERR_LOCK,
TDB_ERR_OOM, TDB_ERR_EXISTS, TDB_ERR_NOLOCK, TDB_ERR_LOCK_TIMEOUT,
TDB_ERR_NOEXIST};
#ifndef u32
#define u32 unsigned
#endif
typedef struct {
char *dptr;
size_t dsize;
} TDB_DATA;
typedef u32 tdb_len;
typedef u32 tdb_off;
/* this is stored at the front of every database */
struct tdb_header {
char magic_food[32]; /* for /etc/magic */
u32 version; /* version of the code */
u32 hash_size; /* number of hash entries */
tdb_off rwlocks;
tdb_off reserved[31];
};
struct tdb_lock_type {
u32 count;
u32 ltype;
};
struct tdb_traverse_lock {
struct tdb_traverse_lock *next;
u32 off;
u32 hash;
};
/* this is the context structure that is returned from a db open */
typedef struct tdb_context {
char *name; /* the name of the database */
void *map_ptr; /* where it is currently mapped */
int fd; /* open file descriptor for the database */
tdb_len map_size; /* how much space has been mapped */
int read_only; /* opened read-only */
struct tdb_lock_type *locked; /* array of chain locks */
enum TDB_ERROR ecode; /* error code for last tdb error */
struct tdb_header header; /* a cached copy of the header */
u32 flags; /* the flags passed to tdb_open */
struct tdb_traverse_lock travlocks; /* current traversal locks */
struct tdb_context *next; /* all tdbs to avoid multiple opens */
dev_t device; /* uniquely identifies this tdb */
ino_t inode; /* uniquely identifies this tdb */
void (*log_fn)(struct tdb_context *tdb, int level, const char *, ...) PRINTF_ATTRIBUTE(3,4); /* logging function */
u32 (*hash_fn)(TDB_DATA *key);
int open_flags; /* flags used in the open - needed by reopen */
} TDB_CONTEXT;
typedef int (*tdb_traverse_func)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *);
typedef void (*tdb_log_func)(TDB_CONTEXT *, int , const char *, ...);
typedef u32 (*tdb_hash_func)(TDB_DATA *key);
TDB_CONTEXT *tdb_open(const char *name, int hash_size, int tdb_flags,
int open_flags, mode_t mode);
TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
int open_flags, mode_t mode,
tdb_log_func log_fn,
tdb_hash_func hash_fn);
int tdb_reopen(TDB_CONTEXT *tdb);
int tdb_reopen_all(void);
void tdb_logging_function(TDB_CONTEXT *tdb, tdb_log_func);
enum TDB_ERROR tdb_error(TDB_CONTEXT *tdb);
const char *tdb_errorstr(TDB_CONTEXT *tdb);
TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key);
int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key);
int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag);
int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf);
int tdb_close(TDB_CONTEXT *tdb);
TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb);
TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA key);
int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *);
int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key);
int tdb_lockkeys(TDB_CONTEXT *tdb, u32 number, TDB_DATA keys[]);
void tdb_unlockkeys(TDB_CONTEXT *tdb);
int tdb_lockall(TDB_CONTEXT *tdb);
void tdb_unlockall(TDB_CONTEXT *tdb);
/* Low level locking functions: use with care */
void tdb_set_lock_alarm(sig_atomic_t *palarm);
int tdb_chainlock(TDB_CONTEXT *tdb, TDB_DATA key);
int tdb_chainunlock(TDB_CONTEXT *tdb, TDB_DATA key);
/* Debug functions. Not used in production. */
void tdb_dump_all(TDB_CONTEXT *tdb);
int tdb_printfreelist(TDB_CONTEXT *tdb);
extern TDB_DATA tdb_null;
#ifdef __cplusplus
}
#endif
#endif /* tdb.h */