ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/hash.c
(Generate patch)

Comparing:
ircd-hybrid-8/src/hash.c (file contents), Revision 1309 by michael, Sun Mar 25 11:24:18 2012 UTC vs.
ircd-hybrid/trunk/src/hash.c (file contents), Revision 3347 by michael, Sun Apr 20 14:03:06 2014 UTC

# Line 1 | Line 1
1   /*
2 < *  ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 < *  hash.c: Maintains hashtables.
2 > *  ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3   *
4 < *  Copyright (C) 2002 by the past and present ircd coders, and others.
4 > *  Copyright (c) 1997-2014 ircd-hybrid development team
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
# Line 18 | Line 17
17   *  along with this program; if not, write to the Free Software
18   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
19   *  USA
20 < *
21 < *  $Id$
20 > */
21 >
22 > /*! \file hash.c
23 > * \brief Hash table management.
24 > * \version $Id$
25   */
26  
27   #include "stdinc.h"
28   #include "list.h"
27 – #include "balloc.h"
29   #include "conf.h"
30   #include "channel.h"
31   #include "channel_mode.h"
# Line 39 | Line 40
40   #include "numeric.h"
41   #include "send.h"
42   #include "memory.h"
43 + #include "mempool.h"
44   #include "dbuf.h"
45 < #include "s_user.h"
45 > #include "user.h"
46  
47  
48 < static BlockHeap *userhost_heap = NULL;
49 < static BlockHeap *namehost_heap = NULL;
48 < static struct UserHost *find_or_add_userhost(const char *);
48 > static mp_pool_t *userhost_pool = NULL;
49 > static mp_pool_t *namehost_pool = NULL;
50  
51   static unsigned int hashf_xor_key = 0;
52  
53   /* The actual hash tables, They MUST be of the same HASHSIZE, variable
54   * size tables could be supported but the rehash routine should also
55 < * rebuild the transformation maps, I kept the tables of equal size
55 > * rebuild the transformation maps, I kept the tables of equal size
56   * so that I can use one hash function.
57   */
58   static struct Client *idTable[HASHSIZE];
59   static struct Client *clientTable[HASHSIZE];
60   static struct Channel *channelTable[HASHSIZE];
61   static struct UserHost *userhostTable[HASHSIZE];
61 – static struct ResvChannel *resvchannelTable[HASHSIZE];
62  
63  
64   /* init_hash()
# Line 69 | Line 69 | static struct ResvChannel *resvchannelTa
69   *                functions and clear the tables
70   */
71   void
72 < init_hash(void)
72 > hash_init(void)
73   {
74 <  unsigned int i;
75 <
76 <  /* Default the userhost/namehost sizes to CLIENT_HEAP_SIZE for now,
77 <   * should be a good close approximation anyway
78 <   * - Dianora
79 <   */
80 <  userhost_heap = BlockHeapCreate("userhost", sizeof(struct UserHost), CLIENT_HEAP_SIZE);
81 <  namehost_heap = BlockHeapCreate("namehost", sizeof(struct NameHost), CLIENT_HEAP_SIZE);
74 >  userhost_pool = mp_pool_new(sizeof(struct UserHost), MP_CHUNK_SIZE_USERHOST);
75 >  namehost_pool = mp_pool_new(sizeof(struct NameHost), MP_CHUNK_SIZE_NAMEHOST);
76  
77    hashf_xor_key = genrand_int32() % 256;  /* better than nothing --adx */
78   }
# Line 96 | Line 90 | strhash(const char *name)
90    const unsigned char *p = (const unsigned char *)name;
91    unsigned int hval = FNV1_32_INIT;
92  
93 <  if (*p == '\0')
93 >  if (EmptyString(p))
94      return 0;
95    for (; *p != '\0'; ++p)
96    {
# Line 156 | Line 150 | hash_add_channel(struct Channel *chptr)
150   }
151  
152   void
159 – hash_add_resv(struct ResvChannel *chptr)
160 – {
161 –  unsigned int hashv = strhash(chptr->name);
162 –
163 –  chptr->hnext = resvchannelTable[hashv];
164 –  resvchannelTable[hashv] = chptr;
165 – }
166 –
167 – void
153   hash_add_userhost(struct UserHost *userhost)
154   {
155    unsigned int hashv = strhash(userhost->host);
# Line 194 | Line 179 | hash_del_id(struct Client *client_p)
179    unsigned int hashv = strhash(client_p->id);
180    struct Client *tmp = idTable[hashv];
181  
182 <  if (tmp != NULL)
182 >  if (tmp)
183    {
184      if (tmp == client_p)
185      {
# Line 225 | Line 210 | hash_del_client(struct Client *client_p)
210    unsigned int hashv = strhash(client_p->name);
211    struct Client *tmp = clientTable[hashv];
212  
213 <  if (tmp != NULL)
213 >  if (tmp)
214    {
215      if (tmp == client_p)
216      {
# Line 256 | Line 241 | hash_del_userhost(struct UserHost *userh
241    unsigned int hashv = strhash(userhost->host);
242    struct UserHost *tmp = userhostTable[hashv];
243  
244 <  if (tmp != NULL)
244 >  if (tmp)
245    {
246      if (tmp == userhost)
247      {
# Line 288 | Line 273 | hash_del_channel(struct Channel *chptr)
273    unsigned int hashv = strhash(chptr->chname);
274    struct Channel *tmp = channelTable[hashv];
275  
276 <  if (tmp != NULL)
276 >  if (tmp)
277    {
278      if (tmp == chptr)
279      {
# Line 307 | Line 292 | hash_del_channel(struct Channel *chptr)
292    }
293   }
294  
310 – void
311 – hash_del_resv(struct ResvChannel *chptr)
312 – {
313 –  unsigned int hashv = strhash(chptr->name);
314 –  struct ResvChannel *tmp = resvchannelTable[hashv];
315 –
316 –  if (tmp != NULL)
317 –  {
318 –    if (tmp == chptr)
319 –    {
320 –      resvchannelTable[hashv] = chptr->hnext;
321 –      chptr->hnext = chptr;
322 –    }
323 –    else
324 –    {
325 –      while (tmp->hnext != chptr)
326 –        if ((tmp = tmp->hnext) == NULL)
327 –          return;
328 –
329 –      tmp->hnext = tmp->hnext->hnext;
330 –      chptr->hnext = chptr;
331 –    }
332 –  }
333 – }
334 –
295   /* hash_find_client()
296   *
297   * inputs       - pointer to name
# Line 346 | Line 306 | hash_find_client(const char *name)
306    unsigned int hashv = strhash(name);
307    struct Client *client_p;
308  
309 <  if ((client_p = clientTable[hashv]) != NULL)
309 >  if ((client_p = clientTable[hashv]))
310    {
311      if (irccmp(name, client_p->name))
312      {
313        struct Client *prev;
314  
315 <      while (prev = client_p, (client_p = client_p->hnext) != NULL)
315 >      while (prev = client_p, (client_p = client_p->hnext))
316        {
317          if (!irccmp(name, client_p->name))
318          {
# Line 374 | Line 334 | hash_find_id(const char *name)
334    unsigned int hashv = strhash(name);
335    struct Client *client_p;
336  
337 <  if ((client_p = idTable[hashv]) != NULL)
337 >  if ((client_p = idTable[hashv]))
338    {
339      if (strcmp(name, client_p->id))
340      {
341        struct Client *prev;
342  
343 <      while (prev = client_p, (client_p = client_p->idhnext) != NULL)
343 >      while (prev = client_p, (client_p = client_p->idhnext))
344        {
345          if (!strcmp(name, client_p->id))
346          {
# Line 403 | Line 363 | hash_find_server(const char *name)
363    struct Client *client_p = NULL;
364  
365    if (IsDigit(*name) && strlen(name) == IRC_MAXSID)
366 <    client_p = hash_find_id(name);
366 >    return hash_find_id(name);
367  
368 <  if ((client_p == NULL) && (client_p = clientTable[hashv]) != NULL)
368 >  if ((client_p = clientTable[hashv]))
369    {
370      if ((!IsServer(client_p) && !IsMe(client_p)) ||
371          irccmp(name, client_p->name))
372      {
373        struct Client *prev;
374  
375 <      while (prev = client_p, (client_p = client_p->hnext) != NULL)
375 >      while (prev = client_p, (client_p = client_p->hnext))
376        {
377          if ((IsServer(client_p) || IsMe(client_p)) &&
378              !irccmp(name, client_p->name))
# Line 433 | Line 393 | hash_find_server(const char *name)
393   *
394   * inputs       - pointer to name
395   * output       - NONE
396 < * side effects - New semantics: finds a channel whose name is 'name',
396 > * side effects - New semantics: finds a channel whose name is 'name',
397   *                if can't find one returns NULL, if can find it moves
398   *                it to the top of the list and returns it.
399   */
# Line 443 | Line 403 | hash_find_channel(const char *name)
403    unsigned int hashv = strhash(name);
404    struct Channel *chptr = NULL;
405  
406 <  if ((chptr = channelTable[hashv]) != NULL)
406 >  if ((chptr = channelTable[hashv]))
407    {
408      if (irccmp(name, chptr->chname))
409      {
410        struct Channel *prev;
411  
412 <      while (prev = chptr, (chptr = chptr->hnextch) != NULL)
412 >      while (prev = chptr, (chptr = chptr->hnextch))
413        {
414          if (!irccmp(name, chptr->chname))
415          {
# Line 496 | Line 456 | hash_get_bucket(int type, unsigned int h
456      case HASH_TYPE_USERHOST:
457        return userhostTable[hashv];
458        break;
499 –    case HASH_TYPE_RESERVED:
500 –      return resvchannelTable[hashv];
501 –      break;
459      default:
460        assert(0);
461    }
# Line 506 | Line 463 | hash_get_bucket(int type, unsigned int h
463    return NULL;
464   }
465  
509 – /* hash_find_resv()
510 – *
511 – * inputs       - pointer to name
512 – * output       - NONE
513 – * side effects - New semantics: finds a reserved channel whose name is 'name',
514 – *                if can't find one returns NULL, if can find it moves
515 – *                it to the top of the list and returns it.
516 – */
517 – struct ResvChannel *
518 – hash_find_resv(const char *name)
519 – {
520 –  unsigned int hashv = strhash(name);
521 –  struct ResvChannel *chptr;
522 –
523 –  if ((chptr = resvchannelTable[hashv]) != NULL)
524 –  {
525 –    if (irccmp(name, chptr->name))
526 –    {
527 –      struct ResvChannel *prev;
528 –
529 –      while (prev = chptr, (chptr = chptr->hnext) != NULL)
530 –      {
531 –        if (!irccmp(name, chptr->name))
532 –        {
533 –          prev->hnext = chptr->hnext;
534 –          chptr->hnext = resvchannelTable[hashv];
535 –          resvchannelTable[hashv] = chptr;
536 –          break;
537 –        }
538 –      }
539 –    }
540 –  }
541 –
542 –  return chptr;
543 – }
544 –
466   struct UserHost *
467   hash_find_userhost(const char *host)
468   {
# Line 554 | Line 475 | hash_find_userhost(const char *host)
475      {
476        struct UserHost *prev;
477  
478 <      while (prev = userhost, (userhost = userhost->next) != NULL)
478 >      while (prev = userhost, (userhost = userhost->next))
479        {
480          if (!irccmp(host, userhost->host))
481          {
# Line 582 | Line 503 | hash_find_userhost(const char *host)
503   * side effects -
504   */
505   void
506 < count_user_host(const char *user, const char *host, int *global_p,
507 <                int *local_p, int *icount_p)
506 > count_user_host(const char *user, const char *host, unsigned int *global_p,
507 >                unsigned int *local_p, unsigned int *icount_p)
508   {
509    dlink_node *ptr;
510    struct UserHost *found_userhost;
# Line 598 | Line 519 | count_user_host(const char *user, const
519  
520      if (!irccmp(user, nameh->name))
521      {
522 <      if (global_p != NULL)
522 >      if (global_p)
523          *global_p = nameh->gcount;
524 <      if (local_p != NULL)
524 >      if (local_p)
525          *local_p  = nameh->lcount;
526 <      if (icount_p != NULL)
526 >      if (icount_p)
527          *icount_p = nameh->icount;
528        return;
529      }
530    }
531   }
532  
533 + /* find_or_add_userhost()
534 + *
535 + * inputs       - host name
536 + * output       - none
537 + * side effects - find UserHost * for given host name
538 + */
539 + static struct UserHost *
540 + find_or_add_userhost(const char *host)
541 + {
542 +  struct UserHost *userhost = NULL;
543 +
544 +  if ((userhost = hash_find_userhost(host)))
545 +    return userhost;
546 +
547 +  userhost = mp_pool_get(userhost_pool);
548 +
549 +  memset(userhost, 0, sizeof(*userhost));
550 +  strlcpy(userhost->host, host, sizeof(userhost->host));
551 +  hash_add_userhost(userhost);
552 +
553 +  return userhost;
554 + }
555 +
556   /* add_user_host()
557   *
558   * inputs       - user name
# Line 641 | Line 585 | add_user_host(const char *user, const ch
585      if (!irccmp(user, nameh->name))
586      {
587        nameh->gcount++;
588 +
589        if (!global)
590        {
591 <        if (hasident)
592 <          nameh->icount++;
593 <        nameh->lcount++;
591 >        if (hasident)
592 >          nameh->icount++;
593 >        nameh->lcount++;
594        }
595 +
596        return;
597      }
598    }
599  
600 <  nameh = BlockHeapAlloc(namehost_heap);
600 >  nameh = mp_pool_get(namehost_pool);
601 >  memset(nameh, 0, sizeof(*nameh));
602    strlcpy(nameh->name, user, sizeof(nameh->name));
603  
604    nameh->gcount = 1;
605 +
606    if (!global)
607    {
608      if (hasident)
# Line 676 | Line 624 | add_user_host(const char *user, const ch
624   void
625   delete_user_host(const char *user, const char *host, int global)
626   {
627 <  dlink_node *ptr = NULL, *next_ptr = NULL;
628 <  struct UserHost *found_userhost;
629 <  struct NameHost *nameh;
682 <  int hasident = 1;
627 >  dlink_node *ptr = NULL;
628 >  struct UserHost *found_userhost = NULL;
629 >  unsigned int hasident = 1;
630  
631    if (*user == '~')
632    {
# Line 690 | Line 637 | delete_user_host(const char *user, const
637    if ((found_userhost = hash_find_userhost(host)) == NULL)
638      return;
639  
640 <  DLINK_FOREACH_SAFE(ptr, next_ptr, found_userhost->list.head)
640 >  DLINK_FOREACH(ptr, found_userhost->list.head)
641    {
642 <    nameh = ptr->data;
642 >    struct NameHost *nameh = ptr->data;
643  
644      if (!irccmp(user, nameh->name))
645      {
# Line 700 | Line 647 | delete_user_host(const char *user, const
647          nameh->gcount--;
648        if (!global)
649        {
650 <        if (nameh->lcount > 0)
651 <          nameh->lcount--;
652 <        if (hasident && nameh->icount > 0)
653 <          nameh->icount--;
650 >        if (nameh->lcount > 0)
651 >          nameh->lcount--;
652 >        if (hasident && nameh->icount > 0)
653 >          nameh->icount--;
654        }
655  
656        if (nameh->gcount == 0 && nameh->lcount == 0)
657        {
658 <        dlinkDelete(&nameh->node, &found_userhost->list);
659 <        BlockHeapFree(namehost_heap, nameh);
658 >        dlinkDelete(&nameh->node, &found_userhost->list);
659 >        mp_pool_release(nameh);
660        }
661  
662        if (dlink_list_length(&found_userhost->list) == 0)
663        {
664 <        hash_del_userhost(found_userhost);
665 <        BlockHeapFree(userhost_heap, found_userhost);
664 >        hash_del_userhost(found_userhost);
665 >        mp_pool_release(found_userhost);
666        }
667  
668        return;
# Line 723 | Line 670 | delete_user_host(const char *user, const
670    }
671   }
672  
726 – /* find_or_add_userhost()
727 – *
728 – * inputs       - host name
729 – * output       - none
730 – * side effects - find UserHost * for given host name
731 – */
732 – static struct UserHost *
733 – find_or_add_userhost(const char *host)
734 – {
735 –  struct UserHost *userhost;
736 –
737 –  if ((userhost = hash_find_userhost(host)) != NULL)
738 –    return userhost;
739 –
740 –  userhost = BlockHeapAlloc(userhost_heap);
741 –  strlcpy(userhost->host, host, sizeof(userhost->host));
742 –  hash_add_userhost(userhost);
743 –
744 –  return userhost;
745 – }
746 –
673   /*
674   * Safe list code.
675   *
# Line 767 | Line 693 | find_or_add_userhost(const char *host)
693   * Sendq limit is fairly conservative at 1/2 (In original anyway)
694   */
695   static int
696 < exceeding_sendq(struct Client *to)
696 > exceeding_sendq(const struct Client *to)
697   {
698 <  if (dbuf_length(&to->localClient->buf_sendq) > (get_sendq(to) / 2))
698 >  if (dbuf_length(&to->localClient->buf_sendq) > (get_sendq(&to->localClient->confs) / 2))
699      return 1;
700    else
701      return 0;
702   }
703  
704   void
705 < free_list_task(struct ListTask *lt, struct Client *source_p)
705 > free_list_task(struct Client *source_p)
706   {
707 <  dlink_node *dl, *dln;
707 >  struct ListTask *lt = source_p->localClient->list_task;
708 >  dlink_node *ptr = NULL, *ptr_next = NULL;
709  
710 <  if ((dl = dlinkFindDelete(&listing_client_list, source_p)) != NULL)
711 <    free_dlink_node(dl);
710 >  if ((ptr = dlinkFindDelete(&listing_client_list, source_p)))
711 >    free_dlink_node(ptr);
712  
713 <  DLINK_FOREACH_SAFE(dl, dln, lt->show_mask.head)
713 >  DLINK_FOREACH_SAFE(ptr, ptr_next, lt->show_mask.head)
714    {
715 <    MyFree(dl->data);
716 <    free_dlink_node(dl);
715 >    MyFree(ptr->data);
716 >    free_dlink_node(ptr);
717    }
718  
719 <  DLINK_FOREACH_SAFE(dl, dln, lt->hide_mask.head)
719 >  DLINK_FOREACH_SAFE(ptr, ptr_next, lt->hide_mask.head)
720    {
721 <    MyFree(dl->data);
722 <    free_dlink_node(dl);
721 >    MyFree(ptr->data);
722 >    free_dlink_node(ptr);
723    }
724  
725    MyFree(lt);
# Line 810 | Line 737 | free_list_task(struct ListTask *lt, stru
737   * side effects -
738   */
739   static int
740 < list_allow_channel(const char *chname, struct ListTask *lt)
740 > list_allow_channel(const char *chname, const struct ListTask *lt)
741   {
742 <  dlink_node *dl = NULL;
742 >  const dlink_node *ptr = NULL;
743  
744 <  DLINK_FOREACH(dl, lt->show_mask.head)
745 <    if (!match_chan(dl->data, chname))
744 >  DLINK_FOREACH(ptr, lt->show_mask.head)
745 >    if (match(ptr->data, chname) != 0)
746        return 0;
747  
748 <  DLINK_FOREACH(dl, lt->hide_mask.head)
749 <    if (match_chan(dl->data, chname))
748 >  DLINK_FOREACH(ptr, lt->hide_mask.head)
749 >    if (match(ptr->data, chname) == 0)
750        return 0;
751  
752    return 1;
# Line 834 | Line 761 | list_allow_channel(const char *chname, s
761   * side effects -
762   */
763   static void
764 < list_one_channel(struct Client *source_p, struct Channel *chptr,
838 <                 struct ListTask *list_task)
764 > list_one_channel(struct Client *source_p, struct Channel *chptr)
765   {
766 <  if (SecretChannel(chptr) && !IsMember(source_p, chptr))
766 >  struct ListTask *lt = source_p->localClient->list_task;
767 >  char listbuf[MODEBUFLEN] = "";
768 >  char modebuf[MODEBUFLEN] = "";
769 >  char parabuf[MODEBUFLEN] = "";
770 >
771 >  if (SecretChannel(chptr) &&
772 >      !(IsMember(source_p, chptr) || HasUMode(source_p, UMODE_ADMIN)))
773      return;
774 <  if (dlink_list_length(&chptr->members) < list_task->users_min ||
775 <      dlink_list_length(&chptr->members) > list_task->users_max ||
774 >  if (dlink_list_length(&chptr->members) < lt->users_min ||
775 >      dlink_list_length(&chptr->members) > lt->users_max ||
776        (chptr->channelts != 0 &&
777 <       ((unsigned int)chptr->channelts < list_task->created_min ||
778 <        (unsigned int)chptr->channelts > list_task->created_max)) ||
779 <      (unsigned int)chptr->topic_time < list_task->topicts_min ||
777 >       ((unsigned int)chptr->channelts < lt->created_min ||
778 >        (unsigned int)chptr->channelts > lt->created_max)) ||
779 >      (unsigned int)chptr->topic_time < lt->topicts_min ||
780        (chptr->topic_time ? (unsigned int)chptr->topic_time : UINT_MAX) >
781 <      list_task->topicts_max)
781 >      lt->topicts_max)
782      return;
783  
784 <  if (!list_allow_channel(chptr->chname, list_task))
784 >  if (!list_allow_channel(chptr->chname, lt))
785      return;
786 <  sendto_one(source_p, form_str(RPL_LIST), me.name, source_p->name,
787 <             chptr->chname, dlink_list_length(&chptr->members),
788 <             chptr->topic);
786 >
787 >  if (HasUMode(source_p, UMODE_ADMIN))
788 >  {
789 >    channel_modes(chptr, source_p, modebuf, parabuf);
790 >
791 >    if (chptr->topic[0])
792 >      snprintf(listbuf, sizeof(listbuf), "[%s] ", modebuf);
793 >    else
794 >      snprintf(listbuf, sizeof(listbuf), "[%s]",  modebuf);
795 >  }
796 >
797 >  sendto_one_numeric(source_p, &me, RPL_LIST, chptr->chname,
798 >                     dlink_list_length(&chptr->members),
799 >                     listbuf, chptr->topic);
800   }
801  
802   /* safe_list_channels()
# Line 871 | Line 814 | list_one_channel(struct Client *source_p
814   * - Dianora
815   */
816   void
817 < safe_list_channels(struct Client *source_p, struct ListTask *list_task,
875 <                   int only_unmasked_channels)
817 > safe_list_channels(struct Client *source_p, int only_unmasked_channels)
818   {
819 +  struct ListTask *lt = source_p->localClient->list_task;
820    struct Channel *chptr = NULL;
821  
822    if (!only_unmasked_channels)
823    {
824 <    unsigned int i;
882 <
883 <    for (i = list_task->hash_index; i < HASHSIZE; ++i)
824 >    for (unsigned int i = lt->hash_index; i < HASHSIZE; ++i)
825      {
826 <      if (exceeding_sendq(source_p->from))
826 >      if (exceeding_sendq(source_p))
827        {
828 <        list_task->hash_index = i;
829 <        return;    /* still more to do */
828 >        lt->hash_index = i;
829 >        return;  /* Still more to do */
830        }
831  
832        for (chptr = channelTable[i]; chptr; chptr = chptr->hnextch)
833 <        list_one_channel(source_p, chptr, list_task);
833 >        list_one_channel(source_p, chptr);
834      }
835    }
836    else
837    {
838 <    dlink_node *dl;
838 >    dlink_node *ptr = NULL;
839  
840 <    DLINK_FOREACH(dl, list_task->show_mask.head)
841 <      if ((chptr = hash_find_channel(dl->data)) != NULL)
842 <        list_one_channel(source_p, chptr, list_task);
840 >    DLINK_FOREACH(ptr, lt->show_mask.head)
841 >      if ((chptr = hash_find_channel(ptr->data)))
842 >        list_one_channel(source_p, chptr);
843    }
844  
845 <  free_list_task(list_task, source_p);
846 <  sendto_one(source_p, form_str(RPL_LISTEND),
906 <             me.name, source_p->name);
845 >  free_list_task(source_p);
846 >  sendto_one_numeric(source_p, &me, RPL_LISTEND);
847   }

Diff Legend

– Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)