From 8c60d317d9048eeec14c64b29cf507a4821081d0 Mon Sep 17 00:00:00 2001
From: David Byers <byers@lysator.liu.se>
Date: Fri, 2 Jul 1999 00:14:40 +0000
Subject: [PATCH] Server:     Eliminated calls to build_matching_info when
 creating, renaming     and deleting conferences. Integrated the conf_table
 array into     match_table.

    Name matcher can handle holes in the table.

Testing:
    Added some name lookup test cases.

Distribution:
    Distribute lyskomd tests 12.exp and 13.exp.

Documentation:
    sub-comment was incorrectly marked obsolete. Fixed.
---
 ChangeLog                             |  51 +++++++
 doc/Protocol-A.texi                   |   9 +-
 src/libraries/libcommon/parser.c      | 138 ++++++++++---------
 src/libraries/libcommon/parser.h      |  11 +-
 src/server/cache.h                    |   5 +-
 src/server/conference.c               |  11 +-
 src/server/dbck.c                     |  25 +++-
 src/server/simple-cache.c             | 190 +++++++++++++++++++++++---
 src/server/testsuite/Makefile.am      |   3 +-
 src/server/testsuite/config/unix.exp  |  15 +-
 src/server/testsuite/lyskomd.0/11.exp |  29 +++-
 src/server/testsuite/lyskomd.0/13.exp | 102 ++++++++++++++
 12 files changed, 483 insertions(+), 106 deletions(-)
 create mode 100644 src/server/testsuite/lyskomd.0/13.exp

diff --git a/ChangeLog b/ChangeLog
index 88001f57e..ca89e5308 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,54 @@
+1999-07-02  David Byers  <davby@ida.liu.se>
+
+	Some test cases for name lookup:
+	* src/server/testsuite/Makefile.am (EXTRA_DIST): Added 12 and
+	13.exp.
+
+	* src/server/testsuite/lyskomd.0/13.exp: New file. Some name
+	lookup tests.
+
+	* src/server/testsuite/lyskomd.0/11.exp: Do the right thing when
+	traced allocations are on.
+
+1999-07-01  David Byers  <davby@ida.liu.se>
+
+	* src/server/dbck.c (main): Stole code from test-l2g.c for when
+	traced allocations are on.
+
+	Eliminate the need to call build_matching_info all the time:
+	* src/server/simple-cache.c (rebuild_matching_info_entry): New
+	function to rebuild a single entry in the matching info table.
+	(find_matching_info_index): New function.
+	(cached_change_name): Use rebuild_matching_info_entry insead of
+	build_matching_info.
+
+	* src/libraries/libcommon/parser.c (parse): Loop until we see a
+	zero conf-no instead of an empty name. Just skip empty names.
+
+	* src/server/cache.h (cached_no_of_existing_conferences): Removed
+	extern declaration of build_matching_info.
+
+	Eliminate conf_table:
+	* src/libraries/libcommon/parser.c: Include kom-types.h so we can
+	include parser.h.
+	
+	* src/server/conference.c: Removed extern declaration of
+	conf_table. Added extern declaration of match_table.
+	(unique_name): Use match_table, not conf_table.
+
+	* src/server/simple-cache.c: (conf_table): Removed.
+	(build_matching_info): Removed conf_table.
+	(cached_lookup_name): Use match_table instead of conf_table.
+	(free_all_cache): Removed conf_table.
+
+	* src/libraries/libcommon/parser.h (Matching_info): Added conf_no
+	field.
+
+1999-06-29  David Byers  <davby@ida.liu.se>
+
+	* doc/Protocol-A.texi (sub-comment): Changed sub-comment from
+	obsolete to recommended.
+
 1999-07-01  Per Cederqvist  <ceder@lysator.liu.se>
 
 	Added the ``wanted_access'' argument to access_perm(), removed
diff --git a/doc/Protocol-A.texi b/doc/Protocol-A.texi
index a9f4f039e..8c1ad5993 100644
--- a/doc/Protocol-A.texi
+++ b/doc/Protocol-A.texi
@@ -2,7 +2,7 @@
 @c
 @c FIXME: Explain how the garb works with nice and keep-commented
 @c
-@c $Id: Protocol-A.texi,v 1.81 1999/06/27 10:16:26 ceder Exp $
+@c $Id: Protocol-A.texi,v 1.82 1999/07/02 00:12:55 byers Exp $
 @c %**start of header
 @setfilename protocol-a.info
 @settitle LysKOM Protocol A
@@ -134,6 +134,10 @@ The LysKOM developers can be reached by email to
 
 @table @asis
 
+@item 10.0: 1999-06-31
+Call @code{sub-comment} was incorrectly marked obsolete. This has been
+corrected.
+
 @item 10.0: 1999-06-27
 The specification was translated to English and converted to Texinfo by
 David Byers.  Protocol version 10.  Distributed with lyskomd 2.0.0.
