]> jfr.im git - irc/quakenet/newserv.git/blame - chanindex/chanindex.c
merge
[irc/quakenet/newserv.git] / chanindex / chanindex.c
CommitLineData
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"
240bbd21 8#include "../lib/version.h"
47a18d37 9
c86edd1d 10#include <stdio.h>
4ad1cf7a 11#include <string.h>
c86edd1d 12
240bbd21
CP
13MODULE_VERSION("")
14
47a18d37 15#define ALLOCUNIT 1000
16
c86edd1d
Q
17#define channelhash(x) (crc32i(x)%CHANNELHASHSIZE)
18
19chanindex *chantable[CHANNELHASHSIZE];
20sstring *extnames[MAXCHANNELEXTS];
47a18d37 21chanindex *freechanindices;
c86edd1d
Q
22
23unsigned int channelmarker;
24
4c2d8b3e 25void _init() {
c86edd1d
Q
26 memset(chantable,0,sizeof(chantable));
27 memset(extnames,0,sizeof(extnames));
28 channelmarker=0;
47a18d37 29 freechanindices=NULL;
30}
31
4c2d8b3e 32void _fini() {
47a18d37 33 nsfreeall(POOL_CHANINDEX);
34}
35
36chanindex *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
54void freechanindex(chanindex *cip) {
55 cip->next=freechanindices;
56 freechanindices=cip;
c86edd1d
Q
57}
58
59chanindex *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
72chanindex *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
98void 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
131int 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
150int 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
162void 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
181unsigned 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}