ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/watch.c
Revision: 8590
Committed: Sun Oct 21 15:44:08 2018 UTC (6 years, 10 months ago) by michael
Content type: text/x-csrc
File size: 6046 byte(s)
Log Message:
- watch: cache hash values

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 michael 8279 * Copyright (c) 2005-2018 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 michael 4565 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
20 michael 876 * 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 8385 #include "memory.h"
31 michael 876 #include "client.h"
32     #include "hash.h"
33     #include "irc_string.h"
34     #include "ircd.h"
35     #include "numeric.h"
36     #include "send.h"
37     #include "watch.h"
38    
39    
40     static dlink_list watchTable[HASHSIZE];
41    
42    
43     /*
44     * Rough figure of the datastructures for watch:
45     *
46     * NOTIFY HASH client_p1
47     * | |- nick1
48     * nick1-|- client_p1 |- nick2
49     * | |- client_p2 client_p3
50     * | |- client_p3 client_p2 |- nick1
51     * | |- nick1
52     * nick2-|- client_p2 |- nick2
53     * |- client_p1
54     */
55    
56     /*! \brief Counts up memory used by watch list headers
57     */
58     void
59 michael 6719 watch_count_memory(unsigned int *const count, size_t *const bytes)
60 michael 876 {
61 michael 3250 for (unsigned int i = 0; i < HASHSIZE; ++i)
62     (*count) += dlink_list_length(&watchTable[i]);
63 michael 876
64 michael 2297 (*bytes) = *count * sizeof(struct Watch);
65 michael 876 }
66    
67 michael 7084 /*! \brief Notifies all clients that have client_p's name on
68 michael 876 * their watch list.
69 michael 2855 * \param client_p Pointer to Client struct
70     * \param reply Numeric to send. Either RPL_LOGON or RPL_LOGOFF
71 michael 876 */
72     void
73 michael 4785 watch_check_hash(const struct Client *client_p, const enum irc_numerics reply)
74 michael 876 {
75 michael 4815 struct Watch *watch = NULL;
76 michael 4800 dlink_node *node = NULL;
77 michael 3250
78 michael 876 assert(IsClient(client_p));
79 michael 3250
80 michael 4815 if ((watch = watch_find_hash(client_p->name)) == NULL)
81 michael 7084 return; /* This name isn't on watch */
82 michael 876
83 michael 1359 /* Update the time of last change to item */
84 michael 4815 watch->lasttime = CurrentTime;
85 michael 876
86 michael 1359 /* Send notifies out to everybody on the list in header */
87 michael 4815 DLINK_FOREACH(node, watch->watched_by.head)
88 michael 4800 sendto_one_numeric(node->data, &me, reply, client_p->name,
89 michael 3109 client_p->username, client_p->host,
90 michael 4815 watch->lasttime, client_p->info);
91 michael 876 }
92    
93 michael 7084 /*! \brief Looks up the watch table for a given name
94 michael 2855 * \param name Nick name to look up
95 michael 876 */
96     struct Watch *
97     watch_find_hash(const char *name)
98     {
99 michael 4800 dlink_node *node = NULL;
100 michael 876
101 michael 4800 DLINK_FOREACH(node, watchTable[strhash(name)].head)
102 michael 876 {
103 michael 4815 struct Watch *watch = node->data;
104 michael 876
105 michael 8512 if (irccmp(watch->name, name) == 0)
106 michael 4815 return watch;
107 michael 876 }
108    
109     return NULL;
110     }
111    
112     /*! \brief Adds a watch entry to client_p's watch list
113 michael 7084 * \param name Nick name to add
114 michael 876 * \param client_p Pointer to Client struct
115     */
116     void
117 michael 7084 watch_add_to_hash_table(const char *name, struct Client *client_p)
118 michael 876 {
119 michael 4815 struct Watch *watch = NULL;
120 michael 4800 dlink_node *node = NULL;
121 michael 876
122 michael 7084 /* If found NULL (no header for this name), make one... */
123     if ((watch = watch_find_hash(name)) == NULL)
124 michael 876 {
125 michael 8385 watch = xcalloc(sizeof(*watch));
126 michael 3250
127 michael 8590 strlcpy(watch->name, name, sizeof(watch->name));
128     watch->hash_value = strhash(watch->name);
129 michael 4815 watch->lasttime = CurrentTime;
130 michael 876
131 michael 8590 dlinkAdd(watch, &watch->node, &watchTable[watch->hash_value]);
132 michael 876 }
133     else
134     {
135 michael 1359 /* Is this client already on the watch-list? */
136 michael 4815 node = dlinkFind(&watch->watched_by, client_p);
137 michael 876 }
138    
139 michael 4800 if (node == NULL)
140 michael 876 {
141 michael 4728 /* No it isn't, so add it in the bucket and client adding it */
142 michael 4815 dlinkAdd(client_p, make_dlink_node(), &watch->watched_by);
143     dlinkAdd(watch, make_dlink_node(), &client_p->connection->watches);
144 michael 876 }
145     }
146    
147     /*! \brief Removes a single entry from client_p's watch list
148 michael 7084 * \param name Name to remove
149 michael 876 * \param client_p Pointer to Client struct
150     */
151     void
152 michael 7084 watch_del_from_hash_table(const char *name, struct Client *client_p)
153 michael 876 {
154 michael 4815 struct Watch *watch = NULL;
155 michael 4800 dlink_node *node = NULL;
156 michael 876
157 michael 7084 if ((watch = watch_find_hash(name)) == NULL)
158     return; /* No header found for that name. i.e. it's not being watched */
159 michael 876
160 michael 4815 if ((node = dlinkFind(&watch->watched_by, client_p)) == NULL)
161 michael 7084 return; /* This name isn't being watched by client_p */
162 michael 876
163 michael 4815 dlinkDelete(node, &watch->watched_by);
164 michael 4800 free_dlink_node(node);
165 michael 876
166 michael 4815 if ((node = dlinkFindDelete(&client_p->connection->watches, watch)))
167 michael 4800 free_dlink_node(node);
168 michael 876
169 michael 1359 /* In case this header is now empty of notices, remove it */
170 michael 4815 if (watch->watched_by.head == NULL)
171 michael 876 {
172 michael 8590 assert(dlinkFind(&watchTable[watch->hash_value], watch));
173     dlinkDelete(&watch->node, &watchTable[watch->hash_value]);
174 michael 8385 xfree(watch);
175 michael 876 }
176     }
177    
178     /*! \brief Removes all entries from client_p's watch list
179     * and deletes headers that are no longer being watched.
180     * \param client_p Pointer to Client struct
181     */
182     void
183     watch_del_watch_list(struct Client *client_p)
184     {
185 michael 4800 dlink_node *node = NULL, *node_next = NULL;
186     dlink_node *temp = NULL;
187 michael 876
188 michael 4800 DLINK_FOREACH_SAFE(node, node_next, client_p->connection->watches.head)
189 michael 876 {
190 michael 4815 struct Watch *watch = node->data;
191 michael 876
192 michael 4815 assert(dlinkFind(&watch->watched_by, client_p));
193 michael 876
194 michael 4815 if ((temp = dlinkFindDelete(&watch->watched_by, client_p)))
195 michael 4800 free_dlink_node(temp);
196 michael 876
197 michael 1359 /* If this leaves a header without notifies, remove it. */
198 michael 4815 if (watch->watched_by.head == NULL)
199 michael 876 {
200 michael 8590 assert(dlinkFind(&watchTable[watch->hash_value], watch));
201     dlinkDelete(&watch->node, &watchTable[watch->hash_value]);
202 michael 876
203 michael 8385 xfree(watch);
204 michael 876 }
205    
206 michael 4800 dlinkDelete(node, &client_p->connection->watches);
207     free_dlink_node(node);
208 michael 876 }
209    
210 michael 4588 assert(client_p->connection->watches.head == NULL);
211     assert(client_p->connection->watches.tail == NULL);
212 michael 876 }

Properties

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