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