1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-11 05:18:09 +03:00

- added tdb_flags option to tdb_open()

- added TDB_CLEAR_IF_FIRST flag to clear the database if this is the
  first attached process. Useful for non-persistent databases like our
  locking area (this will also make upgrades to new database layouts easier)
- use lock_path() in a couple of places
- leave connections database open while smbd running
- cleaned up some tdb code a little, using macros for constants
This commit is contained in:
Andrew Tridgell 0001-01-01 00:00:00 +00:00
parent 88a146ab04
commit 00e9da3ca5
12 changed files with 72 additions and 67 deletions

View File

@ -2428,7 +2428,6 @@ void conn_free(connection_struct *conn);
/*The following definitions come from smbd/connection.c */
BOOL yield_connection(connection_struct *conn,char *name,int max_connections);
int delete_dead(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf);
BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOOL Clear);
/*The following definitions come from smbd/dfree.c */
@ -2856,7 +2855,8 @@ TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb);
TDB_DATA tdb_nextkey(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);
TDB_CONTEXT *tdb_open(char *name, int hash_size, int flags, mode_t mode);
TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags,
int open_flags, mode_t mode);
int tdb_close(TDB_CONTEXT *tdb);
int tdb_writelock(TDB_CONTEXT *tdb);
int tdb_writeunlock(TDB_CONTEXT *tdb);

View File

@ -159,7 +159,7 @@ BOOL locking_init(int read_only)
if (tdb) return True;
tdb = tdb_open(lock_path("locking.tdb"),
0,
0, TDB_CLEAR_IF_FIRST,
read_only?O_RDONLY:O_RDWR|O_CREAT,
0644);

View File

@ -602,21 +602,15 @@ static void dump_subnet_namelist( struct subnet_record *subrec, FILE *fp)
void dump_all_namelists(void)
{
pstring fname;
FILE *fp;
struct subnet_record *subrec;
pstrcpy(fname,lp_lockdir());
trim_string(fname,NULL,"/");
pstrcat(fname,"/");
pstrcat(fname,"namelist.debug");
fp = sys_fopen(fname,"w");
fp = sys_fopen(lock_path("namelist.debug"),"w");
if (!fp)
{
DEBUG(0,("dump_all_namelists: Can't open file %s. Error was %s\n",
fname,strerror(errno)));
"namelist.debug",strerror(errno)));
return;
}

View File

@ -172,7 +172,6 @@ Load or create the WINS database.
BOOL initialise_wins(void)
{
pstring fname;
time_t time_now = time(NULL);
FILE *fp;
pstring line;
@ -182,15 +181,10 @@ BOOL initialise_wins(void)
add_samba_names_to_subnet(wins_server_subnet);
pstrcpy(fname,lp_lockdir());
trim_string(fname,NULL,"/");
pstrcat(fname,"/");
pstrcat(fname,WINS_LIST);
if((fp = sys_fopen(fname,"r")) == NULL)
if((fp = sys_fopen(lock_path(WINS_LIST),"r")) == NULL)
{
DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n",
fname, strerror(errno) ));
WINS_LIST, strerror(errno) ));
return True;
}

View File

