root/gsdl/trunk/src/colservr/collectset.cpp @ 15759

Revision 15759, 13.0 KB (checked in by mdewsnip, 11 years ago)

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

  • Property svn:keywords set to Author Date Id Revision
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 browser.