ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/whowas.c
Revision: 7437
Committed: Thu Mar 10 19:59:52 2016 UTC (9 years, 5 months ago) by michael
Content type: text/x-csrc
File size: 5875 byte(s)
Log Message:
- Change whowas system to use a linked list instead of othe this monolithic WHOWAS table
- Size of the whowas nick name history length is now configurable

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 *
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
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19 * USA
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 "send.h"
36 #include "conf.h"
37
38
39 static mp_pool_t *whowas_pool;
40
41 static dlink_list whowas_list; /*! Chain of struct Whowas pointers */
42 dlink_list WHOWASHASH[HASHSIZE];
43
44
45 /*! \brief Initializes the whowas memory pool
46 */
47 void
48 whowas_init(void)
49 {
50 whowas_pool = mp_pool_new(sizeof(struct Membership), MP_CHUNK_SIZE_WHOWAS);
51 }
52
53 /*! \brief Unlinks a Whowas struct from its associated lists.
54 * \param whowas Pointer to Whowas struct to be unlinked
55 */
56 static struct Whowas *
57 whowas_unlink(struct Whowas *whowas)
58 {
59 if (!whowas) /* Can be NULL. */
60 return NULL;
61
62 if (whowas->online)
63 dlinkDelete(&whowas->cnode, &whowas->online->whowas);
64
65 dlinkDelete(&whowas->tnode, &WHOWASHASH[whowas->hashv]);
66 dlinkDelete(&whowas->lnode, &whowas_list);
67
68 return whowas;
69 }
70
71 /*! \brief Unlinks a Whowas struct from its associated lists
72 * and returns memory back to the pooling allocator.
73 * \param whowas Pointer to Whowas struct to be unlinked and freed
74 */
75 static void
76 whowas_free(struct Whowas *whowas)
77 {
78 whowas_unlink(whowas);
79 mp_pool_release(whowas);
80 }
81
82 /*! \brief Returns a Whowas struct for further use. Either allocates
83 * a new one, or returns the oldest entry from the whowas_list
84 * if it ran over ConfigGeneral.whowas_history_length
85 */
86 static struct Whowas *
87 whowas_make(void)
88 {
89 struct Whowas *whowas;
90
91 if (dlink_list_length(&whowas_list) >= ConfigGeneral.whowas_history_length)
92 whowas = whowas_unlink(whowas_list.tail->data);
93 else
94 whowas = mp_pool_get(whowas_pool);
95
96 return whowas;
97 }
98
99 /*! \brief Trims the whowas_list if necessary until there are no
100 * more than ConfigGeneral.whowas_history_length Whowas
101 * struct items.
102 */
103 void
104 whowas_trim(void)
105 {
106 while (dlink_list_length(&whowas_list) >= ConfigGeneral.whowas_history_length)
107 {
108 if (!whowas_list.tail->data)
109 return; /* whowas_list is now empty. No more items can be freed. */
110
111 whowas_free(whowas_list.tail->data);
112 }
113 }
114
115 /*! \brief Adds the currently defined name of the client to history.
116 * Usually called before changing to a new name (nick).
117 * Client must be a fully registered user.
118 * \param client_p pointer to Client struct to add
119 * \param online either 1 if it's a nick change or 0 on client exit
120 */
121 void
122 whowas_add_history(struct Client *client_p, const int online)
123 {
124 struct Whowas *whowas = whowas_make();
125
126 if (!whowas) /* Can be NULL. */
127 return;
128
129 assert(IsClient(client_p));
130
131 whowas->hashv = strhash(client_p->name);
132 whowas->shide = IsHidden(client_p->servptr) != 0;
133 whowas->logoff = CurrentTime;
134
135 strlcpy(whowas->account, client_p->account, sizeof(whowas->account));
136 strlcpy(whowas->name, client_p->name, sizeof(whowas->name));
137 strlcpy(whowas->username, client_p->username, sizeof(whowas->username));
138 strlcpy(whowas->hostname, client_p->host, sizeof(whowas->hostname));
139 strlcpy(whowas->sockhost, client_p->sockhost, sizeof(whowas->sockhost));
140 strlcpy(whowas->realname, client_p->info, sizeof(whowas->realname));
141 strlcpy(whowas->servername, client_p->servptr->name, sizeof(whowas->servername));
142
143 if (online)
144 {
145 whowas->online = client_p;
146 dlinkAdd(whowas, &whowas->cnode, &client_p->whowas);
147 }
148 else
149 whowas->online = NULL;
150
151 dlinkAdd(whowas, &whowas->tnode, &WHOWASHASH[whowas->hashv]);
152 dlinkAdd(whowas, &whowas->lnode, &whowas_list);
153 }
154
155 /*! \brief This must be called when the client structure is about to
156 * be released. History mechanism keeps pointers to client
157 * structures and it must know when they cease to exist.
158 * \param client_p pointer to Client struct
159 */
160 void
161 whowas_off_history(struct Client *client_p)
162 {
163 while (client_p->whowas.head)
164 {
165 struct Whowas *whowas = client_p->whowas.head->data;
166
167 whowas->online = NULL;
168 dlinkDelete(&whowas->cnode, &client_p->whowas);
169 }
170 }
171
172 /*! \brief Returns the current client that was using the given
173 * nickname within the timelimit. Returns NULL, if no
174 * one found.
175 * \param name name of the nick
176 * \param timelimit maximum age for a client since log-off
177 */
178 struct Client *
179 whowas_get_history(const char *name, uintmax_t timelimit)
180 {
181 dlink_node *node = NULL;
182
183 timelimit = CurrentTime - timelimit;
184
185 DLINK_FOREACH(node, WHOWASHASH[strhash(name)].head)
186 {
187 struct Whowas *whowas = node->data;
188
189 if (whowas->logoff < timelimit)
190 continue;
191 if (irccmp(name, whowas->name))
192 continue;
193 return whowas->online;
194 }
195
196 return NULL;
197 }
198
199 /*! \brief For debugging. Counts allocated structures stored in whowas_list
200 */
201 void
202 whowas_count_memory(unsigned int *const count, size_t *const bytes)
203 {
204 (*count) = dlink_list_length(&whowas_list);
205 (*bytes) = dlink_list_length(&whowas_list) * sizeof(struct Whowas);
206 }

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision