]> jfr.im git - irc/quakenet/newserv.git/blame - chanindex/chanindex.c
Export printchannels in newsearch.
[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"
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
16chanindex *chantable[CHANNELHASHSIZE];
17sstring *extnames[MAXCHANNELEXTS];
47a18d37 18chanindex *freechanindices;
c86edd1d
Q
19
20unsigned int channelmarker;
21
4c2d8b3e 22void _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 29void _fini() {
47a18d37 30 nsfreeall(POOL_CHANINDEX);
31}
32
33chanindex *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
51void freechanindex(chanindex *cip) {
52 cip->next=freechanindices;
53 freechanindices=cip;
c86edd1d
Q
54}
55
56chanindex *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
69chanindex *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
95void 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
128int 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
147int 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
159void 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
178unsigned 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}