@ -23,6 +23,7 @@
extern fstring remote_machine;
static TDB_CONTEXT *tdb;
extern int DEBUGLEVEL;
@ -33,9 +34,7 @@ BOOL yield_connection(connection_struct *conn,char *name,int max_connections)
{
struct connections_key key;
TDB_DATA kbuf;
TDB_CONTEXT *tdb;
tdb = tdb_open(lock_path("connections.tdb"), 0, O_RDWR | O_CREAT, 0644);
if (!tdb) return False;
DEBUG(3,("Yielding connection to %s\n",name));
@ -49,23 +48,10 @@ BOOL yield_connection(connection_struct *conn,char *name,int max_connections)
kbuf.dsize = sizeof(key);
tdb_delete(tdb, kbuf);
tdb_close(tdb);
return(True);
}
/****************************************************************************
claim an entry in the connections database
****************************************************************************/
int delete_dead(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf)
{
struct connections_key key;
memcpy(&key, kbuf.dptr, sizeof(key));
if (!process_exists(key.pid)) tdb_delete(tdb, kbuf);
return 0;
}
/****************************************************************************
claim an entry in the connections database
****************************************************************************/
@ -74,13 +60,15 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO
struct connections_key key;
struct connections_data crec;
TDB_DATA kbuf, dbuf;
TDB_CONTEXT *tdb;
extern int Client;
if (max_connections <= 0)
return(True);
tdb = tdb_open(lock_path("connections.tdb"), 0, O_RDWR | O_CREAT, 0644);
if (!tdb) {
tdb = tdb_open(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST,
O_RDWR | O_CREAT, 0644);
}
if (!tdb) return False;
DEBUG(5,("claiming %s %d\n",name,max_connections));
@ -93,10 +81,6 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO
kbuf.dptr = (char *)&key;
kbuf.dsize = sizeof(key);
if (Clear) {
tdb_traverse(tdb, delete_dead);
}
/* fill in the crec */
ZERO_STRUCT(crec);
crec.magic = 0x280267;

View File

