source: gsdl/trunk/runtime-src/src/colservr/collectset.cpp@ 18978

Last change on this file since 18978 was 18978, checked in by kjdon, 15 years ago

made group col use / instead of
- we check for this later. so now groups work on windows web library

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