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

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

(Adding new DB support) Changed a lot of "gdbmhome" to "dbhome".

  • 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") dbhome = 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 (dbhome.empty()) dbhome = 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(dbhome, "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.