/********************************************************************** * * collectserver.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 "collectserver.h" #include "infodbclass.h" #include "OIDtools.h" #include collectserver::collectserver () { configinfo.collection = "null"; } collectserver::~collectserver () { // clean up the sources sourcelistclass::iterator source_here = sources.begin(); sourcelistclass::iterator source_end = sources.end(); while (source_here != source_end) { if ((*source_here).s != NULL) delete (*source_here).s; source_here++; } sources.clear(); // clean up the filters filtermapclass::iterator filter_here = filters.begin(); filtermapclass::iterator filter_end = filters.end(); while (filter_here != filter_end) { if ((*filter_here).second.f != NULL) delete (*filter_here).second.f; filter_here++; } filters.clear(); } // configure should be called for each line in the // configuration files to configure the collection server and everything // it contains. The configuration should take place just before initialisation. void collectserver::configure (const text_t &key, const text_tarray &cfgline) { if (cfgline.size() >= 1) { const text_t &value = cfgline[0]; if (key == "gsdlhome") configinfo.gsdlhome = value; else if (key == "gdbmhome") configinfo.gdbmhome = value; else if (key == "collection") { configinfo.collection = value; collectinfo.shortInfo.name = value; } else if (key == "collectdir") configinfo.collectdir = value; else if (key == "host") collectinfo.shortInfo.host = value; else if (key == "port") collectinfo.shortInfo.port = value.getint(); else if (key == "public") { if (value == "true") collectinfo.isPublic = true; else collectinfo.isPublic = false; } else if (key == "beta") { if (value == "true") collectinfo.isBeta = true; else collectinfo.isBeta = false; } else if (key == "ccscols") collectinfo.ccsCols = cfgline; else if (key == "builddate") collectinfo.buildDate = value.getint(); else if (key == "languages") collectinfo.languages = cfgline; else if (key == "numdocs") collectinfo.numDocs = value.getint(); else if (key == "numsections") collectinfo.numSections = value.getint(); else if (key == "numwords") collectinfo.numWords = value.getint(); else if (key == "numbytes") collectinfo.numBytes = value.getint(); else if (key == "collectionmeta" && cfgline.size() == 2) collectinfo.collectionmeta[cfgline[0]] = cfgline[1]; else if (key == "format" && cfgline.size() == 2) collectinfo.format[cfgline[0]] = cfgline[1]; else if (key == "building" && cfgline.size() == 2) collectinfo.building[cfgline[0]] = cfgline[1]; else if (key == "httpdomain") collectinfo.httpdomain = value; else if (key == "httpprefix") collectinfo.httpprefix = value; else if (key == "receptionist") collectinfo.receptionist = value; else if (key == "buildtype") collectinfo.buildType = value; } // configure the filters filtermapclass::iterator filter_here = filters.begin(); filtermapclass::iterator filter_end = filters.end(); while (filter_here != filter_end) { assert ((*filter_here).second.f != NULL); if ((*filter_here).second.f != NULL) (*filter_here).second.f->configure(key, cfgline); filter_here++; } // configure the sources sourcelistclass::iterator source_here = sources.begin(); sourcelistclass::iterator source_end = sources.end(); while (source_here != source_end) { assert ((*source_here).s != NULL); if ((*source_here).s != NULL) (*source_here).s->configure(key, cfgline); source_here++; } } void collectserver::configure (const text_t &key, const text_t &value) { text_tarray cfgline; cfgline.push_back (value); configure(key, cfgline); } void collectserver::ping (bool &wasSuccess, comerror_t &error, ostream &logout) { // if we've not been properly configured, then it is a foregone // conclusion that we cannot be active if (this->configinfo.collection == "null") { wasSuccess = false; } // if no build date exists, then the collection was probably not built; // ditto if the number of documents is zero, then something is pretty // wrong else if (this->collectinfo.buildDate == 0 || this->collectinfo.numDocs == 0) { wasSuccess = false; } // it is probably okay else wasSuccess = true; } bool collectserver::init (ostream &logout) { // init the filters filtermapclass::iterator filter_here = filters.begin(); filtermapclass::iterator filter_end = filters.end(); while (filter_here != filter_end) { assert ((*filter_here).second.f != NULL); if (((*filter_here).second.f != NULL) && !(*filter_here).second.f->init(logout)) return false; filter_here++; } // init the sources sourcelistclass::iterator source_here = sources.begin(); sourcelistclass::iterator source_end = sources.end(); while (source_here != source_end) { assert ((*source_here).s != NULL); if (((*source_here).s != NULL) && !(*source_here).s->init(logout)) return false; source_here++; } return true; } void collectserver::get_collectinfo (ColInfoResponse_t &reponse, comerror_t &err, ostream &/*logout*/) { reponse = collectinfo; err = noError; } void collectserver::get_filterinfo (InfoFiltersResponse_t &response, comerror_t &err, ostream &/*logout*/) { response.clear (); // get a list of filter names filtermapclass::iterator filter_here = filters.begin(); filtermapclass::iterator filter_end = filters.end(); while (filter_here != filter_end) { response.filterNames.insert ((*filter_here).first); filter_here++; } err = noError; } void collectserver::get_filteroptions (const InfoFilterOptionsRequest_t &request, InfoFilterOptionsResponse_t &response, comerror_t &err, ostream &logout) { outconvertclass text_t2ascii; filterclass *thisfilter = filters.getfilter(request.filterName); if (thisfilter != NULL) { thisfilter->get_filteroptions (response, err, logout); } else { response.clear (); err = protocolError; logout << text_t2ascii << "Protocol Error: filter options requested for non-existent\n" << "filter \"" << request.filterName << "\".\n\n"; } } void collectserver::filter (FilterRequest_t &request, FilterResponse_t &response, comerror_t &err, ostream &logout) { outconvertclass text_t2ascii; // translate any ".fc", ".pr" etc. stuff in the docSet text_t translatedOID; text_tarray translatedOIDs; text_tarray::iterator doc_here = request.docSet.begin(); text_tarray::iterator doc_end = request.docSet.end(); while (doc_here != doc_end) { if (needs_translating (*doc_here)) { sourcelistclass::iterator source_here = sources.begin(); sourcelistclass::iterator source_end = sources.end(); while (source_here != source_end) { assert ((*source_here).s != NULL); if (((*source_here).s != NULL) && ((*source_here).s->translate_OID (*doc_here, translatedOID, err, logout))) { if (err != noError) return; break; } source_here++; } translatedOIDs.push_back (translatedOID); } else { translatedOIDs.push_back (*doc_here); } doc_here ++; } request.docSet = translatedOIDs; response.clear(); filterclass *thisfilter = filters.getfilter(request.filterName); if (thisfilter != NULL) { // filter the data thisfilter->filter (request, response, err, logout); // fill in the metadata for each of the OIDs (if it is requested) if (request.filterResultOptions & FRmetadata) { bool processed = false; ResultDocInfo_tarray::iterator resultdoc_here = response.docInfo.begin(); ResultDocInfo_tarray::iterator resultdoc_end = response.docInfo.end(); while (resultdoc_here != resultdoc_end) { // try each of the sources in turn sourcelistclass::iterator source_here = sources.begin(); sourcelistclass::iterator source_end = sources.end(); while (source_here != source_end) { assert ((*source_here).s != NULL); if (((*source_here).s != NULL) && ((*source_here).s->get_metadata(request.requestParams, request.refParams, request.getParents, request.fields, (*resultdoc_here).OID, (*resultdoc_here).metadata, err, logout))) { if (err != noError) return; processed = true; break; } source_here++; } if (!processed) { err = protocolError; return; } resultdoc_here++; } } } else { response.clear (); err = protocolError; logout << text_t2ascii << "Protocol Error: filter options requested for non-existent\n" << "filter \"" << request.filterName << "\".\n\n"; } err = noError; } void collectserver::get_document (const DocumentRequest_t &request, DocumentResponse_t &response, comerror_t &err, ostream &logout) { sourcelistclass::iterator source_here = sources.begin(); sourcelistclass::iterator source_end = sources.end(); while (source_here != source_end) { assert ((*source_here).s != NULL); if (((*source_here).s != NULL) && ((*source_here).s->get_document (request.OID, response.doc, err, logout))) { if (err != noError) return; break; } source_here++; } } bool operator==(const collectserverptr &x, const collectserverptr &y) { return (x.c == y.c); } bool operator<(const collectserverptr &x, const collectserverptr &y) { return (x.c < y.c); } // thecollectserver remains the property of the calling code but // should not be deleted until it is removed from this list. void collectservermapclass::addcollectserver (collectserver *thecollectserver) { // can't add a null collection server assert (thecollectserver != NULL); if (thecollectserver == NULL) return; // can't add an collection server with no collection name assert (!(thecollectserver->get_collection_name()).empty()); if ((thecollectserver->get_collection_name()).empty()) return; collectserverptr cptr; cptr.c = thecollectserver; collectserverptrs[thecollectserver->get_collection_name()] = cptr; } // getcollectserver will return NULL if the collectserver could not be found collectserver *collectservermapclass::getcollectserver (const text_t &collection) { // can't find a collection with no name if (collection.empty()) return NULL; iterator here = collectserverptrs.find (collection); if (here == collectserverptrs.end()) return NULL; return (*here).second.c; }