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

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

(Adding dynamic classifiers) Now creates a sqlbrowsefilter if sqlite is being used.

  • Property svn:keywords set to Author Date Id Revision
File size: 13.0 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 "gdbmclass.h"
32#include "fileutil.h"
33#include "filter.h"
34#include "browsefilter.h"
35#include "sqlbrowsefilter.h"
36#include "queryfilter.h"
37#include "mgqueryfilter.h"
38#include "mgppqueryfilter.h"
39#include "mgsource.h"
40#include "lucenequeryfilter.h"
41#include "lucenesource.h"
42
43#include <assert.h>
44
45#ifdef USE_SQLITE
46#include "sqlitedbclass.h"
47#endif
48
49
50collectset::collectset (text_t &gsdlhome) {
51
52 text_tarray collections;
53 text_t collectdir;
54
55 // get gsdlhome (if we fail the error will be picked up later -- in
56 // cgiwrapper)
57
58 if (site_cfg_read (gsdlhome, httpdomain, httpprefix)) {
59 if (!gsdlhome.empty() && directory_exists(gsdlhome)) {
60 collectdir = filename_cat (gsdlhome, "collect");
61 if (read_dir (collectdir, collections)) {
62
63 text_tarray::const_iterator thiscol = collections.begin();
64 text_tarray::const_iterator endcol = collections.end();
65
66 while (thiscol != endcol) {
67 // ignore the modelcol
68 if (*thiscol == "modelcol") {
69 ++thiscol;
70 continue;
71 }
72
73 this->add_collection (*thiscol, gsdlhome);
74
75 ++thiscol;
76 }
77
78 this->add_all_collection_groups(gsdlhome);
79 }
80 }
81 }
82}
83
84collectset::~collectset () {
85 collectservermapclass::iterator here = cservers.begin();
86 collectservermapclass::iterator end = cservers.end();
87
88 while (here != end) {
89 if ((*here).second.c != NULL) {
90 delete (*here).second.c;
91 }
92 ++here;
93 }
94 cservers.clear();
95}
96
97bool collectset::init (ostream &logout) {
98 collectservermapclass::iterator here = cservers.begin();
99 collectservermapclass::iterator end = cservers.end();
100
101 while (here != end) {
102 assert ((*here).second.c != NULL);
103 if ((*here).second.c != NULL) {
104 const colservrconf &configinfo = (*here).second.c->get_configinfo ();
105
106 // configure this collection server
107
108 // note that we read build.cfg before collect.cfg so that the indexmaps
109 // are available to decode defaultindex, defaultsubcollection, and
110 // defaultlanguage
111
112 bool failed_build_cfg = false;
113 if (!build_cfg_read (*((*here).second.c), configinfo.gsdlhome,
114 configinfo.collection)) {
115 failed_build_cfg = true;
116
117 outconvertclass text_t2ascii;
118 logout << text_t2ascii
119 << "Warning: couldn't read build.cfg file for collection \"" //****
120 << configinfo.collection << "\", gsdlhome=\""
121 << configinfo.gsdlhome << "\"\n";
122 }
123
124 bool failed_collect_cfg = false;
125 if (!collect_cfg_read (*((*here).second.c), configinfo.gsdlhome,
126 configinfo.collection)) {
127 failed_collect_cfg = true;
128 outconvertclass text_t2ascii;
129 logout << text_t2ascii
130 << "Warning: couldn't read collect.cfg file for collection \""
131 << configinfo.collection << "\", gsdlhome=\""
132 << configinfo.gsdlhome << "\"\n";
133 }
134
135
136 bool is_colgroup = (*here).second.c->is_collection_group();
137
138 if (failed_collect_cfg) {
139 ++here;
140 continue;
141 }
142
143 if (failed_build_cfg && (!is_colgroup)) {
144 ++here;
145 continue;
146 }
147 // let a failed build.cfg through if its 'collect.cfg' marks it as 'collectgroup true'
148
149 if (!(*here).second.c->init (logout)) return false;
150
151 (*here).second.c->configure("httpdomain",httpdomain);
152 (*here).second.c->configure("httpprefix",httpprefix);
153 }
154 ++here;
155 }
156
157 return true;
158}
159
160collectservermapclass collectset::servers()
161{ return cservers;
162}
163
164
165void collectset::add_all_collections(const text_t &gsdlhome) {
166
167 text_tarray collections;
168 text_t collectdir = filename_cat(gsdlhome, "collect");
169 if (read_dir(collectdir, collections)) {
170
171 text_tarray::const_iterator thiscol = collections.begin();
172 text_tarray::const_iterator endcol = collections.end();
173
174 while (thiscol != endcol) {
175
176 // ignore the modelcol
177 if (*thiscol == "modelcol") {
178 ++thiscol;
179 continue;
180 }
181
182 // create collection server for this collection
183 this->add_collection (*thiscol, gsdlhome);
184
185 ++thiscol;
186 }
187
188 this->add_all_collection_groups(gsdlhome);
189 }
190}
191
192// add_collection sets up the collectionserver and calls
193// add_collectserver
194void collectset::add_collection (const text_t &collection,
195 const text_t &gsdlhome) {
196
197 this->remove_collection(collection);
198
199 // read config file to see if built with mg, mgpp, or lucene
200 text_t buildtype = "mg"; // mg is default
201 text_t infodbtype = "gdbm"; // gdbm is default
202
203 text_tarray cfgline;
204 text_t key;
205 text_t build_cfg = filename_cat(gsdlhome, "collect", collection, "index", "build.cfg");
206 char *build_cfgc = build_cfg.getcstr();
207 ifstream confin(build_cfgc);
208
209 if (confin) {
210 while (read_cfg_line(confin, cfgline) >= 0) {
211 if (cfgline.size() == 2) {
212 key = cfgline[0];
213 cfgline.erase(cfgline.begin());
214 if (key == "buildtype") {
215 buildtype = cfgline[0];
216 }
217 if (key == "infodbtype") {
218 infodbtype = cfgline[0];
219 }
220 }
221 }
222 confin.close();
223 }
224 delete []build_cfgc;
225
226 collectserver *cserver = new collectserver();
227
228 // Create a dbclass of the correct type
229 dbclass *db_ptr = NULL;
230
231#ifdef USE_SQLITE
232 if (infodbtype == "sqlite")
233 {
234 sqlitedbclass *sql_db_ptr = new sqlitedbclass();
235 db_ptr = sql_db_ptr;
236
237 // add a sql browse filter
238 sqlbrowsefilterclass *sqlbrowsefilter = new sqlbrowsefilterclass();
239 sqlbrowsefilter->set_sql_db_ptr(sql_db_ptr);
240 cserver->add_filter (sqlbrowsefilter);
241 }
242#endif
243
244 // Use GDBM if the infodb type is empty or not one of the values above
245 if (db_ptr == NULL)
246 {
247 db_ptr = new gdbmclass();
248 }
249
250 // add a null filter
251 filterclass *filter = new filterclass ();
252 cserver->add_filter (filter);
253
254 // add a browse filter
255 browsefilterclass *browsefilter = new browsefilterclass();
256 browsefilter->set_db_ptr(db_ptr);
257 cserver->add_filter (browsefilter);
258
259 if (buildtype == "mg") {
260 mgsearch = new mgsearchclass();
261
262 // add a query filter
263 mgqueryfilterclass *queryfilter = new mgqueryfilterclass();
264 queryfilter->set_db_ptr(db_ptr);
265 queryfilter->set_textsearchptr (mgsearch);
266 cserver->add_filter (queryfilter);
267
268 // add a mg source
269 mgsourceclass *mgsource = new mgsourceclass ();
270 mgsource->set_db_ptr(db_ptr);
271 mgsource->set_textsearchptr (mgsearch);
272 cserver->add_source (mgsource);
273 }
274 else if (buildtype == "mgpp") {
275 mgppsearch = new mgppsearchclass();
276
277 // add a query filter
278 mgppqueryfilterclass *queryfilter = new mgppqueryfilterclass();
279 queryfilter->set_db_ptr(db_ptr);
280 queryfilter->set_textsearchptr (mgppsearch);
281 cserver->add_filter (queryfilter);
282
283 // add a mg source
284 mgsourceclass *mgsource = new mgsourceclass ();
285 mgsource->set_db_ptr(db_ptr);
286 mgsource->set_textsearchptr (mgppsearch);
287 cserver->add_source (mgsource);
288 }
289 else if (buildtype == "lucene") {
290 lucenesearch = new lucenesearchclass();
291 lucenesearch->set_gsdlhome(gsdlhome);
292
293 // add a query filter
294 lucenequeryfilterclass *queryfilter = new lucenequeryfilterclass();
295 queryfilter->set_db_ptr(db_ptr);
296 queryfilter->set_textsearchptr (lucenesearch);
297 cserver->add_filter (queryfilter);
298
299 // add a lucene source
300 lucenesourceclass *lucenesource = new lucenesourceclass ();
301 lucenesource->set_db_ptr(db_ptr);
302 lucenesource->set_textsearchptr (lucenesearch);
303 cserver->add_source (lucenesource);
304 }
305
306 // inform collection server and everything it contains about its
307 // collection name
308 cserver->configure ("collection", collection);
309 cserver->configure ("gsdlhome", gsdlhome);
310
311 cservers.addcollectserver (cserver);
312}
313
314void collectset::remove_all_collections () {
315
316 // first unload any cached mg databases
317 if (mgsearch != NULL) {
318 mgsearch->unload_database();
319 }
320
321 // now delete the collection server objects
322 collectservermapclass::iterator here = cservers.begin();
323 collectservermapclass::iterator end = cservers.end();
324
325 while (here != end) {
326 if ((*here).second.c != NULL) {
327 delete (*here).second.c;
328 }
329 ++here;
330 }
331 cservers.clear();
332}
333
334void collectset::add_collection_group(const text_t& collection,
335 const text_t& gsdlhome)
336{
337 text_tarray group;
338 text_t collect_group_dir = filename_cat (gsdlhome, "collect", collection);
339
340 // need to read collect.cfg for 'collectgroup' as class hasn't been initialised through 'init' yet
341 text_t is_collect_group;
342 text_tarray cfgline;
343 text_t key;
344 text_t build_cfg = filename_cat(gsdlhome, "collect", collection, "etc", "collect.cfg");
345 char *collect_cfgc = build_cfg.getcstr();
346 ifstream confin(collect_cfgc);
347
348 if (confin) {
349 while (read_cfg_line(confin, cfgline) >= 0) {
350 if (cfgline.size() == 2) {
351 key = cfgline[0];
352 cfgline.erase(cfgline.begin());
353 if (key == "collectgroup") {
354 is_collect_group = cfgline[0];
355 break;
356 }
357 }
358 }
359 confin.close();
360 }
361 delete []collect_cfgc;
362
363 if (is_collect_group == "true") {
364
365 if (read_dir (collect_group_dir, group)) {
366
367 text_tarray::const_iterator thiscol = group.begin();
368 text_tarray::const_iterator endcol = group.end();
369
370 while (thiscol != endcol) {
371 // ignore the modelcol
372 if (*thiscol == "etc") {
373 ++thiscol;
374 continue;
375 }
376
377 this->add_collection (collection + "/" + *thiscol, gsdlhome);
378
379 ++thiscol;
380 }
381 }
382 }
383}
384
385void collectset::add_all_collection_groups (const text_t& gsdlhome)
386
387{
388 collectservermapclass::iterator here = cservers.begin();
389 collectservermapclass::iterator end = cservers.end();
390
391 while (here != end) {
392 text_t collection = (*here).second.c->get_collection_name();
393 this->add_collection_group(collection,gsdlhome);
394
395 ++here;
396 }
397}
398
399
400// remove_collection deletes the collection server of collection.
401// This only needs to be called if a collectionserver is to be
402// removed while the library is running. The destructor function
403// cleans up all collectservers when the program exits.
404void collectset::remove_collection (const text_t &collection) {
405
406 // do nothing if no collection server exists for this collection
407 if (cservers.getcollectserver(collection) == NULL) return;
408
409 // first unload any cached mg databases - we may need to do something
410 // similar to this for mgpp and lucene too
411 if (mgsearch != NULL) {
412 mgsearch->unload_database();
413 }
414
415 // now delete the collection server object
416 collectservermapclass::iterator here = cservers.begin();
417 collectservermapclass::iterator end = cservers.end();
418
419 while (here != end) {
420 if ((*here).second.c != NULL && (*here).first == collection) {
421 delete (*here).second.c;
422 cservers.erase (here);
423 return;
424 }
425 ++here;
426 }
427}
428
429
430// remove_collection deletes the collection server of collection.
431// This only needs to be called if a collectionserver is to be
432// removed while the library is running. The destructor function
433// cleans up all collectservers when the program exits.
434void collectset::remove_collection (const text_t &collection, ostream &logout) {
435
436 remove_collection(collection);
437
438 outconvertclass text_t2ascii;
439 logout << text_t2ascii << "collectset::remove_collection: failed to remove collectserver for "
440 << collection << "\n";
441}
442
443void collectset::configure(const text_t &key, const text_tarray &cfgline)
444{
445 if (key == "collection" || key == "collectdir") return;
446
447 collectservermapclass::iterator here = cservers.begin();
448 collectservermapclass::iterator end = cservers.end();
449
450 while (here != end) {
451 assert ((*here).second.c != NULL);
452 if ((*here).second.c != NULL) {
453 if (key == "collectinfo") {
454 if ((*here).first == cfgline[0]) {
455 (*here).second.c->configure ("gsdlhome", cfgline[1]);
456 (*here).second.c->configure ("gdbmhome", cfgline[2]);
457 }
458 } else {
459 (*here).second.c->configure (key, cfgline);
460 }
461 }
462
463 ++here;
464 }
465}
466
467void collectset::getCollectionList (text_tarray &collist)
468{
469 collist.erase(collist.begin(),collist.end());
470
471 collectservermapclass::iterator here = cservers.begin();
472 collectservermapclass::iterator end = cservers.end();
473 while (here != end) {
474 assert ((*here).second.c != NULL);
475 if ((*here).second.c != NULL) {
476 collist.push_back ((*here).second.c->get_collection_name());
477 }
478 ++here;
479 }
480}
Note: See TracBrowser for help on using the repository browser.