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

Comparing ircd-hybrid/trunk/src/whowas.c (file contents):
Revision 1997 by michael, Sat May 11 17:35:07 2013 UTC vs.
Revision 8664 by michael, Thu Nov 22 14:26:32 2018 UTC

# Line 1 | Line 1
1   /*
2 < *  ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 < *  whowas.c: WHOWAS user cache.
2 > *  ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3   *
4 < *  Copyright (C) 2005 by the past and present ircd coders, and others.
4 > *  Copyright (c) 1997-2018 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 16 | Line 15
15   *
16   *  You should have received a copy of the GNU General Public License
17   *  along with this program; if not, write to the Free Software
18 < *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
18 > *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19   *  USA
20 < *
21 < *  $Id$
20 > */
21 >
22 > /*! \file whowas.c
23 > * \brief WHOWAS user cache.
24 > * \version $Id$
25   */
26  
27   #include "stdinc.h"
28   #include "list.h"
29 + #include "memory.h"
30   #include "whowas.h"
31   #include "client.h"
32   #include "hash.h"
33   #include "irc_string.h"
34   #include "ircd.h"
35 + #include "conf.h"
36  
37  
38 < static struct Whowas WHOWAS[NICKNAMEHISTORYLENGTH];
39 < dlink_list WHOWASHASH[HASHSIZE];
38 > static dlink_list whowas_list;  /*! Chain of struct Whowas pointers */
39 > static dlink_list whowas_hash[HASHSIZE];
40  
41  
42 < void
43 < whowas_init(void)
42 > /*! \brief Returns a slot of the whowas_hash by the hash value associated with it.
43 > * \param hashv Hash value.
44 > */
45 > const dlink_list *
46 > whowas_get_hash(unsigned int hashv)
47   {
48 <  unsigned int idx;
48 >  if (hashv >= HASHSIZE)
49 >    return NULL;
50  
51 <  for (idx = 0; idx < NICKNAMEHISTORYLENGTH; ++idx)
44 <    WHOWAS[idx].hashv = -1;
51 >  return &whowas_hash[hashv];
52   }
53  
54 < void
55 < add_history(struct Client *client_p, const int online)
54 > /*! \brief Unlinks a Whowas struct from its associated lists.
55 > * \param whowas Pointer to Whowas struct to be unlinked.
56 > */
57 > static struct Whowas *
58 > whowas_unlink(struct Whowas *whowas)
59   {
60 <  static unsigned int whowas_next = 0;
61 <  struct Whowas *who = &WHOWAS[whowas_next];
60 >  if (whowas->online)
61 >    dlinkDelete(&whowas->cnode, &whowas->online->whowas_list);
62  
63 <  assert(client_p && client_p->servptr);
63 >  dlinkDelete(&whowas->hnode, &whowas_hash[whowas->hashv]);
64 >  dlinkDelete(&whowas->lnode, &whowas_list);
65  
66 <  if (++whowas_next == NICKNAMEHISTORYLENGTH)
67 <    whowas_next = 0;
66 >  return whowas;
67 > }
68  
69 <  if (who->hashv != -1)
70 <  {
71 <    if (who->online)
72 <      dlinkDelete(&who->cnode, &who->online->whowas);
69 > /*! \brief Unlinks a Whowas struct from its associated lists
70 > *         and frees memory.
71 > * \param whowas Pointer to Whowas struct to be unlinked and freed.
72 > */
73 > static void
74 > whowas_free(struct Whowas *whowas)
75 > {
76 >  whowas_unlink(whowas);
77 >  xfree(whowas);
78 > }
79  
80 <    dlinkDelete(&who->tnode, &WHOWASHASH[who->hashv]);
81 <  }
80 > /*! \brief Returns a Whowas struct for further use. Either allocates
81 > *         a new one, or returns the oldest entry from the whowas_list
82 > *         if it ran over ConfigGeneral.whowas_history_length
83 > */
84 > static struct Whowas *
85 > whowas_make(void)
86 > {
87 >  struct Whowas *whowas;
88  
89 <  who->hashv = strhash(client_p->name);
90 <  who->logoff = CurrentTime;
89 >  if (dlink_list_length(&whowas_list) &&
90 >      dlink_list_length(&whowas_list) >= ConfigGeneral.whowas_history_length)
91 >    whowas = whowas_unlink(whowas_list.tail->data);  /* Re-use oldest item */
92 >  else
93 >    whowas = xcalloc(sizeof(*whowas));
94  
95 <  strlcpy(who->name, client_p->name, sizeof(who->name));
96 <  strlcpy(who->username, client_p->username, sizeof(who->username));
71 <  strlcpy(who->hostname, client_p->host, sizeof(who->hostname));
72 <  strlcpy(who->realname, client_p->info, sizeof(who->realname));
73 <  strlcpy(who->servername, client_p->servptr->name, sizeof(who->servername));
95 >  return whowas;
96 > }
97  
98 <  if (online)
98 > /*! \brief Trims the whowas_list if necessary until there are no
99 > *         more than ConfigGeneral.whowas_history_length Whowas
100 > *         struct items.
101 > */
102 > void
103 > whowas_trim(void)
104 > {
105 >  while (dlink_list_length(&whowas_list) &&
106 >         dlink_list_length(&whowas_list) >= ConfigGeneral.whowas_history_length)
107 >    whowas_free(whowas_list.tail->data);
108 > }
109 >
110 > /*! \brief Adds the currently defined name of the client to history.
111 > *         Usually called before changing to a new name (nick).
112 > *         Client must be a fully registered user.
113 > * \param client_p Pointer to Client struct to add to whowas history
114 > * \param online   Either 1 if it's a nick change or 0 on client exit
115 > */
116 > void
117 > whowas_add_history(struct Client *client_p, bool online)
118 > {
119 >  struct Whowas *whowas = whowas_make();
120 >
121 >  assert(IsClient(client_p));
122 >
123 >  whowas->hashv = strhash(client_p->name);
124 >  whowas->logoff = CurrentTime;
125 >  whowas->server_hidden = IsHidden(client_p->servptr) != 0;
126 >
127 >  strlcpy(whowas->account, client_p->account, sizeof(whowas->account));
128 >  strlcpy(whowas->name, client_p->name, sizeof(whowas->name));
129 >  strlcpy(whowas->username, client_p->username, sizeof(whowas->username));
130 >  strlcpy(whowas->hostname, client_p->host, sizeof(whowas->hostname));
131 >  strlcpy(whowas->realhost, client_p->realhost, sizeof(whowas->realhost));
132 >  strlcpy(whowas->sockhost, client_p->sockhost, sizeof(whowas->sockhost));
133 >  strlcpy(whowas->realname, client_p->info, sizeof(whowas->realname));
134 >  strlcpy(whowas->servername, client_p->servptr->name, sizeof(whowas->servername));
135 >
136 >  if (online == true)
137    {
138 <    who->online = client_p;
139 <    dlinkAdd(who, &who->cnode, &client_p->whowas);
138 >    whowas->online = client_p;
139 >    dlinkAdd(whowas, &whowas->cnode, &client_p->whowas_list);
140    }
141    else
142 <    who->online = NULL;
142 >    whowas->online = NULL;
143  
144 <  dlinkAdd(who, &who->tnode, &WHOWASHASH[who->hashv]);
144 >  dlinkAdd(whowas, &whowas->hnode, &whowas_hash[whowas->hashv]);
145 >  dlinkAdd(whowas, &whowas->lnode, &whowas_list);
146   }
147  
148 + /*! \brief This must be called when the client structure is about to
149 + *         be released. History mechanism keeps pointers to client
150 + *         structures and it must know when they cease to exist.
151 + * \param client_p Pointer to Client struct
152 + */
153   void
154 < off_history(struct Client *client_p)
154 > whowas_off_history(struct Client *client_p)
155   {
156 <  dlink_node *ptr = NULL, *ptr_next = NULL;
90 <
91 <  DLINK_FOREACH_SAFE(ptr, ptr_next, client_p->whowas.head)
156 >  while (client_p->whowas_list.head)
157    {
158 <    struct Whowas *temp = ptr->data;
158 >    struct Whowas *whowas = client_p->whowas_list.head->data;
159  
160 <    temp->online = NULL;
161 <    dlinkDelete(&temp->cnode, &client_p->whowas);
160 >    whowas->online = NULL;
161 >    dlinkDelete(&whowas->cnode, &client_p->whowas_list);
162    }
163   }
164  
165 + /*! \brief Returns the current client that was using the given
166 + *         nickname within the timelimit. Returns NULL, if no
167 + *         one found.
168 + * \param name      Name of the nick
169 + * \param timelimit Maximum age for a client since log-off
170 + */
171   struct Client *
172 < get_history(const char *nick, time_t timelimit)
172 > whowas_get_history(const char *name, uintmax_t timelimit)
173   {
174 <  dlink_node *ptr = NULL;
174 >  dlink_node *node;
175  
176    timelimit = CurrentTime - timelimit;
177  
178 <  DLINK_FOREACH(ptr, WHOWASHASH[strhash(nick)].head)
178 >  DLINK_FOREACH(node, whowas_hash[strhash(name)].head)
179    {
180 <    struct Whowas *temp = ptr->data;
180 >    struct Whowas *whowas = node->data;
181  
182 <    if (temp->logoff < timelimit)
182 >    if (whowas->logoff < timelimit)
183        continue;
184 <    if (irccmp(nick, temp->name))
184 >    if (irccmp(name, whowas->name))
185        continue;
186 <    return temp->online;
186 >    return whowas->online;
187    }
188  
189    return NULL;
190   }
191  
192 + /*! \brief For debugging. Counts allocated structures stored in whowas_list
193 + */
194   void
195 < count_whowas_memory(unsigned int *wwu, uint64_t *wwum)
195 > whowas_count_memory(unsigned int *const count, size_t *const bytes)
196   {
197 <  const struct Whowas *tmp;
198 <  int i;
126 <  unsigned int u = 0;
127 <  uint64_t um = 0;
128 <
129 <  /* count the number of used whowas structs in 'u'   */
130 <  /* count up the memory used of whowas structs in um */
131 <  for (i = 0, tmp = &WHOWAS[0]; i < NICKNAMEHISTORYLENGTH; ++i, ++tmp)
132 <  {
133 <    if (tmp->hashv != -1)
134 <    {
135 <      ++u;
136 <      um += sizeof(struct Whowas);
137 <    }
138 <  }
139 <
140 <  *wwu = u;
141 <  *wwum = um;
197 >  (*count) = dlink_list_length(&whowas_list);
198 >  (*bytes) = dlink_list_length(&whowas_list) * sizeof(struct Whowas);
199   }

Comparing ircd-hybrid/trunk/src/whowas.c (property svn:keywords):
Revision 1997 by michael, Sat May 11 17:35:07 2013 UTC vs.
Revision 8664 by michael, Thu Nov 22 14:26:32 2018 UTC

# Line 1 | Line 1
1 < Id Revision
1 > Id

Diff Legend

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