@@ -251,7 +255,6 @@ Experimental to Obsolete.
 @item 14=add-member-old
 @item 26=get-text-stat-old
 @item 28=create-text-old
-@item 33=sub-comment
 @item 36=get-info-old
 @item 46=get-membership-old
 @item 47=get-created-texts
@@ -4589,7 +4592,7 @@ The text @code{comment-to} already has the maximum number of comments.
 
 
 @node sub-comment
-@section sub-comment [33] (1) Obsolete (10)
+@section sub-comment [33] (1) Recommended
 
 @findex sub-comment
 @example
diff --git a/src/libraries/libcommon/parser.c b/src/libraries/libcommon/parser.c
index e1d5b92ff..d6cac3316 100644
--- a/src/libraries/libcommon/parser.c
+++ b/src/libraries/libcommon/parser.c
@@ -1,5 +1,5 @@
 /*
- * $Id: parser.c,v 0.15 1999/05/24 09:34:09 ceder Exp $
+ * $Id: parser.c,v 0.16 1999/07/02 00:13:34 byers Exp $
  * Copyright (C) 1990-1991, 1993-1995, 1998-1999  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -48,7 +48,7 @@
 
 
 static const char *
-rcsid = "$Id: parser.c,v 0.15 1999/05/24 09:34:09 ceder Exp $";
+rcsid = "$Id: parser.c,v 0.16 1999/07/02 00:13:34 byers Exp $";
 #include "rcs.h"
 USE(rcsid);
 
@@ -59,6 +59,7 @@ USE(rcsid);
 
 #include "s-string.h"
 #include "s-collat-tabs.h"
+#include "kom-types.h"
 #include "parser.h"
 
 #define EXPORT			/* To emphasize export of objects */
