ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/whowas.c
Revision: 7495
Committed: Mon Mar 21 20:03:46 2016 UTC (9 years, 5 months ago) by michael
Content type: text/x-csrc
File size: 6111 byte(s)
Log Message:
- whowas.c:whowas_trim(): use dlink_list_length

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 "conf.h"
36
37
38 static mp_pool_t *whowas_pool;
39
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 whowas_init(void)
48 {
49 whowas_pool = mp_pool_new(sizeof(struct Whowas), MP_CHUNK_SIZE_WHOWAS);
50 }
51
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 return &whowas_hash[hashv];
62 }
63
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) /* Can be NULL. */
71 return NULL;
72
73 if (whowas->online)
74 dlinkDelete(&whowas->cnode, &whowas->online->whowas_list);
75
76 dlinkDelete(&whowas->hnode, &whowas_hash[whowas->hashv]);
77 dlinkDelete(&whowas->lnode, &whowas_list);
78
79 return whowas;
80 }
81
82 /*! \brief Unlinks a Whowas struct from its associated lists
83 * and returns memory back to the pooling allocator.
84 * \param whowas Pointer to Whowas struct to be unlinked and freed.
85 */
86 static void
87 whowas_free(struct Whowas *whowas)
88 {
89 whowas_unlink(whowas);
90 mp_pool_release(whowas);
91 }
92
93 /*! \brief Returns a Whowas struct for further use. Either allocates
94 * a new one, or returns the oldest entry from the whowas_list
95 * if it ran over ConfigGeneral.whowas_history_length
96 */
97 static struct Whowas *
98 whowas_make(void)
99 {
100 struct Whowas *whowas;
101
102 if (dlink_list_length(&whowas_list) >= ConfigGeneral.whowas_history_length)
103 whowas = whowas_unlink(whowas_list.tail->data); /* Re-use oldest item */
104 else
105 whowas = mp_pool_get(whowas_pool);
106
107 return whowas;
108 }
109
110 /*! \brief Trims the whowas_list if necessary until there are no
111 * more than ConfigGeneral.whowas_history_length Whowas
112 * struct items.
113 */
114 void
115 whowas_trim(void)
116 {
117 while (dlink_list_length(&whowas_list) &&
118 dlink_list_length(&whowas_list) >= ConfigGeneral.whowas_history_length)
119 whowas_free(whowas_list.tail->data);
120 }
121
122 /*! \brief Adds the currently defined name of the client to history.
123 * Usually called before changing to a new name (nick).
124 * Client must be a fully registered user.
125 * \param client_p Pointer to Client struct to add to whowas history
126 * \param online Either 1 if it's a nick change or 0 on client exit
127 */
128 void
129 whowas_add_history(struct Client *client_p, const int online)
130 {
131 struct Whowas *whowas = whowas_make();
132
133 if (!whowas) /* Can be NULL. */
134 return;
135
136 assert(IsClient(client_p));
137
138 whowas->hashv = strhash(client_p->name);
139 whowas->shide = IsHidden(client_p->servptr) != 0;
140 whowas->logoff = CurrentTime;
141
142 strlcpy(whowas->account, client_p->account, sizeof(whowas->account));
143 strlcpy(whowas->name, client_p->name, sizeof(whowas->name));
144 strlcpy(whowas->username, client_p->username, sizeof(whowas->username));
145 strlcpy(whowas->hostname, client_p->host, sizeof(whowas->hostname));
146 strlcpy(whowas->sockhost, client_p->sockhost, sizeof(whowas->sockhost));
147 strlcpy(whowas->realname, client_p->info, sizeof(whowas->realname));
148 strlcpy(whowas->servername, client_p->servptr->name, sizeof(whowas->servername));
149
150 if (online)
151 {
152 whowas->online = client_p;
153 dlinkAdd(whowas, &whowas->cnode, &client_p->whowas_list);
154 }
155 else
156 whowas->online = NULL;
157
158 dlinkAdd(whowas, &whowas->hnode, &whowas_hash[whowas->hashv]);
159 dlinkAdd(whowas, &whowas->lnode, &whowas_list);
160 }
161
162 /*! \brief This must be called when the client structure is about to
163 * be released. History mechanism keeps pointers to client
164 * structures and it must know when they cease to exist.
165 * \param client_p Pointer to Client struct
166 */
167 void
168 whowas_off_history(struct Client *client_p)
169 {
170 while (client_p->whowas_list.head)
171 {
172 struct Whowas *whowas = client_p->whowas_list.head->data;
173
174 whowas->online = NULL;
175 dlinkDelete(&whowas->cnode, &client_p->whowas_list);
176 }
177 }
178
179 /*! \brief Returns the current client that was using the given
180 * nickname within the timelimit. Returns NULL, if no
181 * one found.
182 * \param name Name of the nick
183 * \param timelimit Maximum age for a client since log-off
184 */
185 struct Client *
186 whowas_get_history(const char *name, uintmax_t timelimit)
187 {
188 dlink_node *node = NULL;
189
190 timelimit = CurrentTime - timelimit;
191
192 DLINK_FOREACH(node, whowas_hash[strhash(name)].head)
193 {
194 struct Whowas *whowas = node->data;
195
196 if (whowas->logoff < timelimit)
197 continue;
198 if (irccmp(name, whowas->name))
199 continue;
200 return whowas->online;
201 }
202
203 return NULL;
204 }
205
206 /*! \brief For debugging. Counts allocated structures stored in whowas_list
207 */
208 void
209 whowas_count_memory(unsigned int *const count, size_t *const bytes)
210 {
211 (*count) = dlink_list_length(&whowas_list);
212 (*bytes) = dlink_list_length(&whowas_list) * sizeof(struct Whowas);
213 }

Properties

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