ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/src/watch.c
Revision: 233
Committed: Sat Nov 5 08:05:06 2005 UTC (20 years, 8 months ago) by michael
Content type: text/x-csrc
File size: 5777 byte(s)
Log Message:
- Style correction to watch.c
- Add some statistical information about WATCH headers/entries
  to "STATS z"

File Contents

# User Rev Content
1 michael 214 /*
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 michael 215 #include "stdinc.h"
29     #include "client.h"
30     #include "common.h"
31     #include "hash.h"
32     #include "ircd.h"
33     #include "numeric.h"
34     #include "s_conf.h"
35     #include "s_user.h"
36     #include "send.h"
37     #include "supported.h"
38     #include "watch.h"
39     #include "msg.h"
40    
41 michael 214 #define WATCH_HEAP_SIZE 32
42    
43 michael 231 static dlink_list watchTable[HASHSIZE];
44 michael 214
45     static BlockHeap *watch_heap = NULL;
46    
47     void
48     init_watch(void)
49     {
50 michael 231 memset(watchTable, 0, sizeof(watchTable));
51 michael 214
52     watch_heap = BlockHeapCreate("watch", sizeof(struct Watch), WATCH_HEAP_SIZE);
53     }
54 michael 215
55     /*
56     * Rough figure of the datastructures for watch:
57     *
58     * NOTIFY HASH client_p1
59     * | |- nick1
60     * nick1-|- client_p1 |- nick2
61     * | |- client_p2 client_p3
62     * | |- client_p3 client_p2 |- nick1
63     * | |- nick1
64     * nick2-|- client_p2 |- nick2
65     * |- client_p1
66     */
67    
68     /*
69     * count_watch_memory()
70     */
71     void
72     count_watch_memory(unsigned int *count, unsigned int *memory)
73     {
74     unsigned int idx;
75    
76     for (idx = 0; idx < HASHSIZE; ++idx)
77 michael 231 *count += dlink_list_length(&watchTable[idx]);
78 michael 215
79 michael 231 *memory = *count * sizeof(struct Watch);
80 michael 215 }
81    
82     /*
83     * hash_check_watch()
84     */
85     void
86     hash_check_watch(struct Client *client_p, int reply)
87     {
88     struct Watch *anptr = NULL;
89     dlink_node *ptr = NULL;
90     assert(IsClient(client_p));
91     if ((anptr = hash_get_watch(client_p->name)) == NULL)
92     return; /* This nick isn't on watch */
93    
94     /* Update the time of last change to item */
95     anptr->lasttime = CurrentTime;
96    
97     /* Send notifies out to everybody on the list in header */
98     DLINK_FOREACH(ptr, anptr->watched_by.head)
99     {
100     struct Client *target_p = ptr->data;
101    
102     sendto_one(target_p, form_str(reply),
103     me.name, target_p->name, client_p->name,
104 michael 216 client_p->username, client_p->host,
105 michael 215 anptr->lasttime, client_p->info);
106     }
107     }
108    
109     /*
110     * hash_get_watch()
111     */
112     struct Watch *
113     hash_get_watch(const char *name)
114     {
115 michael 231 dlink_node *ptr = NULL;
116 michael 215
117 michael 233 DLINK_FOREACH(ptr, watchTable[strhash(name)].head)
118     {
119 michael 231 struct Watch *anptr = ptr->data;
120 michael 233
121 michael 231 if (!irccmp(anptr->nick, name))
122     return anptr;
123     }
124 michael 215
125 michael 231 return NULL;
126 michael 215 }
127    
128     /*
129     * add_to_watch_hash_table()
130     */
131     void
132     add_to_watch_hash_table(const char *nick, struct Client *client_p)
133     {
134     struct Watch *anptr = NULL;
135     dlink_node *ptr = NULL;
136    
137     /* If found NULL (no header for this nick), make one... */
138 michael 231 if ((anptr = hash_get_watch(nick)) == NULL)
139 michael 215 {
140     anptr = BlockHeapAlloc(watch_heap);
141     anptr->lasttime = CurrentTime;
142     strlcpy(anptr->nick, nick, sizeof(anptr->nick));
143    
144 michael 231 dlinkAdd(anptr, &anptr->node, &watchTable[strhash(nick)]);
145 michael 215 }
146     else
147     {
148     /* Is this client already on the watch-list? */
149     ptr = dlinkFind(&anptr->watched_by, client_p);
150     }
151    
152     if (ptr == NULL)
153     {
154     /* No it isn't, so add it in the bucket and client addint it */
155     dlinkAdd(client_p, make_dlink_node(), &anptr->watched_by);
156     dlinkAdd(anptr, make_dlink_node(), &client_p->localClient->watches);
157     }
158     }
159    
160     /*
161     * del_from_watch_hash_table()
162     */
163     void
164     del_from_watch_hash_table(const char *nick, struct Client *client_p)
165     {
166     struct Watch *anptr = NULL;
167     dlink_node *ptr = NULL;
168    
169 michael 233 if ((anptr = hash_get_watch(nick)) == NULL)
170 michael 231 return; /* No header found for that nick. i.e. it's not being watched */
171 michael 215
172     if ((ptr = dlinkFind(&anptr->watched_by, client_p)) == NULL)
173     return;
174    
175     dlinkDelete(ptr, &anptr->watched_by);
176     free_dlink_node(ptr);
177    
178     if ((ptr = dlinkFindDelete(&client_p->localClient->watches, anptr)))
179     free_dlink_node(ptr);
180    
181     /* In case this header is now empty of notices, remove it */
182     if (anptr->watched_by.head == NULL)
183     {
184 michael 231 assert(dlinkFind(&watchTable[strhash(nick)], anptr) != NULL);
185     dlinkDelete(&anptr->node, &watchTable[strhash(nick)]);
186 michael 215 BlockHeapFree(watch_heap, anptr);
187     }
188     }
189    
190     /*
191     * hash_del_watch_list()
192     */
193     void
194     hash_del_watch_list(struct Client *client_p)
195     {
196     dlink_node *ptr = NULL, *ptr_next = NULL;
197     dlink_node *tmp = NULL;
198    
199     if (client_p->localClient->watches.head == NULL)
200     return; /* Nothing to do */
201    
202     DLINK_FOREACH_SAFE(ptr, ptr_next, client_p->localClient->watches.head)
203     {
204     struct Watch *anptr = ptr->data;
205    
206     assert(anptr);
207    
208 michael 231 assert(dlinkFind(&anptr->watched_by, client_p) != NULL);
209 michael 215 if ((tmp = dlinkFindDelete(&anptr->watched_by, client_p)))
210     free_dlink_node(tmp);
211    
212     /*
213     * If this leaves a header without notifies, remove it.
214     */
215     if (anptr->watched_by.head == NULL)
216     {
217 michael 231 assert(dlinkFind(&watchTable[strhash(anptr->nick)], anptr) != NULL);
218     dlinkDelete(&anptr->node, &watchTable[strhash(anptr->nick)]);
219 michael 215
220     BlockHeapFree(watch_heap, anptr);
221     }
222    
223     dlinkDelete(ptr, &client_p->localClient->watches);
224     free_dlink_node(ptr);
225     }
226    
227     assert(client_p->localClient->watches.head == NULL);
228     assert(client_p->localClient->watches.tail == NULL);
229     }

Properties

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