summaryrefslogtreecommitdiff
path: root/source3/smbd
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2001-05-14 06:15:46 +0000
committerJeremy Allison <jra@samba.org>2001-05-14 06:15:46 +0000
commit363e378dee1677f865bba3e8b347c600bbc08550 (patch)
tree5e7900c2c449b17a140e3c11163a3a140bd34e1e /source3/smbd
parent13dd825d57d2e7aa9fa5dc787083dae230b75bd6 (diff)
downloadsamba-363e378dee1677f865bba3e8b347c600bbc08550.tar.gz
samba-363e378dee1677f865bba3e8b347c600bbc08550.tar.bz2
samba-363e378dee1677f865bba3e8b347c600bbc08550.zip
Implemented max connections in a similar way to 2.0.x (scan of connection db).
This needs testing ! Tidied up tabs in tdb.c. Jeremy. (This used to be commit 0852465053d0c1a23b6cfe6097267291b0595ef8)
Diffstat (limited to 'source3/smbd')
-rw-r--r--source3/smbd/connection.c88
1 files changed, 83 insertions, 5 deletions
diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c
index 43e89abfbf..6c401264d9 100644
--- a/source3/smbd/connection.c
+++ b/source3/smbd/connection.c
@@ -37,8 +37,9 @@ TDB_CONTEXT *conn_tdb_ctx(void)
}
/****************************************************************************
-delete a connection record
+ Delete a connection record.
****************************************************************************/
+
BOOL yield_connection(connection_struct *conn,char *name,int max_connections)
{
struct connections_key key;
@@ -62,21 +63,92 @@ BOOL yield_connection(connection_struct *conn,char *name,int max_connections)
return(True);
}
+struct count_stat {
+ pid_t mypid;
+ int curr_connections;
+ char *name;
+};
+
+/****************************************************************************
+ Count the entries belonging to a service in the connection db.
+****************************************************************************/
+
+static int count_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *udp)
+{
+ struct connections_data crec;
+ struct count_stat *cs = (struct count_stat *)udp;
+
+ memcpy(&crec, dbuf.dptr, sizeof(crec));
+
+ if (crec.cnum == -1)
+ return 0;
+
+ /* if the pid was not found delete the entry from connections.tdb */
+ if (!process_exists(crec.pid) && (errno == ESRCH)) {
+ DEBUG(2,("pid %u doesn't exist - deleting connections %d [%s]\n",
+ (unsigned int)crec.pid, crec.cnum, crec.name));
+ tdb_delete(the_tdb, kbuf);
+ return 0;
+ }
+
+ if (strequal(crec.name, cs->name))
+ cs->curr_connections++;
+
+ return 0;
+}
/****************************************************************************
-claim an entry in the connections database
+ 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;
+ BOOL db_locked = False;
+ BOOL ret = True;
if (!tdb) {
tdb = tdb_open(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST,
O_RDWR | O_CREAT, 0644);
}
- if (!tdb) return False;
+ if (!tdb)
+ return False;
+
+ /*
+ * Enforce the max connections parameter.
+ */
+
+ if (max_connections > 0) {
+ struct count_stat cs;
+
+ cs.mypid = sys_getpid();
+ cs.curr_connections = 0;
+ cs.name = lp_servicename(SNUM(conn));
+
+ /*
+ * Go through and count the connections with the db locked. This is
+ * slow but essentially what 2.0.x did. JRA.
+ */
+
+ if (tdb_lockall(tdb))
+ return False;
+
+ db_locked = True;
+
+ if (tdb_traverse(tdb, count_fn, &cs)) {
+ ret = False;
+ goto out;
+ }
+
+ if (cs.curr_connections >= max_connections) {
+ DEBUG(1,("claim_connection: Max connections (%d) exceeded for %s\n",
+ max_connections, name ));
+ ret = False;
+ goto out;
+ }
+ }
DEBUG(5,("claiming %s %d\n",name,max_connections));
@@ -108,8 +180,14 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO
dbuf.dptr = (char *)&crec;
dbuf.dsize = sizeof(crec);
- if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) return False;
+ if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0)
+ ret = False;
+
+ out:
+
+ if (db_locked)
+ tdb_unlockall(tdb);
- return True;
+ return ret;
}