summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2000-01-02 23:00:27 +0000
committerAndrew Tridgell <tridge@samba.org>2000-01-02 23:00:27 +0000
commit9a781a8c6de9513ba5f4cafef41379fae96807c1 (patch)
treed9bd28fba6ccdaabe43d2183200310cb6bc4d283
parent321983bb6b68b5fe18f1021dc5851ce3bb0de625 (diff)
downloadsamba-9a781a8c6de9513ba5f4cafef41379fae96807c1.tar.gz
samba-9a781a8c6de9513ba5f4cafef41379fae96807c1.tar.xz
samba-9a781a8c6de9513ba5f4cafef41379fae96807c1.zip
- 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 used to be commit 00e9da3ca577527db392aced62f02c69cfee8f4f)
-rw-r--r--source3/include/proto.h4
-rw-r--r--source3/locking/locking.c2
-rw-r--r--source3/nmbd/nmbd_namelistdb.c10
-rw-r--r--source3/nmbd/nmbd_winsserver.c10
-rw-r--r--source3/smbd/connection.c28
-rw-r--r--source3/tdb/tdb.c53
-rw-r--r--source3/tdb/tdb.h7
-rw-r--r--source3/tdb/tdbtest.c5
-rw-r--r--source3/tdb/tdbtool.c5
-rw-r--r--source3/tdb/tdbtorture.c5
-rw-r--r--source3/utils/status.c8
-rw-r--r--source3/web/statuspage.c2
12 files changed, 72 insertions, 67 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h
index c45da94f461..251f0514529 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -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);
diff --git a/source3/locking/locking.c b/source3/locking/locking.c
index 156ff016ea6..dafd324edc2 100644
--- a/source3/locking/locking.c
+++ b/source3/locking/locking.c
@@ -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);
diff --git a/source3/nmbd/nmbd_namelistdb.c b/source3/nmbd/nmbd_namelistdb.c
index dbb8be1f2d5..e2433f42d3d 100644
--- a/source3/nmbd/nmbd_namelistdb.c
+++ b/source3/nmbd/nmbd_namelistdb.c
@@ -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;
}
diff --git a/source3/nmbd/nmbd_winsserver.c b/source3/nmbd/nmbd_winsserver.c
index 45e93351674..d1a100aaea2 100644
--- a/source3/nmbd/nmbd_winsserver.c
+++ b/source3/nmbd/nmbd_winsserver.c
@@ -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;
}
diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c
index 5b5ab005c80..13c051a5a36 100644
--- a/source3/smbd/connection.c
+++ b/source3/smbd/connection.c
@@ -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,7 +48,6 @@ BOOL yield_connection(connection_struct *conn,char *name,int max_connections)
kbuf.dsize = sizeof(key);
tdb_delete(tdb, kbuf);
- tdb_close(tdb);
return(True);
}
@@ -57,30 +55,20 @@ BOOL yield_connection(connection_struct *conn,char *name,int max_connections)
/****************************************************************************
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
-****************************************************************************/
BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOOL Clear)
{
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;
diff --git a/source3/tdb/tdb.c b/source3/tdb/tdb.c
index 7b8f8db4c08..731d1fdbc8a 100644
--- a/source3/tdb/tdb.c
+++ b/source3/tdb/tdb.c
@@ -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);
diff --git a/source3/tdb/tdb.h b/source3/tdb/tdb.h
index 527e65740a6..9cb8f71a902 100644
--- a/source3/tdb/tdb.h
+++ b/source3/tdb/tdb.h
@@ -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);
diff --git a/source3/tdb/tdbtest.c b/source3/tdb/tdbtest.c
index 8089e7be7d5..581d8192d90 100644
--- a/source3/tdb/tdbtest.c
+++ b/source3/tdb/tdbtest.c
@@ -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);
diff --git a/source3/tdb/tdbtool.c b/source3/tdb/tdbtool.c
index 5eb410d418c..428bae84c2f 100644
--- a/source3/tdb/tdbtool.c
+++ b/source3/tdb/tdbtool.c
@@ -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)
diff --git a/source3/tdb/tdbtorture.c b/source3/tdb/tdbtorture.c
index 1aac6d4a011..3eb462d79eb 100644
--- a/source3/tdb/tdbtorture.c
+++ b/source3/tdb/tdbtorture.c
@@ -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");
}
diff --git a/source3/utils/status.c b/source3/utils/status.c
index 51118914922..3082402d8b5 100644
--- a/source3/utils/status.c
+++ b/source3/utils/status.c
@@ -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))
diff --git a/source3/web/statuspage.c b/source3/web/statuspage.c
index e3e10f09d5d..eaf3fdb8648 100644
--- a/source3/web/statuspage.c
+++ b/source3/web/statuspage.c
@@ -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");