ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/watch.c
Revision: 3235
Committed: Sat Mar 29 19:34:16 2014 UTC (11 years, 5 months ago) by michael
Content type: text/x-csrc
File size: 6257 byte(s)
Log Message:
- Style corrections all over the place

File Contents

# User Rev Content
1 michael 876 /*
2 michael 2855 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 michael 876 *
4 michael 2855 * Copyright (c) 1997 Jukka Santala (Donwulff)
5     * Copyright (c) 2005-2014 ircd-hybrid development team
6 michael 876 *
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 michael 879 * \version $Id$
26 michael 876 */
27    
28     #include "stdinc.h"
29 michael 1011 #include "list.h"
30 michael 876 #include "client.h"
31     #include "hash.h"
32     #include "irc_string.h"
33     #include "ircd.h"
34     #include "numeric.h"
35 michael 1309 #include "conf.h"
36 michael 876 #include "send.h"
37 michael 1654 #include "mempool.h"
38 michael 876 #include "watch.h"
39    
40    
41     static dlink_list watchTable[HASHSIZE];
42    
43 michael 1654 static mp_pool_t *watch_pool = NULL;
44 michael 876
45     /*! \brief Initializes the watch table
46     */
47     void
48     watch_init(void)
49     {
50 michael 1654 watch_pool = mp_pool_new(sizeof(struct Watch), MP_CHUNK_SIZE_WATCH);
51 michael 876 }
52    
53     /*
54     * Rough figure of the datastructures for watch:
55     *
56     * NOTIFY HASH client_p1
57     * | |- nick1
58     * nick1-|- client_p1 |- nick2
59     * | |- client_p2 client_p3
60     * | |- client_p3 client_p2 |- nick1
61     * | |- nick1
62     * nick2-|- client_p2 |- nick2
63     * |- client_p1
64     */
65    
66     /*! \brief Counts up memory used by watch list headers
67     */
68     void
69 michael 2297 watch_count_memory(unsigned int *const count, uint64_t *const bytes)
70 michael 876 {
71 michael 2297 unsigned int idx = 0;
72 michael 876
73 michael 2297 for (; idx < HASHSIZE; ++idx)
74     (*count) += dlink_list_length(&watchTable[idx]);
75 michael 876
76 michael 2297 (*bytes) = *count * sizeof(struct Watch);
77 michael 876 }
78    
79     /*! \brief Notifies all clients that have client_p's nick name on
80     * their watch list.
81 michael 2855 * \param client_p Pointer to Client struct
82     * \param reply Numeric to send. Either RPL_LOGON or RPL_LOGOFF
83 michael 876 */
84     void
85 michael 3109 watch_check_hash(struct Client *client_p, const enum irc_numerics reply)
86 michael 876 {
87     struct Watch *anptr = NULL;
88     dlink_node *ptr = NULL;
89     assert(IsClient(client_p));
90     if ((anptr = watch_find_hash(client_p->name)) == NULL)
91 michael 2855 return; /* This nick isn't on watch */
92 michael 876
93 michael 1359 /* Update the time of last change to item */
94 michael 876 anptr->lasttime = CurrentTime;
95    
96 michael 1359 /* Send notifies out to everybody on the list in header */
97 michael 876 DLINK_FOREACH(ptr, anptr->watched_by.head)
98 michael 3109 sendto_one_numeric(ptr->data, &me, reply, client_p->name,
99     client_p->username, client_p->host,
100     anptr->lasttime, client_p->info);
101 michael 876 }
102    
103     /*! \brief Looks up the watch table for a given nick
104 michael 2855 * \param name Nick name to look up
105 michael 876 */
106     struct Watch *
107     watch_find_hash(const char *name)
108     {
109     dlink_node *ptr = NULL;
110    
111     DLINK_FOREACH(ptr, watchTable[strhash(name)].head)
112     {
113     struct Watch *anptr = ptr->data;
114    
115     if (!irccmp(anptr->nick, name))
116     return anptr;
117     }
118    
119     return NULL;
120     }
121    
122     /*! \brief Adds a watch entry to client_p's watch list
123 michael 2855 * \param nick Nick name to add
124 michael 876 * \param client_p Pointer to Client struct
125     */
126     void
127     watch_add_to_hash_table(const char *nick, struct Client *client_p)
128     {
129     struct Watch *anptr = NULL;
130     dlink_node *ptr = NULL;
131    
132 michael 1359 /* If found NULL (no header for this nick), make one... */
133 michael 876 if ((anptr = watch_find_hash(nick)) == NULL)
134     {
135 michael 1654 anptr = mp_pool_get(watch_pool);
136     memset(anptr, 0, sizeof(*anptr));
137 michael 876 anptr->lasttime = CurrentTime;
138     strlcpy(anptr->nick, nick, sizeof(anptr->nick));
139    
140     dlinkAdd(anptr, &anptr->node, &watchTable[strhash(nick)]);
141     }
142     else
143     {
144 michael 1359 /* Is this client already on the watch-list? */
145 michael 876 ptr = dlinkFind(&anptr->watched_by, client_p);
146     }
147    
148     if (ptr == NULL)
149     {
150 michael 1359 /* No it isn't, so add it in the bucket and client addint it */
151 michael 876 dlinkAdd(client_p, make_dlink_node(), &anptr->watched_by);
152     dlinkAdd(anptr, make_dlink_node(), &client_p->localClient->watches);
153     }
154     }
155    
156     /*! \brief Removes a single entry from client_p's watch list
157 michael 2855 * \param nick Nick name to remove
158 michael 876 * \param client_p Pointer to Client struct
159     */
160     void
161     watch_del_from_hash_table(const char *nick, struct Client *client_p)
162     {
163     struct Watch *anptr = NULL;
164     dlink_node *ptr = NULL;
165    
166     if ((anptr = watch_find_hash(nick)) == NULL)
167 michael 2855 return; /* No header found for that nick. i.e. it's not being watched */
168 michael 876
169     if ((ptr = dlinkFind(&anptr->watched_by, client_p)) == NULL)
170 michael 2855 return; /* This nick isn't being watched by client_p */
171 michael 876
172     dlinkDelete(ptr, &anptr->watched_by);
173     free_dlink_node(ptr);
174    
175     if ((ptr = dlinkFindDelete(&client_p->localClient->watches, anptr)))
176     free_dlink_node(ptr);
177    
178 michael 1359 /* In case this header is now empty of notices, remove it */
179 michael 876 if (anptr->watched_by.head == NULL)
180     {
181 michael 3235 assert(dlinkFind(&watchTable[strhash(nick)], anptr));
182 michael 876 dlinkDelete(&anptr->node, &watchTable[strhash(nick)]);
183 michael 1654 mp_pool_release(anptr);
184 michael 876 }
185     }
186    
187     /*! \brief Removes all entries from client_p's watch list
188     * and deletes headers that are no longer being watched.
189     * \param client_p Pointer to Client struct
190     */
191     void
192     watch_del_watch_list(struct Client *client_p)
193     {
194     dlink_node *ptr = NULL, *ptr_next = NULL;
195     dlink_node *tmp = NULL;
196    
197     DLINK_FOREACH_SAFE(ptr, ptr_next, client_p->localClient->watches.head)
198     {
199     struct Watch *anptr = ptr->data;
200    
201     assert(anptr);
202    
203 michael 3235 assert(dlinkFind(&anptr->watched_by, client_p));
204 michael 876 if ((tmp = dlinkFindDelete(&anptr->watched_by, client_p)))
205     free_dlink_node(tmp);
206    
207 michael 1359 /* If this leaves a header without notifies, remove it. */
208 michael 876 if (anptr->watched_by.head == NULL)
209     {
210 michael 3235 assert(dlinkFind(&watchTable[strhash(anptr->nick)], anptr));
211 michael 876 dlinkDelete(&anptr->node, &watchTable[strhash(anptr->nick)]);
212    
213 michael 1654 mp_pool_release(anptr);
214 michael 876 }
215    
216     dlinkDelete(ptr, &client_p->localClient->watches);
217     free_dlink_node(ptr);
218     }
219    
220     assert(client_p->localClient->watches.head == NULL);
221     assert(client_p->localClient->watches.tail == NULL);
222     }

Properties

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