patche for samba-2.0.7/source/smbd/conn.c

Kenichi Okuyama okuyama at trl.ibm.co.jp
Wed May 10 02:41:30 GMT 2000


Dear all,

I have made patch for samba-2.0.7/source/smbd/conn.c
This will, instead of using by-directional link, use
array for managing connections.

# The patch does seems to work on my RHL6.1Ja(fixed) version of
# Linux machine. I don't know about other OS/Architecture.

This should work better then original because:

1) The original code used bitmap.c for looking empty area.
  But using bitmap.c is still nothing more then liniar search (
  though it is fast ). 
  So, I added several extra parameters so this is a bit less cost.
  ( very little bit..., for calling conn.c itself, is very rare ).

2) Since we can only manage upto 128 connection, it is not very good
   idea to manage them with by-directional link list, for tracing
   link list will cause 'jump around the page' and 'jump around the
   cache' behavior. So, instead, I made 'array of pointer' with
   128 pointers.
   ( I didn't change structure of `connection_struct', so they still
    contains next/prev pointers. It might be true that we no longer
    need it, or we can use it for another perpose ... like managing
    snum in some way better then simple search ).

3) I made entire "global" variable to single structure.

do
% patch -p0 < [The patch below]
and you'll get patched conn.c.

best regards,
---- 
Kenichi Okuyama at Tokyo Research Lab. IBM-Japan.Co.


---- Patch starts from line below ----
--- ./source/smbd/conn.c	2000/05/02 14:49:30	1.1
+++ ./source/smbd/conn.c	2000/05/08 16:23:12
@@ -25,165 +25,268 @@
 
 /* set these to define the limits of the server. NOTE These are on a
    per-client basis. Thus any one machine can't connect to more than
    MAX_CONNECTIONS services, but any number of machines may connect at
    one time. */
+
+
 #define MAX_CONNECTIONS 128
 
-static connection_struct *Connections;
+#define	BIGGEST_NONE		-1
+#define	SMALLEST_NONE		-1
+#define	SMALLEST_UNKNOWN	-2
+
+typedef struct {
+    connection_struct	*Connections[MAX_CONNECTIONS];
+    int			num_open;
+    int                 biggest_in_use;
+    int                 smallest_released;
+} connection_total_handler;
+
+static connection_total_handler	cth;
 
