source: gsdl/trunk/src/colservr/collectset.cpp@ 15402

Last change on this file since 15402 was 15402, checked in by mdewsnip, 16 years ago

(Untangling colservr/recpt) Split recpt/recptconfig into two: lib/gsdlsitecfg (reads gsdlsite.cfg file; used by both colservr and recpt) and recpt/maincfg (reads main.cfg file; used by recpt only).

  • Property svn:keywords set to Author Date Id Revision
File size: 12.7 KB
Line 
1/**********************************************************************
2 *
3 * collectset.cpp --
4 * Copyright (C) 1999 The New Zealand Digital Library Project
5 *
6 * A component of the Greenstone digital library software
7 * from the New Zealand Digital Library Project at the
8 * University of Waikato, New Zealand.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 *********************************************************************/
25
26
27#include "collectset.h"
28#include "collectserver.h"
29#include "colservrconfig.h"
30#include "gsdlsitecfg.h"
31#include "filter.h"
32#include "browsefilter.h"
33#include "queryfilter.h"
34#include "infodbclass.h"
35#include "mgqueryfilter.h"
36#include "mgppqueryfilter.h"
37#include "mggdbmsource.h"
38#include "lucenequeryfilter.h"
39#include "lucenegdbmsource.h"
40
41#include "fileutil.h"
42#include <assert.h>
43
44
45collectset::collectset (text_t &gsdlhome) {
46
47 text_tarray collections;
48 text_t collectdir;
49
50 // get gsdlhome (if we fail the error will be picked up later -- in
51 // cgiwrapper)
52
53 if (site_cfg_read (gsdlhome, httpdomain, httpprefix)) {
54 if (!gsdlhome.empty() && directory_exists(gsdlhome)) {
55 collectdir = filename_cat (gsdlhome, "collect");
56 if (read_dir (collectdir, collections)) {
57
58 text_tarray::const_iterator thiscol = collections.begin();
59 text_tarray::const_iterator endcol = collections.end();
60
61 while (thiscol != endcol) {
62 // ignore the modelcol
63 if (*thiscol == "modelcol") {
64 ++thiscol;
65 continue;
66 }
67
68 this->add_collection (*thiscol, gsdlhome);
69
70 ++thiscol;
71 }
72
73 this->add_all_collection_groups(gsdlhome);
74 }
75 }
76 }
77}
78
79collectset::~collectset () {
80 collectservermapclass::iterator here = cservers.begin();
81 collectservermapclass::iterator end = cservers.end();
82
83 while (here != end) {
84 if ((*here).second.c != NULL) {
85 delete (*here).second.c;
86 }
87 ++here;
88 }
89 cservers.clear();
90}
91
92bool collectset::init (ostream &logout) {
93 collectservermapclass::iterator here = cservers.begin();
94 collectservermapclass::iterator end = cservers.end();
95
96 while (here != end) {
97 assert ((*here).second.c != NULL);
98 if ((*here).second.c != NULL) {
99 const colservrconf &configinfo = (*here).second.c->get_configinfo ();
100
101 // configure this collection server
102
103 // note that we read build.cfg before collect.cfg so that the indexmaps
104 // are available to decode defaultindex, defaultsubcollection, and
105 // defaultlanguage
106
107 bool failed_build_cfg = false;
108 if (!build_cfg_read (*((*here).second.c), configinfo.gsdlhome,
109 configinfo.collection)) {
110 failed_build_cfg = true;
111
112 outconvertclass text_t2ascii;
113 logout << text_t2ascii
114 << "Warning: couldn't read build.cfg file for collection \"" //****
115 << configinfo.collection << "\", gsdlhome=\""
116 << configinfo.gsdlhome << "\"\n";
117 }
118
119 bool failed_collect_cfg = false;
120 if (!collect_cfg_read (*((*here).second.c), configinfo.gsdlhome,
121 configinfo.collection)) {
122 failed_collect_cfg = true;
123 outconvertclass text_t2ascii;
124 logout << text_t2ascii
125 << "Warning: couldn't read collect.cfg file for collection \""
126 << configinfo.collection << "\", gsdlhome=\""
127 << configinfo.gsdlhome << "\"\n";
128 }
129
130
131 bool is_colgroup = (*here).second.c->is_collection_group();
132
133 if (failed_collect_cfg) {
134 ++here;
135 continue;
136 }
137
138 if (failed_build_cfg && (!is_colgroup)) {
139 ++here;
140 continue;
141 }
142 // let a failed build.cfg through if its 'collect.cfg' marks it as 'collectgroup true'
143
144 if (!(*here).second.c->init (logout)) return false;
145
146 (*here).second.c->configure("httpdomain",httpdomain);
147 (*here).second.c->configure("httpprefix",httpprefix);
148 }
149 ++here;
150 }
151
152 return true;
153}
154
155collectservermapclass collectset::servers()
156{ return cservers;
157}
158
159
160void collectset::add_all_collections(const text_t &gsdlhome) {
161
162 text_tarray collections;
163 text_t collectdir = filename_cat(gsdlhome, "collect");
164 if (read_dir(collectdir, collections)) {
165
166 text_tarray::const_iterator thiscol = collections.begin();
167 text_tarray::const_iterator endcol = collections.end();
168
169 while (thiscol != endcol) {
170
171 // ignore the modelcol
172 if (*thiscol == "modelcol") {
173 ++thiscol;
174 continue;
175 }
176
177 // create collection server and add to null protocol
178 this->add_collection (*thiscol, gsdlhome);
179
180 ++thiscol;
181 }
182
183 this->add_all_collection_groups(gsdlhome);
184 }
185}
186
187// add_collection sets up the collectionserver and calls
188// add_collectserver
189void collectset::add_collection (const text_t &collection,
190 const text_t &gsdlhome) {
191
192 this->remove_collection(collection);
193
194 // read config file to see if built with mg, mgpp, or lucene
195 // -- we can rely on the collection (and therefore the build.cfg)
196 // being here since this is the null protocol - a nicer way to
197 // do this would be preferable though - Stefan.
198 text_t buildtype = "mg"; // mg is default
199
200 text_tarray cfgline;
201 text_t key;
202 text_t build_cfg = filename_cat(gsdlhome, "collect", collection, "index", "build.cfg");
203 char *build_cfgc = build_cfg.getcstr();
204 ifstream confin(build_cfgc);
205
206 if (confin) {
207 while (read_cfg_line(confin, cfgline) >= 0) {
208 if (cfgline.size() == 2) {
209 key = cfgline[0];
210 cfgline.erase(cfgline.begin());
211 if (key == "buildtype") {
212 buildtype = cfgline[0];
213 break;
214 }
215 }
216 }
217 confin.close();
218 }
219 delete []build_cfgc;
220
221 collectserver *cserver = new collectserver();
222 gdbmclass *gdbmhandler = new gdbmclass();
223
224 // add a null filter
225 filterclass *filter = new filterclass ();
226 cserver->add_filter (filter);
227
228 // add a browse filter
229 browsefilterclass *browsefilter = new browsefilterclass();
230 browsefilter->set_gdbmptr (gdbmhandler);
231
232 cserver->add_filter (browsefilter);
233
234 if (buildtype == "mg") {
235 mgsearch = new mgsearchclass();
236
237 // add a query filter
238 mgqueryfilterclass *queryfilter = new mgqueryfilterclass();
239 queryfilter->set_gdbmptr (gdbmhandler);
240 queryfilter->set_textsearchptr (mgsearch);
241 cserver->add_filter (queryfilter);
242
243 // add a mg and gdbm source
244 mggdbmsourceclass *mggdbmsource = new mggdbmsourceclass ();
245 mggdbmsource->set_gdbmptr (gdbmhandler);
246 mggdbmsource->set_textsearchptr (mgsearch);
247 cserver->add_source (mggdbmsource);
248 }
249 else if (buildtype == "mgpp") {
250 mgppsearch = new mgppsearchclass();
251
252 // add a query filter
253 mgppqueryfilterclass *queryfilter = new mgppqueryfilterclass();
254 queryfilter->set_gdbmptr (gdbmhandler);
255 queryfilter->set_textsearchptr (mgppsearch);
256 cserver->add_filter (queryfilter);
257
258 // add a mg and gdbm source
259 mggdbmsourceclass *mggdbmsource = new mggdbmsourceclass ();
260 mggdbmsource->set_gdbmptr (gdbmhandler);
261 mggdbmsource->set_textsearchptr (mgppsearch);
262 cserver->add_source (mggdbmsource);
263 }
264 else if (buildtype == "lucene") {
265 lucenesearch = new lucenesearchclass();
266 lucenesearch->set_gsdlhome(gsdlhome);
267
268 // add a query filter
269 lucenequeryfilterclass *queryfilter = new lucenequeryfilterclass();
270 queryfilter->set_gdbmptr (gdbmhandler);
271 queryfilter->set_textsearchptr (lucenesearch);
272 cserver->add_filter (queryfilter);
273
274 // add a lucene and gdbm source
275 lucenegdbmsourceclass *lucenegdbmsource = new lucenegdbmsourceclass ();
276 lucenegdbmsource->set_gdbmptr (gdbmhandler);
277 lucenegdbmsource->set_textsearchptr (lucenesearch);
278 cserver->add_source (lucenegdbmsource);
279 }
280
281 // inform collection server and everything it contains about its
282 // collection name
283 cserver->configure ("collection", collection);
284 cserver->configure ("gsdlhome", gsdlhome);
285
286 cservers.addcollectserver (cserver);
287}
288
289void collectset::remove_all_collections () {
290
291 // first unload any cached mg databases
292 if (mgsearch != NULL) {
293 mgsearch->unload_database();
294 }
295
296 // now delete the collection server objects
297 collectservermapclass::iterator here = cservers.begin();
298 collectservermapclass::iterator end = cservers.end();
299
300 while (here != end) {
301 if ((*here).second.c != NULL) {
302 delete (*here).second.c;
303 }
304 ++here;
305 }
306 cservers.clear();
307}
308
309void collectset::add_collection_group(const text_t& collection,
310 const text_t& gsdlhome)
311{
312 text_tarray group;
313 text_t collect_group_dir = filename_cat (gsdlhome, "collect", collection);
314
315 // need to read collect.cfg for 'collectgroup' as class hasn't been initialised through 'init' yet
316 text_t is_collect_group;
317 text_tarray cfgline;
318 text_t key;
319 text_t build_cfg = filename_cat(gsdlhome, "collect", collection, "etc", "collect.cfg");
320 char *collect_cfgc = build_cfg.getcstr();
321 ifstream confin(collect_cfgc);
322
323 if (confin) {
324 while (read_cfg_line(confin, cfgline) >= 0) {
325 if (cfgline.size() == 2) {
326 key = cfgline[0];
327 cfgline.erase(cfgline.begin());
328 if (key == "collectgroup") {
329 is_collect_group = cfgline[0];
330 break;
331 }
332 }
333 }
334 confin.close();
335 }
336 delete []collect_cfgc;
337
338 if (is_collect_group == "true") {
339
340 if (read_dir (collect_group_dir, group)) {
341
342 text_tarray::const_iterator thiscol = group.begin();
343 text_tarray::const_iterator endcol = group.end();
344
345 while (thiscol != endcol) {
346 // ignore the modelcol
347 if (*thiscol == "etc") {
348 ++thiscol;
349 continue;
350 }
351
352 this->add_collection (collection + "/" + *thiscol, gsdlhome);
353
354 ++thiscol;
355 }
356 }
357 }
358}
359
360void collectset::add_all_collection_groups (const text_t& gsdlhome)
361
362{
363 collectservermapclass::iterator here = cservers.begin();
364 collectservermapclass::iterator end = cservers.end();
365
366 while (here != end) {
367 text_t collection = (*here).second.c->get_collection_name();
368 this->add_collection_group(collection,gsdlhome);
369
370 ++here;
371 }
372}
373
374
375// remove_collection deletes the collection server of collection.
376// This only needs to be called if a collectionserver is to be
377// removed while the library is running. The destructor function
378// cleans up all collectservers when the program exits.
379void collectset::remove_collection (const text_t &collection) {
380
381 // do nothing if no collection server exists for this collection
382 if (cservers.getcollectserver(collection) == NULL) return;
383
384 // first unload any cached mg databases - we may need to do something
385 // similar to this for mgpp and lucene too
386 if (mgsearch != NULL) {
387 mgsearch->unload_database();
388 }
389
390 // now delete the collection server object
391 collectservermapclass::iterator here = cservers.begin();
392 collectservermapclass::iterator end = cservers.end();
393
394 while (here != end) {
395 if ((*here).second.c != NULL && (*here).first == collection) {
396 delete (*here).second.c;
397 cservers.erase (here);
398 return;
399 }
400 ++here;
401 }
402}
403
404
405// remove_collection deletes the collection server of collection.
406// This only needs to be called if a collectionserver is to be
407// removed while the library is running. The destructor function
408// cleans up all collectservers when the program exits.
409void collectset::remove_collection (const text_t &collection, ostream &logout) {
410
411 remove_collection(collection);
412
413 outconvertclass text_t2ascii;
414 logout << text_t2ascii << "nullproto::remove_collection: failed to remove collectserver for "
415 << collection << "\n";
416}
417
418void collectset::configure(const text_t &key, const text_tarray &cfgline)
419{
420 if (key == "collection" || key == "collectdir") return;
421
422 collectservermapclass::iterator here = cservers.begin();
423 collectservermapclass::iterator end = cservers.end();
424
425 while (here != end) {
426 assert ((*here).second.c != NULL);
427 if ((*here).second.c != NULL) {
428 if (key == "collectinfo") {
429 if ((*here).first == cfgline[0]) {
430 (*here).second.c->configure ("gsdlhome", cfgline[1]);
431 (*here).second.c->configure ("gdbmhome", cfgline[2]);
432 }
433 } else {
434 (*here).second.c->configure (key, cfgline);
435 }
436 }
437
438 ++here;
439 }
440}
441
442void collectset::getCollectionList (text_tarray &collist)
443{
444 collist.erase(collist.begin(),collist.end());
445
446 collectservermapclass::iterator here = cservers.begin();
447 collectservermapclass::iterator end = cservers.end();
448 while (here != end) {
449 assert ((*here).second.c != NULL);
450 if ((*here).second.c != NULL) {
451 collist.push_back ((*here).second.c->get_collection_name());
452 }
453 ++here;
454 }
455}
Note: See TracBrowser for help on using the repository browser.