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