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:
parent
88a146ab04
commit
00e9da3ca5
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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))
|
||||
|
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user