ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/watch.c
Revision: 1654
Committed: Fri Nov 16 19:39:37 2012 UTC (12 years, 9 months ago) by michael
Content type: text/x-csrc
File size: 6491 byte(s)
Log Message:
- Implemented memory pool allocator which basically is taken from Tor's
  mempool allocator for Tor cells
- Fixed compile warnings in conf_class.c
- ./configure --enable-assert works again

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 *
4 * Copyright (C) 1997 Jukka Santala (Donwulff)
5 * Copyright (C) 2005 by the Hybrid Development Team.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 * USA
21 */
22
23 /*! \file watch.c
24 * \brief File including functions for WATCH support
25 * \version $Id$
26 */
27
28 #include "stdinc.h"
29 #include "list.h"
30 #include "s_user.h"
31 #include "s_misc.h"
32 #include "client.h"
33 #include "hash.h"
34 #include "irc_string.h"
35 #include "sprintf_irc.h"
36 #include "ircd.h"
37 #include "numeric.h"
38 #include "conf.h"
39 #include "s_serv.h"
40 #include "send.h"
41 #include "supported.h"
42 #include "whowas.h"
43 #include "memory.h"
44 #include "mempool.h"
45 #include "packet.h"
46 #include "watch.h"
47
48
49 static dlink_list watchTable[HASHSIZE];
50
51 static mp_pool_t *watch_pool = NULL;
52
53 /*! \brief Initializes the watch table
54 */
55 void
56 watch_init(void)
57 {
58 watch_pool = mp_pool_new(sizeof(struct Watch), MP_CHUNK_SIZE_WATCH);
59 }
60
61 /*
62 * Rough figure of the datastructures for watch:
63 *
64 * NOTIFY HASH client_p1
65 * | |- nick1
66 * nick1-|- client_p1 |- nick2
67 * | |- client_p2 client_p3
68 * | |- client_p3 client_p2 |- nick1
69 * | |- nick1
70 * nick2-|- client_p2 |- nick2
71 * |- client_p1
72 */
73
74 /*! \brief Counts up memory used by watch list headers
75 */
76 void
77 watch_count_memory(unsigned int *const count, uint64_t *const memory)
78 {
79 unsigned int idx;
80
81 for (idx = 0; idx < HASHSIZE; ++idx)
82 *count += dlink_list_length(&watchTable[idx]);
83
84 *memory = *count * sizeof(struct Watch);
85 }
86
87 /*! \brief Notifies all clients that have client_p's nick name on
88 * their watch list.
89 * \param client_p pointer to Client struct
90 * \param reply numeric to send. Either RPL_LOGON or RPL_LOGOFF
91 */
92 void
93 watch_check_hash(struct Client *client_p, int reply)
94 {
95 struct Watch *anptr = NULL;
96 dlink_node *ptr = NULL;
97 assert(IsClient(client_p));
98 if ((anptr = watch_find_hash(client_p->name)) == NULL)
99 return; /* This nick isn't on watch */
100
101 /* Update the time of last change to item */
102 anptr->lasttime = CurrentTime;
103
104 /* Send notifies out to everybody on the list in header */
105 DLINK_FOREACH(ptr, anptr->watched_by.head)
106 {
107 struct Client *target_p = ptr->data;
108
109 sendto_one(target_p, form_str(reply),
110 me.name, target_p->name, client_p->name,
111 client_p->username, client_p->host,
112 anptr->lasttime, client_p->info);
113 }
114 }
115
116 /*! \brief Looks up the watch table for a given nick
117 * \param name nick name to look up
118 */
119 struct Watch *
120 watch_find_hash(const char *name)
121 {
122 dlink_node *ptr = NULL;
123
124 DLINK_FOREACH(ptr, watchTable[strhash(name)].head)
125 {
126 struct Watch *anptr = ptr->data;
127
128 if (!irccmp(anptr->nick, name))
129 return anptr;
130 }
131
132 return NULL;
133 }
134
135 /*! \brief Adds a watch entry to client_p's watch list
136 * \param nick nick name to add
137 * \param client_p Pointer to Client struct
138 */
139 void
140 watch_add_to_hash_table(const char *nick, struct Client *client_p)
141 {
142 struct Watch *anptr = NULL;
143 dlink_node *ptr = NULL;
144
145 /* If found NULL (no header for this nick), make one... */
146 if ((anptr = watch_find_hash(nick)) == NULL)
147 {
148 anptr = mp_pool_get(watch_pool);
149 memset(anptr, 0, sizeof(*anptr));
150 anptr->lasttime = CurrentTime;
151 strlcpy(anptr->nick, nick, sizeof(anptr->nick));
152
153 dlinkAdd(anptr, &anptr->node, &watchTable[strhash(nick)]);
154 }
155 else
156 {
157 /* Is this client already on the watch-list? */
158 ptr = dlinkFind(&anptr->watched_by, client_p);
159 }
160
161 if (ptr == NULL)
162 {
163 /* No it isn't, so add it in the bucket and client addint it */
164 dlinkAdd(client_p, make_dlink_node(), &anptr->watched_by);
165 dlinkAdd(anptr, make_dlink_node(), &client_p->localClient->watches);
166 }
167 }
168
169 /*! \brief Removes a single entry from client_p's watch list
170 * \param nick nick name to remove
171 * \param client_p Pointer to Client struct
172 */
173 void
174 watch_del_from_hash_table(const char *nick, struct Client *client_p)
175 {
176 struct Watch *anptr = NULL;
177 dlink_node *ptr = NULL;
178
179 if ((anptr = watch_find_hash(nick)) == NULL)
180 return; /* No header found for that nick. i.e. it's not being watched */
181
182 if ((ptr = dlinkFind(&anptr->watched_by, client_p)) == NULL)
183 return; /* This nick isn't being watched by client_p */
184
185 dlinkDelete(ptr, &anptr->watched_by);
186 free_dlink_node(ptr);
187
188 if ((ptr = dlinkFindDelete(&client_p->localClient->watches, anptr)))
189 free_dlink_node(ptr);
190
191 /* In case this header is now empty of notices, remove it */
192 if (anptr->watched_by.head == NULL)
193 {
194 assert(dlinkFind(&watchTable[strhash(nick)], anptr) != NULL);
195 dlinkDelete(&anptr->node, &watchTable[strhash(nick)]);
196 mp_pool_release(anptr);
197 }
198 }
199
200 /*! \brief Removes all entries from client_p's watch list
201 * and deletes headers that are no longer being watched.
202 * \param client_p Pointer to Client struct
203 */
204 void
205 watch_del_watch_list(struct Client *client_p)
206 {
207 dlink_node *ptr = NULL, *ptr_next = NULL;
208 dlink_node *tmp = NULL;
209
210 DLINK_FOREACH_SAFE(ptr, ptr_next, client_p->localClient->watches.head)
211 {
212 struct Watch *anptr = ptr->data;
213
214 assert(anptr);
215
216 assert(dlinkFind(&anptr->watched_by, client_p) != NULL);
217 if ((tmp = dlinkFindDelete(&anptr->watched_by, client_p)))
218 free_dlink_node(tmp);
219
220 /* If this leaves a header without notifies, remove it. */
221 if (anptr->watched_by.head == NULL)
222 {
223 assert(dlinkFind(&watchTable[strhash(anptr->nick)], anptr) != NULL);
224 dlinkDelete(&anptr->node, &watchTable[strhash(anptr->nick)]);
225
226 mp_pool_release(anptr);
227 }
228
229 dlinkDelete(ptr, &client_p->localClient->watches);
230 free_dlink_node(ptr);
231 }
232
233 assert(client_p->localClient->watches.head == NULL);
234 assert(client_p->localClient->watches.tail == NULL);
235 }

Properties

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