Commit 8c60d317 authored by David Byers's avatar David Byers

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.
parent 15a018fa
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
......
......@@ -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
......
/*
* $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 */
......
/*
* $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;
......
/*
* $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);
/*
* $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;
}
......
/*
* $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)
{
......
/*
* $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++ )