@@ -357,72 +358,75 @@ parse (String		  source_string,
     index = -1;
     best_match = 1;			/* At least one word */
     highest_priority = 1;
-    while (! s_empty (match_table[++index].name))
+    while (match_table[++index].conf_no != 0)
     {
-	first_non_matching = match (source_words, match_table[index].tokens,
-				    collat_tab);
-
-	if (   (    ! allow_trailing_words
-		&&  first_non_matching < no_of_source_words)
-	    || (    number_of_words_must_match == TRUE
-		&&  first_non_matching != count_words (match_table[index].tokens)))
-	{
-	    continue;			/* Try next entry in table */
-	}
-
-	if (first_non_matching < best_match)
-	    continue;			/* Try next entry in table */
-
-	if (    first_non_matching == best_match
-	    &&  highest_priority > match_table[index].priority)
-	    continue;
-
-	/*  If we reach this far, then we have a match that should be
-	 *  inserted in the table.  But if it is a better match than any
-	 *  before, then we clear the table first.			*/
-	if (    first_non_matching > best_match
-	    ||  match_table[index].priority > highest_priority)
-	{
-	    highest_priority = match_table[index].priority;
-	    best_match = first_non_matching;
-	    answer.no_of_matches = 0;
-	}
-
-	/* Insert the match in the table */
-
-	/* Increase the size if necessary */
-	if (answer.no_of_matches >= size_of_index_list)
-	{
-	    temp_indexes = REALLOC (answer.indexes,
-				    (size_of_index_list += chunk_size)
-				    * sizeof(answer.indexes));
-	    if (temp_indexes == NULL)
-	    {
-		/* Grumble!  Out of memory. */
-		FREE (source_words);
-		FREE (answer.indexes);
-		answer.no_of_matches = -1;
-		return  answer;
-	    }
-
-	    answer.indexes = temp_indexes;
-	}
-
-	highest_priority = match_table [index].priority;
-	answer.indexes[answer.no_of_matches] = index;
-	/*  Find out where the arguments start.
-	 *  This value should not be used if more than one match is found.
-	 */
-	/* Special hack needed if no parameters */
-	if (s_empty (source_words [first_non_matching].word))
-	    answer.arguments = EMPTY_STRING;
-	else
-	    answer.arguments =
-		s_fsubstr(source_string,
-			  source_words[first_non_matching].
-			  start_in_string,
-			  END_OF_STRING);
-	answer.no_of_matches++;
+        if (! s_empty (match_table[index].name))
+        {
+            first_non_matching = match (source_words, match_table[index].tokens,
+                                        collat_tab);
+
+            if (   (    ! allow_trailing_words
+                        &&  first_non_matching < no_of_source_words)
+                   || (    number_of_words_must_match == TRUE
+                           &&  first_non_matching != count_words (match_table[index].tokens)))
+            {
+                continue;			/* Try next entry in table */
+            }
+
+            if (first_non_matching < best_match)
+                continue;			/* Try next entry in table */
+
+            if (    first_non_matching == best_match
+                    &&  highest_priority > match_table[index].priority)
+                continue;
+
+            /*  If we reach this far, then we have a match that should be
+             *  inserted in the table.  But if it is a better match than any
+             *  before, then we clear the table first.			*/
+            if (    first_non_matching > best_match
+                    ||  match_table[index].priority > highest_priority)
+            {
+                highest_priority = match_table[index].priority;
+                best_match = first_non_matching;
+                answer.no_of_matches = 0;
+            }
+
+            /* Insert the match in the table */
+
+            /* Increase the size if necessary */
+            if (answer.no_of_matches >= size_of_index_list)
+            {
+                temp_indexes = REALLOC (answer.indexes,
+                                        (size_of_index_list += chunk_size)
+                                        * sizeof(answer.indexes));
+                if (temp_indexes == NULL)
+                {
+                    /* Grumble!  Out of memory. */
+                    FREE (source_words);
+                    FREE (answer.indexes);
+                    answer.no_of_matches = -1;
+                    return  answer;
+                }
+
+                answer.indexes = temp_indexes;
+            }
+
+            highest_priority = match_table [index].priority;
+            answer.indexes[answer.no_of_matches] = index;
+            /*  Find out where the arguments start.
+             *  This value should not be used if more than one match is found.
+             */
+            /* Special hack needed if no parameters */
+            if (s_empty (source_words [first_non_matching].word))
+                answer.arguments = EMPTY_STRING;
+            else
+                answer.arguments =
+                    s_fsubstr(source_string,
+                              source_words[first_non_matching].
+                              start_in_string,
+                              END_OF_STRING);
+            answer.no_of_matches++;
+        }
     }
 
     /* All matches found by now */
diff --git a/src/libraries/libcommon/parser.h b/src/libraries/libcommon/parser.h
index aae3502ec..03f2ab127 100644
--- a/src/libraries/libcommon/parser.h
+++ b/src/libraries/libcommon/parser.h
@@ -1,5 +1,5 @@
 /*
- * $Id: parser.h,v 0.9 1999/05/24 09:38:22 ceder Exp $
+ * $Id: parser.h,v 0.10 1999/07/02 00:13:34 byers Exp $
  * Copyright (C) 1990-1991, 1994-1995, 1998-1999  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -23,7 +23,7 @@
  * Please mail bug reports to bug-lyskom@lysator.liu.se. 
  */
 /*
- * $Id: parser.h,v 0.9 1999/05/24 09:38:22 ceder Exp $
+ * $Id: parser.h,v 0.10 1999/07/02 00:13:34 byers Exp $
  *
  *  client/parser.h  --  Header file for LysKOM command parsing routines
  *
@@ -72,9 +72,10 @@ typedef	struct {
  *	I.tokens = tokenize(I.name, Separators);
  */
 typedef	struct matching_info {
-	String		   name;	/* Name to match against */
-	Parse_token	 * tokens;	/* Tokenized version of name */
-	int		   priority;	/* Normally in interval 1..15 */
+    Conf_no        conf_no;         /* Conference */
+    String	   name;	    /* Name to match against */
+    Parse_token	 * tokens;          /* Tokenized version of name */
+    int		   priority;        /* Normally in interval 1..15 */
 } Matching_info;
 
 
diff --git a/src/server/cache.h b/src/server/cache.h
index 60b990aae..f470e4f9d 100644
--- a/src/server/cache.h
+++ b/src/server/cache.h
@@ -1,5 +1,5 @@
 /*
- * $Id: cache.h,v 0.20 1999/05/24 09:34:20 ceder Exp $
+ * $Id: cache.h,v 0.21 1999/07/02 00:14:00 byers Exp $
  * Copyright (C) 1991-1996, 1999  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -128,7 +128,4 @@ Success   cached_lookup_name(const String name,Conf_list_old *result);
 /* How many conferences exists?  */
 Conf_no   cached_no_of_existing_conferences(void);
 
-/******** miscellanous wierd routines ************************************/
-
-Success build_matching_info(void);
 
diff --git a/src/server/conference.c b/src/server/conference.c
index 8e8eb7627..ffef78235 100644
--- a/src/server/conference.c
+++ b/src/server/conference.c
@@ -1,5 +1,5 @@
 /*
- * $Id: conference.c,v 0.55 1999/07/01 21:23:36 ceder Exp $
+ * $Id: conference.c,v 0.56 1999/07/02 00:14:01 byers Exp $
  * Copyright (C) 1991-1999  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -35,7 +35,7 @@
 
 
 static const char *
-rcsid = "$Id: conference.c,v 0.55 1999/07/01 21:23:36 ceder Exp $";
+rcsid = "$Id: conference.c,v 0.56 1999/07/02 00:14:01 byers Exp $";
 #include "rcs.h"
 USE(rcsid);
 
@@ -76,7 +76,7 @@ BUGDECL;
  * Defined in conference.c. This will go away when we use regexp-matching.
  * This is only temporary. FIXME+++***
  */
-extern Conf_no       *conf_table;
+extern Matching_info       *match_table;
 
 /*
  * Static functions
@@ -114,7 +114,8 @@ do_delete_conf (Conf_no      conf_no,
     sfree( conf_c->members.members );
     conf_c->members.members = NULL;
     
-    /* Delete the name */
+    /* Delete the name.
+       FIXME: This is done by cached_delete_conf */
 
     s_clear( &conf_c->name );
     cached_change_name( conf_no, EMPTY_STRING);
@@ -252,7 +253,7 @@ unique_name( const String name, Conf_no conf_no )
 	    diff_found = TRUE;
 	}
 