@ -44,6 +44,14 @@
#define TDB_LEN_MULTIPLIER 10
#define FREELIST_TOP (sizeof(struct tdb_header))
#define LOCK_SET 1
#define LOCK_CLEAR 0
/* lock offsets */
#define GLOBAL_LOCK 0
#define ACTIVE_LOCK 4
#define LIST_LOCK_BASE 1024
#define BUCKET(hash) ((hash) % tdb->header.hash_size)
/* the body of the database is made of one list_struct for the free space
@ -85,7 +93,8 @@ static char *memdup(char *d, int size)
/* a byte range locking function - return 0 on success
this functions locks/unlocks 1 byte at the specified offset */
static int tdb_brlock(TDB_CONTEXT *tdb, tdb_off offset, int set)
static int tdb_brlock(TDB_CONTEXT *tdb, tdb_off offset,
int set, int rw_type, int lck_type)
{
#if NOLOCK
return 0;
@ -94,13 +103,13 @@ static int tdb_brlock(TDB_CONTEXT *tdb, tdb_off offset, int set)
if (tdb->read_only) return -1;
fl.l_type = set?F_WRLCK:F_UNLCK;
fl.l_type = set==LOCK_SET?rw_type:F_UNLCK;
fl.l_whence = SEEK_SET;
fl.l_start = offset;
fl.l_len = 1;
fl.l_pid = 0;
if (fcntl(tdb->fd, F_SETLKW, &fl) != 0) {
if (fcntl(tdb->fd, lck_type, &fl) != 0 && lck_type == F_SETLKW) {
#if TDB_DEBUG
printf("lock %d failed at %d (%s)\n",
set, offset, strerror(errno));
@ -121,7 +130,8 @@ static int tdb_lock(TDB_CONTEXT *tdb, int list)
return -1;
}
if (tdb->locked[list+1] == 0) {
if (tdb_brlock(tdb, 4*(list+1), 1) != 0) {
if (tdb_brlock(tdb, LIST_LOCK_BASE + 4*list, LOCK_SET,
F_WRLCK, F_SETLKW) != 0) {
return -1;
}
}
@ -146,7 +156,8 @@ static int tdb_unlock(TDB_CONTEXT *tdb, int list)
return -1;
}
if (tdb->locked[list+1] == 1) {
if (tdb_brlock(tdb, 4*(list+1), 0) != 0) {
if (tdb_brlock(tdb, LIST_LOCK_BASE + 4*list, LOCK_CLEAR,
F_WRLCK, F_SETLKW) != 0) {
return -1;
}
}
@ -264,6 +275,8 @@ static char *tdb_alloc_read(TDB_CONTEXT *tdb, tdb_off offset, tdb_len len)
buf = (char *)malloc(len);
if (!buf) return NULL;
if (tdb_read(tdb, offset, buf, len) == -1) {
free(buf);
return NULL;
@ -1091,7 +1104,8 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
return is NULL on error
*/
TDB_CONTEXT *tdb_open(char *name, int hash_size, int flags, mode_t mode)
TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags,
int open_flags, mode_t mode)
{
TDB_CONTEXT tdb, *ret;
struct stat st;
@ -1100,21 +1114,36 @@ TDB_CONTEXT *tdb_open(char *name, int hash_size, int flags, mode_t mode)
tdb.name = NULL;
tdb.map_ptr = NULL;
if ((flags & O_ACCMODE) == O_WRONLY) goto fail;
if ((open_flags & O_ACCMODE) == O_WRONLY) goto fail;
if (hash_size == 0) hash_size = DEFAULT_HASH_SIZE;
memset(&tdb, 0, sizeof(tdb));
tdb.fd = open(name, flags, mode);
tdb.read_only = ((open_flags & O_ACCMODE) == O_RDONLY);
tdb.fd = open(name, open_flags, mode);
if (tdb.fd == -1) goto fail;
tdb_brlock(&tdb, 0, 1);
/* ensure there is only one process initialising at once */
tdb_brlock(&tdb, GLOBAL_LOCK, LOCK_SET, F_WRLCK, F_SETLKW);
if (tdb_flags & TDB_CLEAR_IF_FIRST) {
/* we need to zero the database if we are the only
one with it open */
if (tdb_brlock(&tdb, ACTIVE_LOCK, LOCK_SET, F_WRLCK, F_SETLK) == 0) {
ftruncate(tdb.fd, 0);
tdb_brlock(&tdb, ACTIVE_LOCK, LOCK_CLEAR, F_WRLCK, F_SETLK);
}
}
/* leave this lock in place */
tdb_brlock(&tdb, ACTIVE_LOCK, LOCK_SET, F_RDLCK, F_SETLKW);
if (read(tdb.fd, &tdb.header, sizeof(tdb.header)) != sizeof(tdb.header) ||
tdb.header.version != TDB_VERSION) {
/* its not a valid database - possibly initialise it */
if (!(flags & O_CREAT)) {
if (!(open_flags & O_CREAT)) {
goto fail;
}
if (tdb_new_database(&tdb, hash_size) == -1) goto fail;
@ -1131,7 +1160,6 @@ TDB_CONTEXT *tdb_open(char *name, int hash_size, int flags, mode_t mode)
sizeof(tdb.locked[0]));
if (!tdb.locked) goto fail;
tdb.map_size = st.st_size;
tdb.read_only = ((flags & O_ACCMODE) == O_RDONLY);
#if HAVE_MMAP
tdb.map_ptr = (void *)mmap(NULL, st.st_size,
tdb.read_only? PROT_READ : PROT_READ|PROT_WRITE,
@ -1148,11 +1176,10 @@ TDB_CONTEXT *tdb_open(char *name, int hash_size, int flags, mode_t mode)
hash_size, tdb.map_size);
#endif
tdb_brlock(&tdb, 0, 0);
tdb_brlock(&tdb, GLOBAL_LOCK, LOCK_CLEAR, F_WRLCK, F_SETLKW);
return ret;
fail:
tdb_brlock(&tdb, 0, 0);
if (tdb.name) free(tdb.name);
if (tdb.fd != -1) close(tdb.fd);
if (tdb.map_ptr) munmap(tdb.map_ptr, tdb.map_size);

View File

@ -44,16 +44,21 @@ typedef struct {
struct tdb_header header; /* a cached copy of the header */
} TDB_CONTEXT;
/* flags to tdb_store() */
#define TDB_REPLACE 1
#define TDB_INSERT 2
/* flags for tdb_open() */
#define TDB_CLEAR_IF_FIRST 1
#if STANDALONE
TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags,
int open_flags, mode_t mode);
int tdb_writelock(TDB_CONTEXT *tdb);
int tdb_writeunlock(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);
TDB_CONTEXT *tdb_open(char *name, int hash_size, int flags, mode_t mode);
int tdb_close(TDB_CONTEXT *tdb);
TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb);
TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA key);

View File

@ -180,11 +180,12 @@ static int traverse_fn(TDB_CONTEXT *db, TDB_DATA key, TDB_DATA dbuf)
int main(int argc, char *argv[])
{
int i, seed=0;
int loops = 50000;
int loops = 10000;
unlink("test.gdbm");
db = tdb_open("test.db", 0, O_RDWR | O_CREAT | O_TRUNC, 0600);
db = tdb_open("test.db", 0, TDB_CLEAR_IF_FIRST,
O_RDWR | O_CREAT | O_TRUNC, 0600);
gdbm = gdbm_open("test.gdbm", 512, GDBM_WRITER|GDBM_NEWDB|GDBM_FAST,
0600, NULL);

View File

@ -41,7 +41,8 @@ static void create_tdb(void)
return;
}
if (tdb) tdb_close(tdb);
tdb = tdb_open(tok, 0, O_RDWR | O_CREAT | O_TRUNC, 0600);
tdb = tdb_open(tok, 0, TDB_CLEAR_IF_FIRST,
O_RDWR | O_CREAT | O_TRUNC, 0600);
}
static void open_tdb(void)
@ -52,7 +53,7 @@ static void open_tdb(void)
return;
}
if (tdb) tdb_close(tdb);
tdb = tdb_open(tok, 0, O_RDWR, 0600);
tdb = tdb_open(tok, 0, 0, O_RDWR, 0600);
}
static void insert_tdb(void)

