summaryrefslogtreecommitdiffstats
path: root/debian/htdig/htdig-3.2.0b6/htword/WordDB.h
blob: e48ffc4df954da03470338b29339bf856614e214 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
//
// WordDB.h
//
// WordDB: Interface to Berkeley DB
//         uses String and WordReference instead of Dbt, add some convenience
//	   methods and implements string translation of Berkeley DB error codes.
//         It does not include the 'join' feature.
//         Beside this, the interface it identical to the Db class.
//         The next evolution for this set of class is to have a single object per
//         application so that they all share the same environment (transactions,
//         shared pool, database directory). This implies a static common object
//         that is refered by each actual instance of WordDB. The static object
//         holds the DbEnv and DbInfo, the instances of WordDB only have an open
//         descriptor using the same DbEnv and DbInfo.
//
// Part of the ht://Dig package   <http://www.htdig.org/>
// Copyright (c) 1999-2004 The ht://Dig Group
// For copyright details, see the file COPYING in your distribution
// or the GNU Library General Public License (LGPL) version 2 or later
// <http://www.gnu.org/copyleft/lgpl.html>
//
// $Id: WordDB.h,v 1.7 2004/05/28 13:15:26 lha Exp $
//

#ifndef _WordDB_h_
#define _WordDB_h_

#include <stdio.h>
#include <errno.h>

#include "db.h"
#include "WordReference.h"
#include "WordDBInfo.h"
#include "htString.h"

#define WORD_DBT_DCL(v) \
    DBT v; \
    memset((char*)&(v), '\0', sizeof(DBT))

#define WORD_DBT_SET(v,d,s) \
    v.data = (d); \
    v.size = (s)

#define WORD_DBT_INIT(v,d,s) \
    WORD_DBT_DCL(v); \
    WORD_DBT_SET(v,d,s)

//
// Encapsulate the Berkeley DB DB type
//
// Implements the same methods with String instead of Dbt.
//
// Add convenience methods taking WordReference instead of String
//
// The error model is *not* to use exceptions. 
//
// To get a cursor use the Open method of WordDBCursor. I find this
// more convinient than getting a cursor from WordDB.
//
// The WordDB has DbInfo and DbEnv members that can be set before
// calling Open to configure it.
//
class WordDB {
 public:
  inline WordDB() { Alloc(); }
  inline ~WordDB() { Dealloc(); }

  inline int Alloc() {
    db = 0;
    is_open = 0;
    dbenv = WordDBInfo::Instance()->dbenv;
    return CDB_db_create(&db, dbenv, 0);
  }

  inline int Dealloc() {
    int error = 0;
    is_open = 0;
    if(db)
      error = db->close(db, 0);
    else
      fprintf(stderr, "WordDB::Dealloc: null db\n");
    dbenv = 0;
    db = 0;
    return error;
  }

  int Open(const String& filename, DBTYPE type, int flags, int mode);

  inline int Close() {
    int error;
    if((error = Dealloc()) != 0)
      return error;
    return Alloc();
  }

  inline int Fd(int *fdp) {
    if(!is_open) return DB_UNKNOWN;
    return db->fd(db, fdp);
  }

  inline int Stat(void *sp, void *(*db_malloc)(size_t), int flags) {
    if(!is_open) return DB_UNKNOWN;
    return db->stat(db, sp, db_malloc, (u_int32_t) flags);
  }
  
  inline int Sync(int flags) {
    if(!is_open) return DB_UNKNOWN;
    return db->sync(db, (u_int32_t) flags);
  }

  inline int get_byteswapped() const {
    if(!is_open) return DB_UNKNOWN;
    return db->get_byteswapped(db);
  }

  inline DBTYPE get_type() const {
    if(!is_open) return DB_UNKNOWN;
    return db->get_type(db);
  }

  //
  // String arguments
  //
  inline int Put(DB_TXN *txn, const String& key, const String& data, int flags) {
    WORD_DBT_INIT(rkey, (void*)key.get(), key.length());
    WORD_DBT_INIT(rdata, (void*)data.get(), data.length());

    return db->put(db, txn, &rkey, &rdata, flags);
  }