-	if ( !diff_found && conf_table[ parse_info.indexes[ i ] ] != conf_no )
+	if ( !diff_found && match_table[ parse_info.indexes[ i ] ].conf_no != conf_no )
 	    exact_match_found = TRUE;
     }
 	    
diff --git a/src/server/dbck.c b/src/server/dbck.c
index d2fc882ed..bb4599a1d 100644
--- a/src/server/dbck.c
+++ b/src/server/dbck.c
@@ -1,5 +1,5 @@
 /*
- * $Id: dbck.c,v 0.57 1999/06/27 15:55:39 ceder Exp $
+ * $Id: dbck.c,v 0.58 1999/07/02 00:14:02 byers Exp $
  * Copyright (C) 1991-1999  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -35,7 +35,7 @@
 
 
 static const char *
-rcsid = "$Id: dbck.c,v 0.57 1999/06/27 15:55:39 ceder Exp $";
+rcsid = "$Id: dbck.c,v 0.58 1999/07/02 00:14:02 byers Exp $";
 #include "rcs.h"
 USE(rcsid);
 
@@ -1516,6 +1516,27 @@ main (int    argc,
     int need_rw = 0;
     int have_lock = 0;
 
+#ifdef TRACED_ALLOCATIONS
+    /* We must do this before we allocate any memory... */
+    {
+      char buf[1024];
+      char *nl;
+
+      fputs("Where does the trace want to go today? [stderr]\n", stdout);
+      fflush(stdout);
+      if (fgets(buf, sizeof(buf), stdin) != buf)
+      {
+	  fprintf(stderr, "unable to read trace location\n");
+	  exit(1);
+      }
+
+      if ((nl = strchr(buf, '\n')) != NULL)
+	  *nl = '\0';
+      trace_alloc_file(buf);
+    }
+#endif
+
+
     while ((optc = getopt_long(argc, argv, "girvstdcP:G:Fo:",
 			       longopts, (int *) 0)) != EOF)
     {
diff --git a/src/server/simple-cache.c b/src/server/simple-cache.c
index b2cc7c924..a631807fd 100644
--- a/src/server/simple-cache.c
+++ b/src/server/simple-cache.c
@@ -1,5 +1,5 @@
 /*
- * $Id: simple-cache.c,v 0.82 1999/07/01 18:20:39 ceder Exp $
+ * $Id: simple-cache.c,v 0.83 1999/07/02 00:14:04 byers Exp $
  * Copyright (C) 1991-1999  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -40,12 +40,15 @@
 #endif
 
 static const char *
-rcsid = "$Id: simple-cache.c,v 0.82 1999/07/01 18:20:39 ceder Exp $";
+rcsid = "$Id: simple-cache.c,v 0.83 1999/07/02 00:14:04 byers Exp $";
 #include "rcs.h"
 USE(rcsid);
 
 #include <errno.h>
 #include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#   include <stdlib.h>
+#endif
 #include <sys/types.h>
 #ifdef HAVE_UNISTD_H
 #   include <unistd.h>
@@ -117,8 +120,6 @@ static Text_no		  next_text_num = 1;
  */
 static int    no_of_match_info;
 EXPORT Matching_info *match_table = NULL;
-EXPORT Conf_no       *conf_table  = NULL; /* Used in conference.c. */
-
 
 static FILE	*text_file= NULL;
 static FILE	*file_a = NULL;	/* Current file. */
@@ -222,6 +223,15 @@ static void log_access(Log_type t,
 #define LOGACC(a,b)
 #endif
 
+
+/* Local functions */
+
+static Success build_matching_info(void);
+static Success rebuild_matching_info_entry(Conf_no conf_no);
+static Matching_info *find_matching_info(Conf_no conf_no);
+
+
+
 
 /* Macros */
 
@@ -375,7 +385,7 @@ cached_change_name( Conf_no name_num,
 
     s_clear( &small_conf_arr[name_num]->name );
     s_strcpy( &small_conf_arr[name_num]->name, new_name);
-    build_matching_info();
+    rebuild_matching_info_entry(name_num);
 }
 
 
@@ -712,7 +722,7 @@ cached_delete_conf( Conf_no	conf )
 
     LOGACC(lt_delete_conf, conf);
 
-    build_matching_info();
+    rebuild_matching_info_entry(conf);
     return OK;
 }
 
@@ -1280,7 +1290,7 @@ free_match_table(Matching_info *mtch)
     if ( mtch == NULL )
 	return;
     
-    while ( ! s_empty( mtch->name ))
+    while ( mtch->conf_no != 0 )
     {
 	free_tokens( mtch->tokens );
 	/* mtch->name is not freed since it points into conf_arr[]. */
@@ -1289,7 +1299,156 @@ free_match_table(Matching_info *mtch)
     }
 }    
 