-/* number of open connections */
-static struct bitmap *bmap;
-static int num_open;
 
 /****************************************************************************
 init the conn structures
 ****************************************************************************/
 void conn_init(void)
 {
-	bmap = bitmap_allocate(MAX_CONNECTIONS);
+    /* This is quick initialization code */
+
+    memset( (void *)(&cth), 0, sizeof( connection_total_handler ));
+    cth.biggest_in_use	        = BIGGEST_NONE;
+    cth.smallest_released	= SMALLEST_NONE;
 }
 
 /****************************************************************************
 return the number of open connections
 ****************************************************************************/
 int conn_num_open(void)
 {
-	return num_open;
+    return cth.num_open;
 }
 
 
 /****************************************************************************
 check if a snum is in use
 ****************************************************************************/
 BOOL conn_snum_used(int snum)
 {
-	connection_struct *conn;
-	for (conn=Connections;conn;conn=conn->next) {
-		if (conn->service == snum) {
-			return(True);
-		}
-	}
-	return(False);
+    int		i, inuse;
+
+    inuse	= 0;
+    for ( i = 0; i < MAX_CONNECTIONS; i++ ) {
+        if ( cth.Connections[i] ) {
+            if ( cth.Connections[i]->service == snum ) {
+                return True;
+            }
+            inuse++;
+            if ( inuse >= cth.num_open ) {
+                return False;
+            }
+        }
+    }
+    return False;
 }
 
 
 /****************************************************************************
 find a conn given a cnum
 ****************************************************************************/
 connection_struct *conn_find(int cnum)
 {
-	int count=0;
-	connection_struct *conn;
-
-	for (conn=Connections;conn;conn=conn->next,count++) {
-		if (conn->cnum == cnum) {
-			if (count > 10) {
-				DLIST_PROMOTE(Connections, conn);
-			}
-			return conn;
-		}
-	}
+    if (( cnum >= MAX_CONNECTIONS )||( cnum < 0 )) {
+        return NULL;
+    }
 
-	return NULL;
+    return cth.Connections[cnum];
 }
 
 
 /****************************************************************************
   find first available connection slot, starting from a random position.
 The randomisation stops problems with the server dieing and clients
 thinking the server is still available.
 ****************************************************************************/
 connection_struct *conn_new(void)
 {
-	connection_struct *conn;
-	int i;
-
-	i = bitmap_find(bmap, 1);
-	
-	if (i == -1) {
-		DEBUG(1,("ERROR! Out of connection structures\n"));	       
-		return NULL;
-	}
+    connection_struct *conn;
+    int i;
 
-	conn = (connection_struct *)malloc(sizeof(*conn));
-	if (!conn) return NULL;
+    if ( cth.num_open >= MAX_CONNECTIONS ) {
+        DEBUG(1,("ERROR! Out of connection structures\n"));
+        return NULL;
+    }
+
+    conn	= ( connection_struct *)malloc( sizeof( *conn ));
+    if ( !conn ) {
+        return NULL;
+    }
+    ZERO_STRUCTP( conn );
+
+
+    /* find empty */
+    if ( cth.smallest_released >= 0 ) {
+        i			= cth.smallest_released;
+        cth.smallest_released	= SMALLEST_UNKNOWN;
+        /* cth.smallest_released will not be re-setted now. */
+    } else if ( cth.smallest_released == SMALLEST_NONE ) {
+        i			= cth.num_open;
+        cth.biggest_in_use	= i;
+    } else /*if ( cth.smallest_released == SMALLEST_UNKNOWN )*/ {
+        int	j;
+
+        /* scan for empty */
+        i	= -1;
+        for ( j = 0; j < cth.biggest_in_use; j++ ) {
+            if ( cth.Connections[j] == NULL ) {
+                if ( i < 0 ) {
+                    i	= j;
+                    break;
+                }
+            }
+        }
+        if ( i < 0 ) {
+            i			= cth.num_open;
+            cth.biggest_in_use	= i;
+        }
+    }
+
+
+    conn->cnum	= i;
+    cth.Connections[i]	= conn;
+    cth.num_open++;
+
+    string_set(&conn->user,"");
+    string_set(&conn->dirpath,"");
+    string_set(&conn->connectpath,"");
+    string_set(&conn->origpath,"");
+    
 
-	ZERO_STRUCTP(conn);
-	conn->cnum = i;
-
-	bitmap_set(bmap, i);
-
-	num_open++;
-
-	string_set(&conn->user,"");
-	string_set(&conn->dirpath,"");
-	string_set(&conn->connectpath,"");
-	string_set(&conn->origpath,"");
-	
-	DLIST_ADD(Connections, conn);
-
-	return conn;
+    return conn;
 }
 
 /****************************************************************************
 close all conn structures
 ****************************************************************************/
 void conn_close_all(void)
 {
-	connection_struct *conn, *next;
-	for (conn=Connections;conn;conn=next) {
-		next=conn->next;
-		close_cnum(conn, (uint16)-1);
-	}
+    int		i;
+
+    for ( i = 0; i < MAX_CONNECTIONS; i++ ) {
+        if ( cth.Connections[i] ) {
+            close_cnum( cth.Connections[i], (uint16)-1 );
+            cth.Connections[i]	= NULL;
+        }
+    }
+
+    /* re-initialize */
+    cth.num_open		= 0;
+    cth.biggest_in_use	        = BIGGEST_NONE;
+    cth.smallest_released	= SMALLEST_NONE;
 }
 
 /****************************************************************************
 idle inactive connections
 ****************************************************************************/
 BOOL conn_idle_all(time_t t, int deadtime)
 {
-	BOOL allidle = True;
-	connection_struct *conn, *next;
+    BOOL        allidle	= True;
+    int		i, num_passed;
 
-	for (conn=Connections;conn;conn=next) {
-		next=conn->next;
-		/* close dirptrs on connections that are idle */
-		if ((t-conn->lastused) > DPTR_IDLE_TIMEOUT)
-			dptr_idlecnum(conn);
-
-		if (conn->num_files_open > 0 || 
-		    (t-conn->lastused)<deadtime)
-			allidle = False;
-	}
+    for ( num_passed = 0, i = 0; i < MAX_CONNECTIONS; i++ ) {
+        if ( cth.Connections[i] ) {
+            connection_struct *conn	= cth.Connections[i];
+
+            /* close dirptrs on connections that are idle */
+            if ((t-conn->lastused) > DPTR_IDLE_TIMEOUT) {
+                dptr_idlecnum( conn );
+            }
+
+            if (( conn->num_files_open > 0 )||
+                ( t-conn->lastused < deadtime )) {
+                allidle = False;
+            }
+
+            num_passed++;
+            if ( num_passed >= cth.num_open ) {
+                break;
+            }
+        }
+    }
 
-	return allidle;
+    return allidle;
 }
 
 /****************************************************************************
 free a conn structure
 ****************************************************************************/
 void conn_free(connection_struct *conn)
 {
-	DLIST_REMOVE(Connections, conn);
-
-	if (conn->ngroups && conn->groups) {
-		free(conn->groups);
-		conn->groups = NULL;
-		conn->ngroups = 0;
-	}
-
-	free_namearray(conn->veto_list);
-	free_namearray(conn->hide_list);
-	free_namearray(conn->veto_oplock_list);
+    if ( !conn ) {
+        return;
+    }
+
+    if ( cth.Connections[ conn->cnum ] != conn ) {
+	/* that conn does not seems to be proper conn */
+	return;
+    }
+
+    /* release conn from cth */
+    cth.Connections[ conn->cnum ]	= NULL;
+    cth.num_open--;
+
+    if ( conn->cnum < cth.biggest_in_use ) {
+        if (( cth.smallest_released < 0 )||
+            ( cth.smallest_released < conn->cnum )) {
+            cth.smallest_released	= conn->cnum;
+        }
+    } else {
+        /* shrink biggest_in_use */
+        int	i;
+
+        for ( i = conn->cnum - 1; i >= 0; i-- ) {
+            if ( cth.Connections[i] ) {
+                break;
+            }
+        }
+        if ( i < 0 ) {
+            cth.biggest_in_use		= BIGGEST_NONE;
+            cth.smallest_released	= SMALLEST_NONE;
+        } else {
+            cth.biggest_in_use	= i;
+            if ( cth.smallest_released >= i ) {
+                cth.smallest_released	= SMALLEST_UNKNOWN;
+            }
+        }
+    }
+
+    if ( cth.smallest_released == SMALLEST_UNKNOWN ) {
+        int	i;
+        for ( i = 0; i < cth.biggest_in_use; i++ ) {
+            if ( cth.Connections[i] == NULL ) {
+                break;
+            }
+        }
+        if ( i >= cth.biggest_in_use ) {
+            cth.smallest_released	= SMALLEST_NONE;
+        } else {
+            cth.smallest_released	= i;
+        }
+    }
+
+
+    if ( conn->ngroups && conn->groups ) {
+        free(conn->groups);
+    }
+
+    free_namearray(conn->veto_list);
+    free_namearray(conn->hide_list);
+    free_namearray(conn->veto_oplock_list);
 	
-	string_free(&conn->user);
-	string_free(&conn->dirpath);
-	string_free(&conn->connectpath);
-	string_free(&conn->origpath);
-
-	bitmap_clear(bmap, conn->cnum);
-	num_open--;
+    string_free(&conn->user);
+    string_free(&conn->dirpath);
+    string_free(&conn->connectpath);
+    string_free(&conn->origpath);
 
-	ZERO_STRUCTP(conn);
-	free(conn);
+    free(conn);
 }


More information about the samba mailing list