  inline int Get(DB_TXN *txn, String& key, String& data, int flags) const {
    WORD_DBT_INIT(rkey, (void*)key.get(), (u_int32_t)key.length());
    WORD_DBT_INIT(rdata, (void*)data.get(), (u_int32_t)data.length());

    int error;
    if((error = db->get(db, txn, &rkey, &rdata, 0)) != 0) {
      if(error != DB_NOTFOUND)
	fprintf(stderr, "WordDB::Get(%s,%s) using %d failed %s\n", (char*)key, (char*)data, flags, CDB_db_strerror(error));
    } else {
      //
      // Only set arguments if found something.
      //
      key.set((const char*)rkey.data, (int)rkey.size);
      data.set((const char*)rdata.data, (int)rdata.size);
    }

    return error;
  }

  inline int Del(DB_TXN *txn, const String& key) {
    WORD_DBT_INIT(rkey, (void*)key.get(), (u_int32_t)key.length());

    return db->del(db, txn, &rkey, 0);
  }

  //
  // WordReference argument
  //
  inline int Put(const WordReference& wordRef, int flags) {
    if(!is_open) return DB_UNKNOWN;

    int ret;
    String key;
    String record;

    if((ret = wordRef.Pack(key, record)) != OK) return DB_RUNRECOVERY;

    return Put(0, key, record, flags);
  }

  inline int Del(const WordReference& wordRef) {
    String key;

    wordRef.Key().Pack(key);

    return Del(0, key);
  }

  //
  // Search entry matching wkey exactly, return key and data
  // in wordRef.
  //
  inline int Get(WordReference& wordRef) const {
    if(!is_open) return DB_UNKNOWN;

    String data;
    String key;

    if(wordRef.Key().Pack(key) != OK) return DB_RUNRECOVERY;

    int ret;
    if((ret = Get(0, key, data, 0)) != 0)
      return ret;

    return wordRef.Unpack(key, data) == OK ? 0 : DB_RUNRECOVERY;
  }

  //
  // Returns 0 of the key of wordRef matches an entry in the database.
  // Could be implemented with Get but is not because we don't
  // need to build a wordRef with the entry found in the base. 
  //
  inline int Exists(const WordReference& wordRef) const {
    if(!is_open) return DB_UNKNOWN;

    String key;
    String data;

    if(wordRef.Key().Pack(key) != OK) return DB_RUNRECOVERY;

    return Get(0, key, data, 0);
  }

  //
  // Accessors
  //
  inline int set_bt_compare(int (*compare)(const DBT *, const DBT *)) {
    return db->set_bt_compare(db, compare);
  }

  inline int set_pagesize(u_int32_t pagesize) {
    return db->set_pagesize(db, pagesize);
  }

  //
  // Accessors for description of the compression scheme
  //
  inline DB_CMPR_INFO* CmprInfo() { return dbenv->mp_cmpr_info; }
  inline void CmprInfo(DB_CMPR_INFO* info) { dbenv->mp_cmpr_info = info; }

  int			is_open;
  DB*			db;
  DB_ENV*            	dbenv;
};

//
// Interface to DBC that uses String instead of DBT
//
class WordDBCursor {
 public:
  inline WordDBCursor() { cursor = 0; }
  inline ~WordDBCursor() {
    Close();
  }

  inline int Open(DB* db) {
    Close();
    return db->cursor(db, 0, &cursor, 0);
  }

  inline int Close() {
    if(cursor) cursor->c_close(cursor);
    cursor = 0;
    return 0;
  }

  //
  // String arguments
  //
  inline int Get(String& key, String& data, int flags) {
    WORD_DBT_DCL(rkey);
    WORD_DBT_DCL(rdata);
    switch(flags & DB_OPFLAGS_MASK) {
    case DB_SET_RANGE:
    case DB_SET:
    case DB_GET_BOTH:
      WORD_DBT_SET(rkey, (void*)key.get(), key.length());
      break;
    }
    int error;
    if((error = cursor->c_get(cursor, &rkey, &rdata, (u_int32_t)flags)) != 0) {
      if(error != DB_NOTFOUND)
	fprintf(stderr, "WordDBCursor::Get(%d) failed %s\n", flags, CDB_db_strerror(error));
    } else {
      key.set((const char*)rkey.data, (int)rkey.size);
      data.set((const char*)rdata.data, (int)rdata.size);
    }
    return error;
  }

  inline int Put(const String& key, const String& data, int flags) {
    WORD_DBT_INIT(rkey, (void*)key.get(), (size_t)key.length());
    WORD_DBT_INIT(rdata, (void*)data.get(), (size_t)data.length());
    return cursor->c_put(cursor, &rkey, &rdata, (u_int32_t)flags);
  }

  inline int Del() {
    return cursor->c_del(cursor, (u_int32_t)0);
  }

private:
  DBC* cursor;
};

#endif /* _WordDB_h */