commands and aliases go from horrible hashtable code to dictionary... try 1

This commit is contained in:
William Pitcock 2007-12-02 09:34:45 -06:00
parent c98390004f
commit 8ac7552983
4 changed files with 48 additions and 190 deletions

View file

@ -32,15 +32,6 @@
struct Message; struct Message;
struct Client; struct Client;
struct MessageHash
{
char *cmd;
struct Message *msg;
struct MessageHash *next;
};
#define MAX_MSG_HASH 387
extern void parse(struct Client *, char *, char *); extern void parse(struct Client *, char *, char *);
extern void handle_encap(struct Client *, struct Client *, extern void handle_encap(struct Client *, struct Client *,
const char *, int, const char *parv[]); const char *, int, const char *parv[]);
@ -49,6 +40,6 @@ extern void mod_add_cmd(struct Message *msg);
extern void mod_del_cmd(struct Message *msg); extern void mod_del_cmd(struct Message *msg);
extern void report_messages(struct Client *); extern void report_messages(struct Client *);
extern dlink_list alias_hash_table[MAX_MSG_HASH]; extern struct Dictionary *alias_dict;
#endif /* INCLUDED_parse_h_h */ #endif /* INCLUDED_parse_h_h */

View file

@ -1580,20 +1580,6 @@ conf_set_service_name(void *data)
target_p->flags |= FLAGS_SERVICE; target_p->flags |= FLAGS_SERVICE;
} }
static int
alias_hash(const char *p)
{
int hash_val = 0;
while (*p)
{
hash_val += ((int) (*p) & 0xDF);
p++;
}
return (hash_val % MAX_MSG_HASH);
}
static int static int
conf_begin_alias(struct TopConf *tc) conf_begin_alias(struct TopConf *tc)
{ {
@ -1611,8 +1597,6 @@ conf_begin_alias(struct TopConf *tc)
static int static int
conf_end_alias(struct TopConf *tc) conf_end_alias(struct TopConf *tc)
{ {
int hashval;
if (yy_alias == NULL) if (yy_alias == NULL)
return -1; return -1;
@ -1634,9 +1618,10 @@ conf_end_alias(struct TopConf *tc)
return -1; return -1;
} }
hashval = alias_hash(yy_alias->name); if (!alias_dict)
alias_dict = irc_dictionary_create(alias_dict);
dlinkAddAlloc(yy_alias, &alias_hash_table[hashval]); irc_dictionary_add(alias_dict, yy_alias->name, yy_alias);
return 0; return 0;
} }

View file