View File

@ -93,13 +93,12 @@ int main(int argc, char *argv[])
int i, seed=0;
int loops = NLOOPS;
unlink("test.tdb");
for (i=0;i<NPROC-1;i++) {
if (fork() == 0) break;
}
db = tdb_open("test.tdb", 0, O_RDWR | O_CREAT, 0600);
db = tdb_open("test.tdb", 0, TDB_CLEAR_IF_FIRST,
O_RDWR | O_CREAT, 0600);
if (!db) {
fatal("db open failed");
}

View File

@ -261,11 +261,11 @@ static int traverse_fn1(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf)
case 's':
pstrcpy(servicesf, optarg);
break;
case 'u': /* added by OH */
Ucrit_addUsername(optarg); /* added by OH */
case 'u':
Ucrit_addUsername(optarg);
break;
default:
fprintf(stderr, "Usage: %s [-P] [-d] [-L] [-p] [-S] [-s configfile] [-u username]\n", *argv); /* changed by OH */
fprintf(stderr, "Usage: %s [-P] [-d] [-L] [-p] [-S] [-s configfile] [-u username]\n", *argv);
return (-1);
}
}
@ -283,7 +283,7 @@ static int traverse_fn1(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf)
return profile_dump();
}
tdb = tdb_open(lock_path("connections.tdb"), 0, O_RDONLY, 0);
tdb = tdb_open(lock_path("connections.tdb"), 0, 0, O_RDONLY, 0);
if (!tdb) {
printf("connections.tdb not initialised\n");
if (!lp_status(-1))

View File

@ -172,7 +172,7 @@ void status_page(void)
refresh_interval = atoi(v);
}
tdb = tdb_open(lock_path("connections.tdb"), 0, O_RDONLY, 0);
tdb = tdb_open(lock_path("connections.tdb"), 0, 0, O_RDONLY, 0);
if (tdb) tdb_traverse(tdb, traverse_fn1);
printf("<H2>Server Status</H2>\n");