-extern Success
+/* Find the entry for CONF_NO in match_table. Return something if
+   there is a nonempty name or a list of tokens in the entry. The
+   caller is responsible to checking that the name of the returned
+   entry is nonempty. The reason for this is that cached_delete_conf
+   clears the name before rebuilding the matching_info, and
+   rebuild_matching_info_entry needs to get the entry to free the
+   token list when it is called from cached_delete_conf */
+
+
+static int
+find_matching_info_compare(const void *a, const void *b)
+{
+    Matching_info *info_a = (Matching_info *)a;
+    Matching_info *info_b = (Matching_info *)b;
+
+    return info_a->conf_no - info_b->conf_no;
+}
+
+static Matching_info *
+find_matching_info(Conf_no conf_no)
+{
+    Matching_info   *info, key;
+
+    /* FIXME: Do a binary search here! The search must be able to
+       FIXME: deal with NULL entries. We could do this with a regular
+       FIXME: bearch and a final check that the entry has a non-NULL
+       FIXME: tokens field. */
+
+    key.conf_no = conf_no;
+    info = bsearch(&key,
+                   match_table,
+                   no_of_match_info,
+                   sizeof(Matching_info),
+                   find_matching_info_compare);
+    if (info == NULL)
+        return NULL;
+    else if (s_empty(info->name) && info->tokens == NULL)
+        return NULL;
+    else
+        return info;
+}
+
+
+/* Rebuild the matching info entry for a conference. If the conference
+   does not exist in the table, it will be added. If it is not a new
+   conference (conf_no higher than the highest in the table) the entire
+   table will be rebuilt.
+*/
+
+static Success
+rebuild_matching_info_entry(Conf_no conf_no)
+{
+    Matching_info *mtch;
+    Cache_node  *node;
+
+    mtch = find_matching_info(conf_no);
+    if (mtch != NULL)
+    {
+        /* The entry was found. Free the old data */
+        free_tokens(mtch->tokens);
+        
+        /* Add or remove the new entry, depending on if the conf exists */
+        if (small_conf_arr[conf_no] != NULL)
+        {
+            /* Renamed a conference */
+            mtch->name = small_conf_arr[conf_no]->name;
+            mtch->tokens = tokenize(small_conf_arr[conf_no]->name,
+                                    s_fcrea_str(WHITESPACE));
+        }
+        else
+        {
+            /* Deleted a conference. Clear everything but the conf_no */
+
+            /*
+              FIXME: We should compress the table by moving the entries
+              FIXME: Above the deleted one down one step. This will save
+              FIXME: a little time in lookup, and make realloc the next
+              FIXME: time someone creates a conference not have to move
+              FIXME: memory.
+            */
+            mtch->name = EMPTY_STRING;
+            mtch->tokens = NULL;
+            mtch->priority = 0;
+        }
+    }
+    else
+    {
+
+        /*
+          The entry was not found in match_table. This can mean one
+          of two things...
+
+          (1) The name was deleted earlier. This happens when a name
+              is deleted, build_match_info is called, and then this
+              function is called on the same conference. This is an
+              error, of sorts, but can be safely ignored.
+
+          (2) We are being called on a new conference. When this
+              happens, make sure the new conference has a conf_no
+              higher than the highest in the array, then add it to
+              the end (if it has a conf_no not higher than the last
+              entry, rebuild the entire thing.)
+        */
+
+        /* Check that the conference actually exists. The cache node
+           must exist, the node must have the exists flag set and the
+           name must be in small_conf_arr (the last bit is really just
+           a precaution to avoid a crash later on.) */
+        
+        node = get_conf_node(conf_no);
+        if (node == NULL ||
+            node->s.exists == 0 ||
+            s_empty(small_conf_arr[conf_no]->name))
+        {
+            return OK;
+        }
+
+        /* The conference exists. Check if it's conf_no is higher
+           than the last current entry in the list */
+
+        if (conf_no <= match_table[no_of_match_info - 1].conf_no)
+        {
+            kom_log("Rebuilding entire match_table. It doesn't look right.\n");
+            return build_matching_info();
+        }
+
+
+        /* Add an entry to the match table */
+
+        match_table = srealloc(match_table, (no_of_match_info + 2) *
+                               sizeof(Matching_info));
+        match_table[no_of_match_info].name = small_conf_arr[conf_no]->name;
+        match_table[no_of_match_info].tokens = tokenize(small_conf_arr[conf_no]->name,
+                                                        s_fcrea_str(WHITESPACE));
+        match_table[no_of_match_info].priority = 7;
+        match_table[no_of_match_info].conf_no = conf_no;
+
+        /* Bump the number of match infos and enter the ending dummy */
+
+        no_of_match_info += 1;
+        match_table[no_of_match_info].name = EMPTY_STRING;
+        match_table[no_of_match_info].tokens = NULL;
+        match_table[no_of_match_info].priority = 0;
+        match_table[no_of_match_info].conf_no = 0;
+    }
+
+    return OK;
+}
+
+static Success
 build_matching_info(void)
 {
     Conf_no i;
@@ -1299,12 +1458,10 @@ build_matching_info(void)
     free_match_table(match_table);
     
     match_table = srealloc(match_table, next_free_num * sizeof(Matching_info));
-    conf_table = srealloc(conf_table, next_free_num * sizeof(Conf_no));
 
     no_of_match_info = 0;
 
     mtch = match_table;
-    conf = conf_table;
     
     for ( i = 1; i < next_free_num; i++ )
     {
@@ -1314,7 +1471,7 @@ build_matching_info(void)
 	    mtch->name = small_conf_arr[ i ]->name;
 	    mtch->tokens = tokenize(mtch->name, s_fcrea_str(WHITESPACE));
 	    mtch->priority = 7;
-	    *conf = i;
+            mtch->conf_no = i;
 	    ++mtch;
 	    ++conf;
 	    ++no_of_match_info;
@@ -1324,7 +1481,7 @@ build_matching_info(void)
     mtch->name = EMPTY_STRING;
     mtch->tokens = NULL;
     mtch->priority = 0;
-    *conf = 0;
+    mtch->conf_no = 0;
     
     return OK;
 }
@@ -1358,8 +1515,8 @@ cached_lookup_name(const String name,
 
 	for ( i = 0; i < no_of_match_info; i++ )
 	{
-	    result->conf_nos[ i ] = conf_table[ i ];
-	    result->type_of_conf[ i ] = small_conf_arr[ conf_table[i] ]->type;
+	    result->conf_nos[ i ] = match_table[i].conf_no;
+	    result->type_of_conf[ i ] = small_conf_arr[ match_table[i].conf_no ]->type;
 	}
     }
     else
@@ -1372,9 +1529,9 @@ cached_lookup_name(const String name,
 
 	for ( i = 0; i < tmp.no_of_matches; i++ )
 	{
-	    result->conf_nos[ i ] = conf_table[ tmp.indexes[ i ] ];
+	    result->conf_nos[ i ] = match_table[ tmp.indexes[ i ] ].conf_no;
 	    result->type_of_conf[ i ]
-		= small_conf_arr[ conf_table[ tmp.indexes[ i ] ] ]->type;
+		= small_conf_arr[ match_table[ tmp.indexes[ i ] ].conf_no ]->type;
 	}
     }		
     sfree(tmp.indexes);
@@ -2603,7 +2760,6 @@ free_all_cache (void)
     sfree(small_conf_arr);
 
     sfree (match_table);
-    sfree (conf_table);
 }
 
 
