source: gsdl/trunk/src/colservr/gdbmsource.cpp@ 15584

Last change on this file since 15584 was 15584, checked in by mdewsnip, 16 years ago

(Adding new DB support) Changed the gdbmsource classes to use dbclass instead of gdbmclass, as part of reducing the dependence on gdbm.

  • Property svn:keywords set to Author Date Id Revision
File size: 11.3 KB
Line 
1/**********************************************************************
2 *
3 * gdbmsource.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#include "gdbmsource.h"
27#include "fileutil.h"
28#include "OIDtools.h"
29#include "gsdltools.h"
30
31
32gdbmsourceclass::gdbmsourceclass () {
33 db_ptr = NULL;
34 textsearchptr = NULL;
35 classname = "gdbmsource";
36}
37
38gdbmsourceclass::~gdbmsourceclass () {
39 if (db_ptr != NULL) delete db_ptr;
40 if (textsearchptr != NULL) delete textsearchptr;
41}
42
43void gdbmsourceclass::configure (const text_t &key, const text_tarray &cfgline) {
44 if (cfgline.size() >= 1) {
45 const text_t &value = cfgline[0];
46
47 if (key == "collection") collection = value;
48 else if (key == "collectdir") collectdir = value;
49 else if (key == "gsdlhome") gsdlhome = value;
50 else if (key == "gdbmhome") gdbmhome = value;
51 }
52
53 if (key == "indexmap") {
54 indexmap.importmap (cfgline);
55
56 } else if (key == "defaultindex") {
57 indexmap.from2to (cfgline[0], defaultindex);
58
59 } else if (key == "subcollectionmap") {
60 subcollectionmap.importmap (cfgline);
61
62 } else if (key == "defaultsubcollection") {
63 subcollectionmap.from2to (cfgline[0], defaultsubcollection);
64
65 } else if (key == "languagemap") {
66 languagemap.importmap (cfgline);
67
68 } else if (key == "defaultlanguage") {
69 languagemap.from2to (cfgline[0], defaultlanguage);
70 } else if (key == "indexstem") {
71 indexstem = cfgline[0];
72 }
73
74}
75
76bool gdbmsourceclass::init (ostream &logout) {
77 outconvertclass text_t2ascii;
78
79 if (gdbmhome.empty()) gdbmhome = gsdlhome;
80
81 if (!sourceclass::init (logout)) return false;
82
83 if (defaultindex.empty()) {
84 // use first index in map as default if no default is set explicitly
85 text_tarray toarray;
86 indexmap.gettoarray(toarray);
87 if (toarray.size()) {
88 defaultindex = toarray[0];
89 }
90 }
91
92 if (defaultsubcollection.empty()) {
93 // use first subcollection in map as default if no default is set explicitly
94 text_tarray toarray;
95 subcollectionmap.gettoarray(toarray);
96 if (toarray.size()) {
97 defaultsubcollection = toarray[0];
98 }
99 }
100
101 if (defaultlanguage.empty()) {
102 // use first language in map as default if no default is set explicitly
103 text_tarray toarray;
104 languagemap.gettoarray(toarray);
105 if (toarray.size()) {
106 defaultlanguage = toarray[0];
107 }
108 }
109
110 // get the collection directory name
111 if (collectdir.empty()) {
112 collectdir = filename_cat (gsdlhome, "collect", collection);
113 }
114
115 // get the filename for the database and make sure it exists
116 if (indexstem.empty()) {
117 indexstem = collection;
118 }
119 db_filename = filename_cat(gdbmhome, "collect", collection, "index", "text", indexstem);
120 if (littleEndian()) db_filename += ".ldb";
121 else db_filename += ".bdb";
122
123 if (!file_exists(db_filename)) {
124 logout << text_t2ascii
125 << "warning: database \"" << db_filename << "\" does not exist\n\n";
126 // return false;
127 }
128
129 return true;
130}
131
132bool gdbmsourceclass::translate_OID (const text_t &OIDin, text_t &OIDout,
133 comerror_t &err, ostream &logout) {
134
135 outconvertclass text_t2ascii;
136
137 err = noError;
138 if (db_ptr == NULL) {
139 // most likely a configuration problem
140 logout << text_t2ascii
141 << "configuration error: " << classname << " contains a null dbclass\n\n";
142 err = configurationError;
143 return true;
144 }
145
146 // open the database
147 db_ptr->setlogout(&logout);
148 if (!db_ptr->opendatabase (db_filename, DB_READER, 100, false)) {
149 // most likely a system problem (we have already checked that the database exists)
150 logout << text_t2ascii
151 << "system problem: open on database \"" << db_filename << "\" failed\n\n";
152 err = systemProblem;
153 return true;
154 }
155
156 infodbclass info;
157 OIDout = db_ptr->translate_OID (OIDin, info);
158 db_ptr->closedatabase(); // Important that local library doesn't leave any files open
159 return true;
160}
161
162bool gdbmsourceclass::get_metadata (const text_t &/*requestParams*/, const text_t &/*refParams*/,
163 bool getParents, const text_tset &fields,
164 const text_t &OID, MetadataInfo_tmap &metadata,
165 comerror_t &err, ostream &logout) {
166 outconvertclass text_t2ascii;
167
168 metadata.erase(metadata.begin(), metadata.end());
169
170 err = noError;
171 if (db_ptr == NULL) {
172 // most likely a configuration problem
173 logout << text_t2ascii
174 << "configuration error: " << classname <<" contains a null dbclass\n\n";
175 err = configurationError;
176 return true;
177 }
178
179 // open the database
180 db_ptr->setlogout(&logout);
181 if (!db_ptr->opendatabase (db_filename, DB_READER, 100, false)) {
182 // most likely a system problem (we have already checked that the database exists)
183 logout << text_t2ascii
184 << "system problem: open on database \"" << db_filename << "\" failed\n\n";
185 err = systemProblem;
186 return true;
187 }
188
189 // get the metadata - if getParents is set we need to get
190 // info for all parents of OID as well as OID
191 vector<infodbclass> info_array;
192 text_tarray OIDs;
193 if (getParents) get_parents_array (OID, OIDs);
194 OIDs.push_back (OID);
195
196 text_tarray::const_iterator this_OID = OIDs.begin();
197 text_tarray::const_iterator end_OID = OIDs.end();
198
199 while (this_OID != end_OID) {
200 infodbclass info;
201 if (!db_ptr->getinfo(*this_OID, info)) return false;
202
203 // adjust the metadata
204 text_t &contains = info["contains"];
205 if (contains.empty()) info["haschildren"] = 0;
206 else info["haschildren"] = 1;
207 //contains.clear();
208
209 info_array.push_back(info);
210 ++this_OID;
211 }
212
213 // if fields set is empty we want to get all available metadata
214 text_tset tfields = fields;
215 if (tfields.empty() && !info_array.empty()) {
216 infodbclass::iterator t_info = info_array[0].begin();
217 infodbclass::iterator e_info = info_array[0].end();
218 while (t_info != e_info) {
219 if ((*t_info).first != "contains")
220 tfields.insert ((*t_info).first);
221 ++t_info;
222 }
223 tfields.insert ("hasnext");
224 tfields.insert ("hasprevious");
225 }
226
227 // collect together the metadata
228 bool donenextprevtest = false;
229 bool hasnext=false, hasprevious=false;
230 MetadataInfo_t this_metadata;
231 text_tarray *pos_metadata;
232 text_tset::const_iterator fields_here = tfields.begin();
233 text_tset::const_iterator fields_end = tfields.end();
234
235 while (fields_here != fields_end) {
236 this_metadata.clear();
237 this_metadata.isRef = false;
238
239 vector<infodbclass>::reverse_iterator this_info = info_array.rbegin();
240 vector<infodbclass>::reverse_iterator end_info = info_array.rend();
241 MetadataInfo_t *tmetaptr = &this_metadata;
242 while (this_info != end_info) {
243
244 pos_metadata = (*this_info).getmultinfo(*fields_here);
245 if ((*fields_here == "hasnext" || *fields_here == "hasprevious")) {
246
247 // collect metadata
248 if (!donenextprevtest) {
249 donenextprevtest = true;
250
251 // cache parent contents array
252 text_t thisparent = get_parent (OID);
253 if (!thisparent.empty()) {
254 if (thisparent != parentOID) {
255 parentOID = thisparent;
256 parentcontents.erase(parentcontents.begin(), parentcontents.end());
257 if (db_ptr->getinfo(parentOID, parentinfo)) {
258 text_t &parentinfocontains = parentinfo["contains"];
259 if (!parentinfocontains.empty())
260 splitchar (parentinfocontains.begin(), parentinfocontains.end(),
261 ';', parentcontents);
262 }
263 }
264
265 // do tests
266 text_tarray::const_iterator parentcontents_here = parentcontents.begin();
267 text_tarray::const_iterator parentcontents_end = parentcontents.end();
268 text_t shrunk_OID = OID;
269 shrink_parent (shrunk_OID);
270 while (parentcontents_here != parentcontents_end) {
271 if (*parentcontents_here == shrunk_OID) {
272 if (parentcontents_here == parentcontents.begin()) hasprevious = false;
273 else hasprevious = true;
274
275 ++parentcontents_here;
276
277 if (parentcontents_here == parentcontents.end()) hasnext = false;
278 else hasnext = true;
279
280 break;
281 }
282
283 ++parentcontents_here;
284 }
285
286 // fill in metadata
287 if ((*fields_here == "hasnext" && hasnext) ||
288 (*fields_here == "hasprevious" && hasprevious))
289 tmetaptr->values.push_back("1");
290 else
291 tmetaptr->values.push_back("0");
292 } else
293 tmetaptr->values.push_back("0");
294 }
295 }
296 //else if (pos_metadata != NULL && *fields_here != "contains") {
297 else if (pos_metadata != NULL) {
298 tmetaptr->values = *pos_metadata;
299 }
300 else
301 tmetaptr->values.push_back("");
302
303 ++this_info;
304 if (this_info != end_info) {
305 tmetaptr->parent = new MetadataInfo_t();
306 tmetaptr = tmetaptr->parent;
307 }
308 }
309 metadata[*fields_here] = this_metadata;
310 ++fields_here;
311 }
312
313 db_ptr->closedatabase(); // Important that local library doesn't leave any files open
314 return true;
315}
316
317
318bool gdbmsourceclass::get_document (const text_t &OID, text_t &doc,
319 comerror_t &err, ostream &logout) {
320
321 outconvertclass text_t2ascii;
322
323 err = noError;
324 if (db_ptr == NULL) {
325 // most likely a configuration problem
326 logout << text_t2ascii
327 << "configuration error: " << classname << " contains a null dbclass\n\n";
328 err = configurationError;
329 return true;
330 }
331
332 // open the database
333 db_ptr->setlogout(&logout);
334 if (!db_ptr->opendatabase (db_filename, DB_READER, 100, false)) {
335 // most likely a system problem (we have already checked that the database exists)
336 logout << text_t2ascii
337 << "system problem: open on database \"" << db_filename << "\" failed\n\n";
338 err = systemProblem;
339 return true;
340 }
341
342 text_t tOID = OID;
343 if (needs_translating (OID))
344 translate_OID (OID, tOID, err, logout);
345 infodbclass info;
346 if (!db_ptr->getinfo(tOID, info)) {
347 db_ptr->closedatabase(); // Important that local library doesn't leave any files open
348 return false;
349 }
350
351 if (info["hastxt"].getint() == 1) {
352 int docnum = info["docnum"].getint();
353
354 // set the collection directory
355 textsearchptr->setcollectdir (collectdir);
356
357 // get the text
358 textsearchptr->docTargetDocument(defaultindex, defaultsubcollection,
359 defaultlanguage, collection, docnum, doc);
360 }
361
362 db_ptr->closedatabase(); // Important that local library doesn't leave any files open
363 return true;
364}
365
366bool gdbmsourceclass::is_searchable(bool &issearchable, comerror_t &err, ostream &logout) {
367 err = noError;
368 issearchable = false;
369
370 text_tarray fromarray;
371 indexmap.getfromarray(fromarray);
372 if (fromarray.size() == 0) {
373 return true;
374 } else if (fromarray.size() == 1) {
375 if (fromarray[0] == "dummy:text") {
376 // always return true - issearchable is false here though
377 return true;
378 }
379 }
380 issearchable = true;
381 return true;
382}
Note: See TracBrowser for help on using the repository browser.