root/gsdl/trunk/runtime-src/src/colservr/collectset.cpp @ 19788

Revision 19788, 14.8 KB (checked in by kjdon, 10 years ago)

moved the text for existence of build.cfg out of w32server/cgiwrapper and into colserver/collectset. This was preventing collect groups from being loaded up as they are not built. Now, unbuilt collections will not be loaded up for linux either

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