diff --git a/src/server/testsuite/Makefile.am b/src/server/testsuite/Makefile.am
index 529beab51..af3f114e2 100644
--- a/src/server/testsuite/Makefile.am
+++ b/src/server/testsuite/Makefile.am
@@ -1,4 +1,4 @@
-# $Id: Makefile.am,v 1.29 1999/06/26 21:56:59 ceder Exp $
+# $Id: Makefile.am,v 1.30 1999/07/02 00:14:22 byers Exp $
 # Copyright (C) 1998-1999  Lysator Academic Computer Association.
 #
 # This file is part of the LysKOM server.
@@ -42,6 +42,7 @@ EXTRA_DIST = .cvsignore \
 	lyskomd.0/00.exp lyskomd.0/01.exp lyskomd.0/02.exp lyskomd.0/03.exp \
 	lyskomd.0/04.exp lyskomd.0/05.exp lyskomd.0/06.exp lyskomd.0/07.exp \
 	lyskomd.0/08.exp lyskomd.0/09.exp lyskomd.0/10.exp lyskomd.0/11.exp \
+	lyskomd.0/12.exp lyskomd.0/13.exp \
 	lyskomd.0/admin-cov.exp \
 	lyskomd.0/aux-items-cov.exp \
 	lyskomd.0/aux-items.conf \
