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

Comparing:
ircd-hybrid/trunk/src/whowas.c (file contents), Revision 1857 by michael, Wed Apr 24 20:47:21 2013 UTC vs.
ircd-hybrid/branches/8.2.x/src/whowas.c (file contents), Revision 7796 by michael, Tue Oct 18 17:26:37 2016 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-2016 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 "mempool.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 mp_pool_t *whowas_pool;
39  
40 < static struct Whowas WHOWAS[NICKNAMEHISTORYLENGTH];
41 < dlink_list WHOWASHASH[HASHSIZE];
40 > static dlink_list whowas_list;  /*! Chain of struct Whowas pointers */
41 > static dlink_list whowas_hash[HASHSIZE];
42  
43  
44 + /*! \brief Initializes the whowas memory pool.
45 + */
46   void
47 < add_history(struct Client *client_p, const int online)
47 > whowas_init(void)
48   {
49 <  static unsigned int whowas_next = 0;
50 <  struct Whowas *who = &WHOWAS[whowas_next];
49 >  whowas_pool = mp_pool_new(sizeof(struct Whowas), MP_CHUNK_SIZE_WHOWAS);
50 > }
51  
52 <  assert(client_p && client_p->servptr);
52 > /*! \brief Returns a slot of the whowas_hash by the hash value associated with it.
53 > * \param hashv Hash value.
54 > */
55 > const dlink_list *
56 > whowas_get_hash(unsigned int hashv)
57 > {
58 >  if (hashv >= HASHSIZE)
59 >    return NULL;
60  
61 <  if (++whowas_next == NICKNAMEHISTORYLENGTH)
62 <    whowas_next = 0;
61 >  return &whowas_hash[hashv];
62 > }
63  
64 <  if (who->hashv != -1)
65 <  {
66 <    if (who->online)
67 <      dlinkDelete(&who->cnode, &who->online->whowas);
64 > /*! \brief Unlinks a Whowas struct from its associated lists.
65 > * \param whowas Pointer to Whowas struct to be unlinked.
66 > */
67 > static struct Whowas *
68 > whowas_unlink(struct Whowas *whowas)
69 > {
70 >  if (whowas->online)
71 >    dlinkDelete(&whowas->cnode, &whowas->online->whowas_list);
72  
73 <    dlinkDelete(&who->tnode, &WHOWASHASH[who->hashv]);
74 <  }
73 >  dlinkDelete(&whowas->hnode, &whowas_hash[whowas->hashv]);
74 >  dlinkDelete(&whowas->lnode, &whowas_list);
75 >
76 >  return whowas;
77 > }
78 >
79 > /*! \brief Unlinks a Whowas struct from its associated lists
80 > *         and returns memory back to the pooling allocator.
81 > * \param whowas Pointer to Whowas struct to be unlinked and freed.
82 > */
83 > static void
84 > whowas_free(struct Whowas *whowas)
85 > {
86 >  whowas_unlink(whowas);
87 >  mp_pool_release(whowas);
88 > }
89 >
90 > /*! \brief Returns a Whowas struct for further use. Either allocates
91 > *         a new one, or returns the oldest entry from the whowas_list
92 > *         if it ran over ConfigGeneral.whowas_history_length
93 > */
94 > static struct Whowas *
95 > whowas_make(void)
96 > {
97 >  struct Whowas *whowas;
98  
99 <  who->hashv = strhash(client_p->name);
100 <  who->logoff = CurrentTime;
99 >  if (dlink_list_length(&whowas_list) &&
100 >      dlink_list_length(&whowas_list) >= ConfigGeneral.whowas_history_length)
101 >    whowas = whowas_unlink(whowas_list.tail->data);  /* Re-use oldest item */
102 >  else
103 >    whowas = mp_pool_get(whowas_pool);
104  
105 <  strlcpy(who->name, client_p->name, sizeof(who->name));
106 <  strlcpy(who->username, client_p->username, sizeof(who->username));
107 <  strlcpy(who->hostname, client_p->host, sizeof(who->hostname));
108 <  strlcpy(who->realname, client_p->info, sizeof(who->realname));
109 <  strlcpy(who->servername, client_p->servptr->name, sizeof(who->servername));
105 >  return whowas;
106 > }
107 >
108 > /*! \brief Trims the whowas_list if necessary until there are no
109 > *         more than ConfigGeneral.whowas_history_length Whowas
110 > *         struct items.
111 > */
112 > void
113 > whowas_trim(void)
114 > {
115 >  while (dlink_list_length(&whowas_list) &&
116 >         dlink_list_length(&whowas_list) >= ConfigGeneral.whowas_history_length)
117 >    whowas_free(whowas_list.tail->data);
118 > }
119 >
120 > /*! \brief Adds the currently defined name of the client to history.
121 > *         Usually called before changing to a new name (nick).
122 > *         Client must be a fully registered user.
123 > * \param client_p Pointer to Client struct to add to whowas history
124 > * \param online   Either 1 if it's a nick change or 0 on client exit
125 > */
126 > void
127 > whowas_add_history(struct Client *client_p, const int online)
128 > {
129 >  struct Whowas *whowas = whowas_make();
130 >
131 >  assert(IsClient(client_p));
132 >
133 >  whowas->hashv = strhash(client_p->name);
134 >  whowas->shide = IsHidden(client_p->servptr) != 0;
135 >  whowas->logoff = CurrentTime;
136 >
137 >  strlcpy(whowas->account, client_p->account, sizeof(whowas->account));
138 >  strlcpy(whowas->name, client_p->name, sizeof(whowas->name));
139 >  strlcpy(whowas->username, client_p->username, sizeof(whowas->username));
140 >  strlcpy(whowas->hostname, client_p->host, sizeof(whowas->hostname));
141 >  strlcpy(whowas->sockhost, client_p->sockhost, sizeof(whowas->sockhost));
142 >  strlcpy(whowas->realname, client_p->info, sizeof(whowas->realname));
143 >  strlcpy(whowas->servername, client_p->servptr->name, sizeof(whowas->servername));
144  
145    if (online)
146    {
147 <    who->online = client_p;
148 <    dlinkAdd(who, &who->cnode, &client_p->whowas);
147 >    whowas->online = client_p;
148 >    dlinkAdd(whowas, &whowas->cnode, &client_p->whowas_list);
149    }
150    else
151 <    who->online = NULL;
151 >    whowas->online = NULL;
152  
153 <  dlinkAdd(who, &who->tnode, &WHOWASHASH[who->hashv]);
153 >  dlinkAdd(whowas, &whowas->hnode, &whowas_hash[whowas->hashv]);
154 >  dlinkAdd(whowas, &whowas->lnode, &whowas_list);
155   }
156  
157 + /*! \brief This must be called when the client structure is about to
158 + *         be released. History mechanism keeps pointers to client
159 + *         structures and it must know when they cease to exist.
160 + * \param client_p Pointer to Client struct
161 + */
162   void
163 < off_history(struct Client *client_p)
163 > whowas_off_history(struct Client *client_p)
164   {
165 <  dlink_node *ptr = NULL, *ptr_next = NULL;
81 <
82 <  DLINK_FOREACH_SAFE(ptr, ptr_next, client_p->whowas.head)
165 >  while (client_p->whowas_list.head)
166    {
167 <    struct Whowas *temp = ptr->data;
167 >    struct Whowas *whowas = client_p->whowas_list.head->data;
168  
169 <    temp->online = NULL;
170 <    dlinkDelete(&temp->cnode, &client_p->whowas);
169 >    whowas->online = NULL;
170 >    dlinkDelete(&whowas->cnode, &client_p->whowas_list);
171    }
172   }
173  
174 + /*! \brief Returns the current client that was using the given
175 + *         nickname within the timelimit. Returns NULL, if no
176 + *         one found.
177 + * \param name      Name of the nick
178 + * \param timelimit Maximum age for a client since log-off
179 + */
180   struct Client *
181 < get_history(const char *nick, time_t timelimit)
181 > whowas_get_history(const char *name, uintmax_t timelimit)
182   {
183 <  dlink_node *ptr = NULL;
183 >  dlink_node *node;
184  
185    timelimit = CurrentTime - timelimit;
186  
187 <  DLINK_FOREACH(ptr, WHOWASHASH[strhash(nick)].head)
187 >  DLINK_FOREACH(node, whowas_hash[strhash(name)].head)
188    {
189 <    struct Whowas *temp = ptr->data;
189 >    struct Whowas *whowas = node->data;
190  
191 <    if (temp->logoff < timelimit)
191 >    if (whowas->logoff < timelimit)
192        continue;
193 <    if (irccmp(nick, temp->name))
193 >    if (irccmp(name, whowas->name))
194        continue;
195 <    return temp->online;
195 >    return whowas->online;
196    }
197  
198    return NULL;
199   }
200  
201 + /*! \brief For debugging. Counts allocated structures stored in whowas_list
202 + */
203   void
204 < count_whowas_memory(unsigned int *wwu, uint64_t *wwum)
114 < {
115 <  const struct Whowas *tmp;
116 <  int i;
117 <  unsigned int u = 0;
118 <  uint64_t um = 0;
119 <
120 <  /* count the number of used whowas structs in 'u'   */
121 <  /* count up the memory used of whowas structs in um */
122 <  for (i = 0, tmp = &WHOWAS[0]; i < NICKNAMEHISTORYLENGTH; ++i, ++tmp)
123 <  {
124 <    if (tmp->hashv != -1)
125 <    {
126 <      ++u;
127 <      um += sizeof(struct Whowas);
128 <    }
129 <  }
130 <
131 <  *wwu = u;
132 <  *wwum = um;
133 < }
134 <
135 < void
136 < whowas_init(void)
204 > whowas_count_memory(unsigned int *const count, size_t *const bytes)
205   {
206 <  unsigned int idx;
207 <
140 <  for (idx = 0; idx < NICKNAMEHISTORYLENGTH; ++idx)
141 <    WHOWAS[idx].hashv = -1;
206 >  (*count) = dlink_list_length(&whowas_list);
207 >  (*bytes) = dlink_list_length(&whowas_list) * sizeof(struct Whowas);
208   }

Comparing:
ircd-hybrid/trunk/src/whowas.c (property svn:keywords), Revision 1857 by michael, Wed Apr 24 20:47:21 2013 UTC vs.
ircd-hybrid/branches/8.2.x/src/whowas.c (property svn:keywords), Revision 7796 by michael, Tue Oct 18 17:26:37 2016 UTC

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

Diff Legend

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