]>
Commit | Line | Data |
---|---|---|
c86edd1d Q |
1 | /* channelindex.c */ |
2 | ||
47a18d37 | 3 | #include "chanindex.h" |
c86edd1d Q |
4 | #include "../irc/irc_config.h" |
5 | #include "../lib/irc_string.h" | |
47a18d37 | 6 | #include "../core/error.h" |
7 | #include "../core/nsmalloc.h" | |
8 | ||
c86edd1d | 9 | #include <stdio.h> |
4ad1cf7a | 10 | #include <string.h> |
c86edd1d | 11 | |
47a18d37 | 12 | #define ALLOCUNIT 1000 |
13 | ||
c86edd1d Q |
14 | #define channelhash(x) (crc32i(x)%CHANNELHASHSIZE) |
15 | ||
16 | chanindex *chantable[CHANNELHASHSIZE]; | |
17 | sstring *extnames[MAXCHANNELEXTS]; | |
47a18d37 | 18 | chanindex *freechanindices; |
c86edd1d Q |
19 | |
20 | unsigned int channelmarker; | |
21 | ||
4c2d8b3e | 22 | void _init() { |
c86edd1d Q |
23 | memset(chantable,0,sizeof(chantable)); |
24 | memset(extnames,0,sizeof(extnames)); | |
25 | channelmarker=0; | |
47a18d37 | 26 | freechanindices=NULL; |
27 | } | |
28 | ||
4c2d8b3e | 29 | void _fini() { |
47a18d37 | 30 | nsfreeall(POOL_CHANINDEX); |
31 | } | |
32 | ||
33 | chanindex *getchanindex() { | |
34 | int i; | |
35 | chanindex *cip; | |
36 | ||
37 | if (freechanindices==NULL) { | |
38 | freechanindices=(chanindex *)nsmalloc(POOL_CHANINDEX, ALLOCUNIT*sizeof(chanindex)); | |
39 | for(i=0;i<ALLOCUNIT-1;i++) { | |
40 | freechanindices[i].next=&(freechanindices[i+1]); | |
41 | } | |
42 | freechanindices[ALLOCUNIT-1].next=NULL; | |
43 | } | |
44 | ||
45 | cip=freechanindices; | |
46 | freechanindices=cip->next; | |
47 | ||
48 | return cip; | |
49 | } | |
50 | ||
51 | void freechanindex(chanindex *cip) { | |
52 | cip->next=freechanindices; | |
53 | freechanindices=cip; | |
c86edd1d Q |
54 | } |
55 | ||
56 | chanindex *findchanindex(const char *name) { | |
57 | chanindex *cip; | |
58 | int hash=channelhash(name); | |
59 | ||
60 | for (cip=chantable[hash];cip;cip=cip->next) { | |
61 | if (!ircd_strcmp(cip->name->content,name)) { | |
62 | return cip; | |
63 | } | |
64 | } | |
65 | ||
66 | return NULL; | |
67 | } | |
68 | ||
69 | chanindex *findorcreatechanindex(const char *name) { | |
70 | chanindex *cip; | |
71 | int hash=channelhash(name); | |
72 | int i; | |
73 | ||
74 | for (cip=chantable[hash];cip;cip=cip->next) { | |
75 | if (!ircd_strcmp(cip->name->content,name)) { | |
76 | return cip; | |
77 | } | |
78 | } | |
79 | ||
80 | cip=getchanindex(); | |
81 | ||
82 | cip->name=getsstring(name,CHANNELLEN); | |
83 | cip->channel=NULL; | |
84 | cip->marker=0; | |
85 | cip->next=chantable[hash]; | |
86 | chantable[hash]=cip; | |
87 | ||
88 | for(i=0;i<MAXCHANNELEXTS;i++) { | |
89 | cip->exts[i]=NULL; | |
90 | } | |
91 | ||
92 | return cip; | |
93 | } | |
94 | ||
95 | void releasechanindex(chanindex *cip) { | |
96 | int i; | |
97 | chanindex **cih; | |
98 | int hash; | |
99 | ||
100 | /* If any module is still using the channel, do nothing */ | |
101 | /* Same if the channel is still present on the network */ | |
102 | ||
103 | if (cip->channel!=NULL) { | |
104 | return; | |
105 | } | |
106 | ||
107 | for (i=0;i<MAXCHANNELEXTS;i++) { | |
108 | if (cip->exts[i]!=NULL) { | |
109 | return; | |
110 | } | |
111 | } | |
112 | ||
113 | /* Now remove the index record from the index. */ | |
114 | hash=channelhash(cip->name->content); | |
115 | ||
116 | for(cih=&(chantable[hash]);*cih;cih=&((*cih)->next)) { | |
117 | if (*cih==cip) { | |
118 | (*cih)=cip->next; | |
119 | freesstring(cip->name); | |
120 | freechanindex(cip); | |
121 | return; | |
122 | } | |
123 | } | |
124 | ||
125 | Error("channel",ERR_ERROR,"Tried to release chanindex record for %s not found in hash",cip->name->content); | |
126 | } | |
127 | ||
128 | int registerchanext(const char *name) { | |
129 | int i; | |
130 | ||
131 | if (findchanext(name)!=-1) { | |
132 | Error("channel",ERR_WARNING,"Tried to register duplicate extension %s",name); | |
133 | return -1; | |
134 | } | |
135 | ||
136 | for (i=0;i<MAXCHANNELEXTS;i++) { | |
137 | if (extnames[i]==NULL) { | |
138 | extnames[i]=getsstring(name,100); | |
139 | return i; | |
140 | } | |
141 | } | |
142 | ||
143 | Error("channel",ERR_WARNING,"Tried to register too many extensions: %s",name); | |
144 | return -1; | |
145 | } | |
146 | ||
147 | int findchanext(const char *name) { | |
148 | int i; | |
149 | ||
150 | for (i=0;i<MAXCHANNELEXTS;i++) { | |
151 | if (extnames[i]!=NULL && !ircd_strcmp(name,extnames[i]->content)) { | |
152 | return i; | |
153 | } | |
154 | } | |
155 | ||
156 | return -1; | |
157 | } | |
158 | ||
159 | void releasechanext(int index) { | |
160 | int i; | |
161 | chanindex *cip,*ncip; | |
162 | ||
163 | freesstring(extnames[index]); | |
164 | extnames[index]=NULL; | |
165 | ||
166 | for (i=0;i<CHANNELHASHSIZE;i++) { | |
167 | for (cip=chantable[i];cip;cip=ncip) { | |
168 | /* CAREFUL: deleting items from chains you're walking is bad */ | |
169 | ncip=cip->next; | |
170 | if (cip->exts[index]!=NULL) { | |
171 | cip->exts[index]=NULL; | |
172 | releasechanindex(cip); | |
173 | } | |
174 | } | |
175 | } | |
176 | } | |
177 | ||
178 | unsigned int nextchanmarker() { | |
179 | int i; | |
180 | chanindex *cip; | |
181 | ||
182 | channelmarker++; | |
183 | if (!channelmarker) { | |
184 | /* If we wrapped to zero, zap the marker on all records */ | |
185 | for (i=0;i<CHANNELHASHSIZE;i++) | |
186 | for (cip=chantable[i];cip;cip=cip->next) | |
187 | cip->marker=0; | |
188 | channelmarker++; | |
189 | } | |
190 | ||
191 | return channelmarker; | |
192 | } |