/********************************************************************** * * collectset.cpp -- * Copyright (C) 1999 The New Zealand Digital Library Project * * A component of the Greenstone digital library software * from the New Zealand Digital Library Project at the * University of Waikato, New Zealand. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * *********************************************************************/ #include "collectset.h" #include "collectserver.h" #include "colservrconfig.h" #include "gsdlsitecfg.h" #include "gdbmclass.h" #include "fileutil.h" #include "filter.h" #include "browsefilter.h" #include "sqlbrowsefilter.h" #include "queryfilter.h" #include "mgqueryfilter.h" #include "mgppqueryfilter.h" #include "mgsource.h" #include "lucenequeryfilter.h" #include "lucenesource.h" #include #ifdef USE_SQLITE #include "sqlitedbclass.h" #endif collectset::collectset (text_t &gsdlhome) { text_tarray collections; text_t collectdir; // get gsdlhome (if we fail the error will be picked up later -- in // cgiwrapper) if (site_cfg_read (gsdlhome, httpdomain, httpprefix)) { if (!gsdlhome.empty() && directory_exists(gsdlhome)) { collectdir = filename_cat (gsdlhome, "collect"); if (read_dir (collectdir, collections)) { text_tarray::const_iterator thiscol = collections.begin(); text_tarray::const_iterator endcol = collections.end(); while (thiscol != endcol) { // ignore the modelcol if (*thiscol == "modelcol") { ++thiscol; continue; } this->add_collection (*thiscol, gsdlhome); ++thiscol; } this->add_all_collection_groups(gsdlhome); } } } } collectset::~collectset () { collectservermapclass::iterator here = cservers.begin(); collectservermapclass::iterator end = cservers.end(); while (here != end) { if ((*here).second.c != NULL) { delete (*here).second.c; } ++here; } cservers.clear(); } bool collectset::init (ostream &logout) { collectservermapclass::iterator here = cservers.begin(); collectservermapclass::iterator end = cservers.end(); while (here != end) { assert ((*here).second.c != NULL); if ((*here).second.c != NULL) { const colservrconf &configinfo = (*here).second.c->get_configinfo (); // configure this collection server // note that we read build.cfg before collect.cfg so that the indexmaps // are available to decode defaultindex, defaultsubcollection, and // defaultlanguage bool failed_build_cfg = false; if (!build_cfg_read (*((*here).second.c), configinfo.gsdlhome, configinfo.collection)) { failed_build_cfg = true; outconvertclass text_t2ascii; logout << text_t2ascii << "Warning: couldn't read build.cfg file for collection \"" //**** << configinfo.collection << "\", gsdlhome=\"" << configinfo.gsdlhome << "\"\n"; } bool failed_collect_cfg = false; if (!collect_cfg_read (*((*here).second.c), configinfo.gsdlhome, configinfo.collection)) { failed_collect_cfg = true; outconvertclass text_t2ascii; logout << text_t2ascii << "Warning: couldn't read collect.cfg file for collection \"" << configinfo.collection << "\", gsdlhome=\"" << configinfo.gsdlhome << "\"\n"; } bool is_colgroup = (*here).second.c->is_collection_group(); if (failed_collect_cfg) { ++here; continue; } if (failed_build_cfg && (!is_colgroup)) { ++here; continue; } // let a failed build.cfg through if its 'collect.cfg' marks it as 'collectgroup true' if (!(*here).second.c->init (logout)) return false; (*here).second.c->configure("httpdomain",httpdomain); (*here).second.c->configure("httpprefix",httpprefix); } ++here; } return true; } collectservermapclass collectset::servers() { return cservers; } void collectset::add_all_collections(const text_t &gsdlhome) { text_tarray collections; text_t collectdir = filename_cat(gsdlhome, "collect"); if (read_dir(collectdir, collections)) { text_tarray::const_iterator thiscol = collections.begin(); text_tarray::const_iterator endcol = collections.end(); while (thiscol != endcol) { // ignore the modelcol if (*thiscol == "modelcol") { ++thiscol; continue; } // create collection server for this collection this->add_collection (*thiscol, gsdlhome); ++thiscol; } this->add_all_collection_groups(gsdlhome); } } // add_collection sets up the collectionserver and calls // add_collectserver void collectset::add_collection (const text_t &collection, const text_t &gsdlhome) { this->remove_collection(collection); // read config file to see if built with mg, mgpp, or lucene text_t buildtype = "mg"; // mg is default text_t infodbtype = "gdbm"; // gdbm is default text_tarray cfgline; text_t key; text_t build_cfg = filename_cat(gsdlhome, "collect", collection, "index", "build.cfg"); char *build_cfgc = build_cfg.getcstr(); ifstream confin(build_cfgc); if (confin) { while (read_cfg_line(confin, cfgline) >= 0) { if (cfgline.size() == 2) { key = cfgline[0]; cfgline.erase(cfgline.begin()); if (key == "buildtype") { buildtype = cfgline[0]; } if (key == "infodbtype") { infodbtype = cfgline[0]; } } } confin.close(); } delete []build_cfgc; collectserver *cserver = new collectserver(); // Create a dbclass of the correct type dbclass *db_ptr = NULL; #ifdef USE_SQLITE if (infodbtype == "sqlite") { sqlitedbclass *sql_db_ptr = new sqlitedbclass(); db_ptr = sql_db_ptr; // add a sql browse filter sqlbrowsefilterclass *sqlbrowsefilter = new sqlbrowsefilterclass(); sqlbrowsefilter->set_sql_db_ptr(sql_db_ptr); cserver->add_filter (sqlbrowsefilter); } #endif // Use GDBM if the infodb type is empty or not one of the values above if (db_ptr == NULL) { db_ptr = new gdbmclass(); } // add a null filter filterclass *filter = new filterclass (); cserver->add_filter (filter); // add a browse filter browsefilterclass *browsefilter = new browsefilterclass(); browsefilter->set_db_ptr(db_ptr); cserver->add_filter (browsefilter); if (buildtype == "mg") { mgsearch = new mgsearchclass(); // add a query filter mgqueryfilterclass *queryfilter = new mgqueryfilterclass(); queryfilter->set_db_ptr(db_ptr); queryfilter->set_textsearchptr (mgsearch); cserver->add_filter (queryfilter); // add a mg source mgsourceclass *mgsource = new mgsourceclass (); mgsource->set_db_ptr(db_ptr); mgsource->set_textsearchptr (mgsearch); cserver->add_source (mgsource); } else if (buildtype == "mgpp") { mgppsearch = new mgppsearchclass(); // add a query filter mgppqueryfilterclass *queryfilter = new mgppqueryfilterclass(); queryfilter->set_db_ptr(db_ptr); queryfilter->set_textsearchptr (mgppsearch); cserver->add_filter (queryfilter); // add a mg source mgsourceclass *mgsource = new mgsourceclass (); mgsource->set_db_ptr(db_ptr); mgsource->set_textsearchptr (mgppsearch); cserver->add_source (mgsource); } else if (buildtype == "lucene") { lucenesearch = new lucenesearchclass(); lucenesearch->set_gsdlhome(gsdlhome); // add a query filter lucenequeryfilterclass *queryfilter = new lucenequeryfilterclass(); queryfilter->set_db_ptr(db_ptr); queryfilter->set_textsearchptr (lucenesearch); cserver->add_filter (queryfilter); // add a lucene source lucenesourceclass *lucenesource = new lucenesourceclass (); lucenesource->set_db_ptr(db_ptr); lucenesource->set_textsearchptr (lucenesearch); cserver->add_source (lucenesource); } // inform collection server and everything it contains about its // collection name cserver->configure ("collection", collection); cserver->configure ("gsdlhome", gsdlhome); cservers.addcollectserver (cserver); } void collectset::remove_all_collections () { // first unload any cached mg databases if (mgsearch != NULL) { mgsearch->unload_database(); } // now delete the collection server objects collectservermapclass::iterator here = cservers.begin(); collectservermapclass::iterator end = cservers.end(); while (here != end) { if ((*here).second.c != NULL) { delete (*here).second.c; } ++here; } cservers.clear(); } void collectset::add_collection_group(const text_t& collection, const text_t& gsdlhome) { text_tarray group; text_t collect_group_dir = filename_cat (gsdlhome, "collect", collection); // need to read collect.cfg for 'collectgroup' as class hasn't been initialised through 'init' yet text_t is_collect_group; text_tarray cfgline; text_t key; text_t build_cfg = filename_cat(gsdlhome, "collect", collection, "etc", "collect.cfg"); char *collect_cfgc = build_cfg.getcstr(); ifstream confin(collect_cfgc); if (confin) { while (read_cfg_line(confin, cfgline) >= 0) { if (cfgline.size() == 2) { key = cfgline[0]; cfgline.erase(cfgline.begin()); if (key == "collectgroup") { is_collect_group = cfgline[0]; break; } } } confin.close(); } delete []collect_cfgc; if (is_collect_group == "true") { if (read_dir (collect_group_dir, group)) { text_tarray::const_iterator thiscol = group.begin(); text_tarray::const_iterator endcol = group.end(); while (thiscol != endcol) { // ignore the modelcol if (*thiscol == "etc") { ++thiscol; continue; } this->add_collection (collection + "/" + *thiscol, gsdlhome); ++thiscol; } } } } void collectset::add_all_collection_groups (const text_t& gsdlhome) { collectservermapclass::iterator here = cservers.begin(); collectservermapclass::iterator end = cservers.end(); while (here != end) { text_t collection = (*here).second.c->get_collection_name(); this->add_collection_group(collection,gsdlhome); ++here; } } // remove_collection deletes the collection server of collection. // This only needs to be called if a collectionserver is to be // removed while the library is running. The destructor function // cleans up all collectservers when the program exits. void collectset::remove_collection (const text_t &collection) { // do nothing if no collection server exists for this collection if (cservers.getcollectserver(collection) == NULL) return; // first unload any cached mg databases - we may need to do something // similar to this for mgpp and lucene too if (mgsearch != NULL) { mgsearch->unload_database(); } // now delete the collection server object collectservermapclass::iterator here = cservers.begin(); collectservermapclass::iterator end = cservers.end(); while (here != end) { if ((*here).second.c != NULL && (*here).first == collection) { delete (*here).second.c; cservers.erase (here); return; } ++here; } } // remove_collection deletes the collection server of collection. // This only needs to be called if a collectionserver is to be // removed while the library is running. The destructor function // cleans up all collectservers when the program exits. void collectset::remove_collection (const text_t &collection, ostream &logout) { remove_collection(collection); outconvertclass text_t2ascii; logout << text_t2ascii << "collectset::remove_collection: failed to remove collectserver for " << collection << "\n"; } void collectset::configure(const text_t &key, const text_tarray &cfgline) { if (key == "collection" || key == "collectdir") return; collectservermapclass::iterator here = cservers.begin(); collectservermapclass::iterator end = cservers.end(); while (here != end) { assert ((*here).second.c != NULL); if ((*here).second.c != NULL) { if (key == "collectinfo") { if ((*here).first == cfgline[0]) { (*here).second.c->configure ("gsdlhome", cfgline[1]); (*here).second.c->configure ("gdbmhome", cfgline[2]); } } else { (*here).second.c->configure (key, cfgline); } } ++here; } } void collectset::getCollectionList (text_tarray &collist) { collist.erase(collist.begin(),collist.end()); collectservermapclass::iterator here = cservers.begin(); collectservermapclass::iterator end = cservers.end(); while (here != end) { assert ((*here).second.c != NULL); if ((*here).second.c != NULL) { collist.push_back ((*here).second.c->get_collection_name()); } ++here; } }