diff options
author | Andrew Tridgell <tridge@samba.org> | 2000-01-02 23:00:27 +0000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2000-01-02 23:00:27 +0000 |
commit | 9a781a8c6de9513ba5f4cafef41379fae96807c1 (patch) | |
tree | d9bd28fba6ccdaabe43d2183200310cb6bc4d283 | |
parent | 321983bb6b68b5fe18f1021dc5851ce3bb0de625 (diff) | |
download | samba-9a781a8c6de9513ba5f4cafef41379fae96807c1.tar.gz samba-9a781a8c6de9513ba5f4cafef41379fae96807c1.tar.bz2 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.h | 4 | ||||
-rw-r--r-- | source3/locking/locking.c | 2 | ||||
-rw-r--r-- | source3/nmbd/nmbd_namelistdb.c | 10 | ||||
-rw-r--r-- | source3/nmbd/nmbd_winsserver.c | 10 | ||||
-rw-r--r-- | source3/smbd/connection.c | 28 | ||||
-rw-r--r-- | source3/tdb/tdb.c | 53 | ||||
-rw-r--r-- | source3/tdb/tdb.h | 7 | ||||
-rw-r--r-- | source3/tdb/tdbtest.c | 5 | ||||
-rw-r--r-- | source3/tdb/tdbtool.c | 5 | ||||
-rw-r--r-- | source3/tdb/tdbtorture.c | 5 | ||||
-rw-r--r-- | source3/utils/status.c | 8 | ||||
-rw-r--r-- | source3/web/statuspage.c | 2 |
12 files changed, 72 insertions, 67 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h index c45da94f46..251f051452 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 156ff016ea..dafd324edc 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 dbb8be1f2d..e2433f42d3 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 45e9335167..d1a100aaea 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 5b5ab005c8..13c051a5a3 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 7b8f8db4c0..731d1fdbc8 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 527e65740a..9cb8f71a90 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 8089e7be7d..581d8192d9 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 5eb410d418..428bae84c2 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 1aac6d4a01..3eb462d79e 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 5111891492..3082402d8b 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 e3e10f09d5..eaf3fdb864 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"); |