@ -1,10 +1,11 @@
/* /*
* ircd-ratbox: A slightly useful ircd. * charybdis: an advanced ircd.
* parse.c: The message parser. * parse.c: The message parser.
* *
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
* Copyright (C) 1996-2002 Hybrid Development Team * Copyright (C) 1996-2002 Hybrid Development Team
* Copyright (C) 2002-2005 ircd-ratbox development team * Copyright (C) 2002-2005 ircd-ratbox development team
* Copyright (C) 2007 William Pitcock
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -43,6 +44,9 @@
#include "s_serv.h" #include "s_serv.h"
#include "packet.h" #include "packet.h"
static struct Dictionary *cmd_dict = NULL;
struct Dictionary *alias_dict = NULL;
/* /*
* NOTE: parse() should not be called recursively by other functions! * NOTE: parse() should not be called recursively by other functions!
*/ */
@ -60,15 +64,9 @@ static void do_alias(struct alias_entry *, struct Client *, char *);
static int handle_command(struct Message *, struct Client *, struct Client *, int, const char**); static int handle_command(struct Message *, struct Client *, struct Client *, int, const char**);
static int cmd_hash(const char *p); static int cmd_hash(const char *p);
static struct Message *hash_parse(const char *);
static struct alias_entry *alias_parse(const char *);
struct MessageHash *msg_hash_table[MAX_MSG_HASH];
static char buffer[1024]; static char buffer[1024];
dlink_list alias_hash_table[MAX_MSG_HASH];
/* turn a string into a parc/parv pair */ /* turn a string into a parc/parv pair */
@ -220,7 +218,7 @@ parse(struct Client *client_p, char *pbuffer, char *bufend)
if((s = strchr(ch, ' '))) if((s = strchr(ch, ' ')))
*s++ = '\0'; *s++ = '\0';
mptr = hash_parse(ch); mptr = irc_dictionary_retrieve(cmd_dict, mptr);
/* no command or its encap only, error */ /* no command or its encap only, error */
if(!mptr || !mptr->cmd) if(!mptr || !mptr->cmd)
@ -240,7 +238,7 @@ parse(struct Client *client_p, char *pbuffer, char *bufend)
{ {
if (IsPerson(client_p)) if (IsPerson(client_p))
{ {
struct alias_entry *aptr = alias_parse(ch); struct alias_entry *aptr = irc_dictionary_retrieve(alias_dict, ch);
if (aptr != NULL) if (aptr != NULL)
{ {
do_alias(aptr, client_p, s); do_alias(aptr, client_p, s);
@ -391,7 +389,7 @@ handle_encap(struct Client *client_p, struct Client *source_p,
parv[0] = source_p->name; parv[0] = source_p->name;
mptr = hash_parse(command); mptr = irc_dictionary_retrieve(cmd_dict, command);
if(mptr == NULL || mptr->cmd == NULL) if(mptr == NULL || mptr->cmd == NULL)
return; return;
@ -418,7 +416,7 @@ handle_encap(struct Client *client_p, struct Client *source_p,
void void
clear_hash_parse() clear_hash_parse()
{ {
memset(msg_hash_table, 0, sizeof(msg_hash_table)); cmd_dict = irc_dictionary_create(strcasecmp);
} }
/* mod_add_cmd /* mod_add_cmd
@ -433,38 +431,18 @@ clear_hash_parse()
void void
mod_add_cmd(struct Message *msg) mod_add_cmd(struct Message *msg)
{ {
struct MessageHash *ptr;
struct MessageHash *last_ptr = NULL;
struct MessageHash *new_ptr;
int msgindex;
s_assert(msg != NULL); s_assert(msg != NULL);
if(msg == NULL) if(msg == NULL)
return; return;
msgindex = cmd_hash(msg->cmd); if (irc_dictionary_find(cmd_dict, msg->cmd) != NULL)
return;
for (ptr = msg_hash_table[msgindex]; ptr; ptr = ptr->next)
{
if(strcasecmp(msg->cmd, ptr->cmd) == 0)
return; /* Its already added */
last_ptr = ptr;
}
new_ptr = (struct MessageHash *) MyMalloc(sizeof(struct MessageHash));
new_ptr->next = NULL;
DupString(new_ptr->cmd, msg->cmd);
new_ptr->msg = msg;
msg->count = 0; msg->count = 0;
msg->rcount = 0; msg->rcount = 0;
msg->bytes = 0; msg->bytes = 0;
if(last_ptr == NULL) irc_dictionary_add(cmd_dict, msg->cmd, msg);
msg_hash_table[msgindex] = new_ptr;
else
last_ptr->next = new_ptr;
} }
/* mod_del_cmd /* mod_del_cmd
@ -476,101 +454,11 @@ mod_add_cmd(struct Message *msg)
void void
mod_del_cmd(struct Message *msg) mod_del_cmd(struct Message *msg)
{ {
struct MessageHash *ptr;
struct MessageHash *last_ptr = NULL;
int msgindex;
s_assert(msg != NULL); s_assert(msg != NULL);
if(msg == NULL) if(msg == NULL)
return; return;
msgindex = cmd_hash(msg->cmd); irc_dictionary_delete(cmd_dict, msg->cmd);
for (ptr = msg_hash_table[msgindex]; ptr; ptr = ptr->next)
{
if(strcasecmp(msg->cmd, ptr->cmd) == 0)
{
MyFree(ptr->cmd);
if(last_ptr != NULL)
last_ptr->next = ptr->next;
else
msg_hash_table[msgindex] = ptr->next;
MyFree(ptr);
return;
}
last_ptr = ptr;
}
}
/* hash_parse
*
* inputs - command name
* output - pointer to struct Message
* side effects -
*/
static struct Message *
hash_parse(const char *cmd)
{
struct MessageHash *ptr;
int msgindex;
msgindex = cmd_hash(cmd);
for (ptr = msg_hash_table[msgindex]; ptr; ptr = ptr->next)
{
if(strcasecmp(cmd, ptr->cmd) == 0)
return (ptr->msg);
}
return NULL;
}
/* alias_parse
*
* inputs - command name
* output - pointer to struct Message
* side effects -
*/
static struct alias_entry *
alias_parse(const char *cmd)
{
dlink_node *ptr;
int msgindex;
msgindex = cmd_hash(cmd);
DLINK_FOREACH(ptr, alias_hash_table[msgindex].head)
{
struct alias_entry *ent = (struct alias_entry *) ptr->data;
if(strcasecmp(cmd, ent->name) == 0)
return ent;
}
return NULL;
}
/*
* hash
*
* inputs - char string
* output - hash index
* side effects - NONE
*
* BUGS - This a HORRIBLE hash function
*/
static int
cmd_hash(const char *p)
{
int hash_val = 0;
while (*p)
{
hash_val += ((int) (*p) & 0xDF);
p++;
}
return (hash_val % MAX_MSG_HASH);
} }
/* /*
@ -583,33 +471,25 @@ cmd_hash(const char *p)
void void
report_messages(struct Client *source_p) report_messages(struct Client *source_p)
{ {
int i; struct DictionaryIter iter;
struct MessageHash *ptr; struct Message *msg;
dlink_node *pptr; struct alias_entry *amsg;
for (i = 0; i < MAX_MSG_HASH; i++) IRC_DICTIONARY_FOREACH(msg, &iter, cmd_dict)
{ {
for (ptr = msg_hash_table[i]; ptr; ptr = ptr->next) s_assert(msg->cmd != NULL);
{
s_assert(ptr->msg != NULL);
s_assert(ptr->cmd != NULL);
sendto_one_numeric(source_p, RPL_STATSCOMMANDS, sendto_one_numeric(source_p, RPL_STATSCOMMANDS,
form_str(RPL_STATSCOMMANDS), form_str(RPL_STATSCOMMANDS),
ptr->cmd, ptr->msg->count, msg->cmd, msg->count,
ptr->msg->bytes, ptr->msg->rcount); msg->bytes, msg->rcount);
} }
DLINK_FOREACH(pptr, alias_hash_table[i].head) IRC_DICTIONARY_FOREACH(amsg, &iter, alias_dict)
{ {
struct alias_entry *aptr = (struct alias_entry *) pptr->data; s_assert(amsg->name != NULL);
s_assert(aptr->name != NULL);
sendto_one_numeric(source_p, RPL_STATSCOMMANDS, sendto_one_numeric(source_p, RPL_STATSCOMMANDS,
form_str(RPL_STATSCOMMANDS), form_str(RPL_STATSCOMMANDS),
aptr->name, aptr->hits, 0, 0); amsg->name, amsg->hits, 0, 0);
}
} }
} }

View file

@ -1199,6 +1199,19 @@ read_conf_files(int cold)
fclose(conf_fbfile_in); fclose(conf_fbfile_in);
} }
/*
* free an alias{} entry.
*/
static void
free_alias_cb(struct DictionaryElement *ptr, void *unused)
{
struct alias_entry *aptr = ptr->data;
MyFree(aptr->name);
MyFree(aptr->target);
MyFree(aptr);
}
/* /*
* clear_out_old_conf * clear_out_old_conf
* *
@ -1269,19 +1282,8 @@ clear_out_old_conf(void)
} }
/* remove any aliases... -- nenolod */ /* remove any aliases... -- nenolod */
for (i = 0; i < MAX_MSG_HASH; i++) irc_dictionary_destroy(alias_dict, free_alias_cb, NULL);
{ alias_dict = NULL;
DLINK_FOREACH_SAFE(ptr, next_ptr, alias_hash_table[i].head)
{
struct alias_entry *aptr = ptr->data;
MyFree(aptr->name);
MyFree(aptr->target);
MyFree(aptr);
dlinkDestroy(ptr, &alias_hash_table[i]);
}
}
destroy_blacklists(); destroy_blacklists();