diff --git a/src/server/testsuite/config/unix.exp b/src/server/testsuite/config/unix.exp
index 17d1e88b6..83db44c74 100644
--- a/src/server/testsuite/config/unix.exp
+++ b/src/server/testsuite/config/unix.exp
@@ -9,6 +9,10 @@ if { ![info exists MEMTRACE] } {
     set MEMTRACE /dev/null
 }
 
+if { ![info exists DBCK_MEMTRACE] } {
+    set DBCK_MEMTRACE /dev/null
+}
+
 if { ![info exists EFENCE] } {
     set EFENCE 0
 }
@@ -506,6 +510,7 @@ proc dbck_run {} {
     global nl
     global test
     global any_num
+    global DBCK_MEMTRACE
 
     spawn ../dbck -d config/lyskomd-config
     set test "dbck started"
@@ -514,8 +519,16 @@ proc dbck_run {} {
 	eof { fail "$test (eof)" }
     }
     expect {
-	-re "^MSG: init_cache: using datafile\.$nl" { pass "$test" }
+	-re "^Where does the trace want to go today. .stderr.$nl" {
+	    pass "Tracing is activated ($DBCK_MEMTRACE)"
+	    send "$DBCK_MEMTRACE\n"
+	    continue -expect
+	}
+	-re "^MSG: init_cache: using datafile\.$nl" { 
+            pass "$test" 
+        }
     }
+
     set test "dbck sent second line"
     expect {
 	-re "^Read $any_num confs/persons and $any_num texts, eof at $any_num$nl" {
diff --git a/src/server/testsuite/lyskomd.0/11.exp b/src/server/testsuite/lyskomd.0/11.exp
index 035a8206f..8be53e6f2 100644
--- a/src/server/testsuite/lyskomd.0/11.exp
+++ b/src/server/testsuite/lyskomd.0/11.exp
@@ -30,7 +30,14 @@ lyskomd_start
 spawn ../dbck -d config/lyskomd-config
 set test "dbck started in read-only mode"
 expect {
-    -re "^MSG: init_cache: using datafile\.$nl" { pass "$test" }
+    -re "^Where does the trace want to go today. .stderr.$nl" {
+        pass "Tracing is activated (/dev/null)"
+        send "/dev/null\n"
+        continue -expect
+    }
+    -re "^MSG: init_cache: using datafile\.$nl" {
+        pass "$test" 
+    }
 }
 set test "read-only dbck sent second line"
 expect {
@@ -55,6 +62,11 @@ unset test
 spawn ../dbck -d -i config/lyskomd-config
 set test "dbck finds a lock"
 expect {
+    -re "^Where does the trace want to go today. .stderr.$nl" {
+        pass "Tracing is activated (/dev/null)"
+        send "/dev/null\n"
+        continue -expect
+    }
     -re "^Database already locked by $any*\.$nl" { pass "$test" }
 }
 set test "read-write dbck sent final line"
@@ -74,6 +86,11 @@ unset test
 spawn ../lyskomd -d config/lyskomd-config
 set test "lyskomd finds a lock"
 expect {
+    -re "^Where does the trace want to go today. .stderr.$nl" {
+        pass "Tracing is activated (/dev/null)"
+        send "/dev/null\n"
+        continue -expect
+    }
     -re "Database already locked by $any*:$lyskomd_pid$nl" { pass "$test" }
 }
 set test "lyskomd writes an exiting message."
@@ -111,6 +128,11 @@ expect {
 set new_pid [spawn ../lyskomd -d config/lyskomd-config]
 set test "stale lock file removed"
 expect {
+    -re "^Where does the trace want to go today. .stderr.$nl" {
+        pass "Tracing is activated (/dev/null)"
+        send "/dev/null\n"
+        continue -expect
+    }
     -re " $new_pid Removed stale lock file left by $any*:$lyskomd_pid\.$nl" {
 	pass "$test"
     }
@@ -135,6 +157,11 @@ system "ln -s inet.lysator.liu.se:4711 db/lyskomd-lock"
 spawn ../lyskomd -d config/lyskomd-config
 set test "remote lock file found"
 expect {
+    -re "^Where does the trace want to go today. .stderr.$nl" {
+        pass "Tracing is activated (/dev/null)"
+        send "/dev/null\n"
+        continue -expect
+    }
     -re "Database already locked by inet\.lysator\.liu\.se:4711$nl" {
 	pass "$test"
     }
diff --git a/src/server/testsuite/lyskomd.0/13.exp b/src/server/testsuite/lyskomd.0/13.exp
new file mode 100644
index 000000000..815584db9
--- /dev/null
+++ b/src/server/testsuite/lyskomd.0/13.exp
@@ -0,0 +1,102 @@
+# Test suite for lyskomd.
+# Copyright (C) 1999  Lysator Academic Computer Association.
+#
+# This file is part of the LysKOM server.
+# 
+# LysKOM is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by 
+# the Free Software Foundation; either version 1, or (at your option) 
+# any later version.
+# 
+# LysKOM is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with LysKOM; see the file COPYING.  If not, write to
+# Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN,
+# or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, 
+# MA 02139, USA.
+#
+# Please mail bug reports to bug-lyskom@lysator.liu.se. 
+
+read_versions
+source "$srcdir/config/prot-a.exp"
+
+lyskomd_start
+
+client_start 0
+kom_connect "DejaGnu Test Suite"
+kom_accept_async "0 { }"
+
+kom_login 5 "gazonk" 0
+
+kom_create_conference "Match 6" "00000000" "0 { }"
+kom_create_conference "Match 7" "00000000" "0 { }"
+kom_create_conference "Match 8" "00000000" "0 { }"
+
+send "1000 76 [holl "Match"] 1 1\n"
+simple_expect "=1000 3 { [holl "Match 6"] 0000 6 [holl "Match 7"] 0000 7 [holl "Match 8"] 0000 8 }"
+
+kom_create_conference "Match 9" "00000000" "0 { }"
+kom_create_conference "Junk 10" "00000000" "0 { }"
+
+send "1001 76 [holl "Match"] 1 1\n"
+simple_expect "=1001 4 { [holl "Match 6"] 0000 6 [holl "Match 7"] 0000 7 [holl "Match 8"] 0000 8 [holl "Match 9"] 0000 9 }"
+
+send "1002 3 6 [holl "Junk 6"]\n"
+simple_expect "=1002"
+
+send "1003 76 [holl "Match"] 1 1\n"
+simple_expect "=1003 3 { [holl "Match 7"] 0000 7 [holl "Match 8"] 0000 8 [holl "Match 9"] 0000 9 }"
+
+send "1004 3 8 [holl "Junk 8"]\n"
+simple_expect "=1004"
+
+send "1005 76 [holl "Match"] 1 1\n"
+simple_expect "=1005 2 { [holl "Match 7"] 0000 7 [holl "Match 9"] 0000 9 }"
+
+send "1006 3 7 [holl "Junk 7"]\n"
+simple_expect "=1006"
+
+send "1007 76 [holl "Match"] 1 1\n"
+simple_expect "=1007 1 { [holl "Match 9"] 0000 9 }"
+
+send "1008 76 [holl "Junk"] 1 1\n"
+simple_expect "=1008 4 { [holl "Junk 6"] 0000 6 [holl "Junk 7"] 0000 7 [holl "Junk 8"] 0000 8 [holl "Junk 10"] 0000 10 }"
+
+send "1009 11 6\n"
+simple_expect "=1009"
+
+send "1010 76 [holl "Match"] 1 1\n"
+simple_expect "=1010 1 { [holl "Match 9"] 0000 9 }"
+
+send "1011 11 9\n"
+simple_expect "=1011"
+
+send "1012 76 [holl "Junk"] 1 1\n"
+simple_expect "=1012 3 { [holl "Junk 7"] 0000 7 [holl "Junk 8"] 0000 8 [holl "Junk 10"] 0000 10 }"
+
+send "1013 76 [holl "Match"] 1 1\n"
+simple_expect "=1013 0 \\*"
+
+kom_create_conference "Junk 11" 00000000 "0 { }\n" 
+
+send "1014 76 [holl "Junk"] 1 1\n"
+simple_expect "=1014 4 { [holl "Junk 7"] 0000 7 [holl "Junk 8"] 0000 8 [holl "Junk 10"] 0000 10 [holl "Junk 11"] 0000 11 }"
+
+kom_create_conference "Match 12" 00000000 "0 { }\n"
+
+send "1015 76 [holl "Junk"] 1 1\n"
+simple_expect "=1015 4 { [holl "Junk 7"] 0000 7 [holl "Junk 8"] 0000 8 [holl "Junk 10"] 0000 10 [holl "Junk 11"] 0000 11 }"
+
+send "1016 76 [holl "Match"] 1 1\n"
+simple_expect "=1016 1 { [holl "Match 12"] 0000 12 }"
+
+kom_enable 255
+send "9999 44 0\n"
+simple_expect "=9999"
+client_death 0
+lyskomd_death
+
-- 
GitLab