dk-bdb 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +20 -0
- data/README.md +102 -0
- data/VERSION +1 -0
- data/examples/replication.rb +29 -0
- data/ext/bdb.c +3421 -0
- data/ext/bdb.h +104 -0
- data/ext/extconf.rb +59 -0
- data/lib/bdb/base.rb +68 -0
- data/lib/bdb/database.rb +207 -0
- data/lib/bdb/environment.rb +135 -0
- data/lib/bdb/partitioned_database.rb +74 -0
- data/lib/bdb/replication.rb +68 -0
- data/lib/bdb/result_set.rb +41 -0
- data/test/benchmark.rb +31 -0
- data/test/cursor_test.rb +150 -0
- data/test/database_test.rb +18 -0
- data/test/database_test_helper.rb +37 -0
- data/test/db_test.rb +157 -0
- data/test/deadlock_test.rb +125 -0
- data/test/env_test.rb +101 -0
- data/test/replication_test.rb +47 -0
- data/test/stat_test.rb +22 -0
- data/test/test_helper.rb +14 -0
- data/test/txn_test.rb +74 -0
- metadata +92 -0
data/ext/bdb.c
ADDED
|
@@ -0,0 +1,3421 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Ruby library that wraps the Sleepycat Berkeley DB.
|
|
3
|
+
*
|
|
4
|
+
* Developed against 4.3/4.4. No support for prior versions.
|
|
5
|
+
*
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#include <bdb.h>
|
|
9
|
+
#include <stdio.h>
|
|
10
|
+
|
|
11
|
+
#define LMEMFLAG 0
|
|
12
|
+
#define NOFLAGS 0
|
|
13
|
+
#undef DEBUG_DB
|
|
14
|
+
|
|
15
|
+
#ifdef HAVE_STDARG_PROTOTYPES
|
|
16
|
+
#include <stdarg.h>
|
|
17
|
+
#define va_init_list(a,b) va_start(a,b)
|
|
18
|
+
#else
|
|
19
|
+
#include <varargs.h>
|
|
20
|
+
#define va_init_list(a,b) va_start(a)
|
|
21
|
+
#endif
|
|
22
|
+
|
|
23
|
+
VALUE mBdb; /* Top level module */
|
|
24
|
+
VALUE cDb; /* DBT class */
|
|
25
|
+
VALUE cDbStat; /* db status class, not specialized for DBTYPE */
|
|
26
|
+
VALUE cEnv; /* Environment class */
|
|
27
|
+
VALUE cTxn; /* Transaction class */
|
|
28
|
+
VALUE cCursor; /* Cursors */
|
|
29
|
+
VALUE cTxnStat; /* Transaction Status class */
|
|
30
|
+
VALUE cTxnStatActive; /* Active Transaction Status class */
|
|
31
|
+
VALUE eDbError;
|
|
32
|
+
|
|
33
|
+
static ID fv_call,fv_uniq,fv_err_new,fv_err_code,fv_err_msg;
|
|
34
|
+
|
|
35
|
+
#define EXCEPTIONS_CREATE \
|
|
36
|
+
eDbE_create(BUFFER_SMALL, BufferSmall)\
|
|
37
|
+
eDbE_create(LOCK_DEADLOCK, LockDeadlock)\
|
|
38
|
+
eDbE_create(LOCK_NOTGRANTED, LockNotgranted)\
|
|
39
|
+
eDbE_create(REP_HANDLE_DEAD, RepHandleDead)\
|
|
40
|
+
eDbE_create(REP_LEASE_EXPIRED, RepLeaseExpired)\
|
|
41
|
+
eDbE_create(REP_LOCKOUT, RepLockout)\
|
|
42
|
+
eDbE_create(SECONDARY_BAD, SecondaryBad) \
|
|
43
|
+
eDbE_create(FOREIGN_CONFLICT, ForeignConflict) \
|
|
44
|
+
eDbE_create(OLD_VERSION, OldVersion) \
|
|
45
|
+
eDbE_create(KEYEXIST, KeyExist) \
|
|
46
|
+
eDbE_create(KEYEMPTY, KeyEmpty) \
|
|
47
|
+
eDbE_create(RUNRECOVERY, RunRecovery) \
|
|
48
|
+
eDbE_create(VERSION_MISMATCH, VersionMismatch)
|
|
49
|
+
|
|
50
|
+
#define eDbE_create(n,c) VALUE eDbE_##c;
|
|
51
|
+
EXCEPTIONS_CREATE
|
|
52
|
+
|
|
53
|
+
/*
|
|
54
|
+
* Document-class: Bdb::DbError
|
|
55
|
+
*
|
|
56
|
+
* Errors generated by methods under the Bdb hierarchy will be
|
|
57
|
+
* of this class unless Ruby itself raises the error.
|
|
58
|
+
*
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
static void
|
|
62
|
+
#ifdef HAVE_STDARG_PROTOTYPES
|
|
63
|
+
raise_error(int code, const char *fmt, ...)
|
|
64
|
+
#else
|
|
65
|
+
raise_error(code,fmt,va_alist)
|
|
66
|
+
int code;
|
|
67
|
+
const char *fmt;
|
|
68
|
+
va_dcl
|
|
69
|
+
#endif
|
|
70
|
+
{
|
|
71
|
+
va_list args;
|
|
72
|
+
char buf[1024];
|
|
73
|
+
VALUE exc;
|
|
74
|
+
VALUE argv[2];
|
|
75
|
+
|
|
76
|
+
va_init_list(args,fmt);
|
|
77
|
+
vsnprintf(buf,1024,fmt,args);
|
|
78
|
+
va_end(args);
|
|
79
|
+
|
|
80
|
+
argv[0]=rb_str_new2(buf);
|
|
81
|
+
argv[1]=INT2NUM(code);
|
|
82
|
+
VALUE cl;
|
|
83
|
+
switch( code) {
|
|
84
|
+
#define eDbE_create(n,c) case DB_##n: cl = eDbE_##c; break;
|
|
85
|
+
EXCEPTIONS_CREATE
|
|
86
|
+
default: cl = eDbError; break;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
exc=rb_class_new_instance(2,argv,cl);
|
|
90
|
+
rb_exc_raise(exc);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/*
|
|
94
|
+
* An error can only be generated internally
|
|
95
|
+
*/
|
|
96
|
+
VALUE err_initialize(VALUE obj, VALUE message, VALUE code)
|
|
97
|
+
{
|
|
98
|
+
VALUE args[1];
|
|
99
|
+
args[0]=message;
|
|
100
|
+
rb_call_super(1,args);
|
|
101
|
+
return rb_ivar_set(obj,fv_err_code,code);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/*
|
|
105
|
+
* call-seq:
|
|
106
|
+
* err.code() -> Bdb error code integer
|
|
107
|
+
*
|
|
108
|
+
*/
|
|
109
|
+
VALUE err_code(VALUE obj)
|
|
110
|
+
{
|
|
111
|
+
return rb_ivar_get(obj,fv_err_code);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
static void db_free(t_dbh *dbh)
|
|
115
|
+
{
|
|
116
|
+
#ifdef DEBUG_DB
|
|
117
|
+
if ( RTEST(ruby_debug) )
|
|
118
|
+
fprintf(stderr,"%s/%d %s 0x%x\n",__FILE__,__LINE__,"db_free cleanup!",dbh);
|
|
119
|
+
#endif
|
|
120
|
+
|
|
121
|
+
if (dbh) {
|
|
122
|
+
if (dbh->db) {
|
|
123
|
+
if (dbh->db_opened == 1)
|
|
124
|
+
dbh->db->close(dbh->db,NOFLAGS);
|
|
125
|
+
if ( RTEST(ruby_debug) && dbh->filename[0] != '\0')
|
|
126
|
+
fprintf(stderr,"%s/%d %s %p %s\n",__FILE__,__LINE__,
|
|
127
|
+
"db_free database was still open!",(void*)dbh->db,dbh->filename);
|
|
128
|
+
dbh->db=NULL;
|
|
129
|
+
}
|
|
130
|
+
free(dbh);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
static void db_mark(t_dbh *dbh)
|
|
135
|
+
{
|
|
136
|
+
if ( dbh == NULL ) return;
|
|
137
|
+
if ( ! NIL_P(dbh->aproc) )
|
|
138
|
+
rb_gc_mark(dbh->aproc);
|
|
139
|
+
if ( dbh->env )
|
|
140
|
+
rb_gc_mark(dbh->env->self);
|
|
141
|
+
if ( ! NIL_P(dbh->adbc) )
|
|
142
|
+
rb_gc_mark(dbh->adbc);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
static void dbc_mark(t_dbch *dbch)
|
|
146
|
+
{
|
|
147
|
+
if (dbch->db)
|
|
148
|
+
rb_gc_mark(dbch->db->self);
|
|
149
|
+
}
|
|
150
|
+
static void dbc_free(void *p)
|
|
151
|
+
{
|
|
152
|
+
t_dbch *dbch;
|
|
153
|
+
dbch=(t_dbch *)p;
|
|
154
|
+
|
|
155
|
+
#ifdef DEBUG_DB
|
|
156
|
+
if ( RTEST(ruby_debug) )
|
|
157
|
+
fprintf(stderr,"%s/%d %s 0x%x\n",__FILE__,__LINE__,
|
|
158
|
+
"dbc_free cleanup!",p);
|
|
159
|
+
#endif
|
|
160
|
+
|
|
161
|
+
if ( dbch ) {
|
|
162
|
+
if ( dbch->dbc ) {
|
|
163
|
+
dbch->dbc->c_close(dbch->dbc);
|
|
164
|
+
if ( RTEST(ruby_debug) )
|
|
165
|
+
fprintf(stderr,"%s/%d %s %p %s\n",__FILE__,__LINE__,
|
|
166
|
+
"dbc_free cursor was still open!",p,dbch->filename);
|
|
167
|
+
}
|
|
168
|
+
free(p);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
VALUE
|
|
173
|
+
db_alloc(VALUE klass)
|
|
174
|
+
{
|
|
175
|
+
return Data_Wrap_Struct(klass,db_mark,db_free,0);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
VALUE db_init_aux(VALUE obj,t_envh * eh)
|
|
179
|
+
{
|
|
180
|
+
DB *db;
|
|
181
|
+
t_dbh *dbh;
|
|
182
|
+
int rv;
|
|
183
|
+
|
|
184
|
+
/* This excludes possible use of X/Open Transaction Mgr */
|
|
185
|
+
rv = db_create(&db,(eh)?eh->env:NULL,NOFLAGS);
|
|
186
|
+
if (rv != 0) {
|
|
187
|
+
raise_error(rv, "db_new failure: %s",db_strerror(rv));
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
#ifdef DEBUG_DB
|
|
191
|
+
db->set_errfile(db,stderr);
|
|
192
|
+
#endif
|
|
193
|
+
|
|
194
|
+
dbh=ALLOC(t_dbh);
|
|
195
|
+
if (DATA_PTR(obj)) {
|
|
196
|
+
/* if called from env_db, the data ptr has not been allocated,
|
|
197
|
+
* was freeing 0x0 */
|
|
198
|
+
db_free(DATA_PTR(obj));
|
|
199
|
+
}
|
|
200
|
+
DATA_PTR(obj)=dbh;
|
|
201
|
+
dbh->db=db;
|
|
202
|
+
dbh->self=obj;
|
|
203
|
+
dbh->env=eh;
|
|
204
|
+
dbh->aproc=Qnil;
|
|
205
|
+
dbh->sproc=Qnil;
|
|
206
|
+
memset(&(dbh->filename),0,FNLEN+1);
|
|
207
|
+
|
|
208
|
+
dbh->adbc=Qnil;
|
|
209
|
+
|
|
210
|
+
if (dbh->env) {
|
|
211
|
+
#ifdef DEBUG_DB
|
|
212
|
+
fprintf(stderr,"Adding db to env 0x%x 0x%x\n",obj,dbh);
|
|
213
|
+
#endif
|
|
214
|
+
rb_ary_push(dbh->env->adb,obj);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return obj;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/*
|
|
221
|
+
* Document-class: Bdb::Db
|
|
222
|
+
*
|
|
223
|
+
*/
|
|
224
|
+
|
|
225
|
+
VALUE db_initialize(VALUE obj)
|
|
226
|
+
{
|
|
227
|
+
return db_init_aux(obj,NULL);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/*
|
|
231
|
+
* call-seq:
|
|
232
|
+
* db.open(txn_object,disk_file,logical_db,db_type,flags,mode) -> value
|
|
233
|
+
*
|
|
234
|
+
* open a database. disk file is file path. logical_db is
|
|
235
|
+
* a named database within that file, which will be created under
|
|
236
|
+
* conditions noted by DB.
|
|
237
|
+
*
|
|
238
|
+
* db_type is one of the constants:
|
|
239
|
+
* Bdb::DB::BTREE
|
|
240
|
+
* Bdb::DB::HASH
|
|
241
|
+
* Bdb::DB::RECNO
|
|
242
|
+
* Bdb::DB::QUEUE
|
|
243
|
+
* Bdb::DB::UNKNOWN
|
|
244
|
+
*
|
|
245
|
+
* unknown will open an already existing db in the mode created
|
|
246
|
+
*/
|
|
247
|
+
VALUE db_open(VALUE obj, VALUE vtxn, VALUE vdisk_file,
|
|
248
|
+
VALUE vlogical_db,
|
|
249
|
+
VALUE vdbtype, VALUE vflags, VALUE vmode)
|
|
250
|
+
{
|
|
251
|
+
t_dbh *dbh;
|
|
252
|
+
int rv;
|
|
253
|
+
t_txnh *txn=NOTXN;
|
|
254
|
+
u_int32_t flags=0;
|
|
255
|
+
DBTYPE dbtype=DB_UNKNOWN;
|
|
256
|
+
char *logical_db=NULL;
|
|
257
|
+
//long len;
|
|
258
|
+
int mode=0;
|
|
259
|
+
|
|
260
|
+
if ( ! NIL_P(vflags) )
|
|
261
|
+
flags=NUM2UINT(vflags);
|
|
262
|
+
|
|
263
|
+
if ( ! NIL_P(vtxn) ) {
|
|
264
|
+
Data_Get_Struct(vtxn,t_txnh,txn);
|
|
265
|
+
if (!txn->txn)
|
|
266
|
+
raise(0, "txn is closed");
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
if ( TYPE(vlogical_db)==T_STRING && RSTRING_LEN(vlogical_db) > 0 )
|
|
270
|
+
logical_db=StringValueCStr(vlogical_db);
|
|
271
|
+
|
|
272
|
+
if ( FIXNUM_P(vdbtype) ) {
|
|
273
|
+
dbtype=NUM2INT(vdbtype);
|
|
274
|
+
if ( dbtype < DB_BTREE || dbtype > DB_UNKNOWN ) {
|
|
275
|
+
raise_error(0,"db_open Bad access type: %d",dbtype);
|
|
276
|
+
return Qnil;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if ( TYPE(vdisk_file)!=T_STRING || RSTRING_LEN(vdisk_file) < 1 ) {
|
|
281
|
+
raise_error(0,"db_open Bad disk file name");
|
|
282
|
+
return Qnil;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
if ( ! NIL_P(vmode) )
|
|
286
|
+
mode=NUM2INT(vmode);
|
|
287
|
+
|
|
288
|
+
Data_Get_Struct(obj,t_dbh,dbh);
|
|
289
|
+
if ( ! NIL_P(dbh->adbc) )
|
|
290
|
+
raise_error(0,"db handle already opened");
|
|
291
|
+
|
|
292
|
+
dbh->db->app_private=dbh;
|
|
293
|
+
rv = dbh->db->open(dbh->db,txn?txn->txn:NULL,
|
|
294
|
+
StringValueCStr(vdisk_file),
|
|
295
|
+
logical_db,
|
|
296
|
+
dbtype,flags,mode);
|
|
297
|
+
if (rv != 0) {
|
|
298
|
+
raise_error(rv,"db_open failure: %s(%d)",db_strerror(rv),rv);
|
|
299
|
+
}
|
|
300
|
+
filename_copy(dbh->filename,vdisk_file)
|
|
301
|
+
dbh->adbc=rb_ary_new();
|
|
302
|
+
dbh->db_opened = 1;
|
|
303
|
+
return obj;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* call-seq:
|
|
308
|
+
* db.set_re_len( db, re_len)
|
|
309
|
+
*
|
|
310
|
+
* Set record-length
|
|
311
|
+
*/
|
|
312
|
+
VALUE db_set_re_len(VALUE obj, VALUE re_len) {
|
|
313
|
+
int rv;
|
|
314
|
+
t_dbh *dbh;
|
|
315
|
+
Data_Get_Struct(obj,t_dbh,dbh);
|
|
316
|
+
if (!dbh->db)
|
|
317
|
+
raise_error(0,"db isn't created");
|
|
318
|
+
rv = dbh->db->set_re_len(dbh->db,NUM2UINT(re_len));
|
|
319
|
+
if ( rv != 0 )
|
|
320
|
+
raise_error(rv, "set_re_len failure: %s",db_strerror(rv));
|
|
321
|
+
return re_len;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
VALUE db_get_re_len( VALUE obj) {
|
|
325
|
+
u_int32_t re_len;
|
|
326
|
+
t_dbh *dbh;
|
|
327
|
+
Data_Get_Struct(obj,t_dbh,dbh);
|
|
328
|
+
if (!dbh->db)
|
|
329
|
+
raise_error(0,"db isn't created");
|
|
330
|
+
int rv = dbh->db->get_re_len(dbh->db,&re_len);
|
|
331
|
+
if ( rv != 0 )
|
|
332
|
+
raise_error(rv, "db_get_re_len failure: %s",db_strerror(rv));
|
|
333
|
+
return UINT2NUM(re_len);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/*
|
|
337
|
+
* call-seq:
|
|
338
|
+
* db.flags=value
|
|
339
|
+
*
|
|
340
|
+
* set database flags based on DB constants.
|
|
341
|
+
* see http://www.sleepycat.com/docs/api_c/db_set_flags.html
|
|
342
|
+
*
|
|
343
|
+
*/
|
|
344
|
+
VALUE db_flags_set(VALUE obj, VALUE vflags)
|
|
345
|
+
{
|
|
346
|
+
t_dbh *dbh;
|
|
347
|
+
int rv;
|
|
348
|
+
u_int32_t flags;
|
|
349
|
+
|
|
350
|
+
flags=NUM2UINT(vflags);
|
|
351
|
+
Data_Get_Struct(obj,t_dbh,dbh);
|
|
352
|
+
if (!dbh->db)
|
|
353
|
+
raise_error(0,"db is closed");
|
|
354
|
+
|
|
355
|
+
rv = dbh->db->set_flags(dbh->db,flags);
|
|
356
|
+
if ( rv != 0 ) {
|
|
357
|
+
raise_error(rv, "db_flag_set failure: %s",db_strerror(rv));
|
|
358
|
+
}
|
|
359
|
+
return vflags;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/*
|
|
363
|
+
* call-seq:
|
|
364
|
+
* db.flags -> value
|
|
365
|
+
*
|
|
366
|
+
* get database flags.
|
|
367
|
+
* see http://www.sleepycat.com/docs/api_c/db_get_flags.html
|
|
368
|
+
*
|
|
369
|
+
*/
|
|
370
|
+
VALUE db_flags_get(VALUE obj)
|
|
371
|
+
{
|
|
372
|
+
t_dbh *dbh;
|
|
373
|
+
int rv;
|
|
374
|
+
u_int32_t flags;
|
|
375
|
+
|
|
376
|
+
Data_Get_Struct(obj,t_dbh,dbh);
|
|
377
|
+
if (!dbh->db)
|
|
378
|
+
raise_error(0,"db is closed");
|
|
379
|
+
|
|
380
|
+
rv = dbh->db->get_flags(dbh->db,&flags);
|
|
381
|
+
if ( rv != 0 ) {
|
|
382
|
+
raise_error(rv, "db_flag_get failure: %s",db_strerror(rv));
|
|
383
|
+
}
|
|
384
|
+
return INT2NUM(flags);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/*
|
|
388
|
+
* call-seq:
|
|
389
|
+
* db.pagesize=value
|
|
390
|
+
*
|
|
391
|
+
* set database flags based on DB constants.
|
|
392
|
+
* see http://www.sleepycat.com/docs/api_c/db_set_flags.html
|
|
393
|
+
*
|
|
394
|
+
*/
|
|
395
|
+
VALUE db_pagesize_set(VALUE obj, VALUE vpagesize)
|
|
396
|
+
{
|
|
397
|
+
t_dbh *dbh;
|
|
398
|
+
int rv;
|
|
399
|
+
u_int32_t pagesize;
|
|
400
|
+
|
|
401
|
+
pagesize=NUM2INT(vpagesize);
|
|
402
|
+
Data_Get_Struct(obj,t_dbh,dbh);
|
|
403
|
+
if (!dbh->db)
|
|
404
|
+
raise_error(0,"db is closed");
|
|
405
|
+
rv = dbh->db->set_pagesize(dbh->db,pagesize);
|
|
406
|
+
if ( rv != 0 ) {
|
|
407
|
+
raise_error(rv, "db_pagesize_set failure: %s",db_strerror(rv));
|
|
408
|
+
}
|
|
409
|
+
return vpagesize;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/*
|
|
413
|
+
* call-seq:
|
|
414
|
+
* db.pagesize
|
|
415
|
+
*
|
|
416
|
+
* set database flags based on DB constants.
|
|
417
|
+
* see http://www.sleepycat.com/docs/api_c/db_set_flags.html
|
|
418
|
+
*
|
|
419
|
+
*/
|
|
420
|
+
VALUE db_pagesize(VALUE obj)
|
|
421
|
+
{
|
|
422
|
+
t_dbh *dbh;
|
|
423
|
+
int rv;
|
|
424
|
+
u_int32_t pagesize;
|
|
425
|
+
|
|
426
|
+
Data_Get_Struct(obj,t_dbh,dbh);
|
|
427
|
+
if (!dbh->db)
|
|
428
|
+
raise_error(0,"db is closed");
|
|
429
|
+
rv = dbh->db->get_pagesize(dbh->db,&pagesize);
|
|
430
|
+
if ( rv != 0 ) {
|
|
431
|
+
raise_error(rv, "db_pagesize_get failure: %s",db_strerror(rv));
|
|
432
|
+
}
|
|
433
|
+
return INT2NUM(pagesize);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/*
|
|
437
|
+
* call-seq:
|
|
438
|
+
* db.h_ffactor=value
|
|
439
|
+
*
|
|
440
|
+
* get hash db fill factor
|
|
441
|
+
* formula:
|
|
442
|
+
* (pagesize - 32) / (average_key_size + average_data_size + 8)
|
|
443
|
+
*
|
|
444
|
+
*/
|
|
445
|
+
VALUE db_h_ffactor_set(VALUE obj, VALUE vint)
|
|
446
|
+
{
|
|
447
|
+
t_dbh *dbh;
|
|
448
|
+
int rv;
|
|
449
|
+
u_int32_t cint;
|
|
450
|
+
|
|
451
|
+
cint=NUM2INT(vint);
|
|
452
|
+
Data_Get_Struct(obj,t_dbh,dbh);
|
|
453
|
+
if (!dbh->db)
|
|
454
|
+
raise_error(0,"db is closed");
|
|
455
|
+
rv = dbh->db->set_h_ffactor(dbh->db,cint);
|
|
456
|
+
if ( rv != 0 ) {
|
|
457
|
+
raise_error(rv, "db_h_ffactor_set failure: %s",db_strerror(rv));
|
|
458
|
+
}
|
|
459
|
+
return vint;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/*
|
|
463
|
+
* call-seq:
|
|
464
|
+
* db.h_ffactor
|
|
465
|
+
*
|
|
466
|
+
* get hash db fill factor
|
|
467
|
+
* formula:
|
|
468
|
+
* (pagesize - 32) / (average_key_size + average_data_size + 8)
|
|
469
|
+
* see http://www.sleepycat.com/docs/api_c/db_set_flags.html
|
|
470
|
+
*
|
|
471
|
+
*/
|
|
472
|
+
VALUE db_h_ffactor(VALUE obj)
|
|
473
|
+
{
|
|
474
|
+
t_dbh *dbh;
|
|
475
|
+
int rv;
|
|
476
|
+
u_int32_t cint;
|
|
477
|
+
|
|
478
|
+
Data_Get_Struct(obj,t_dbh,dbh);
|
|
479
|
+
if (!dbh->db)
|
|
480
|
+
raise_error(0,"db is closed");
|
|
481
|
+
rv = dbh->db->get_h_ffactor(dbh->db,&cint);
|
|
482
|
+
if ( rv != 0 ) {
|
|
483
|
+
raise_error(rv, "db_h_ffactor failure: %s",db_strerror(rv));
|
|
484
|
+
}
|
|
485
|
+
return INT2NUM(cint);
|
|
486
|
+
}
|
|
487
|
+
/*
|
|
488
|
+
* call-seq:
|
|
489
|
+
* db.h_nelem=value
|
|
490
|
+
*
|
|
491
|
+
* set estimate number of elements in hash table
|
|
492
|
+
* see http://www.sleepycat.com/docs/api_c/db_set_flags.html
|
|
493
|
+
*
|
|
494
|
+
*/
|
|
495
|
+
VALUE db_h_nelem_set(VALUE obj, VALUE vint)
|
|
496
|
+
{
|
|
497
|
+
t_dbh *dbh;
|
|
498
|
+
int rv;
|
|
499
|
+
u_int32_t cint;
|
|
500
|
+
|
|
501
|
+
cint=NUM2INT(vint);
|
|
502
|
+
Data_Get_Struct(obj,t_dbh,dbh);
|
|
503
|
+
if (!dbh->db)
|
|
504
|
+
raise_error(0,"db is closed");
|
|
505
|
+
rv = dbh->db->set_h_nelem(dbh->db,cint);
|
|
506
|
+
if ( rv != 0 ) {
|
|
507
|
+
raise_error(rv, "db_h_nelem_set failure: %s",db_strerror(rv));
|
|
508
|
+
}
|
|
509
|
+
return vint;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/*
|
|
513
|
+
* call-seq:
|
|
514
|
+
* db.h_nelem
|
|
515
|
+
*
|
|
516
|
+
* get estimate number of element in the hash table
|
|
517
|
+
* see http://www.sleepycat.com/docs/api_c/db_set_flags.html
|
|
518
|
+
*
|
|
519
|
+
*/
|
|
520
|
+
VALUE db_h_nelem(VALUE obj)
|
|
521
|
+
{
|
|
522
|
+
t_dbh *dbh;
|
|
523
|
+
int rv;
|
|
524
|
+
u_int32_t nelem;
|
|
525
|
+
|
|
526
|
+
Data_Get_Struct(obj,t_dbh,dbh);
|
|
527
|
+
if (!dbh->db)
|
|
528
|
+
raise_error(0,"db is closed");
|
|
529
|
+
rv = dbh->db->get_h_nelem(dbh->db,&nelem);
|
|
530
|
+
if ( rv != 0 ) {
|
|
531
|
+
raise_error(rv, "db_h_nelem failure: %s",db_strerror(rv));
|
|
532
|
+
}
|
|
533
|
+
return INT2NUM(nelem);
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
VALUE dbc_close(VALUE);
|
|
537
|
+
|
|
538
|
+
/* call-seq:
|
|
539
|
+
* db.close(flags) -> value
|
|
540
|
+
*
|
|
541
|
+
* close a database handle. Will close open cursors.
|
|
542
|
+
*/
|
|
543
|
+
VALUE db_close(VALUE obj, VALUE vflags)
|
|
544
|
+
{
|
|
545
|
+
t_dbh *dbh;
|
|
546
|
+
int rv;
|
|
547
|
+
u_int32_t flags;
|
|
548
|
+
VALUE cur;
|
|
549
|
+
|
|
550
|
+
flags=NUM2UINT(vflags);
|
|
551
|
+
Data_Get_Struct(obj,t_dbh,dbh);
|
|
552
|
+
if ( dbh->db==NULL )
|
|
553
|
+
return Qnil;
|
|
554
|
+
|
|
555
|
+
if (! NIL_P(dbh->adbc) && RARRAY_LEN(dbh->adbc) > 0 ) {
|
|
556
|
+
rb_warning("%s/%d %s",__FILE__,__LINE__,
|
|
557
|
+
"cursor handles still open");
|
|
558
|
+
while ( (cur=rb_ary_pop(dbh->adbc)) != Qnil ) {
|
|
559
|
+
dbc_close(cur);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
if ( RTEST(ruby_debug) )
|
|
564
|
+
rb_warning("%s/%d %s 0x%p %s",__FILE__,__LINE__,"db_close!", (void*)dbh,
|
|
565
|
+
(dbh->filename==NULL||*(dbh->filename)=='0') ? (char*)"unknown" : dbh->filename);
|
|
566
|
+
|
|
567
|
+
rv = dbh->db->close(dbh->db,flags);
|
|
568
|
+
dbh->db=NULL;
|
|
569
|
+
dbh->aproc=Qnil;
|
|
570
|
+
dbh->sproc=Qnil;
|
|
571
|
+
if ( dbh->env ) {
|
|
572
|
+
if ( RTEST(ruby_debug) )
|
|
573
|
+
rb_warning("%s/%d %s 0x%p",__FILE__,__LINE__,"db_close! removing",(void*)obj);
|
|
574
|
+
rb_ary_delete(dbh->env->adb,obj);
|
|
575
|
+
dbh->env = NULL;
|
|
576
|
+
}
|
|
577
|
+
if ( rv != 0 ) {
|
|
578
|
+
raise_error(rv, "db_close failure: %s",db_strerror(rv));
|
|
579
|
+
}
|
|
580
|
+
dbh->db_opened = 0;
|
|
581
|
+
return obj;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
/*
|
|
585
|
+
* call-seq:
|
|
586
|
+
* db.put(txn,key,data,flags) -> self
|
|
587
|
+
*
|
|
588
|
+
* put a key/data pair into the database. returns db. Will
|
|
589
|
+
* raise an error on DB_KEYEXIST but error.code will indicate
|
|
590
|
+
* so it can be easily caught.
|
|
591
|
+
*/
|
|
592
|
+
VALUE db_put(VALUE obj, VALUE vtxn, VALUE vkey, VALUE vdata, VALUE vflags)
|
|
593
|
+
{
|
|
594
|
+
t_dbh *dbh;
|
|
595
|
+
int rv;
|
|
596
|
+
u_int32_t flags=0;
|
|
597
|
+
DBT key,data;
|
|
598
|
+
t_txnh *txn=NULL;
|
|
599
|
+
|
|
600
|
+
memset(&key,0,sizeof(DBT));
|
|
601
|
+
memset(&data,0,sizeof(DBT));
|
|
602
|
+
|
|
603
|
+
if ( ! NIL_P(vtxn) ) {
|
|
604
|
+
Data_Get_Struct(vtxn,t_txnh,txn);
|
|
605
|
+
if (!txn->txn)
|
|
606
|
+
raise(0, "txn is closed");
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
if ( ! NIL_P(vflags) )
|
|
610
|
+
flags=NUM2UINT(vflags);
|
|
611
|
+
|
|
612
|
+
Data_Get_Struct(obj,t_dbh,dbh);
|
|
613
|
+
if (!dbh->db)
|
|
614
|
+
raise_error(0,"db is closed");
|
|
615
|
+
|
|
616
|
+
key.data = RSTRING_PTR(vkey);
|
|
617
|
+
key.size = RSTRING_LEN(vkey);
|
|
618
|
+
key.flags = LMEMFLAG;
|
|
619
|
+
|
|
620
|
+
StringValue(vdata);
|
|
621
|
+
data.data = RSTRING_PTR(vdata);
|
|
622
|
+
data.size = RSTRING_LEN(vdata);
|
|
623
|
+
data.flags = LMEMFLAG;
|
|
624
|
+
|
|
625
|
+
rv = dbh->db->put(dbh->db,txn?txn->txn:NULL,&key,&data,flags);
|
|
626
|
+
/*
|
|
627
|
+
if (rv == DB_KEYEXIST)
|
|
628
|
+
return Qnil;
|
|
629
|
+
*/
|
|
630
|
+
if (rv != 0) {
|
|
631
|
+
raise_error(rv, "db_put fails: %s",db_strerror(rv));
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
if ( flags & DB_APPEND == DB_APPEND ) {
|
|
635
|
+
VALUE str = rb_str_new(key.data,key.size);
|
|
636
|
+
if (key.data) free(key.data);
|
|
637
|
+
return str;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
return obj;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
/*
|
|
644
|
+
* call-seq:
|
|
645
|
+
* db.get(txn,key,data,flags) -> String(data)
|
|
646
|
+
*
|
|
647
|
+
* get a key/data pair from database. data as a string.
|
|
648
|
+
*
|
|
649
|
+
*/
|
|
650
|
+
|
|
651
|
+
VALUE db_get(VALUE obj, VALUE vtxn, VALUE vkey, VALUE vdata, VALUE vflags)
|
|
652
|
+
{
|
|
653
|
+
t_dbh *dbh;
|
|
654
|
+
int rv;
|
|
655
|
+
u_int32_t flags=0;
|
|
656
|
+
DBT key,data;
|
|
657
|
+
VALUE str;
|
|
658
|
+
t_txnh *txn=NULL;
|
|
659
|
+
|
|
660
|
+
memset(&key,0,sizeof(DBT));
|
|
661
|
+
memset(&data,0,sizeof(DBT));
|
|
662
|
+
|
|
663
|
+
if ( ! NIL_P(vtxn) ) {
|
|
664
|
+
Data_Get_Struct(vtxn,t_txnh,txn);
|
|
665
|
+
if (!txn->txn)
|
|
666
|
+
raise(0, "txn is closed");
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
if ( ! NIL_P(vflags) ) {
|
|
670
|
+
flags=NUM2UINT(vflags);
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
Data_Get_Struct(obj,t_dbh,dbh);
|
|
674
|
+
if (!dbh->db)
|
|
675
|
+
raise_error(0,"db is closed");
|
|
676
|
+
|
|
677
|
+
StringValue(vkey);
|
|
678
|
+
|
|
679
|
+
key.data = RSTRING_PTR(vkey);
|
|
680
|
+
key.size = RSTRING_LEN(vkey);
|
|
681
|
+
key.flags = LMEMFLAG;
|
|
682
|
+
|
|
683
|
+
if ( ! NIL_P(vdata) ) {
|
|
684
|
+
StringValue(vdata);
|
|
685
|
+
data.data = RSTRING_PTR(vdata);
|
|
686
|
+
data.size = RSTRING_LEN(vdata);
|
|
687
|
+
}
|
|
688
|
+
data.flags = DB_DBT_MALLOC;
|
|
689
|
+
|
|
690
|
+
rv = dbh->db->get(dbh->db,txn?txn->txn:NULL,&key,&data,flags);
|
|
691
|
+
if ( rv == 0 ) {
|
|
692
|
+
str = rb_str_new(data.data,data.size);
|
|
693
|
+
if (data.data) free(data.data);
|
|
694
|
+
return str;
|
|
695
|
+
} else if (rv == DB_NOTFOUND) {
|
|
696
|
+
return Qnil;
|
|
697
|
+
} else {
|
|
698
|
+
raise_error(rv, "db_get failure: %s",db_strerror(rv));
|
|
699
|
+
}
|
|
700
|
+
return Qnil;
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
/*
|
|
704
|
+
* call-seq:
|
|
705
|
+
* db.pget(txn,key,data,flags) -> [pkey,data]
|
|
706
|
+
*
|
|
707
|
+
* get a key/data pair from database using a secondary index.
|
|
708
|
+
* returns an array with a primary key and the data element.
|
|
709
|
+
*
|
|
710
|
+
*/
|
|
711
|
+
VALUE db_pget(VALUE obj, VALUE vtxn, VALUE vkey, VALUE vdata, VALUE vflags)
|
|
712
|
+
{
|
|
713
|
+
t_dbh *dbh;
|
|
714
|
+
int rv;
|
|
715
|
+
u_int32_t flags=0;
|
|
716
|
+
DBT key,data,pkey;
|
|
717
|
+
//VALUE str;
|
|
718
|
+
t_txnh *txn=NULL;
|
|
719
|
+
|
|
720
|
+
memset(&key,0,sizeof(DBT));
|
|
721
|
+
memset(&data,0,sizeof(DBT));
|
|
722
|
+
memset(&pkey,0,sizeof(DBT));
|
|
723
|
+
|
|
724
|
+
if ( ! NIL_P(vtxn) ) {
|
|
725
|
+
Data_Get_Struct(vtxn,t_txnh,txn);
|
|
726
|
+
if (!txn->txn)
|
|
727
|
+
raise(0, "txn is closed");
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
if ( ! NIL_P(vflags) ) {
|
|
731
|
+
flags=NUM2UINT(vflags);
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
Data_Get_Struct(obj,t_dbh,dbh);
|
|
735
|
+
if (!dbh->db)
|
|
736
|
+
raise(0, "db is closed");
|
|
737
|
+
|
|
738
|
+
StringValue(vkey);
|
|
739
|
+
|
|
740
|
+
key.data = RSTRING_PTR(vkey);
|
|
741
|
+
key.size = RSTRING_LEN(vkey);
|
|
742
|
+
key.flags = LMEMFLAG;
|
|
743
|
+
|
|
744
|
+
if ( ! NIL_P(vdata) ) {
|
|
745
|
+
StringValue(vdata);
|
|
746
|
+
data.data = RSTRING_PTR(vdata);
|
|
747
|
+
data.size = RSTRING_LEN(vdata);
|
|
748
|
+
data.flags = LMEMFLAG;
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
rv = dbh->db->pget(dbh->db,txn?txn->txn:NULL,&key,&pkey,&data,flags);
|
|
752
|
+
if ( rv == 0 ) {
|
|
753
|
+
return
|
|
754
|
+
rb_ary_new3(2,
|
|
755
|
+
rb_str_new(pkey.data,pkey.size),
|
|
756
|
+
rb_str_new(data.data,data.size));
|
|
757
|
+
|
|
758
|
+
} else if (rv == DB_NOTFOUND) {
|
|
759
|
+
return Qnil;
|
|
760
|
+
} else {
|
|
761
|
+
raise_error(rv, "db_pget failure: %s",db_strerror(rv));
|
|
762
|
+
}
|
|
763
|
+
return Qnil;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
/*
|
|
767
|
+
* call-seq:
|
|
768
|
+
* db[key] -> data
|
|
769
|
+
*
|
|
770
|
+
* array ref style data retrieval
|
|
771
|
+
*
|
|
772
|
+
*/
|
|
773
|
+
VALUE db_aget(VALUE obj, VALUE vkey)
|
|
774
|
+
{
|
|
775
|
+
return db_get(obj,Qnil,vkey,Qnil,Qnil);
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
/*
|
|
779
|
+
* call-seq:
|
|
780
|
+
* db[key]=data
|
|
781
|
+
*
|
|
782
|
+
* array ref style data storage
|
|
783
|
+
*/
|
|
784
|
+
VALUE db_aset(VALUE obj, VALUE vkey, VALUE vdata)
|
|
785
|
+
{
|
|
786
|
+
return db_put(obj,Qnil,vkey,vdata,Qnil);
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
/*
|
|
790
|
+
* call-seq:
|
|
791
|
+
* db.join([cursors],flags) -> join_cursor
|
|
792
|
+
*
|
|
793
|
+
* create a join cursor from an array of cursors.
|
|
794
|
+
* The input cursors will usually be set_range and, if duplicate
|
|
795
|
+
* data items are allowed the should be DUP_SORT or the performance
|
|
796
|
+
* will be abysmal.
|
|
797
|
+
*/
|
|
798
|
+
VALUE db_join(VALUE obj, VALUE vacurs, VALUE vflags)
|
|
799
|
+
{
|
|
800
|
+
t_dbh *dbh;
|
|
801
|
+
t_dbch *dbch;
|
|
802
|
+
u_int32_t flags;
|
|
803
|
+
DBC **curs;
|
|
804
|
+
int i,rv;
|
|
805
|
+
VALUE jcurs;
|
|
806
|
+
|
|
807
|
+
flags=NUM2UINT(vflags);
|
|
808
|
+
Data_Get_Struct(obj,t_dbh,dbh);
|
|
809
|
+
if (!dbh->db)
|
|
810
|
+
raise(0, "db is closed");
|
|
811
|
+
|
|
812
|
+
curs = ALLOCA_N(DBC *,RARRAY_LEN(vacurs));
|
|
813
|
+
for (i=0; i<RARRAY_LEN(vacurs); i++) {
|
|
814
|
+
Data_Get_Struct(RARRAY_PTR(vacurs)[i],t_dbch,dbch);
|
|
815
|
+
/* cursor is closed? */
|
|
816
|
+
curs[i]=dbch->dbc;
|
|
817
|
+
}
|
|
818
|
+
curs[i]=NULL;
|
|
819
|
+
jcurs=Data_Make_Struct(cCursor,t_dbch,dbc_mark,dbc_free,dbch);
|
|
820
|
+
rv = dbh->db->join(dbh->db,curs,&(dbch->dbc),flags);
|
|
821
|
+
if (rv) {
|
|
822
|
+
raise_error(rv, "db_join: %s",db_strerror(rv));
|
|
823
|
+
}
|
|
824
|
+
dbch->db=dbh;
|
|
825
|
+
rb_ary_push(dbch->db->adbc,jcurs);
|
|
826
|
+
rb_obj_call_init(jcurs,0,NULL);
|
|
827
|
+
return jcurs;
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
#if DB_VERSION_MINOR > 3
|
|
831
|
+
/*
|
|
832
|
+
* call-seq:
|
|
833
|
+
* db.compact(txn,start_key,stop_key,compact_opts,flags) -> end_key
|
|
834
|
+
*
|
|
835
|
+
* compact the database (4.4 an up). start and stop keys limit the
|
|
836
|
+
* range of compaction in BTREE types. compact_opts is currently
|
|
837
|
+
* ignored. Call returns the last key compacted (could be fed into
|
|
838
|
+
* a subsequent call as the start_key).
|
|
839
|
+
*
|
|
840
|
+
*/
|
|
841
|
+
VALUE db_compact(VALUE obj, VALUE vtxn, VALUE vstart_key,
|
|
842
|
+
VALUE vstop_key, VALUE db_compact,
|
|
843
|
+
VALUE vflags)
|
|
844
|
+
{
|
|
845
|
+
t_dbh *dbh;
|
|
846
|
+
u_int32_t flags;
|
|
847
|
+
t_txnh *txn=NULL;
|
|
848
|
+
DBT start_key, stop_key, end_key;
|
|
849
|
+
int rv;
|
|
850
|
+
|
|
851
|
+
flags=NUM2UINT(vflags);
|
|
852
|
+
Data_Get_Struct(obj,t_dbh,dbh);
|
|
853
|
+
if (!dbh->db)
|
|
854
|
+
raise(0, "db is closed");
|
|
855
|
+
|
|
856
|
+
memset(&start_key,0,sizeof(DBT));
|
|
857
|
+
memset(&stop_key,0,sizeof(DBT));
|
|
858
|
+
memset(&end_key,0,sizeof(DBT));
|
|
859
|
+
|
|
860
|
+
if ( ! NIL_P(vstart_key) ) {
|
|
861
|
+
StringValue(vstart_key);
|
|
862
|
+
start_key.data=RSTRING_PTR(vstart_key);
|
|
863
|
+
start_key.size=RSTRING_LEN(vstart_key);
|
|
864
|
+
start_key.flags= LMEMFLAG;
|
|
865
|
+
}
|
|
866
|
+
if ( ! NIL_P(vstop_key) ) {
|
|
867
|
+
StringValue(vstop_key);
|
|
868
|
+
stop_key.data=RSTRING_PTR(vstop_key);
|
|
869
|
+
stop_key.size=RSTRING_LEN(vstop_key);
|
|
870
|
+
stop_key.flags= LMEMFLAG;
|
|
871
|
+
}
|
|
872
|
+
if ( ! NIL_P(vtxn) ) {
|
|
873
|
+
Data_Get_Struct(vtxn,t_txnh,txn);
|
|
874
|
+
if (!txn->txn)
|
|
875
|
+
raise(0, "txn is closed");
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
rv=dbh->db->compact(dbh->db,txn?txn->txn:NULL,
|
|
879
|
+
&start_key,
|
|
880
|
+
&stop_key,
|
|
881
|
+
NULL,
|
|
882
|
+
flags,
|
|
883
|
+
&end_key);
|
|
884
|
+
if (rv)
|
|
885
|
+
raise_error(rv,"db_compact failure: %s",db_strerror(rv));
|
|
886
|
+
|
|
887
|
+
return rb_str_new(end_key.data,end_key.size);
|
|
888
|
+
|
|
889
|
+
}
|
|
890
|
+
#endif
|
|
891
|
+
|
|
892
|
+
/*
|
|
893
|
+
* call-seq:
|
|
894
|
+
* db.get_byteswapped -> true/false
|
|
895
|
+
*
|
|
896
|
+
* true if database is running in swapped mode. This happens when
|
|
897
|
+
* the db is created on a machine with a different endian.
|
|
898
|
+
*/
|
|
899
|
+
VALUE db_get_byteswapped(VALUE obj)
|
|
900
|
+
{
|
|
901
|
+
t_dbh *dbh;
|
|
902
|
+
int rv;
|
|
903
|
+
int is_swapped;
|
|
904
|
+
|
|
905
|
+
Data_Get_Struct(obj,t_dbh,dbh);
|
|
906
|
+
if (!dbh->db)
|
|
907
|
+
raise(0, "db is closed");
|
|
908
|
+
rv=dbh->db->get_byteswapped(dbh->db,&is_swapped);
|
|
909
|
+
if (rv)
|
|
910
|
+
raise_error(rv,"db_get_byteswapped failed: %s",db_strerror(rv));
|
|
911
|
+
if (is_swapped)
|
|
912
|
+
return Qtrue;
|
|
913
|
+
else
|
|
914
|
+
return Qfalse;
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
/*
|
|
918
|
+
* call-seq:
|
|
919
|
+
* db.get_type -> Fixnum(type)
|
|
920
|
+
*
|
|
921
|
+
* an integer indicating the type of db (BTREE, HASH, etc).
|
|
922
|
+
*/
|
|
923
|
+
VALUE db_get_type(VALUE obj)
|
|
924
|
+
{
|
|
925
|
+
t_dbh *dbh;
|
|
926
|
+
int rv;
|
|
927
|
+
DBTYPE dbtype;
|
|
928
|
+
|
|
929
|
+
Data_Get_Struct(obj,t_dbh,dbh);
|
|
930
|
+
if (!dbh->db)
|
|
931
|
+
raise(0, "db is closed");
|
|
932
|
+
rv=dbh->db->get_type(dbh->db,&dbtype);
|
|
933
|
+
if (rv)
|
|
934
|
+
raise_error(rv,"db_get_type failed: %s",db_strerror(rv));
|
|
935
|
+
return INT2FIX(dbtype);
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
/*
|
|
939
|
+
* call-seq:
|
|
940
|
+
* db.remove(disk_file,logical_db,flags) -> true
|
|
941
|
+
*
|
|
942
|
+
* removes a whole database file, or just a logical_db within
|
|
943
|
+
* that file, i.e. if file and logical are both specified, only
|
|
944
|
+
* the logical will be removed. the Bdb::Db instance cannot have
|
|
945
|
+
* been previously used for anything and cannot be used after.
|
|
946
|
+
*/
|
|
947
|
+
VALUE db_remove(VALUE obj, VALUE vdisk_file,
|
|
948
|
+
VALUE vlogical_db, VALUE vflags)
|
|
949
|
+
{
|
|
950
|
+
t_dbh *dbh;
|
|
951
|
+
int rv;
|
|
952
|
+
u_int32_t flags=0;
|
|
953
|
+
//char *logical_db=NULL;
|
|
954
|
+
|
|
955
|
+
if ( ! NIL_P(vflags) )
|
|
956
|
+
flags=NUM2UINT(vflags);
|
|
957
|
+
|
|
958
|
+
Data_Get_Struct(obj,t_dbh,dbh);
|
|
959
|
+
if (!dbh->db)
|
|
960
|
+
raise(0, "db is closed");
|
|
961
|
+
rv=dbh->db->remove(dbh->db,
|
|
962
|
+
NIL_P(vdisk_file)?NULL:StringValueCStr(vdisk_file),
|
|
963
|
+
NIL_P(vlogical_db)?NULL:StringValueCStr(vlogical_db),
|
|
964
|
+
flags);
|
|
965
|
+
/* handle cannot be accessed again per docs */
|
|
966
|
+
dbh->db=NULL;
|
|
967
|
+
if (rv)
|
|
968
|
+
raise_error(rv,"db_remove failed: %s",db_strerror(rv));
|
|
969
|
+
return Qtrue;
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
/*
|
|
973
|
+
* call-seq:
|
|
974
|
+
* db.rename(file,logical,newname,flags) -> true
|
|
975
|
+
*
|
|
976
|
+
* rename a file or logical db to newname.
|
|
977
|
+
*/
|
|
978
|
+
VALUE db_rename(VALUE obj, VALUE vdisk_file,
|
|
979
|
+
VALUE vlogical_db, VALUE newname, VALUE vflags)
|
|
980
|
+
{
|
|
981
|
+
t_dbh *dbh;
|
|
982
|
+
int rv;
|
|
983
|
+
u_int32_t flags=0;
|
|
984
|
+
//char *disk_file=NULL;
|
|
985
|
+
//char *logical_db=NULL;
|
|
986
|
+
|
|
987
|
+
if ( ! NIL_P(vflags) )
|
|
988
|
+
flags=NUM2UINT(vflags);
|
|
989
|
+
|
|
990
|
+
if ( NIL_P(newname) )
|
|
991
|
+
raise_error(0,"db_rename newname must be specified");
|
|
992
|
+
|
|
993
|
+
Data_Get_Struct(obj,t_dbh,dbh);
|
|
994
|
+
if (!dbh->db)
|
|
995
|
+
raise(0, "db is closed");
|
|
996
|
+
rv=dbh->db->rename(dbh->db,
|
|
997
|
+
NIL_P(vdisk_file)?NULL:StringValueCStr(vdisk_file),
|
|
998
|
+
NIL_P(vlogical_db)?NULL:StringValueCStr(vlogical_db),
|
|
999
|
+
StringValueCStr(newname),
|
|
1000
|
+
flags);
|
|
1001
|
+
|
|
1002
|
+
if (rv) {
|
|
1003
|
+
raise_error(rv,"db_rename failed: %s",db_strerror(rv));
|
|
1004
|
+
}
|
|
1005
|
+
return Qtrue;
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
/*
|
|
1009
|
+
* call-seq:
|
|
1010
|
+
* db.sync -> true
|
|
1011
|
+
*
|
|
1012
|
+
* sync the database out to storage.
|
|
1013
|
+
*/
|
|
1014
|
+
VALUE db_sync(VALUE obj)
|
|
1015
|
+
{
|
|
1016
|
+
t_dbh *dbh;
|
|
1017
|
+
int rv;
|
|
1018
|
+
|
|
1019
|
+
Data_Get_Struct(obj,t_dbh,dbh);
|
|
1020
|
+
if (!dbh->db)
|
|
1021
|
+
raise(0, "db is closed");
|
|
1022
|
+
rv=dbh->db->sync(dbh->db,NOFLAGS);
|
|
1023
|
+
|
|
1024
|
+
if (rv)
|
|
1025
|
+
raise_error(rv,"db_sync failed: %s",db_strerror(rv));
|
|
1026
|
+
return Qtrue;
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
/*
|
|
1030
|
+
* call-seq:
|
|
1031
|
+
* db.truncate(txn) -> Fixnum(record_count)
|
|
1032
|
+
*
|
|
1033
|
+
* truncate, i.e. remove all records, purge, trash.
|
|
1034
|
+
*
|
|
1035
|
+
*/
|
|
1036
|
+
VALUE db_truncate(VALUE obj, VALUE vtxn)
|
|
1037
|
+
{
|
|
1038
|
+
t_dbh *dbh;
|
|
1039
|
+
t_txnh *txn=NULL;
|
|
1040
|
+
int rv;
|
|
1041
|
+
//VALUE result;
|
|
1042
|
+
u_int32_t count;
|
|
1043
|
+
|
|
1044
|
+
if ( ! NIL_P(vtxn) ) {
|
|
1045
|
+
Data_Get_Struct(vtxn,t_txnh,txn);
|
|
1046
|
+
if (!txn->txn)
|
|
1047
|
+
raise(0, "txn is closed");
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
Data_Get_Struct(obj,t_dbh,dbh);
|
|
1051
|
+
if (!dbh->db)
|
|
1052
|
+
raise(0, "db is closed");
|
|
1053
|
+
|
|
1054
|
+
rv=dbh->db->truncate(dbh->db,txn?txn->txn:NULL,&count,NOFLAGS);
|
|
1055
|
+
if (rv)
|
|
1056
|
+
raise_error(rv,"db_truncate: %s",db_strerror(rv));
|
|
1057
|
+
|
|
1058
|
+
return INT2FIX(count);
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
/*
|
|
1062
|
+
* call-seq:
|
|
1063
|
+
* db.key_range(txn,vkey,flags) -> [#less,#same,#greater]
|
|
1064
|
+
*
|
|
1065
|
+
* calculate position of key within database. returns the counts
|
|
1066
|
+
* of keys less, same and greater than the given key as an
|
|
1067
|
+
* array of Fixnum-s
|
|
1068
|
+
*/
|
|
1069
|
+
VALUE db_key_range(VALUE obj, VALUE vtxn, VALUE vkey, VALUE vflags)
|
|
1070
|
+
{
|
|
1071
|
+
t_dbh *dbh;
|
|
1072
|
+
t_txnh *txn=NULL;
|
|
1073
|
+
DBT key;
|
|
1074
|
+
u_int32_t flags = 0;
|
|
1075
|
+
int rv;
|
|
1076
|
+
DB_KEY_RANGE key_range;
|
|
1077
|
+
VALUE result;
|
|
1078
|
+
|
|
1079
|
+
if ( ! NIL_P(vtxn) ) {
|
|
1080
|
+
Data_Get_Struct(vtxn,t_txnh,txn);
|
|
1081
|
+
if (!txn->txn)
|
|
1082
|
+
raise(0, "txn is closed");
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
if ( ! NIL_P(vflags) )
|
|
1086
|
+
flags=NUM2UINT(vflags);
|
|
1087
|
+
|
|
1088
|
+
Data_Get_Struct(obj,t_dbh,dbh);
|
|
1089
|
+
if (!dbh->db)
|
|
1090
|
+
raise(0, "db is closed");
|
|
1091
|
+
|
|
1092
|
+
memset(&key,0,sizeof(DBT));
|
|
1093
|
+
StringValue(vkey);
|
|
1094
|
+
key.data = RSTRING_PTR(vkey);
|
|
1095
|
+
key.size = RSTRING_LEN(vkey);
|
|
1096
|
+
key.flags = LMEMFLAG;
|
|
1097
|
+
|
|
1098
|
+
rv=dbh->db->key_range(dbh->db,txn?txn->txn:NULL,&key,
|
|
1099
|
+
&key_range,flags);
|
|
1100
|
+
if (rv)
|
|
1101
|
+
raise_error(rv,"db_key_range: %s",db_strerror(rv));
|
|
1102
|
+
|
|
1103
|
+
result=rb_ary_new3(3,
|
|
1104
|
+
rb_float_new(key_range.less),
|
|
1105
|
+
rb_float_new(key_range.equal),
|
|
1106
|
+
rb_float_new(key_range.greater));
|
|
1107
|
+
return result;
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
/*
|
|
1111
|
+
* call-seq:
|
|
1112
|
+
* db.del(txn,key,flags) -> true/nil
|
|
1113
|
+
*
|
|
1114
|
+
* delete records with the key given. DUP values will removed
|
|
1115
|
+
* as a group. true if deleted extant records. NIL if the
|
|
1116
|
+
* operation resulted in DB indicating DB_NOTFOUND.
|
|
1117
|
+
*
|
|
1118
|
+
*/
|
|
1119
|
+
VALUE db_del(VALUE obj, VALUE vtxn, VALUE vkey, VALUE vflags)
|
|
1120
|
+
{
|
|
1121
|
+
t_dbh *dbh;
|
|
1122
|
+
int rv;
|
|
1123
|
+
u_int32_t flags;
|
|
1124
|
+
DBT key;
|
|
1125
|
+
//VALUE str;
|
|
1126
|
+
t_txnh *txn=NULL;
|
|
1127
|
+
|
|
1128
|
+
memset(&key,0,sizeof(DBT));
|
|
1129
|
+
|
|
1130
|
+
if ( ! NIL_P(vtxn) ) {
|
|
1131
|
+
Data_Get_Struct(vtxn,t_txnh,txn);
|
|
1132
|
+
if (!txn->txn)
|
|
1133
|
+
raise(0, "txn is closed");
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
flags=NUM2UINT(vflags);
|
|
1137
|
+
Data_Get_Struct(obj,t_dbh,dbh);
|
|
1138
|
+
if (!dbh->db)
|
|
1139
|
+
raise(0, "db is closed");
|
|
1140
|
+
|
|
1141
|
+
StringValue(vkey);
|
|
1142
|
+
key.data = RSTRING_PTR(vkey);
|
|
1143
|
+
key.size = RSTRING_LEN(vkey);
|
|
1144
|
+
key.flags = LMEMFLAG;
|
|
1145
|
+
|
|
1146
|
+
rv = dbh->db->del(dbh->db,txn?txn->txn:NULL,&key,flags);
|
|
1147
|
+
if ( rv == DB_NOTFOUND ) {
|
|
1148
|
+
return Qnil;
|
|
1149
|
+
} else if (rv != 0) {
|
|
1150
|
+
raise_error(rv, "db_del failure: %s",db_strerror(rv));
|
|
1151
|
+
}
|
|
1152
|
+
return Qtrue;
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
void assoc_key(DBT* result, VALUE obj) {
|
|
1156
|
+
VALUE key = StringValue(obj);
|
|
1157
|
+
int len = RSTRING_LEN(key);
|
|
1158
|
+
char *str = malloc(len);
|
|
1159
|
+
memcpy(str, RSTRING_PTR(key), len);
|
|
1160
|
+
|
|
1161
|
+
#ifdef DEBUG_DB
|
|
1162
|
+
fprintf(stderr,"assoc_key %*s", len, str);
|
|
1163
|
+
#endif
|
|
1164
|
+
|
|
1165
|
+
result->size = len;
|
|
1166
|
+
result->flags = LMEMFLAG | DB_DBT_APPMALLOC;
|
|
1167
|
+
result->data = str;
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
VALUE assoc_call(VALUE *args)
|
|
1171
|
+
{
|
|
1172
|
+
return rb_funcall(args[0],fv_call,3,args[1],args[2],args[3]);
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
VALUE assoc_rescue(VALUE *error, VALUE e)
|
|
1176
|
+
{
|
|
1177
|
+
VALUE message = StringValue(e);
|
|
1178
|
+
rb_warn(RSTRING_PTR(message));
|
|
1179
|
+
*error = e;
|
|
1180
|
+
return Qnil;
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
int assoc_callback(DB *secdb, const DBT* pkey, const DBT* data, DBT* skey)
|
|
1184
|
+
{
|
|
1185
|
+
t_dbh *dbh;
|
|
1186
|
+
//VALUE proc;
|
|
1187
|
+
VALUE error = Qnil;
|
|
1188
|
+
VALUE retv;
|
|
1189
|
+
VALUE args[4];
|
|
1190
|
+
VALUE keys;
|
|
1191
|
+
int i;
|
|
1192
|
+
|
|
1193
|
+
memset(skey,0,sizeof(DBT));
|
|
1194
|
+
dbh=secdb->app_private;
|
|
1195
|
+
|
|
1196
|
+
args[0]=dbh->aproc;
|
|
1197
|
+
args[1]=dbh->self;
|
|
1198
|
+
args[2]=rb_str_new(pkey->data,pkey->size);
|
|
1199
|
+
args[3]=rb_str_new(data->data,data->size);
|
|
1200
|
+
|
|
1201
|
+
#ifdef DEBUG_DB
|
|
1202
|
+
fprintf(stderr,"assoc_data %*s", data->size, data->data);
|
|
1203
|
+
#endif
|
|
1204
|
+
|
|
1205
|
+
retv=rb_rescue((VALUE(*)_((VALUE)))assoc_call,(VALUE)args,(VALUE(*)_((VALUE)))assoc_rescue,(VALUE)&error);
|
|
1206
|
+
|
|
1207
|
+
if (!NIL_P(error)) return 99999;
|
|
1208
|
+
if (NIL_P(retv))
|
|
1209
|
+
return DB_DONOTINDEX;
|
|
1210
|
+
|
|
1211
|
+
keys = rb_check_array_type(retv);
|
|
1212
|
+
if (!NIL_P(keys)) {
|
|
1213
|
+
keys = rb_funcall(keys,fv_uniq,0); /* secondary keys must be uniq */
|
|
1214
|
+
switch(RARRAY_LEN(keys)) {
|
|
1215
|
+
case 0:
|
|
1216
|
+
return DB_DONOTINDEX;
|
|
1217
|
+
case 1:
|
|
1218
|
+
retv=RARRAY_PTR(keys)[0];
|
|
1219
|
+
break;
|
|
1220
|
+
default:
|
|
1221
|
+
skey->size = RARRAY_LEN(keys);
|
|
1222
|
+
skey->flags = LMEMFLAG | DB_DBT_MULTIPLE | DB_DBT_APPMALLOC;
|
|
1223
|
+
skey->data = malloc(skey->size * sizeof(DBT));
|
|
1224
|
+
memset(skey->data, 0, skey->size * sizeof(DBT));
|
|
1225
|
+
|
|
1226
|
+
for (i=0; i<skey->size; i++) {
|
|
1227
|
+
assoc_key(skey->data + i * sizeof(DBT), (VALUE)RARRAY_PTR(keys)[i]);
|
|
1228
|
+
}
|
|
1229
|
+
return 0;
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1233
|
+
assoc_key(skey, retv);
|
|
1234
|
+
return 0;
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
/*
|
|
1238
|
+
* call-seq:
|
|
1239
|
+
* db.associate(txn,sec_db,flags,proc)
|
|
1240
|
+
*
|
|
1241
|
+
* associate a secondary index(database) with this (primary)
|
|
1242
|
+
* database. The proc can be nil if the database is only opened
|
|
1243
|
+
* DB_RDONLY.
|
|
1244
|
+
*
|
|
1245
|
+
* call back proc has signature:
|
|
1246
|
+
* proc(secdb,key,value)
|
|
1247
|
+
*/
|
|
1248
|
+
VALUE db_associate(VALUE obj, VALUE vtxn, VALUE osecdb,
|
|
1249
|
+
VALUE vflags, VALUE cb_proc)
|
|
1250
|
+
{
|
|
1251
|
+
t_dbh *sdbh,*pdbh;
|
|
1252
|
+
int rv;
|
|
1253
|
+
u_int32_t flags,flagsp,flagss;
|
|
1254
|
+
//int fdp;
|
|
1255
|
+
t_txnh *txn=NOTXN;
|
|
1256
|
+
|
|
1257
|
+
flags=NUM2UINT(vflags);
|
|
1258
|
+
Data_Get_Struct(obj,t_dbh,pdbh);
|
|
1259
|
+
if (!pdbh->db)
|
|
1260
|
+
raise(0, "db is closed");
|
|
1261
|
+
Data_Get_Struct(osecdb,t_dbh,sdbh);
|
|
1262
|
+
if (!sdbh->db)
|
|
1263
|
+
raise(0, "sdb is closed");
|
|
1264
|
+
|
|
1265
|
+
if ( ! NIL_P(vtxn) ) {
|
|
1266
|
+
Data_Get_Struct(vtxn,t_txnh,txn);
|
|
1267
|
+
if (!txn->txn)
|
|
1268
|
+
raise(0, "txn is closed");
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
if ( cb_proc == Qnil ) {
|
|
1272
|
+
rb_warning("db_associate: no association may be applied");
|
|
1273
|
+
pdbh->db->get_open_flags(pdbh->db,&flagsp);
|
|
1274
|
+
sdbh->db->get_open_flags(sdbh->db,&flagss);
|
|
1275
|
+
if ( flagsp & DB_RDONLY & flagss ) {
|
|
1276
|
+
rv=pdbh->db->associate(pdbh->db,txn?txn->txn:NULL,
|
|
1277
|
+
sdbh->db,NULL,flags);
|
|
1278
|
+
if (rv)
|
|
1279
|
+
raise_error(rv,"db_associate: %s",db_strerror(rv));
|
|
1280
|
+
return Qtrue;
|
|
1281
|
+
} else {
|
|
1282
|
+
raise_error(0,"db_associate empty associate only available when both DBs opened with DB_RDONLY");
|
|
1283
|
+
}
|
|
1284
|
+
} else if ( rb_obj_is_instance_of(cb_proc,rb_cProc) != Qtrue ) {
|
|
1285
|
+
raise_error(0, "db_associate proc required");
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
sdbh->aproc=cb_proc;
|
|
1289
|
+
|
|
1290
|
+
rv=pdbh->db->associate(pdbh->db,txn?txn->txn:NULL,sdbh->db,assoc_callback,flags);
|
|
1291
|
+
#ifdef DEBUG_DB
|
|
1292
|
+
fprintf(stderr,"file is %d\n",fdp);
|
|
1293
|
+
fprintf(stderr,"assoc done 0x%x\n",sdbh);
|
|
1294
|
+
#endif
|
|
1295
|
+
if (rv != 0) {
|
|
1296
|
+
raise_error(rv, "db_associate failure: %s",db_strerror(rv));
|
|
1297
|
+
}
|
|
1298
|
+
return Qtrue;
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
VALUE
|
|
1302
|
+
bt_compare_callback2(VALUE *args)
|
|
1303
|
+
{
|
|
1304
|
+
return rb_funcall(args[0],fv_call,3,args[1],args[2],args[3]);
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
int bt_compare_callback(DB *db, const DBT* key1, const DBT* key2)
|
|
1308
|
+
{
|
|
1309
|
+
t_dbh *dbh;
|
|
1310
|
+
//VALUE proc;
|
|
1311
|
+
int cmp;
|
|
1312
|
+
VALUE retv;
|
|
1313
|
+
|
|
1314
|
+
dbh=db->app_private;
|
|
1315
|
+
|
|
1316
|
+
/* Shouldn't catch exceptions in the callback, because bad sort data will corrupt the BTree.*/
|
|
1317
|
+
retv=rb_funcall(dbh->sproc,fv_call,3,dbh->self,
|
|
1318
|
+
rb_str_new(key1->data,key1->size),rb_str_new(key2->data,key2->size));
|
|
1319
|
+
|
|
1320
|
+
if (!FIXNUM_P(retv))
|
|
1321
|
+
rb_raise(rb_eTypeError,"btree comparison should return Fixnum");
|
|
1322
|
+
|
|
1323
|
+
cmp=FIX2INT(retv);
|
|
1324
|
+
|
|
1325
|
+
#ifdef DEBUG_DB
|
|
1326
|
+
fprintf(stderr,"bt_compare %*s <=> %*s: %d", key1->size, key1->data, key2->size, key2->data, cmp);
|
|
1327
|
+
#endif
|
|
1328
|
+
|
|
1329
|
+
return cmp;
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
/*
|
|
1333
|
+
* call-seq:
|
|
1334
|
+
* db.btree_compare = proc
|
|
1335
|
+
*
|
|
1336
|
+
* set the btree key comparison function to the callback proc.
|
|
1337
|
+
*
|
|
1338
|
+
* callback proc has signature:
|
|
1339
|
+
* proc(db,key1,key2)
|
|
1340
|
+
*/
|
|
1341
|
+
VALUE db_btree_compare_set(VALUE obj, VALUE cb_proc)
|
|
1342
|
+
{
|
|
1343
|
+
t_dbh *dbh;
|
|
1344
|
+
int rv;
|
|
1345
|
+
|
|
1346
|
+
Data_Get_Struct(obj,t_dbh,dbh);
|
|
1347
|
+
if (!dbh->db)
|
|
1348
|
+
raise(0, "db is closed");
|
|
1349
|
+
|
|
1350
|
+
if ( rb_obj_is_instance_of(cb_proc,rb_cProc) != Qtrue ) {
|
|
1351
|
+
raise_error(0, "db_associate proc required");
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
dbh->sproc=cb_proc;
|
|
1355
|
+
rv=dbh->db->set_bt_compare(dbh->db,bt_compare_callback);
|
|
1356
|
+
|
|
1357
|
+
#ifdef DEBUG_DB
|
|
1358
|
+
fprintf(stderr,"btree_compare set 0x%x\n",dbh);
|
|
1359
|
+
#endif
|
|
1360
|
+
if (rv != 0) {
|
|
1361
|
+
raise_error(rv, "db_btree_compare_set failure: %s",db_strerror(rv));
|
|
1362
|
+
}
|
|
1363
|
+
return Qtrue;
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
/*
|
|
1367
|
+
* call-seq:
|
|
1368
|
+
* db.cursor(txn,flags)
|
|
1369
|
+
*
|
|
1370
|
+
* open a cursor
|
|
1371
|
+
*/
|
|
1372
|
+
VALUE db_cursor(VALUE obj, VALUE vtxn, VALUE vflags)
|
|
1373
|
+
{
|
|
1374
|
+
t_dbh *dbh;
|
|
1375
|
+
int rv;
|
|
1376
|
+
u_int32_t flags;
|
|
1377
|
+
//DBC *dbc;
|
|
1378
|
+
t_txnh *txn=NOTXN;
|
|
1379
|
+
VALUE c_obj;
|
|
1380
|
+
t_dbch *dbch;
|
|
1381
|
+
|
|
1382
|
+
flags=NUM2UINT(vflags);
|
|
1383
|
+
Data_Get_Struct(obj,t_dbh,dbh);
|
|
1384
|
+
if (!dbh->db)
|
|
1385
|
+
raise(0, "db is closed");
|
|
1386
|
+
|
|
1387
|
+
c_obj=Data_Make_Struct(cCursor, t_dbch, dbc_mark, dbc_free, dbch);
|
|
1388
|
+
|
|
1389
|
+
if ( ! NIL_P(vtxn) ) {
|
|
1390
|
+
Data_Get_Struct(vtxn,t_txnh,txn);
|
|
1391
|
+
if (!txn->txn)
|
|
1392
|
+
raise(0, "txn is closed");
|
|
1393
|
+
}
|
|
1394
|
+
|
|
1395
|
+
rv=dbh->db->cursor(dbh->db,txn?txn->txn:NULL,&(dbch->dbc),flags);
|
|
1396
|
+
if (rv)
|
|
1397
|
+
raise_error(rv,"db_cursor: %s",db_strerror(rv));
|
|
1398
|
+
|
|
1399
|
+
filename_dup(dbch->filename,dbh->filename);
|
|
1400
|
+
dbch->db=dbh;
|
|
1401
|
+
rb_ary_push(dbch->db->adbc,c_obj);
|
|
1402
|
+
rb_obj_call_init(c_obj,0,NULL);
|
|
1403
|
+
return c_obj;
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
/*
|
|
1407
|
+
* call-seq:
|
|
1408
|
+
* dbc.close -> nil
|
|
1409
|
+
*
|
|
1410
|
+
* close an open cursor
|
|
1411
|
+
*/
|
|
1412
|
+
VALUE dbc_close(VALUE obj)
|
|
1413
|
+
{
|
|
1414
|
+
t_dbch *dbch;
|
|
1415
|
+
int rv;
|
|
1416
|
+
Data_Get_Struct(obj,t_dbch,dbch);
|
|
1417
|
+
if ( dbch->dbc ) {
|
|
1418
|
+
rv=dbch->dbc->c_close(dbch->dbc);
|
|
1419
|
+
rb_ary_delete(dbch->db->adbc,obj);
|
|
1420
|
+
dbch->db=NULL;
|
|
1421
|
+
dbch->dbc=NULL;
|
|
1422
|
+
if (rv)
|
|
1423
|
+
raise_error(rv,"dbc_close: %s",db_strerror(rv));
|
|
1424
|
+
}
|
|
1425
|
+
return Qnil;
|
|
1426
|
+
}
|
|
1427
|
+
|
|
1428
|
+
/*
|
|
1429
|
+
* call-seq:
|
|
1430
|
+
* dbc.get(key,data,flags) -> [key,data]
|
|
1431
|
+
*
|
|
1432
|
+
* get data by key or key and data. returns array of key,data
|
|
1433
|
+
*/
|
|
1434
|
+
VALUE dbc_get(VALUE obj, VALUE vkey, VALUE vdata, VALUE vflags)
|
|
1435
|
+
{
|
|
1436
|
+
t_dbch *dbch;
|
|
1437
|
+
u_int32_t flags;
|
|
1438
|
+
DBT key,data;
|
|
1439
|
+
VALUE rar;
|
|
1440
|
+
int rv;
|
|
1441
|
+
|
|
1442
|
+
flags=NUM2UINT(vflags);
|
|
1443
|
+
Data_Get_Struct(obj,t_dbch,dbch);
|
|
1444
|
+
if (!dbch->dbc)
|
|
1445
|
+
raise(0, "dbc is closed");
|
|
1446
|
+
|
|
1447
|
+
memset(&key,0,sizeof(DBT));
|
|
1448
|
+
memset(&data,0,sizeof(DBT));
|
|
1449
|
+
|
|
1450
|
+
if ( ! NIL_P(vkey) ) {
|
|
1451
|
+
StringValue(vkey);
|
|
1452
|
+
key.data = RSTRING_PTR(vkey);
|
|
1453
|
+
key.size = RSTRING_LEN(vkey);
|
|
1454
|
+
key.flags = LMEMFLAG;
|
|
1455
|
+
}
|
|
1456
|
+
if ( ! NIL_P(vdata) ) {
|
|
1457
|
+
StringValue(vdata);
|
|
1458
|
+
data.data = RSTRING_PTR(vdata);
|
|
1459
|
+
data.size = RSTRING_LEN(vdata);
|
|
1460
|
+
data.flags = LMEMFLAG;
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
rv = dbch->dbc->c_get(dbch->dbc,&key,&data,flags);
|
|
1464
|
+
if ( rv == 0 ) {
|
|
1465
|
+
rar = rb_ary_new3(2,rb_str_new(key.data,key.size),
|
|
1466
|
+
rb_str_new(data.data,data.size));
|
|
1467
|
+
return rar;
|
|
1468
|
+
} else if (rv == DB_NOTFOUND) {
|
|
1469
|
+
return Qnil;
|
|
1470
|
+
} else {
|
|
1471
|
+
raise_error(rv, "dbc_get %s",db_strerror(rv));
|
|
1472
|
+
}
|
|
1473
|
+
return Qnil;
|
|
1474
|
+
}
|
|
1475
|
+
/*
|
|
1476
|
+
* call-seq:
|
|
1477
|
+
* dbc.pget(key,data,flags) -> [key,pkey,data]
|
|
1478
|
+
*
|
|
1479
|
+
* cursor pget, returns array(key, primary key, data)
|
|
1480
|
+
*/
|
|
1481
|
+
VALUE dbc_pget(VALUE obj, VALUE vkey, VALUE vdata, VALUE vflags)
|
|
1482
|
+
{
|
|
1483
|
+
t_dbch *dbch;
|
|
1484
|
+
u_int32_t flags;
|
|
1485
|
+
DBT key,data,pkey;
|
|
1486
|
+
VALUE rar;
|
|
1487
|
+
int rv;
|
|
1488
|
+
|
|
1489
|
+
flags=NUM2UINT(vflags);
|
|
1490
|
+
Data_Get_Struct(obj,t_dbch,dbch);
|
|
1491
|
+
if (!dbch->dbc)
|
|
1492
|
+
raise(0, "dbc is closed");
|
|
1493
|
+
|
|
1494
|
+
memset(&key,0,sizeof(DBT));
|
|
1495
|
+
memset(&data,0,sizeof(DBT));
|
|
1496
|
+
memset(&pkey,0,sizeof(DBT));
|
|
1497
|
+
|
|
1498
|
+
if ( ! NIL_P(vkey) ) {
|
|
1499
|
+
StringValue(vkey);
|
|
1500
|
+
key.data = RSTRING_PTR(vkey);
|
|
1501
|
+
key.size = RSTRING_LEN(vkey);
|
|
1502
|
+
key.flags = LMEMFLAG;
|
|
1503
|
+
}
|
|
1504
|
+
if ( ! NIL_P(vdata) ) {
|
|
1505
|
+
StringValue(vdata);
|
|
1506
|
+
data.data = RSTRING_PTR(vdata);
|
|
1507
|
+
data.size = RSTRING_LEN(vdata);
|
|
1508
|
+
data.flags = LMEMFLAG;
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1511
|
+
rv = dbch->dbc->c_pget(dbch->dbc,&key,&pkey,&data,flags);
|
|
1512
|
+
if ( rv == 0 ) {
|
|
1513
|
+
rar = rb_ary_new3(3,
|
|
1514
|
+
rb_str_new(key.data,key.size),
|
|
1515
|
+
rb_str_new(pkey.data,pkey.size),
|
|
1516
|
+
rb_str_new(data.data,data.size));
|
|
1517
|
+
return rar;
|
|
1518
|
+
} else if (rv == DB_NOTFOUND) {
|
|
1519
|
+
return Qnil;
|
|
1520
|
+
} else {
|
|
1521
|
+
raise_error(rv, "dbc_pget %s",db_strerror(rv));
|
|
1522
|
+
}
|
|
1523
|
+
return Qnil;
|
|
1524
|
+
}
|
|
1525
|
+
|
|
1526
|
+
/*
|
|
1527
|
+
* call-seq:
|
|
1528
|
+
* dbc.put(key,data,flags) -> data
|
|
1529
|
+
*
|
|
1530
|
+
* cursor put key/data
|
|
1531
|
+
*/
|
|
1532
|
+
VALUE dbc_put(VALUE obj, VALUE vkey, VALUE vdata, VALUE vflags)
|
|
1533
|
+
{
|
|
1534
|
+
t_dbch *dbch;
|
|
1535
|
+
u_int32_t flags;
|
|
1536
|
+
DBT key,data;
|
|
1537
|
+
int rv;
|
|
1538
|
+
|
|
1539
|
+
if ( NIL_P(vdata) )
|
|
1540
|
+
raise_error(0,"data element is required for put");
|
|
1541
|
+
|
|
1542
|
+
flags=NUM2UINT(vflags);
|
|
1543
|
+
Data_Get_Struct(obj,t_dbch,dbch);
|
|
1544
|
+
if (!dbch->dbc)
|
|
1545
|
+
raise(0, "dbc is closed");
|
|
1546
|
+
|
|
1547
|
+
memset(&key,0,sizeof(DBT));
|
|
1548
|
+
memset(&data,0,sizeof(DBT));
|
|
1549
|
+
|
|
1550
|
+
if ( ! NIL_P(vkey) ) {
|
|
1551
|
+
StringValue(vkey);
|
|
1552
|
+
key.data = RSTRING_PTR(vkey);
|
|
1553
|
+
key.size = RSTRING_LEN(vkey);
|
|
1554
|
+
key.flags = LMEMFLAG;
|
|
1555
|
+
}
|
|
1556
|
+
|
|
1557
|
+
StringValue(vdata);
|
|
1558
|
+
data.data = RSTRING_PTR(vdata);
|
|
1559
|
+
data.size = RSTRING_LEN(vdata);
|
|
1560
|
+
data.flags = LMEMFLAG;
|
|
1561
|
+
|
|
1562
|
+
rv = dbch->dbc->c_put(dbch->dbc,&key,&data,flags);
|
|
1563
|
+
if (rv != 0)
|
|
1564
|
+
raise_error(rv,"dbc_put failure: %s",db_strerror(rv));
|
|
1565
|
+
|
|
1566
|
+
return vdata;
|
|
1567
|
+
}
|
|
1568
|
+
|
|
1569
|
+
/*
|
|
1570
|
+
* call-seq:
|
|
1571
|
+
* dbc.del -> true|nil
|
|
1572
|
+
*
|
|
1573
|
+
* delete tuple at current cursor position. returns true if
|
|
1574
|
+
* something was deleted, nil otherwise (DB_KEYEMPTY)
|
|
1575
|
+
*
|
|
1576
|
+
*/
|
|
1577
|
+
VALUE dbc_del(VALUE obj)
|
|
1578
|
+
{
|
|
1579
|
+
t_dbch *dbch;
|
|
1580
|
+
int rv;
|
|
1581
|
+
|
|
1582
|
+
Data_Get_Struct(obj,t_dbch,dbch);
|
|
1583
|
+
if (!dbch->dbc)
|
|
1584
|
+
raise(0, "dbc is closed");
|
|
1585
|
+
rv = dbch->dbc->c_del(dbch->dbc,NOFLAGS);
|
|
1586
|
+
if (rv == DB_KEYEMPTY)
|
|
1587
|
+
return Qnil;
|
|
1588
|
+
else if (rv != 0) {
|
|
1589
|
+
raise_error(rv, "dbc_del failure: %s",db_strerror(rv));
|
|
1590
|
+
}
|
|
1591
|
+
return Qtrue;
|
|
1592
|
+
}
|
|
1593
|
+
|
|
1594
|
+
/*
|
|
1595
|
+
* call-seq:
|
|
1596
|
+
* dbc.count -> Fixnum(count)
|
|
1597
|
+
*
|
|
1598
|
+
* returns cursor count as per DB.
|
|
1599
|
+
*/
|
|
1600
|
+
VALUE dbc_count(VALUE obj)
|
|
1601
|
+
{
|
|
1602
|
+
t_dbch *dbch;
|
|
1603
|
+
int rv;
|
|
1604
|
+
db_recno_t count;
|
|
1605
|
+
|
|
1606
|
+
Data_Get_Struct(obj,t_dbch,dbch);
|
|
1607
|
+
if (!dbch->dbc)
|
|
1608
|
+
raise(0, "dbc is closed");
|
|
1609
|
+
rv = dbch->dbc->c_count(dbch->dbc,&count,NOFLAGS);
|
|
1610
|
+
if (rv != 0)
|
|
1611
|
+
raise_error(rv, "db_count failure: %s",db_strerror(rv));
|
|
1612
|
+
|
|
1613
|
+
return INT2FIX(count);
|
|
1614
|
+
}
|
|
1615
|
+
|
|
1616
|
+
static void env_free(void *p)
|
|
1617
|
+
{
|
|
1618
|
+
t_envh *eh;
|
|
1619
|
+
eh=(t_envh *)p;
|
|
1620
|
+
|
|
1621
|
+
#ifdef DEBUG_DB
|
|
1622
|
+
if ( RTEST(ruby_debug) )
|
|
1623
|
+
fprintf(stderr,"%s/%d %s 0x%x\n",__FILE__,__LINE__,"env_free cleanup!",p);
|
|
1624
|
+
#endif
|
|
1625
|
+
|
|
1626
|
+
if ( eh ) {
|
|
1627
|
+
if ( eh->env ) {
|
|
1628
|
+
eh->env->close(eh->env,NOFLAGS);
|
|
1629
|
+
eh->env=NULL;
|
|
1630
|
+
}
|
|
1631
|
+
free(p);
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
static void env_mark(t_envh *eh)
|
|
1635
|
+
{
|
|
1636
|
+
rb_gc_mark(eh->adb);
|
|
1637
|
+
rb_gc_mark(eh->atxn);
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1640
|
+
/*
|
|
1641
|
+
* Document-class: Bdb::Env
|
|
1642
|
+
*
|
|
1643
|
+
* Encapsulated DB environment. Create by simple new (with
|
|
1644
|
+
* flags as neede), then open. Database handles created with
|
|
1645
|
+
* env.db -> Bdb::Db object.
|
|
1646
|
+
*/
|
|
1647
|
+
|
|
1648
|
+
/*
|
|
1649
|
+
* call-seq:
|
|
1650
|
+
* new(flags) -> object
|
|
1651
|
+
*
|
|
1652
|
+
*
|
|
1653
|
+
*/
|
|
1654
|
+
VALUE env_new(VALUE class, VALUE vflags)
|
|
1655
|
+
{
|
|
1656
|
+
t_envh *eh;
|
|
1657
|
+
int rv;
|
|
1658
|
+
u_int32_t flags=0;
|
|
1659
|
+
VALUE obj;
|
|
1660
|
+
|
|
1661
|
+
if ( ! NIL_P(vflags) )
|
|
1662
|
+
flags=NUM2UINT(vflags);
|
|
1663
|
+
|
|
1664
|
+
obj=Data_Make_Struct(class,t_envh,env_mark,env_free,eh);
|
|
1665
|
+
rv=db_env_create(&(eh->env),flags);
|
|
1666
|
+
if ( rv != 0 ) {
|
|
1667
|
+
raise_error(rv,"env_new: %s",db_strerror(rv));
|
|
1668
|
+
return Qnil;
|
|
1669
|
+
}
|
|
1670
|
+
eh->self=obj;
|
|
1671
|
+
eh->adb = rb_ary_new();
|
|
1672
|
+
eh->atxn = rb_ary_new();
|
|
1673
|
+
rb_obj_call_init(obj,0,NULL);
|
|
1674
|
+
return obj;
|
|
1675
|
+
}
|
|
1676
|
+
|
|
1677
|
+
/*
|
|
1678
|
+
* call-seq:
|
|
1679
|
+
* env.open(homedir,flags,mode) -> self
|
|
1680
|
+
*
|
|
1681
|
+
* open an environment
|
|
1682
|
+
*/
|
|
1683
|
+
VALUE env_open(VALUE obj, VALUE vhome, VALUE vflags, VALUE vmode)
|
|
1684
|
+
{
|
|
1685
|
+
t_envh *eh;
|
|
1686
|
+
int rv;
|
|
1687
|
+
u_int32_t flags=0;
|
|
1688
|
+
int mode=0;
|
|
1689
|
+
|
|
1690
|
+
if ( ! NIL_P(vflags) )
|
|
1691
|
+
flags=NUM2UINT(vflags);
|
|
1692
|
+
if ( ! NIL_P(vmode) )
|
|
1693
|
+
mode=NUM2INT(vmode);
|
|
1694
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
1695
|
+
if (!eh->env)
|
|
1696
|
+
raise(0, "env is closed");
|
|
1697
|
+
if ( NIL_P(eh->adb) )
|
|
1698
|
+
raise_error(0,"env handle already used and closed");
|
|
1699
|
+
|
|
1700
|
+
rv = eh->env->open(eh->env,StringValueCStr(vhome),flags,mode);
|
|
1701
|
+
eh->env->app_private=eh;
|
|
1702
|
+
|
|
1703
|
+
if (rv != 0) {
|
|
1704
|
+
raise_error(rv, "env_open failure: %s",db_strerror(rv));
|
|
1705
|
+
}
|
|
1706
|
+
return obj;
|
|
1707
|
+
}
|
|
1708
|
+
|
|
1709
|
+
VALUE txn_abort(VALUE);
|
|
1710
|
+
|
|
1711
|
+
/*
|
|
1712
|
+
* call-seq:
|
|
1713
|
+
* env.close -> self
|
|
1714
|
+
*
|
|
1715
|
+
* close an environment. Do not use it after you close it.
|
|
1716
|
+
* The close process will automatically abort any open transactions
|
|
1717
|
+
* and close open databases (which also closes open cursors).
|
|
1718
|
+
* But this is just an effort to keep your dbs and envs from
|
|
1719
|
+
* becoming corrupted due to ruby errors that exit
|
|
1720
|
+
* unintentionally. However, to make this at all worth anything
|
|
1721
|
+
* use ObjectSpace.define_finalizer which calls env.close to
|
|
1722
|
+
* approach some assurance of it happening.
|
|
1723
|
+
*
|
|
1724
|
+
*/
|
|
1725
|
+
VALUE env_close(VALUE obj)
|
|
1726
|
+
{
|
|
1727
|
+
t_envh *eh;
|
|
1728
|
+
VALUE db;
|
|
1729
|
+
int rv;
|
|
1730
|
+
|
|
1731
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
1732
|
+
if ( eh->env==NULL )
|
|
1733
|
+
return Qnil;
|
|
1734
|
+
|
|
1735
|
+
if (RARRAY_LEN(eh->adb) > 0) {
|
|
1736
|
+
rb_warning("%s/%d %s %li",__FILE__,__LINE__,
|
|
1737
|
+
"database handles still open",RARRAY_LEN(eh->adb));
|
|
1738
|
+
while (RARRAY_LEN(eh->adb) > 0)
|
|
1739
|
+
if ((db=rb_ary_pop(eh->adb)) != Qnil ) {
|
|
1740
|
+
rb_warning("%s/%d %s 0x%p",__FILE__,__LINE__,
|
|
1741
|
+
"closing",(void*)db);
|
|
1742
|
+
/* this could raise! needs rb_protect */
|
|
1743
|
+
db_close(db,INT2FIX(0));
|
|
1744
|
+
}
|
|
1745
|
+
}
|
|
1746
|
+
if (RARRAY_LEN(eh->atxn) > 0) {
|
|
1747
|
+
rb_warning("%s/%d %s",__FILE__,__LINE__,
|
|
1748
|
+
"database transactions still open");
|
|
1749
|
+
while ( (db=rb_ary_pop(eh->atxn)) != Qnil ) {
|
|
1750
|
+
/* this could raise! needs rb_protect */
|
|
1751
|
+
txn_abort(db);
|
|
1752
|
+
}
|
|
1753
|
+
}
|
|
1754
|
+
|
|
1755
|
+
if ( RTEST(ruby_debug) )
|
|
1756
|
+
rb_warning("%s/%d %s 0x%p",__FILE__,__LINE__,"env_close!",(void*)eh);
|
|
1757
|
+
|
|
1758
|
+
rv = eh->env->close(eh->env,NOFLAGS);
|
|
1759
|
+
eh->env=NULL;
|
|
1760
|
+
eh->adb=Qnil;
|
|
1761
|
+
eh->atxn=Qnil;
|
|
1762
|
+
if ( rv != 0 ) {
|
|
1763
|
+
raise_error(rv, "env_close failure: %s",db_strerror(rv));
|
|
1764
|
+
return Qnil;
|
|
1765
|
+
}
|
|
1766
|
+
return obj;
|
|
1767
|
+
}
|
|
1768
|
+
|
|
1769
|
+
/*
|
|
1770
|
+
* call-seq:
|
|
1771
|
+
* env.db -> Bdb::Db instance
|
|
1772
|
+
*
|
|
1773
|
+
* create a db associated with an environment
|
|
1774
|
+
*/
|
|
1775
|
+
VALUE env_db(VALUE obj)
|
|
1776
|
+
{
|
|
1777
|
+
t_envh *eh;
|
|
1778
|
+
VALUE dbo;
|
|
1779
|
+
|
|
1780
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
1781
|
+
if (!eh->env)
|
|
1782
|
+
raise(0, "env is closed");
|
|
1783
|
+
dbo = Data_Wrap_Struct(cDb,db_mark,db_free,0);
|
|
1784
|
+
|
|
1785
|
+
return db_init_aux(dbo,eh);
|
|
1786
|
+
}
|
|
1787
|
+
|
|
1788
|
+
/*
|
|
1789
|
+
* call-seq:
|
|
1790
|
+
* env.cachesize=Fixnum|Bignum
|
|
1791
|
+
*
|
|
1792
|
+
* set the environment cache size. If it is a Bignum then it
|
|
1793
|
+
* will populate the bytes and gbytes part of the DB struct.
|
|
1794
|
+
* Fixnums will only populate bytes (which is still pretty big).
|
|
1795
|
+
*/
|
|
1796
|
+
VALUE env_set_cachesize(VALUE obj, VALUE size)
|
|
1797
|
+
{
|
|
1798
|
+
t_envh *eh;
|
|
1799
|
+
unsigned long long ln;
|
|
1800
|
+
u_int32_t bytes=0,gbytes=0;
|
|
1801
|
+
int rv;
|
|
1802
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
1803
|
+
if (!eh->env)
|
|
1804
|
+
raise(0, "env is closed");
|
|
1805
|
+
|
|
1806
|
+
if ( TYPE(size) == T_BIGNUM ) {
|
|
1807
|
+
ln = rb_big2ull(size);
|
|
1808
|
+
gbytes = ln / (1024*1024*1024);
|
|
1809
|
+
bytes = ln - (gbytes*1024*1024*1024);
|
|
1810
|
+
} else if (FIXNUM_P(size) ) {
|
|
1811
|
+
bytes=NUM2UINT(size);
|
|
1812
|
+
} else {
|
|
1813
|
+
raise_error(0,"set_cachesize requires number");
|
|
1814
|
+
return Qnil;
|
|
1815
|
+
}
|
|
1816
|
+
|
|
1817
|
+
rv=eh->env->set_cachesize(eh->env,gbytes,bytes,1);
|
|
1818
|
+
if ( rv != 0 ) {
|
|
1819
|
+
raise_error(rv, "set_cachesize failure: %s",db_strerror(rv));
|
|
1820
|
+
return Qnil;
|
|
1821
|
+
}
|
|
1822
|
+
|
|
1823
|
+
return Qtrue;
|
|
1824
|
+
}
|
|
1825
|
+
|
|
1826
|
+
/*
|
|
1827
|
+
* call-seq:
|
|
1828
|
+
* env.cachesize -> Fixnum|Bignum
|
|
1829
|
+
*
|
|
1830
|
+
* return the environment cache size. If it is a Bignum then it
|
|
1831
|
+
* will populate the bytes and gbytes part of the DB struct.
|
|
1832
|
+
* Fixnums will only populate bytes (which is still pretty big).
|
|
1833
|
+
*/
|
|
1834
|
+
VALUE env_get_cachesize(VALUE obj)
|
|
1835
|
+
{
|
|
1836
|
+
t_envh *eh;
|
|
1837
|
+
//unsigned long long ln;
|
|
1838
|
+
u_int32_t bytes=0,gbytes=0;
|
|
1839
|
+
int ncache;
|
|
1840
|
+
int rv;
|
|
1841
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
1842
|
+
if (!eh->env)
|
|
1843
|
+
raise(0, "env is closed");
|
|
1844
|
+
|
|
1845
|
+
rv=eh->env->get_cachesize(eh->env,&gbytes,&bytes,&ncache);
|
|
1846
|
+
if ( rv != 0 ) {
|
|
1847
|
+
raise_error(rv, "get_cachesize failure: %s",db_strerror(rv));
|
|
1848
|
+
return Qnil;
|
|
1849
|
+
}
|
|
1850
|
+
|
|
1851
|
+
if (gbytes != 0)
|
|
1852
|
+
return ULL2NUM(gbytes*1024*1024*1024+bytes);
|
|
1853
|
+
else
|
|
1854
|
+
return UINT2NUM(bytes);
|
|
1855
|
+
|
|
1856
|
+
return Qtrue;
|
|
1857
|
+
}
|
|
1858
|
+
|
|
1859
|
+
VALUE env_set_flags(VALUE obj, VALUE vflags, int onoff)
|
|
1860
|
+
{
|
|
1861
|
+
t_envh *eh;
|
|
1862
|
+
int rv;
|
|
1863
|
+
u_int32_t flags;
|
|
1864
|
+
|
|
1865
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
1866
|
+
if (!eh->env)
|
|
1867
|
+
raise(0, "env is closed");
|
|
1868
|
+
if ( ! NIL_P(vflags) ) {
|
|
1869
|
+
flags=NUM2UINT(vflags);
|
|
1870
|
+
|
|
1871
|
+
rv=eh->env->set_flags(eh->env,flags,onoff);
|
|
1872
|
+
|
|
1873
|
+
if ( rv != 0 ) {
|
|
1874
|
+
raise_error(rv, "set_flags failure: %s",db_strerror(rv));
|
|
1875
|
+
return Qnil;
|
|
1876
|
+
}
|
|
1877
|
+
}
|
|
1878
|
+
return Qtrue;
|
|
1879
|
+
}
|
|
1880
|
+
|
|
1881
|
+
/*
|
|
1882
|
+
* call-seq:
|
|
1883
|
+
* env.flags -> flags
|
|
1884
|
+
*
|
|
1885
|
+
* get what flags are on.
|
|
1886
|
+
*/
|
|
1887
|
+
VALUE env_get_flags(VALUE obj)
|
|
1888
|
+
{
|
|
1889
|
+
t_envh *eh;
|
|
1890
|
+
int rv;
|
|
1891
|
+
u_int32_t flags;
|
|
1892
|
+
|
|
1893
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
1894
|
+
if (!eh->env)
|
|
1895
|
+
raise(0, "env is closed");
|
|
1896
|
+
|
|
1897
|
+
rv=eh->env->get_flags(eh->env,&flags);
|
|
1898
|
+
|
|
1899
|
+
if ( rv != 0 ) {
|
|
1900
|
+
raise_error(rv, "set_flags failure: %s",db_strerror(rv));
|
|
1901
|
+
return Qnil;
|
|
1902
|
+
}
|
|
1903
|
+
|
|
1904
|
+
return UINT2NUM(flags);
|
|
1905
|
+
}
|
|
1906
|
+
|
|
1907
|
+
/*
|
|
1908
|
+
* call-seq:
|
|
1909
|
+
* env.flags_on=flags
|
|
1910
|
+
*
|
|
1911
|
+
* set the 'flags' on. An or'ed set of flags will be set on.
|
|
1912
|
+
* Only included flags will be affected. Serialized calls
|
|
1913
|
+
* will only affect flags indicated (leaving others, default or
|
|
1914
|
+
* set as they were).
|
|
1915
|
+
*/
|
|
1916
|
+
VALUE env_set_flags_on(VALUE obj, VALUE vflags)
|
|
1917
|
+
{
|
|
1918
|
+
return env_set_flags(obj,vflags,1);
|
|
1919
|
+
}
|
|
1920
|
+
|
|
1921
|
+
/*
|
|
1922
|
+
* call-seq:
|
|
1923
|
+
* env.flags_off=flags
|
|
1924
|
+
*
|
|
1925
|
+
* set the 'flags' off. An or'ed set of flags will be set off.
|
|
1926
|
+
* Only included flags will be affected. Serialized calls
|
|
1927
|
+
* will only affect flags indicated (leaving others, default or
|
|
1928
|
+
* set as they were).
|
|
1929
|
+
*/
|
|
1930
|
+
VALUE env_set_flags_off(VALUE obj, VALUE vflags)
|
|
1931
|
+
{
|
|
1932
|
+
return env_set_flags(obj,vflags,0);
|
|
1933
|
+
}
|
|
1934
|
+
|
|
1935
|
+
/*
|
|
1936
|
+
* call-seq:
|
|
1937
|
+
* env.list_dbs -> [Bdb::Db array]
|
|
1938
|
+
*
|
|
1939
|
+
* return 0 or more open databases within the receiver environment.
|
|
1940
|
+
* If 0, will return [], not nil.
|
|
1941
|
+
*/
|
|
1942
|
+
VALUE env_list_dbs(VALUE obj)
|
|
1943
|
+
{
|
|
1944
|
+
t_envh *eh;
|
|
1945
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
1946
|
+
if (!eh->env)
|
|
1947
|
+
raise(0, "env is closed");
|
|
1948
|
+
return eh->adb;
|
|
1949
|
+
}
|
|
1950
|
+
static void txn_mark(t_txnh *txn)
|
|
1951
|
+
{
|
|
1952
|
+
if (txn->env)
|
|
1953
|
+
rb_gc_mark(txn->env->self);
|
|
1954
|
+
}
|
|
1955
|
+
static void txn_free(t_txnh *txn)
|
|
1956
|
+
{
|
|
1957
|
+
#ifdef DEBUG_DB
|
|
1958
|
+
if ( RTEST(ruby_debug) )
|
|
1959
|
+
fprintf(stderr,"%s/%d %s %p\n",__FILE__,__LINE__,"txn_free",txn);
|
|
1960
|
+
#endif
|
|
1961
|
+
|
|
1962
|
+
if (txn) {
|
|
1963
|
+
if (txn->txn)
|
|
1964
|
+
txn->txn->abort(txn->txn);
|
|
1965
|
+
txn->txn=NULL;
|
|
1966
|
+
if (txn->env) {
|
|
1967
|
+
rb_ary_delete(txn->env->atxn,txn->self);
|
|
1968
|
+
}
|
|
1969
|
+
txn->env=NULL;
|
|
1970
|
+
|
|
1971
|
+
free(txn);
|
|
1972
|
+
}
|
|
1973
|
+
}
|
|
1974
|
+
|
|
1975
|
+
/*
|
|
1976
|
+
* call-seq:
|
|
1977
|
+
* env.txn_begin(txn_parent,flags) -> Bdb::Txn
|
|
1978
|
+
*
|
|
1979
|
+
* start a root transaction or embedded (via txn_parent).
|
|
1980
|
+
*/
|
|
1981
|
+
VALUE env_txn_begin(VALUE obj, VALUE vtxn_parent, VALUE vflags)
|
|
1982
|
+
{
|
|
1983
|
+
t_txnh *parent=NULL, *txn=NULL;
|
|
1984
|
+
u_int32_t flags=0;
|
|
1985
|
+
int rv;
|
|
1986
|
+
t_envh *eh;
|
|
1987
|
+
VALUE t_obj;
|
|
1988
|
+
|
|
1989
|
+
if ( ! NIL_P(vflags))
|
|
1990
|
+
flags=NUM2UINT(vflags);
|
|
1991
|
+
if ( ! NIL_P(vtxn_parent) ) {
|
|
1992
|
+
Data_Get_Struct(vtxn_parent,t_txnh,parent);
|
|
1993
|
+
if (!parent->txn)
|
|
1994
|
+
raise(0, "parent txn is closed");
|
|
1995
|
+
}
|
|
1996
|
+
|
|
1997
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
1998
|
+
if (!eh->env)
|
|
1999
|
+
raise(0, "env is closed");
|
|
2000
|
+
t_obj=Data_Make_Struct(cTxn,t_txnh,txn_mark,txn_free,txn);
|
|
2001
|
+
|
|
2002
|
+
rv=eh->env->txn_begin(eh->env,parent?parent->txn:NULL,
|
|
2003
|
+
&(txn->txn),flags);
|
|
2004
|
+
|
|
2005
|
+
if ( rv != 0 ) {
|
|
2006
|
+
raise_error(rv, "env_txn_begin: %s",db_strerror(rv));
|
|
2007
|
+
return Qnil;
|
|
2008
|
+
}
|
|
2009
|
+
txn->env=eh;
|
|
2010
|
+
txn->self=t_obj;
|
|
2011
|
+
rb_ary_push(eh->atxn,t_obj);
|
|
2012
|
+
|
|
2013
|
+
/* Once we get this working, we'll have to track transactions */
|
|
2014
|
+
rb_obj_call_init(t_obj,0,NULL);
|
|
2015
|
+
return t_obj;
|
|
2016
|
+
}
|
|
2017
|
+
|
|
2018
|
+
/*
|
|
2019
|
+
* call-seq:
|
|
2020
|
+
* env.txn_checkpoint -> true
|
|
2021
|
+
*
|
|
2022
|
+
* Cause env transaction state to be checkpointed.
|
|
2023
|
+
*/
|
|
2024
|
+
VALUE env_txn_checkpoint(VALUE obj, VALUE vkbyte, VALUE vmin,
|
|
2025
|
+
VALUE vflags)
|
|
2026
|
+
{
|
|
2027
|
+
u_int32_t flags=0;
|
|
2028
|
+
int rv;
|
|
2029
|
+
t_envh *eh;
|
|
2030
|
+
u_int32_t kbyte=0, min=0;
|
|
2031
|
+
|
|
2032
|
+
if ( ! NIL_P(vflags))
|
|
2033
|
+
flags=NUM2UINT(vflags);
|
|
2034
|
+
|
|
2035
|
+
if ( FIXNUM_P(vkbyte) )
|
|
2036
|
+
kbyte=FIX2UINT(vkbyte);
|
|
2037
|
+
|
|
2038
|
+
if ( FIXNUM_P(vmin) )
|
|
2039
|
+
min=FIX2UINT(vmin);
|
|
2040
|
+
|
|
2041
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
2042
|
+
if (!eh->env)
|
|
2043
|
+
raise(0, "env is closed");
|
|
2044
|
+
rv=eh->env->txn_checkpoint(eh->env,kbyte,min,flags);
|
|
2045
|
+
if ( rv != 0 ) {
|
|
2046
|
+
raise_error(rv, "env_txn_checkpoint: %s",db_strerror(rv));
|
|
2047
|
+
return Qnil;
|
|
2048
|
+
}
|
|
2049
|
+
return Qtrue;
|
|
2050
|
+
}
|
|
2051
|
+
|
|
2052
|
+
VALUE env_txn_stat_active(DB_TXN_ACTIVE *t)
|
|
2053
|
+
{
|
|
2054
|
+
VALUE ao;
|
|
2055
|
+
|
|
2056
|
+
ao=rb_class_new_instance(0,NULL,cTxnStatActive);
|
|
2057
|
+
|
|
2058
|
+
rb_iv_set(ao,"@txnid",INT2FIX(t->txnid));
|
|
2059
|
+
rb_iv_set(ao,"@parentid",INT2FIX(t->parentid));
|
|
2060
|
+
/* rb_iv_set(ao,"@thread_id",INT2FIX(t->thread_id)); */
|
|
2061
|
+
rb_iv_set(ao,"@lsn",rb_ary_new3(2,
|
|
2062
|
+
INT2FIX(t->lsn.file),
|
|
2063
|
+
INT2FIX(t->lsn.offset)));
|
|
2064
|
+
/* XA status is currently excluded */
|
|
2065
|
+
return ao;
|
|
2066
|
+
}
|
|
2067
|
+
|
|
2068
|
+
/*
|
|
2069
|
+
* call-seq:
|
|
2070
|
+
* db.stat(txn,flags) -> Bdb::Db::Stat
|
|
2071
|
+
*
|
|
2072
|
+
* get database status. Returns a Bdb::Db::Stat object that
|
|
2073
|
+
* is specialized to the db_type and only responds to [] to
|
|
2074
|
+
* retrieve status values. All values are stored in instance
|
|
2075
|
+
* variables, so singleton classes can be created and instance_eval
|
|
2076
|
+
* will work.
|
|
2077
|
+
*/
|
|
2078
|
+
VALUE db_stat(VALUE obj, VALUE vtxn, VALUE vflags)
|
|
2079
|
+
{
|
|
2080
|
+
u_int32_t flags=0;
|
|
2081
|
+
int rv;
|
|
2082
|
+
t_dbh *dbh;
|
|
2083
|
+
t_txnh *txn=NULL;
|
|
2084
|
+
DBTYPE dbtype;
|
|
2085
|
+
union {
|
|
2086
|
+
void *stat;
|
|
2087
|
+
DB_HASH_STAT *hstat;
|
|
2088
|
+
DB_BTREE_STAT *bstat;
|
|
2089
|
+
DB_QUEUE_STAT *qstat;
|
|
2090
|
+
} su;
|
|
2091
|
+
VALUE s_obj;
|
|
2092
|
+
|
|
2093
|
+
if ( ! NIL_P(vflags) )
|
|
2094
|
+
flags=NUM2UINT(vflags);
|
|
2095
|
+
if ( ! NIL_P(vtxn) ) {
|
|
2096
|
+
Data_Get_Struct(vtxn,t_txnh,txn);
|
|
2097
|
+
if (!txn->txn)
|
|
2098
|
+
raise(0, "txn is closed");
|
|
2099
|
+
}
|
|
2100
|
+
|
|
2101
|
+
Data_Get_Struct(obj,t_dbh,dbh);
|
|
2102
|
+
if (!dbh->db)
|
|
2103
|
+
raise(0, "db is closed");
|
|
2104
|
+
|
|
2105
|
+
rv=dbh->db->get_type(dbh->db,&dbtype);
|
|
2106
|
+
if (rv)
|
|
2107
|
+
raise_error(rv,"db_stat %s",db_strerror(rv));
|
|
2108
|
+
#if DB_VERSION_MINOR > 2
|
|
2109
|
+
rv=dbh->db->stat(dbh->db,txn?txn->txn:NULL,&(su.stat),flags);
|
|
2110
|
+
#else
|
|
2111
|
+
rv=dbh->db->stat(dbh->db,&(su.stat),flags);
|
|
2112
|
+
#endif
|
|
2113
|
+
if (rv)
|
|
2114
|
+
raise_error(rv,"db_stat %s",db_strerror(rv));
|
|
2115
|
+
|
|
2116
|
+
s_obj=rb_class_new_instance(0,NULL,cDbStat);
|
|
2117
|
+
rb_iv_set(s_obj,"@dbtype",INT2FIX(dbtype));
|
|
2118
|
+
|
|
2119
|
+
switch(dbtype) {
|
|
2120
|
+
|
|
2121
|
+
#define hs_int(field) \
|
|
2122
|
+
rb_iv_set(s_obj,"@" #field,INT2FIX(su.hstat->field))
|
|
2123
|
+
|
|
2124
|
+
case DB_HASH:
|
|
2125
|
+
hs_int(hash_magic);
|
|
2126
|
+
hs_int(hash_version); /* Version number. */
|
|
2127
|
+
hs_int(hash_metaflags); /* Metadata flags. */
|
|
2128
|
+
hs_int(hash_nkeys); /* Number of unique keys. */
|
|
2129
|
+
hs_int(hash_ndata); /* Number of data items. */
|
|
2130
|
+
hs_int(hash_pagesize); /* Page size. */
|
|
2131
|
+
hs_int(hash_ffactor); /* Fill factor specified at create. */
|
|
2132
|
+
hs_int(hash_buckets); /* Number of hash buckets. */
|
|
2133
|
+
hs_int(hash_free); /* Pages on the free list. */
|
|
2134
|
+
hs_int(hash_bfree); /* Bytes free on bucket pages. */
|
|
2135
|
+
hs_int(hash_bigpages); /* Number of big key/data pages. */
|
|
2136
|
+
hs_int(hash_big_bfree); /* Bytes free on big item pages. */
|
|
2137
|
+
hs_int(hash_overflows); /* Number of overflow pages. */
|
|
2138
|
+
hs_int(hash_ovfl_free); /* Bytes free on ovfl pages. */
|
|
2139
|
+
hs_int(hash_dup); /* Number of dup pages. */
|
|
2140
|
+
hs_int(hash_dup_free); /* Bytes free on duplicate pages. */
|
|
2141
|
+
break;
|
|
2142
|
+
|
|
2143
|
+
#define bs_int(field) \
|
|
2144
|
+
rb_iv_set(s_obj,"@" #field,INT2FIX(su.bstat->field))
|
|
2145
|
+
|
|
2146
|
+
case DB_BTREE:
|
|
2147
|
+
case DB_RECNO:
|
|
2148
|
+
bs_int(bt_magic); /* Magic number. */
|
|
2149
|
+
bs_int(bt_version); /* Version number. */
|
|
2150
|
+
bs_int(bt_metaflags); /* Metadata flags. */
|
|
2151
|
+
bs_int(bt_nkeys); /* Number of unique keys. */
|
|
2152
|
+
bs_int(bt_ndata); /* Number of data items. */
|
|
2153
|
+
bs_int(bt_pagesize); /* Page size. */
|
|
2154
|
+
#if DB_VERSION_MINOR < 4
|
|
2155
|
+
bs_int(bt_maxkey); /* Maxkey value. */
|
|
2156
|
+
#endif
|
|
2157
|
+
bs_int(bt_minkey); /* Minkey value. */
|
|
2158
|
+
bs_int(bt_re_len); /* Fixed-length record length. */
|
|
2159
|
+
bs_int(bt_re_pad); /* Fixed-length record pad. */
|
|
2160
|
+
bs_int(bt_levels); /* Tree levels. */
|
|
2161
|
+
bs_int(bt_int_pg); /* Internal pages. */
|
|
2162
|
+
bs_int(bt_leaf_pg); /* Leaf pages. */
|
|
2163
|
+
bs_int(bt_dup_pg); /* Duplicate pages. */
|
|
2164
|
+
bs_int(bt_over_pg); /* Overflow pages. */
|
|
2165
|
+
#if DB_VERSION_MINOR > 2
|
|
2166
|
+
bs_int(bt_empty_pg); /* Empty pages. */
|
|
2167
|
+
#endif
|
|
2168
|
+
bs_int(bt_free); /* Pages on the free list. */
|
|
2169
|
+
bs_int(bt_int_pgfree); /* Bytes free in internal pages. */
|
|
2170
|
+
bs_int(bt_leaf_pgfree); /* Bytes free in leaf pages. */
|
|
2171
|
+
bs_int(bt_dup_pgfree); /* Bytes free in duplicate pages. */
|
|
2172
|
+
bs_int(bt_over_pgfree); /* Bytes free in overflow pages. */
|
|
2173
|
+
|
|
2174
|
+
break;
|
|
2175
|
+
|
|
2176
|
+
#define qs_int(field) \
|
|
2177
|
+
rb_iv_set(s_obj,"@" #field,INT2FIX(su.qstat->field))
|
|
2178
|
+
|
|
2179
|
+
case DB_QUEUE:
|
|
2180
|
+
qs_int(qs_magic); /* Magic number. */
|
|
2181
|
+
qs_int(qs_version); /* Version number. */
|
|
2182
|
+
qs_int(qs_metaflags); /* Metadata flags. */
|
|
2183
|
+
qs_int(qs_nkeys); /* Number of unique keys. */
|
|
2184
|
+
qs_int(qs_ndata); /* Number of data items. */
|
|
2185
|
+
qs_int(qs_pagesize); /* Page size. */
|
|
2186
|
+
qs_int(qs_extentsize); /* Pages per extent. */
|
|
2187
|
+
qs_int(qs_pages); /* Data pages. */
|
|
2188
|
+
qs_int(qs_re_len); /* Fixed-length record length. */
|
|
2189
|
+
qs_int(qs_re_pad); /* Fixed-length record pad. */
|
|
2190
|
+
qs_int(qs_pgfree); /* Bytes free in data pages. */
|
|
2191
|
+
qs_int(qs_first_recno); /* First not deleted record. */
|
|
2192
|
+
qs_int(qs_cur_recno); /* Next available record number. */
|
|
2193
|
+
|
|
2194
|
+
break;
|
|
2195
|
+
case DB_UNKNOWN:
|
|
2196
|
+
break;
|
|
2197
|
+
}
|
|
2198
|
+
|
|
2199
|
+
free(su.stat);
|
|
2200
|
+
return s_obj;
|
|
2201
|
+
}
|
|
2202
|
+
|
|
2203
|
+
/*
|
|
2204
|
+
* call-seq:
|
|
2205
|
+
* stat[name] -> value
|
|
2206
|
+
*
|
|
2207
|
+
* return status value
|
|
2208
|
+
*/
|
|
2209
|
+
VALUE stat_aref(VALUE obj, VALUE vname)
|
|
2210
|
+
{
|
|
2211
|
+
return rb_iv_get(obj,RSTRING_PTR(rb_str_concat(rb_str_new2("@"),vname)));
|
|
2212
|
+
}
|
|
2213
|
+
|
|
2214
|
+
/*
|
|
2215
|
+
* call-seq:
|
|
2216
|
+
* env.txn_stat -> Bdb::TxnStat
|
|
2217
|
+
*
|
|
2218
|
+
* get the environment transaction status. Each active
|
|
2219
|
+
* transaction will be contained within a Bdb::TxnStat::Active
|
|
2220
|
+
* class.
|
|
2221
|
+
*/
|
|
2222
|
+
VALUE env_txn_stat(VALUE obj, VALUE vflags)
|
|
2223
|
+
{
|
|
2224
|
+
u_int32_t flags=0;
|
|
2225
|
+
int rv;
|
|
2226
|
+
t_envh *eh;
|
|
2227
|
+
DB_TXN_STAT *statp;
|
|
2228
|
+
VALUE s_obj;
|
|
2229
|
+
VALUE active;
|
|
2230
|
+
int i;
|
|
2231
|
+
|
|
2232
|
+
if ( ! NIL_P(vflags))
|
|
2233
|
+
flags=NUM2UINT(vflags);
|
|
2234
|
+
|
|
2235
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
2236
|
+
if (!eh->env)
|
|
2237
|
+
raise(0, "env is closed");
|
|
2238
|
+
|
|
2239
|
+
/* statp will need free() */
|
|
2240
|
+
rv=eh->env->txn_stat(eh->env,&statp,flags);
|
|
2241
|
+
if ( rv != 0 ) {
|
|
2242
|
+
raise_error(rv, "txn_stat: %s",db_strerror(rv));
|
|
2243
|
+
}
|
|
2244
|
+
|
|
2245
|
+
s_obj=rb_class_new_instance(0,NULL,cTxnStat);
|
|
2246
|
+
rb_iv_set(s_obj,"@st_last_ckp",
|
|
2247
|
+
rb_ary_new3(2,
|
|
2248
|
+
INT2FIX(statp->st_last_ckp.file),
|
|
2249
|
+
INT2FIX(statp->st_last_ckp.offset)) );
|
|
2250
|
+
rb_iv_set(s_obj,"@st_time_ckp",
|
|
2251
|
+
rb_time_new(statp->st_time_ckp,0));
|
|
2252
|
+
rb_iv_set(s_obj,"@st_last_txnid",
|
|
2253
|
+
INT2FIX(statp->st_last_txnid));
|
|
2254
|
+
rb_iv_set(s_obj,"@st_maxtxns",
|
|
2255
|
+
INT2FIX(statp->st_maxtxns));
|
|
2256
|
+
rb_iv_set(s_obj,"@st_nactive",
|
|
2257
|
+
INT2FIX(statp->st_nactive));
|
|
2258
|
+
rb_iv_set(s_obj,"@st_maxnactive",
|
|
2259
|
+
INT2FIX(statp->st_maxnactive));
|
|
2260
|
+
rb_iv_set(s_obj,"@st_nbegins",
|
|
2261
|
+
INT2FIX(statp->st_nbegins));
|
|
2262
|
+
rb_iv_set(s_obj,"@st_naborts",
|
|
2263
|
+
INT2FIX(statp->st_naborts));
|
|
2264
|
+
rb_iv_set(s_obj,"@st_ncommits",
|
|
2265
|
+
INT2FIX(statp->st_ncommits));
|
|
2266
|
+
rb_iv_set(s_obj,"@st_nrestores",
|
|
2267
|
+
INT2FIX(statp->st_nrestores));
|
|
2268
|
+
rb_iv_set(s_obj,"@st_regsize",
|
|
2269
|
+
INT2FIX(statp->st_regsize));
|
|
2270
|
+
rb_iv_set(s_obj,"@st_region_wait",
|
|
2271
|
+
INT2FIX(statp->st_region_wait));
|
|
2272
|
+
rb_iv_set(s_obj,"@st_region_nowait",
|
|
2273
|
+
INT2FIX(statp->st_region_nowait));
|
|
2274
|
+
rb_iv_set(s_obj,"@st_txnarray",
|
|
2275
|
+
active=rb_ary_new2(statp->st_nactive));
|
|
2276
|
+
|
|
2277
|
+
for (i=0; i<statp->st_nactive; i++) {
|
|
2278
|
+
rb_ary_push(active,env_txn_stat_active(&(statp->st_txnarray[i])));
|
|
2279
|
+
}
|
|
2280
|
+
|
|
2281
|
+
free(statp);
|
|
2282
|
+
return s_obj;
|
|
2283
|
+
}
|
|
2284
|
+
|
|
2285
|
+
/*
|
|
2286
|
+
* call-seq:
|
|
2287
|
+
* env.set_timeout(timeout,flags) -> timeout
|
|
2288
|
+
*
|
|
2289
|
+
* set lock and transaction timeout
|
|
2290
|
+
*/
|
|
2291
|
+
VALUE env_set_timeout(VALUE obj, VALUE vtimeout, VALUE vflags)
|
|
2292
|
+
{
|
|
2293
|
+
t_envh *eh;
|
|
2294
|
+
u_int32_t flags=0;
|
|
2295
|
+
db_timeout_t timeout;
|
|
2296
|
+
int rv;
|
|
2297
|
+
|
|
2298
|
+
if ( ! NIL_P(vflags))
|
|
2299
|
+
flags=NUM2UINT(vflags);
|
|
2300
|
+
timeout=FIX2UINT(vtimeout);
|
|
2301
|
+
|
|
2302
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
2303
|
+
if (!eh->env)
|
|
2304
|
+
raise(0, "env is closed");
|
|
2305
|
+
rv=eh->env->set_timeout(eh->env,timeout,flags);
|
|
2306
|
+
if ( rv != 0 ) {
|
|
2307
|
+
raise_error(rv, "env_set_timeout: %s",db_strerror(rv));
|
|
2308
|
+
}
|
|
2309
|
+
|
|
2310
|
+
return vtimeout;
|
|
2311
|
+
}
|
|
2312
|
+
|
|
2313
|
+
/*
|
|
2314
|
+
* call-seq:
|
|
2315
|
+
* env.get_timeout(flags) -> Fixnum
|
|
2316
|
+
*
|
|
2317
|
+
* Get current transaction and lock timeout value
|
|
2318
|
+
*/
|
|
2319
|
+
VALUE env_get_timeout(VALUE obj, VALUE vflags)
|
|
2320
|
+
{
|
|
2321
|
+
t_envh *eh;
|
|
2322
|
+
u_int32_t flags=0;
|
|
2323
|
+
db_timeout_t timeout;
|
|
2324
|
+
int rv;
|
|
2325
|
+
|
|
2326
|
+
if ( ! NIL_P(vflags))
|
|
2327
|
+
flags=NUM2UINT(vflags);
|
|
2328
|
+
|
|
2329
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
2330
|
+
if (!eh->env)
|
|
2331
|
+
raise(0, "env is closed");
|
|
2332
|
+
rv=eh->env->get_timeout(eh->env,&timeout,flags);
|
|
2333
|
+
if ( rv != 0 ) {
|
|
2334
|
+
raise_error(rv, "env_get_timeout: %s",db_strerror(rv));
|
|
2335
|
+
}
|
|
2336
|
+
|
|
2337
|
+
return INT2FIX(timeout);
|
|
2338
|
+
}
|
|
2339
|
+
|
|
2340
|
+
/*
|
|
2341
|
+
* call-seq:
|
|
2342
|
+
* env.set_tx_max(max) -> max
|
|
2343
|
+
*
|
|
2344
|
+
* Set the maximum number of transactions with the environment
|
|
2345
|
+
*/
|
|
2346
|
+
VALUE env_set_tx_max(VALUE obj, VALUE vmax)
|
|
2347
|
+
{
|
|
2348
|
+
t_envh *eh;
|
|
2349
|
+
u_int32_t max;
|
|
2350
|
+
int rv;
|
|
2351
|
+
|
|
2352
|
+
max=FIX2UINT(vmax);
|
|
2353
|
+
|
|
2354
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
2355
|
+
if (!eh->env)
|
|
2356
|
+
raise(0, "env is closed");
|
|
2357
|
+
rv=eh->env->set_tx_max(eh->env,max);
|
|
2358
|
+
if ( rv != 0 ) {
|
|
2359
|
+
raise_error(rv, "env_set_tx_max: %s",db_strerror(rv));
|
|
2360
|
+
}
|
|
2361
|
+
|
|
2362
|
+
return vmax;
|
|
2363
|
+
}
|
|
2364
|
+
|
|
2365
|
+
/*
|
|
2366
|
+
* call-seq
|
|
2367
|
+
* env.get_tx_max -> Fixnum
|
|
2368
|
+
*
|
|
2369
|
+
* Get current maximum number of transactions
|
|
2370
|
+
*/
|
|
2371
|
+
VALUE env_get_tx_max(VALUE obj)
|
|
2372
|
+
{
|
|
2373
|
+
t_envh *eh;
|
|
2374
|
+
u_int32_t max;
|
|
2375
|
+
int rv;
|
|
2376
|
+
|
|
2377
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
2378
|
+
if (!eh->env)
|
|
2379
|
+
raise(0, "env is closed");
|
|
2380
|
+
rv=eh->env->get_tx_max(eh->env,&max);
|
|
2381
|
+
if ( rv != 0 ) {
|
|
2382
|
+
raise_error(rv, "env_get_tx_max: %s",db_strerror(rv));
|
|
2383
|
+
}
|
|
2384
|
+
|
|
2385
|
+
return INT2FIX(max);
|
|
2386
|
+
}
|
|
2387
|
+
|
|
2388
|
+
/*
|
|
2389
|
+
* call-seq:
|
|
2390
|
+
* env.mutex_set_max(max) -> max
|
|
2391
|
+
*
|
|
2392
|
+
* Set the maximum number of mutexes with the environment
|
|
2393
|
+
*/
|
|
2394
|
+
VALUE env_mutex_set_max(VALUE obj, VALUE vmax)
|
|
2395
|
+
{
|
|
2396
|
+
t_envh *eh;
|
|
2397
|
+
u_int32_t max;
|
|
2398
|
+
int rv;
|
|
2399
|
+
|
|
2400
|
+
max=FIX2UINT(vmax);
|
|
2401
|
+
|
|
2402
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
2403
|
+
if (!eh->env)
|
|
2404
|
+
raise(0, "env is closed");
|
|
2405
|
+
rv=eh->env->mutex_set_max(eh->env,max);
|
|
2406
|
+
if ( rv != 0 ) {
|
|
2407
|
+
raise_error(rv, "env_mutex_set_max: %s",db_strerror(rv));
|
|
2408
|
+
}
|
|
2409
|
+
|
|
2410
|
+
return vmax;
|
|
2411
|
+
}
|
|
2412
|
+
|
|
2413
|
+
/*
|
|
2414
|
+
* call-seq
|
|
2415
|
+
* env.mutex_get_max -> Fixnum
|
|
2416
|
+
*
|
|
2417
|
+
* Get current maximum number of mutexes.
|
|
2418
|
+
*/
|
|
2419
|
+
VALUE env_mutex_get_max(VALUE obj)
|
|
2420
|
+
{
|
|
2421
|
+
t_envh *eh;
|
|
2422
|
+
u_int32_t max;
|
|
2423
|
+
int rv;
|
|
2424
|
+
|
|
2425
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
2426
|
+
if (!eh->env)
|
|
2427
|
+
raise(0, "env is closed");
|
|
2428
|
+
rv=eh->env->mutex_get_max(eh->env,&max);
|
|
2429
|
+
if ( rv != 0 ) {
|
|
2430
|
+
raise_error(rv, "env_mutex_get_max: %s",db_strerror(rv));
|
|
2431
|
+
}
|
|
2432
|
+
|
|
2433
|
+
return INT2FIX(max);
|
|
2434
|
+
}
|
|
2435
|
+
|
|
2436
|
+
/*
|
|
2437
|
+
* call-seq:
|
|
2438
|
+
* env.set_shm_key(key) -> max
|
|
2439
|
+
*
|
|
2440
|
+
* Set the shared memory key base
|
|
2441
|
+
*/
|
|
2442
|
+
VALUE env_set_shm_key(VALUE obj, VALUE vkey)
|
|
2443
|
+
{
|
|
2444
|
+
t_envh *eh;
|
|
2445
|
+
long key;
|
|
2446
|
+
int rv;
|
|
2447
|
+
|
|
2448
|
+
key=FIX2UINT(vkey);
|
|
2449
|
+
|
|
2450
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
2451
|
+
if (!eh->env)
|
|
2452
|
+
raise(0, "env is closed");
|
|
2453
|
+
rv=eh->env->set_shm_key(eh->env,key);
|
|
2454
|
+
if ( rv != 0 ) {
|
|
2455
|
+
raise_error(rv, "env_set_shm_key: %s",db_strerror(rv));
|
|
2456
|
+
}
|
|
2457
|
+
|
|
2458
|
+
return vkey;
|
|
2459
|
+
}
|
|
2460
|
+
|
|
2461
|
+
/*
|
|
2462
|
+
* call-seq
|
|
2463
|
+
* env.get_shm_key -> Fixnum
|
|
2464
|
+
*
|
|
2465
|
+
* Get the current shm key base
|
|
2466
|
+
*/
|
|
2467
|
+
VALUE env_get_shm_key(VALUE obj)
|
|
2468
|
+
{
|
|
2469
|
+
t_envh *eh;
|
|
2470
|
+
long key;
|
|
2471
|
+
int rv;
|
|
2472
|
+
|
|
2473
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
2474
|
+
if (!eh->env)
|
|
2475
|
+
raise(0, "env is closed");
|
|
2476
|
+
rv=eh->env->get_shm_key(eh->env,&key);
|
|
2477
|
+
if ( rv != 0 ) {
|
|
2478
|
+
raise_error(rv, "env_get_shm_key: %s",db_strerror(rv));
|
|
2479
|
+
}
|
|
2480
|
+
|
|
2481
|
+
return INT2FIX(key);
|
|
2482
|
+
}
|
|
2483
|
+
|
|
2484
|
+
VALUE env_log_set_config_h(VALUE obj, u_int32_t flags, VALUE onoff) {
|
|
2485
|
+
t_envh *eh;
|
|
2486
|
+
int rv;
|
|
2487
|
+
Data_Get_Struct(obj,t_envh, eh);
|
|
2488
|
+
rv=eh->env->log_set_config(eh->env, flags, Qnil != flags && Qfalse != onoff);
|
|
2489
|
+
if(rv != 0)
|
|
2490
|
+
raise_error(rv, "log_set_config: %s", db_strerror(rv));
|
|
2491
|
+
return flags;
|
|
2492
|
+
}
|
|
2493
|
+
|
|
2494
|
+
VALUE env_log_get_config_h( VALUE obj, u_int32_t flags) {
|
|
2495
|
+
t_envh *eh;
|
|
2496
|
+
int rv, onoff;
|
|
2497
|
+
Data_Get_Struct(obj,t_envh, eh);
|
|
2498
|
+
rv=eh->env->log_get_config(eh->env, flags, &onoff);
|
|
2499
|
+
if(rv != 0)
|
|
2500
|
+
raise_error(rv, "log_set_config: %s", db_strerror(rv));
|
|
2501
|
+
return onoff ? Qtrue : Qfalse;
|
|
2502
|
+
}
|
|
2503
|
+
|
|
2504
|
+
#define ENV_LOG_CONFIG_FUNCS \
|
|
2505
|
+
ENV_LOG_CONFIG_FUNC(direct,DIRECT) \
|
|
2506
|
+
ENV_LOG_CONFIG_FUNC(dsync,DSYNC) \
|
|
2507
|
+
ENV_LOG_CONFIG_FUNC(auto_remove,AUTO_REMOVE) \
|
|
2508
|
+
ENV_LOG_CONFIG_FUNC(in_memory,IN_MEMORY) \
|
|
2509
|
+
ENV_LOG_CONFIG_FUNC(zero,ZERO)
|
|
2510
|
+
|
|
2511
|
+
#define ENV_LOG_CONFIG_FUNC( name, cnst) \
|
|
2512
|
+
VALUE env_log_set_##cnst( VALUE obj, VALUE flags) { \
|
|
2513
|
+
return env_log_set_config_h( obj, DB_LOG_##cnst, flags); \
|
|
2514
|
+
} \
|
|
2515
|
+
VALUE env_log_get_##cnst( VALUE obj, VALUE flags) { \
|
|
2516
|
+
return env_log_get_config_h( obj, DB_LOG_##cnst); \
|
|
2517
|
+
}
|
|
2518
|
+
ENV_LOG_CONFIG_FUNCS
|
|
2519
|
+
|
|
2520
|
+
VALUE env_log_set_config( VALUE obj, VALUE flags, VALUE onoff) {
|
|
2521
|
+
return env_log_set_config_h( obj, NUM2UINT(flags), onoff);
|
|
2522
|
+
}
|
|
2523
|
+
|
|
2524
|
+
/*
|
|
2525
|
+
* call-seq:
|
|
2526
|
+
* env.set_lk_detect(detect) -> detect
|
|
2527
|
+
*
|
|
2528
|
+
* Set when lock detector should be run
|
|
2529
|
+
*/
|
|
2530
|
+
VALUE env_set_lk_detect(VALUE obj, VALUE vdetect)
|
|
2531
|
+
{
|
|
2532
|
+
t_envh *eh;
|
|
2533
|
+
u_int32_t detect;
|
|
2534
|
+
int rv;
|
|
2535
|
+
|
|
2536
|
+
detect=NUM2UINT(vdetect);
|
|
2537
|
+
|
|
2538
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
2539
|
+
if (!eh->env)
|
|
2540
|
+
raise(0, "env is closed");
|
|
2541
|
+
rv=eh->env->set_lk_detect(eh->env,detect);
|
|
2542
|
+
if ( rv != 0 ) {
|
|
2543
|
+
raise_error(rv, "env_set_lk_detect: %s",db_strerror(rv));
|
|
2544
|
+
}
|
|
2545
|
+
|
|
2546
|
+
return vdetect;
|
|
2547
|
+
}
|
|
2548
|
+
|
|
2549
|
+
/*
|
|
2550
|
+
* call-seq:
|
|
2551
|
+
* env.get_lk_detect() -> detect
|
|
2552
|
+
*
|
|
2553
|
+
* Get when lock detector should be run
|
|
2554
|
+
*/
|
|
2555
|
+
VALUE env_get_lk_detect(VALUE obj)
|
|
2556
|
+
{
|
|
2557
|
+
t_envh *eh;
|
|
2558
|
+
u_int32_t detect;
|
|
2559
|
+
int rv;
|
|
2560
|
+
|
|
2561
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
2562
|
+
if (!eh->env)
|
|
2563
|
+
raise(0, "env is closed");
|
|
2564
|
+
rv=eh->env->get_lk_detect(eh->env,&detect);
|
|
2565
|
+
if ( rv != 0 ) {
|
|
2566
|
+
raise_error(rv, "env_set_lk_detect: %s",db_strerror(rv));
|
|
2567
|
+
}
|
|
2568
|
+
|
|
2569
|
+
return UINT2NUM(detect);
|
|
2570
|
+
}
|
|
2571
|
+
|
|
2572
|
+
/*
|
|
2573
|
+
* call-seq:
|
|
2574
|
+
* env.set_lk_max_locks(max) -> max
|
|
2575
|
+
*
|
|
2576
|
+
* Set the maximum number of locks in the environment
|
|
2577
|
+
*/
|
|
2578
|
+
VALUE env_set_lk_max_locks(VALUE obj, VALUE vmax)
|
|
2579
|
+
{
|
|
2580
|
+
t_envh *eh;
|
|
2581
|
+
u_int32_t max;
|
|
2582
|
+
int rv;
|
|
2583
|
+
|
|
2584
|
+
max=FIX2UINT(vmax);
|
|
2585
|
+
|
|
2586
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
2587
|
+
if (!eh->env)
|
|
2588
|
+
raise(0, "env is closed");
|
|
2589
|
+
rv=eh->env->set_lk_max_locks(eh->env,max);
|
|
2590
|
+
if ( rv != 0 ) {
|
|
2591
|
+
raise_error(rv, "env_set_lk_max_locks: %s",db_strerror(rv));
|
|
2592
|
+
}
|
|
2593
|
+
|
|
2594
|
+
return vmax;
|
|
2595
|
+
}
|
|
2596
|
+
|
|
2597
|
+
/*
|
|
2598
|
+
* call-seq:
|
|
2599
|
+
* env.get_lk_max_locks -> max
|
|
2600
|
+
*
|
|
2601
|
+
* Get the maximum number of locks in the environment
|
|
2602
|
+
*/
|
|
2603
|
+
VALUE env_get_lk_max_locks(VALUE obj)
|
|
2604
|
+
{
|
|
2605
|
+
t_envh *eh;
|
|
2606
|
+
u_int32_t max;
|
|
2607
|
+
int rv;
|
|
2608
|
+
|
|
2609
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
2610
|
+
if (!eh->env)
|
|
2611
|
+
raise(0, "env is closed");
|
|
2612
|
+
rv=eh->env->get_lk_max_locks(eh->env,&max);
|
|
2613
|
+
if ( rv != 0 ) {
|
|
2614
|
+
raise_error(rv, "env_get_lk_max_locks: %s",db_strerror(rv));
|
|
2615
|
+
}
|
|
2616
|
+
|
|
2617
|
+
return UINT2NUM(max);
|
|
2618
|
+
}
|
|
2619
|
+
|
|
2620
|
+
/*
|
|
2621
|
+
* call-seq:
|
|
2622
|
+
* env.set_lk_max_objects(max) -> max
|
|
2623
|
+
*
|
|
2624
|
+
* Set the maximum number of locks in the environment
|
|
2625
|
+
*/
|
|
2626
|
+
VALUE env_set_lk_max_objects(VALUE obj, VALUE vmax)
|
|
2627
|
+
{
|
|
2628
|
+
t_envh *eh;
|
|
2629
|
+
u_int32_t max;
|
|
2630
|
+
int rv;
|
|
2631
|
+
|
|
2632
|
+
max=FIX2UINT(vmax);
|
|
2633
|
+
|
|
2634
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
2635
|
+
if (!eh->env)
|
|
2636
|
+
raise(0, "env is closed");
|
|
2637
|
+
rv=eh->env->set_lk_max_objects(eh->env,max);
|
|
2638
|
+
if ( rv != 0 ) {
|
|
2639
|
+
raise_error(rv, "env_set_lk_max_objects: %s",db_strerror(rv));
|
|
2640
|
+
}
|
|
2641
|
+
|
|
2642
|
+
return vmax;
|
|
2643
|
+
}
|
|
2644
|
+
|
|
2645
|
+
/*
|
|
2646
|
+
* call-seq:
|
|
2647
|
+
* env.get_lk_max_objects -> max
|
|
2648
|
+
*
|
|
2649
|
+
* Get the maximum number of locks in the environment
|
|
2650
|
+
*/
|
|
2651
|
+
VALUE env_get_lk_max_objects(VALUE obj)
|
|
2652
|
+
{
|
|
2653
|
+
t_envh *eh;
|
|
2654
|
+
u_int32_t max;
|
|
2655
|
+
int rv;
|
|
2656
|
+
|
|
2657
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
2658
|
+
if (!eh->env)
|
|
2659
|
+
raise(0, "env is closed");
|
|
2660
|
+
rv=eh->env->get_lk_max_objects(eh->env,&max);
|
|
2661
|
+
if ( rv != 0 ) {
|
|
2662
|
+
raise_error(rv, "env_get_lk_max_objects: %s",db_strerror(rv));
|
|
2663
|
+
}
|
|
2664
|
+
|
|
2665
|
+
return UINT2NUM(max);
|
|
2666
|
+
}
|
|
2667
|
+
|
|
2668
|
+
VALUE env_report_stderr(VALUE obj)
|
|
2669
|
+
{
|
|
2670
|
+
t_envh *eh;
|
|
2671
|
+
//u_int32_t max;
|
|
2672
|
+
//int rv;
|
|
2673
|
+
|
|
2674
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
2675
|
+
if (!eh->env)
|
|
2676
|
+
raise(0, "env is closed");
|
|
2677
|
+
eh->env->set_errfile(eh->env,stderr);
|
|
2678
|
+
|
|
2679
|
+
return Qtrue;
|
|
2680
|
+
}
|
|
2681
|
+
|
|
2682
|
+
/*
|
|
2683
|
+
* call-seq:
|
|
2684
|
+
* env.set_data_dir(data_dir) -> data_dir
|
|
2685
|
+
*
|
|
2686
|
+
* set data_dir
|
|
2687
|
+
*/
|
|
2688
|
+
VALUE env_set_data_dir(VALUE obj, VALUE vdata_dir)
|
|
2689
|
+
{
|
|
2690
|
+
t_envh *eh;
|
|
2691
|
+
const char *data_dir;
|
|
2692
|
+
int rv;
|
|
2693
|
+
|
|
2694
|
+
data_dir=StringValueCStr(vdata_dir);
|
|
2695
|
+
|
|
2696
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
2697
|
+
if (!eh->env)
|
|
2698
|
+
raise(0, "env is closed");
|
|
2699
|
+
rv=eh->env->set_data_dir(eh->env,data_dir);
|
|
2700
|
+
if ( rv != 0 ) {
|
|
2701
|
+
raise_error(rv, "env_set_data_dir: %s",db_strerror(rv));
|
|
2702
|
+
}
|
|
2703
|
+
|
|
2704
|
+
return vdata_dir;
|
|
2705
|
+
}
|
|
2706
|
+
|
|
2707
|
+
/*
|
|
2708
|
+
* call-seq:
|
|
2709
|
+
* env.get_data_dir -> [data_dir_1, data_dir_2, ...]
|
|
2710
|
+
*
|
|
2711
|
+
* get data_dir
|
|
2712
|
+
*/
|
|
2713
|
+
VALUE env_get_data_dirs(VALUE obj)
|
|
2714
|
+
{
|
|
2715
|
+
t_envh *eh;
|
|
2716
|
+
const char **data_dirs;
|
|
2717
|
+
int rv;
|
|
2718
|
+
int ln;
|
|
2719
|
+
|
|
2720
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
2721
|
+
if (!eh->env)
|
|
2722
|
+
raise(0, "env is closed");
|
|
2723
|
+
rv=eh->env->get_data_dirs(eh->env,&data_dirs);
|
|
2724
|
+
if ( rv != 0 ) {
|
|
2725
|
+
raise_error(rv, "env_get_data_dir: %s",db_strerror(rv));
|
|
2726
|
+
}
|
|
2727
|
+
|
|
2728
|
+
ln = (sizeof (data_dirs))/sizeof(data_dirs[0]);
|
|
2729
|
+
VALUE rb_data_dirs = rb_ary_new2(ln);
|
|
2730
|
+
int i;
|
|
2731
|
+
for (i=0; i<ln; i++) {
|
|
2732
|
+
rb_ary_push(rb_data_dirs, rb_str_new2(data_dirs[i]));
|
|
2733
|
+
}
|
|
2734
|
+
|
|
2735
|
+
return rb_data_dirs;
|
|
2736
|
+
}
|
|
2737
|
+
|
|
2738
|
+
/*
|
|
2739
|
+
* call-seq:
|
|
2740
|
+
* env.set_lg_dir(lg_dir) -> lg_dir
|
|
2741
|
+
*
|
|
2742
|
+
* set lg_dir
|
|
2743
|
+
*/
|
|
2744
|
+
VALUE env_set_lg_dir(VALUE obj, VALUE vlg_dir)
|
|
2745
|
+
{
|
|
2746
|
+
t_envh *eh;
|
|
2747
|
+
const char *lg_dir;
|
|
2748
|
+
int rv;
|
|
2749
|
+
|
|
2750
|
+
lg_dir=StringValueCStr(vlg_dir);
|
|
2751
|
+
|
|
2752
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
2753
|
+
if (!eh->env)
|
|
2754
|
+
raise(0, "env is closed");
|
|
2755
|
+
rv=eh->env->set_lg_dir(eh->env,lg_dir);
|
|
2756
|
+
if ( rv != 0 ) {
|
|
2757
|
+
raise_error(rv, "env_set_lg_dir: %s",db_strerror(rv));
|
|
2758
|
+
}
|
|
2759
|
+
|
|
2760
|
+
return vlg_dir;
|
|
2761
|
+
}
|
|
2762
|
+
|
|
2763
|
+
/*
|
|
2764
|
+
* call-seq:
|
|
2765
|
+
* env.get_lg_dir -> lg_dir
|
|
2766
|
+
*
|
|
2767
|
+
* get lg_dir
|
|
2768
|
+
*/
|
|
2769
|
+
VALUE env_get_lg_dir(VALUE obj)
|
|
2770
|
+
{
|
|
2771
|
+
t_envh *eh;
|
|
2772
|
+
const char *lg_dir;
|
|
2773
|
+
int rv;
|
|
2774
|
+
|
|
2775
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
2776
|
+
if (!eh->env)
|
|
2777
|
+
raise(0, "env is closed");
|
|
2778
|
+
rv=eh->env->get_lg_dir(eh->env,&lg_dir);
|
|
2779
|
+
if ( rv != 0 ) {
|
|
2780
|
+
raise_error(rv, "env_get_lg_dir: %s",db_strerror(rv));
|
|
2781
|
+
}
|
|
2782
|
+
|
|
2783
|
+
return rb_str_new2(lg_dir);
|
|
2784
|
+
}
|
|
2785
|
+
|
|
2786
|
+
/*
|
|
2787
|
+
* call-seq:
|
|
2788
|
+
* env.set_tmp_dir(tmp_dir) -> tmp_dir
|
|
2789
|
+
*
|
|
2790
|
+
* set tmp_dir
|
|
2791
|
+
*/
|
|
2792
|
+
VALUE env_set_tmp_dir(VALUE obj, VALUE vtmp_dir)
|
|
2793
|
+
{
|
|
2794
|
+
t_envh *eh;
|
|
2795
|
+
const char *tmp_dir;
|
|
2796
|
+
int rv;
|
|
2797
|
+
|
|
2798
|
+
tmp_dir=StringValueCStr(vtmp_dir);
|
|
2799
|
+
|
|
2800
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
2801
|
+
if (!eh->env)
|
|
2802
|
+
raise(0, "env is closed");
|
|
2803
|
+
rv=eh->env->set_tmp_dir(eh->env,tmp_dir);
|
|
2804
|
+
if ( rv != 0 ) {
|
|
2805
|
+
raise_error(rv, "env_set_tmp_dir: %s",db_strerror(rv));
|
|
2806
|
+
}
|
|
2807
|
+
|
|
2808
|
+
return vtmp_dir;
|
|
2809
|
+
}
|
|
2810
|
+
|
|
2811
|
+
/*
|
|
2812
|
+
* call-seq:
|
|
2813
|
+
* env.get_tmp_dir -> tmp_dir
|
|
2814
|
+
*
|
|
2815
|
+
* get tmp_dir
|
|
2816
|
+
*/
|
|
2817
|
+
VALUE env_get_tmp_dir(VALUE obj)
|
|
2818
|
+
{
|
|
2819
|
+
t_envh *eh;
|
|
2820
|
+
const char *tmp_dir;
|
|
2821
|
+
int rv;
|
|
2822
|
+
|
|
2823
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
2824
|
+
if (!eh->env)
|
|
2825
|
+
raise(0, "env is closed");
|
|
2826
|
+
rv=eh->env->get_tmp_dir(eh->env,&tmp_dir);
|
|
2827
|
+
if ( rv != 0 ) {
|
|
2828
|
+
raise_error(rv, "env_get_tmp_dir: %s",db_strerror(rv));
|
|
2829
|
+
}
|
|
2830
|
+
|
|
2831
|
+
return rb_str_new2(tmp_dir);
|
|
2832
|
+
}
|
|
2833
|
+
|
|
2834
|
+
/*
|
|
2835
|
+
* call-seq:
|
|
2836
|
+
* env.get_home -> home
|
|
2837
|
+
*
|
|
2838
|
+
* get home
|
|
2839
|
+
*/
|
|
2840
|
+
VALUE env_get_home(VALUE obj)
|
|
2841
|
+
{
|
|
2842
|
+
t_envh *eh;
|
|
2843
|
+
const char *home;
|
|
2844
|
+
int rv;
|
|
2845
|
+
|
|
2846
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
2847
|
+
if (!eh->env)
|
|
2848
|
+
raise(0, "env is closed");
|
|
2849
|
+
rv=eh->env->get_home(eh->env,&home);
|
|
2850
|
+
if ( rv != 0 ) {
|
|
2851
|
+
raise_error(rv, "env_get_home: %s",db_strerror(rv));
|
|
2852
|
+
}
|
|
2853
|
+
|
|
2854
|
+
return rb_str_new2(home);
|
|
2855
|
+
}
|
|
2856
|
+
|
|
2857
|
+
/*
|
|
2858
|
+
* call-seq:
|
|
2859
|
+
* env.set_verbose(which, onoff)
|
|
2860
|
+
*
|
|
2861
|
+
* set verbose messages on or off
|
|
2862
|
+
*/
|
|
2863
|
+
VALUE env_set_verbose(VALUE obj, VALUE which, VALUE onoff)
|
|
2864
|
+
{
|
|
2865
|
+
t_envh *eh;
|
|
2866
|
+
int rv;
|
|
2867
|
+
|
|
2868
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
2869
|
+
rv = eh->env->set_verbose(eh->env, NUM2UINT(which), RTEST(onoff));
|
|
2870
|
+
|
|
2871
|
+
if ( rv != 0 ) raise_error(rv, "env_set_verbose: %s",db_strerror(rv));
|
|
2872
|
+
|
|
2873
|
+
return Qtrue;
|
|
2874
|
+
}
|
|
2875
|
+
|
|
2876
|
+
/*
|
|
2877
|
+
* call-seq:
|
|
2878
|
+
* env.rep_priority = int
|
|
2879
|
+
*
|
|
2880
|
+
* specify how the replication manager will handle acknowledgement of replication messages
|
|
2881
|
+
*/
|
|
2882
|
+
VALUE env_rep_set_priority(VALUE obj, VALUE priority)
|
|
2883
|
+
{
|
|
2884
|
+
t_envh *eh;
|
|
2885
|
+
int rv;
|
|
2886
|
+
|
|
2887
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
2888
|
+
rv = eh->env->rep_set_priority(eh->env, NUM2UINT(priority));
|
|
2889
|
+
|
|
2890
|
+
if ( rv != 0 ) raise_error(rv, "env_rep_set_priority: %s", db_strerror(rv));
|
|
2891
|
+
return priority;
|
|
2892
|
+
}
|
|
2893
|
+
|
|
2894
|
+
/*
|
|
2895
|
+
* call-seq:
|
|
2896
|
+
* env.rep_priority -> int
|
|
2897
|
+
*
|
|
2898
|
+
* returns the replication manager's acknowledgement policy
|
|
2899
|
+
*/
|
|
2900
|
+
VALUE env_rep_get_priority(VALUE obj)
|
|
2901
|
+
{
|
|
2902
|
+
t_envh *eh;
|
|
2903
|
+
u_int32_t priority;
|
|
2904
|
+
|
|
2905
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
2906
|
+
eh->env->rep_get_priority(eh->env, &priority);
|
|
2907
|
+
|
|
2908
|
+
return INT2NUM(priority);
|
|
2909
|
+
}
|
|
2910
|
+
|
|
2911
|
+
/*
|
|
2912
|
+
* call-seq:
|
|
2913
|
+
* env.rep_nsites = int
|
|
2914
|
+
*
|
|
2915
|
+
* specify how the replication manager will handle acknowledgement of replication messages
|
|
2916
|
+
*/
|
|
2917
|
+
VALUE env_rep_set_nsites(VALUE obj, VALUE nsites)
|
|
2918
|
+
{
|
|
2919
|
+
t_envh *eh;
|
|
2920
|
+
int rv;
|
|
2921
|
+
|
|
2922
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
2923
|
+
rv = eh->env->rep_set_nsites(eh->env, NUM2UINT(nsites));
|
|
2924
|
+
|
|
2925
|
+
if ( rv != 0 ) raise_error(rv, "env_rep_set_nsites: %s", db_strerror(rv));
|
|
2926
|
+
return nsites;
|
|
2927
|
+
}
|
|
2928
|
+
|
|
2929
|
+
/*
|
|
2930
|
+
* call-seq:
|
|
2931
|
+
* env.rep_nsites -> int
|
|
2932
|
+
*
|
|
2933
|
+
* returns the replication manager's acknowledgement policy
|
|
2934
|
+
*/
|
|
2935
|
+
VALUE env_rep_get_nsites(VALUE obj)
|
|
2936
|
+
{
|
|
2937
|
+
t_envh *eh;
|
|
2938
|
+
u_int32_t nsites;
|
|
2939
|
+
|
|
2940
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
2941
|
+
eh->env->rep_get_nsites(eh->env, &nsites);
|
|
2942
|
+
|
|
2943
|
+
return INT2NUM(nsites);
|
|
2944
|
+
}
|
|
2945
|
+
|
|
2946
|
+
|
|
2947
|
+
/*
|
|
2948
|
+
* call-seq:
|
|
2949
|
+
* env.repmgr_set_local_site(host, port)
|
|
2950
|
+
*
|
|
2951
|
+
* specify the local site for the replication manager
|
|
2952
|
+
*/
|
|
2953
|
+
VALUE env_repmgr_set_local_site(VALUE obj, VALUE host, VALUE port)
|
|
2954
|
+
{
|
|
2955
|
+
t_envh *eh;
|
|
2956
|
+
int rv;
|
|
2957
|
+
|
|
2958
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
2959
|
+
rv = eh->env->repmgr_set_local_site(eh->env, StringValuePtr(host), NUM2UINT(port), 0);
|
|
2960
|
+
|
|
2961
|
+
if ( rv != 0 ) raise_error(rv, "env_repmgr_set_local_site: %s", db_strerror(rv));
|
|
2962
|
+
return Qtrue;
|
|
2963
|
+
}
|
|
2964
|
+
|
|
2965
|
+
/*
|
|
2966
|
+
* call-seq:
|
|
2967
|
+
* env.repmgr_add_remote_site(host, port)
|
|
2968
|
+
*
|
|
2969
|
+
* add a remote for the replication manager
|
|
2970
|
+
*/
|
|
2971
|
+
VALUE env_repmgr_add_remote_site(VALUE obj, VALUE host, VALUE port)
|
|
2972
|
+
{
|
|
2973
|
+
t_envh *eh;
|
|
2974
|
+
int rv;
|
|
2975
|
+
int eidp;
|
|
2976
|
+
|
|
2977
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
2978
|
+
rv = eh->env->repmgr_add_remote_site(eh->env, StringValuePtr(host), NUM2UINT(port), &eidp, 0);
|
|
2979
|
+
|
|
2980
|
+
if ( rv != 0 ) raise_error(rv, "env_repmgr_add_remote_site: %s", db_strerror(rv));
|
|
2981
|
+
return INT2NUM(eidp);
|
|
2982
|
+
}
|
|
2983
|
+
|
|
2984
|
+
/*
|
|
2985
|
+
* call-seq:
|
|
2986
|
+
* env.repmgr_ack_policy = int
|
|
2987
|
+
*
|
|
2988
|
+
* specify how the replication manager will handle acknowledgement of replication messages
|
|
2989
|
+
*/
|
|
2990
|
+
VALUE env_repmgr_set_ack_policy(VALUE obj, VALUE policy)
|
|
2991
|
+
{
|
|
2992
|
+
t_envh *eh;
|
|
2993
|
+
int rv;
|
|
2994
|
+
|
|
2995
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
2996
|
+
rv = eh->env->repmgr_set_ack_policy(eh->env, NUM2INT(policy));
|
|
2997
|
+
|
|
2998
|
+
if ( rv != 0 ) raise_error(rv, "env_repmgr_set_ack_policy: %s", db_strerror(rv));
|
|
2999
|
+
return policy;
|
|
3000
|
+
}
|
|
3001
|
+
|
|
3002
|
+
/*
|
|
3003
|
+
* call-seq:
|
|
3004
|
+
* env.repmgr_ack_policy -> int
|
|
3005
|
+
*
|
|
3006
|
+
* returns the replication manager's acknowledgement policy
|
|
3007
|
+
*/
|
|
3008
|
+
VALUE env_repmgr_get_ack_policy(VALUE obj)
|
|
3009
|
+
{
|
|
3010
|
+
t_envh *eh;
|
|
3011
|
+
int policy;
|
|
3012
|
+
|
|
3013
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
3014
|
+
eh->env->repmgr_get_ack_policy(eh->env, &policy);
|
|
3015
|
+
|
|
3016
|
+
return INT2NUM(policy);
|
|
3017
|
+
}
|
|
3018
|
+
|
|
3019
|
+
/*
|
|
3020
|
+
* call-seq:
|
|
3021
|
+
* env.repmgr_start(num_threads, flags)
|
|
3022
|
+
*
|
|
3023
|
+
* start the replication manager
|
|
3024
|
+
*/
|
|
3025
|
+
VALUE env_repmgr_start(VALUE obj, VALUE num_threads, VALUE flags)
|
|
3026
|
+
{
|
|
3027
|
+
t_envh *eh;
|
|
3028
|
+
int rv;
|
|
3029
|
+
|
|
3030
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
3031
|
+
rv = eh->env->repmgr_start(eh->env, NUM2INT(num_threads), NUM2UINT(flags));
|
|
3032
|
+
|
|
3033
|
+
if ( rv != 0 ) raise_error(rv, "env_repmgr_start: %s", db_strerror(rv));
|
|
3034
|
+
return Qtrue;
|
|
3035
|
+
}
|
|
3036
|
+
|
|
3037
|
+
/*
|
|
3038
|
+
* call-seq:
|
|
3039
|
+
* env.repmgr_stat_print
|
|
3040
|
+
*
|
|
3041
|
+
* prints replication manager stats
|
|
3042
|
+
*/
|
|
3043
|
+
VALUE env_repmgr_stat_print(VALUE obj, VALUE flags)
|
|
3044
|
+
{
|
|
3045
|
+
t_envh *eh;
|
|
3046
|
+
int rv;
|
|
3047
|
+
|
|
3048
|
+
Data_Get_Struct(obj,t_envh,eh);
|
|
3049
|
+
rv = eh->env->repmgr_stat_print(eh->env, NUM2UINT(flags));
|
|
3050
|
+
|
|
3051
|
+
if ( rv != 0 ) raise_error(rv, "env_repmgr_stat_print: %s", db_strerror(rv));
|
|
3052
|
+
return Qtrue;
|
|
3053
|
+
}
|
|
3054
|
+
|
|
3055
|
+
VALUE env_set_lg_bsize( VALUE obj, VALUE size) {
|
|
3056
|
+
t_envh *eh;
|
|
3057
|
+
int rv;
|
|
3058
|
+
Data_Get_Struct(obj, t_envh, eh);
|
|
3059
|
+
rv = eh->env->set_lg_bsize( eh->env, NUM2UINT( size));
|
|
3060
|
+
if ( rv != 0 )
|
|
3061
|
+
raise_error(rv, "env_set_lg_bsize: %s", db_strerror(rv));
|
|
3062
|
+
return size;
|
|
3063
|
+
}
|
|
3064
|
+
|
|
3065
|
+
VALUE env_get_lg_bsize( VALUE obj) {
|
|
3066
|
+
t_envh *eh;
|
|
3067
|
+
int rv;
|
|
3068
|
+
u_int32_t size;
|
|
3069
|
+
Data_Get_Struct( obj, t_envh, eh);
|
|
3070
|
+
rv = eh->env->get_lg_bsize( eh->env, &size);
|
|
3071
|
+
if ( rv != 0 )
|
|
3072
|
+
raise_error(rv, "env_get_lg_bsize: %s", db_strerror(rv));
|
|
3073
|
+
return UINT2FIX(size);
|
|
3074
|
+
}
|
|
3075
|
+
|
|
3076
|
+
VALUE env_set_lg_max( VALUE obj, VALUE size) {
|
|
3077
|
+
t_envh *eh;
|
|
3078
|
+
int rv;
|
|
3079
|
+
Data_Get_Struct(obj, t_envh, eh);
|
|
3080
|
+
rv = eh->env->set_lg_max( eh->env, NUM2UINT( size));
|
|
3081
|
+
if ( rv != 0 )
|
|
3082
|
+
raise_error(rv, "env_set_lg_max: %s", db_strerror(rv));
|
|
3083
|
+
return size;
|
|
3084
|
+
}
|
|
3085
|
+
|
|
3086
|
+
VALUE env_get_lg_max( VALUE obj) {
|
|
3087
|
+
t_envh *eh;
|
|
3088
|
+
int rv;
|
|
3089
|
+
u_int32_t size;
|
|
3090
|
+
Data_Get_Struct( obj, t_envh, eh);
|
|
3091
|
+
rv = eh->env->get_lg_max( eh->env, &size);
|
|
3092
|
+
if ( rv != 0 )
|
|
3093
|
+
raise_error(rv, "env_get_lg_max: %s", db_strerror(rv));
|
|
3094
|
+
return UINT2FIX(size);
|
|
3095
|
+
}
|
|
3096
|
+
|
|
3097
|
+
VALUE env_set_lg_regionmax( VALUE obj, VALUE size) {
|
|
3098
|
+
t_envh *eh;
|
|
3099
|
+
int rv;
|
|
3100
|
+
Data_Get_Struct(obj, t_envh, eh);
|
|
3101
|
+
rv = eh->env->set_lg_regionmax( eh->env, NUM2UINT( size));
|
|
3102
|
+
if ( rv != 0 )
|
|
3103
|
+
raise_error(rv, "env_set_lg_regionmax: %s", db_strerror(rv));
|
|
3104
|
+
return size;
|
|
3105
|
+
}
|
|
3106
|
+
|
|
3107
|
+
VALUE env_get_lg_regionmax( VALUE obj) {
|
|
3108
|
+
t_envh *eh;
|
|
3109
|
+
int rv;
|
|
3110
|
+
u_int32_t size;
|
|
3111
|
+
Data_Get_Struct( obj, t_envh, eh);
|
|
3112
|
+
rv = eh->env->get_lg_regionmax( eh->env, &size);
|
|
3113
|
+
if ( rv != 0 )
|
|
3114
|
+
raise_error(rv, "env_get_lg_regionmax: %s", db_strerror(rv));
|
|
3115
|
+
return UINT2FIX(size);
|
|
3116
|
+
}
|
|
3117
|
+
|
|
3118
|
+
|
|
3119
|
+
static void txn_finish(t_txnh *txn)
|
|
3120
|
+
{
|
|
3121
|
+
if ( RTEST(ruby_debug) )
|
|
3122
|
+
rb_warning("%s/%d %s 0x%p",__FILE__,__LINE__,"txn_finish",(void*)txn);
|
|
3123
|
+
|
|
3124
|
+
txn->txn=NULL;
|
|
3125
|
+
if (txn->env) {
|
|
3126
|
+
rb_ary_delete(txn->env->atxn,txn->self);
|
|
3127
|
+
txn->env=NULL;
|
|
3128
|
+
}
|
|
3129
|
+
}
|
|
3130
|
+
|
|
3131
|
+
/*
|
|
3132
|
+
* call-seq:
|
|
3133
|
+
* txn.commit(flags) -> true
|
|
3134
|
+
*
|
|
3135
|
+
* commit a transaction
|
|
3136
|
+
*/
|
|
3137
|
+
VALUE txn_commit(VALUE obj, VALUE vflags)
|
|
3138
|
+
{
|
|
3139
|
+
t_txnh *txn=NULL;
|
|
3140
|
+
u_int32_t flags=0;
|
|
3141
|
+
int rv;
|
|
3142
|
+
|
|
3143
|
+
if ( ! NIL_P(vflags))
|
|
3144
|
+
flags=NUM2UINT(vflags);
|
|
3145
|
+
|
|
3146
|
+
Data_Get_Struct(obj,t_txnh,txn);
|
|
3147
|
+
|
|
3148
|
+
if (!txn->txn)
|
|
3149
|
+
return Qfalse;
|
|
3150
|
+
|
|
3151
|
+
rv=txn->txn->commit(txn->txn,flags);
|
|
3152
|
+
txn_finish(txn);
|
|
3153
|
+
if ( rv != 0 ) {
|
|
3154
|
+
raise_error(rv, "txn_commit: %s",db_strerror(rv));
|
|
3155
|
+
return Qnil;
|
|
3156
|
+
}
|
|
3157
|
+
return Qtrue;
|
|
3158
|
+
}
|
|
3159
|
+
|
|
3160
|
+
/*
|
|
3161
|
+
* call-seq:
|
|
3162
|
+
* txn.abort -> true
|
|
3163
|
+
*
|
|
3164
|
+
* abort a transaction
|
|
3165
|
+
*/
|
|
3166
|
+
VALUE txn_abort(VALUE obj)
|
|
3167
|
+
{
|
|
3168
|
+
t_txnh *txn=NULL;
|
|
3169
|
+
int rv;
|
|
3170
|
+
|
|
3171
|
+
Data_Get_Struct(obj,t_txnh,txn);
|
|
3172
|
+
|
|
3173
|
+
if (!txn->txn)
|
|
3174
|
+
return Qfalse;
|
|
3175
|
+
|
|
3176
|
+
rv=txn->txn->abort(txn->txn);
|
|
3177
|
+
txn_finish(txn);
|
|
3178
|
+
if ( rv != 0 ) {
|
|
3179
|
+
raise_error(rv, "txn_abort: %s",db_strerror(rv));
|
|
3180
|
+
return Qnil;
|
|
3181
|
+
}
|
|
3182
|
+
return Qtrue;
|
|
3183
|
+
}
|
|
3184
|
+
|
|
3185
|
+
/*
|
|
3186
|
+
* call-seq:
|
|
3187
|
+
* txn.discard -> true
|
|
3188
|
+
*
|
|
3189
|
+
* discard a transaction. Since prepare is not yet supported,
|
|
3190
|
+
* I don't think this has much value.
|
|
3191
|
+
*/
|
|
3192
|
+
VALUE txn_discard(VALUE obj)
|
|
3193
|
+
{
|
|
3194
|
+
t_txnh *txn=NULL;
|
|
3195
|
+
int rv;
|
|
3196
|
+
|
|
3197
|
+
Data_Get_Struct(obj,t_txnh,txn);
|
|
3198
|
+
|
|
3199
|
+
if (!txn->txn)
|
|
3200
|
+
raise_error(0,"txn is closed");
|
|
3201
|
+
|
|
3202
|
+
rv=txn->txn->discard(txn->txn,NOFLAGS);
|
|
3203
|
+
txn_finish(txn);
|
|
3204
|
+
if ( rv != 0 ) {
|
|
3205
|
+
raise_error(rv, "txn_abort: %s",db_strerror(rv));
|
|
3206
|
+
return Qnil;
|
|
3207
|
+
}
|
|
3208
|
+
return Qtrue;
|
|
3209
|
+
}
|
|
3210
|
+
|
|
3211
|
+
/*
|
|
3212
|
+
* call-seq:
|
|
3213
|
+
* txn.tid -> Fixnum
|
|
3214
|
+
*
|
|
3215
|
+
* return the transaction id, (named tid to not conflict with
|
|
3216
|
+
* ruby's id method)
|
|
3217
|
+
*/
|
|
3218
|
+
VALUE txn_id(VALUE obj)
|
|
3219
|
+
{
|
|
3220
|
+
t_txnh *txn=NULL;
|
|
3221
|
+
int rv;
|
|
3222
|
+
|
|
3223
|
+
Data_Get_Struct(obj,t_txnh,txn);
|
|
3224
|
+
if (!txn->txn)
|
|
3225
|
+
raise_error(0,"txn is closed");
|
|
3226
|
+
|
|
3227
|
+
rv=txn->txn->id(txn->txn);
|
|
3228
|
+
return INT2FIX(rv);
|
|
3229
|
+
}
|
|
3230
|
+
|
|
3231
|
+
/*
|
|
3232
|
+
* call-seq:
|
|
3233
|
+
* tx.set_timeout(timeout,flags) -> true
|
|
3234
|
+
*
|
|
3235
|
+
* set transaction lock timeout
|
|
3236
|
+
*/
|
|
3237
|
+
VALUE txn_set_timeout(VALUE obj, VALUE vtimeout, VALUE vflags)
|
|
3238
|
+
{
|
|
3239
|
+
t_txnh *txn=NULL;
|
|
3240
|
+
db_timeout_t timeout;
|
|
3241
|
+
u_int32_t flags=0;
|
|
3242
|
+
int rv;
|
|
3243
|
+
|
|
3244
|
+
if ( ! NIL_P(vflags))
|
|
3245
|
+
flags=NUM2UINT(vflags);
|
|
3246
|
+
|
|
3247
|
+
if ( ! FIXNUM_P(vtimeout) )
|
|
3248
|
+
raise_error(0,"timeout must be a fixed integer");
|
|
3249
|
+
timeout=FIX2UINT(vtimeout);
|
|
3250
|
+
|
|
3251
|
+
Data_Get_Struct(obj,t_txnh,txn);
|
|
3252
|
+
|
|
3253
|
+
if (!txn->txn)
|
|
3254
|
+
raise_error(0,"txn is closed");
|
|
3255
|
+
|
|
3256
|
+
rv=txn->txn->set_timeout(txn->txn,timeout,flags);
|
|
3257
|
+
if ( rv != 0 ) {
|
|
3258
|
+
raise_error(rv, "txn_set_timeout: %s",db_strerror(rv));
|
|
3259
|
+
return Qnil;
|
|
3260
|
+
}
|
|
3261
|
+
return Qtrue;
|
|
3262
|
+
}
|
|
3263
|
+
|
|
3264
|
+
/*
|
|
3265
|
+
* Document-class: Bdb
|
|
3266
|
+
*
|
|
3267
|
+
* Ruby library that wraps the Sleepycat Berkeley DB.
|
|
3268
|
+
*
|
|
3269
|
+
* Developed against 4.3/4.4. No support for prior versions.
|
|
3270
|
+
*/
|
|
3271
|
+
|
|
3272
|
+
void Init_bdb() {
|
|
3273
|
+
fv_call=rb_intern("call");
|
|
3274
|
+
fv_uniq=rb_intern("uniq");
|
|
3275
|
+
fv_err_new=rb_intern("new");
|
|
3276
|
+
fv_err_code=rb_intern("@code");
|
|
3277
|
+
fv_err_msg=rb_intern("@message");
|
|
3278
|
+
|
|
3279
|
+
mBdb = rb_define_module("Bdb");
|
|
3280
|
+
|
|
3281
|
+
#include "bdb_aux._c"
|
|
3282
|
+
|
|
3283
|
+
cDb = rb_define_class_under(mBdb,"Db", rb_cObject);
|
|
3284
|
+
eDbError = rb_define_class_under(mBdb,"DbError",rb_eStandardError);
|
|
3285
|
+
#define eDbE_create(n,c) eDbE_##c = rb_define_class_under(mBdb, #c, eDbError);
|
|
3286
|
+
EXCEPTIONS_CREATE
|
|
3287
|
+
|
|
3288
|
+
rb_define_method(eDbError,"initialize",err_initialize,2);
|
|
3289
|
+
rb_define_method(eDbError,"code",err_code,0);
|
|
3290
|
+
|
|
3291
|
+
rb_define_const(cDb,"BTREE",INT2FIX((DBTYPE)(DB_BTREE)));
|
|
3292
|
+
rb_define_const(cDb,"HASH",INT2FIX((DBTYPE)(DB_HASH)));
|
|
3293
|
+
rb_define_const(cDb,"RECNO",INT2FIX((DBTYPE)(DB_RECNO)));
|
|
3294
|
+
rb_define_const(cDb,"QUEUE",INT2FIX((DBTYPE)(DB_QUEUE)));
|
|
3295
|
+
rb_define_const(cDb,"UNKNOWN",INT2FIX((DBTYPE)(DB_UNKNOWN)));
|
|
3296
|
+
|
|
3297
|
+
rb_define_alloc_func(cDb,db_alloc);
|
|
3298
|
+
rb_define_method(cDb,"initialize",db_initialize,0);
|
|
3299
|
+
|
|
3300
|
+
rb_define_method(cDb,"put",db_put,4);
|
|
3301
|
+
rb_define_method(cDb,"get",db_get,4);
|
|
3302
|
+
rb_define_method(cDb,"pget",db_pget,4);
|
|
3303
|
+
rb_define_method(cDb,"del",db_del,3);
|
|
3304
|
+
rb_define_method(cDb,"cursor",db_cursor,2);
|
|
3305
|
+
rb_define_method(cDb,"associate",db_associate,4);
|
|
3306
|
+
rb_define_method(cDb,"btree_compare=",db_btree_compare_set,1);
|
|
3307
|
+
rb_define_method(cDb,"re_len=",db_set_re_len,1);
|
|
3308
|
+
rb_define_method(cDb,"re_len",db_get_re_len,0);
|
|
3309
|
+
rb_define_method(cDb,"flags=",db_flags_set,1);
|
|
3310
|
+
rb_define_method(cDb,"flags",db_flags_get,0);
|
|
3311
|
+
rb_define_method(cDb,"open",db_open,6);
|
|
3312
|
+
rb_define_method(cDb,"close",db_close,1);
|
|
3313
|
+
rb_define_method(cDb,"[]",db_aget,1);
|
|
3314
|
+
rb_define_method(cDb,"[]=",db_aset,2);
|
|
3315
|
+
rb_define_method(cDb,"join",db_join,2);
|
|
3316
|
+
rb_define_method(cDb,"get_byteswapped",db_get_byteswapped,0);
|
|
3317
|
+
rb_define_method(cDb,"get_type",db_get_type,0);
|
|
3318
|
+
rb_define_method(cDb,"remove",db_remove,3);
|
|
3319
|
+
rb_define_method(cDb,"key_range",db_key_range,3);
|
|
3320
|
+
rb_define_method(cDb,"rename",db_rename,4);
|
|
3321
|
+
rb_define_method(cDb,"pagesize",db_pagesize,0);
|
|
3322
|
+
rb_define_method(cDb,"pagesize=",db_pagesize_set,1);
|
|
3323
|
+
rb_define_method(cDb,"h_ffactor",db_h_ffactor,0);
|
|
3324
|
+
rb_define_method(cDb,"h_ffactor=",db_h_ffactor_set,1);
|
|
3325
|
+
rb_define_method(cDb,"h_nelem",db_h_nelem,0);
|
|
3326
|
+
rb_define_method(cDb,"h_nelem=",db_h_nelem_set,1);
|
|
3327
|
+
rb_define_method(cDb,"stat",db_stat,2);
|
|
3328
|
+
cDbStat = rb_define_class_under(cDb,"Stat",rb_cObject);
|
|
3329
|
+
rb_define_method(cDbStat,"[]",stat_aref,1);
|
|
3330
|
+
|
|
3331
|
+
rb_define_method(cDb,"sync",db_sync,0);
|
|
3332
|
+
rb_define_method(cDb,"truncate",db_truncate,1);
|
|
3333
|
+
|
|
3334
|
+
#if DB_VERSION_MINOR > 3
|
|
3335
|
+
rb_define_method(cDb,"compact",db_compact,5);
|
|
3336
|
+
#endif
|
|
3337
|
+
|
|
3338
|
+
cCursor = rb_define_class_under(cDb,"Cursor",rb_cObject);
|
|
3339
|
+
rb_define_method(cCursor,"get",dbc_get,3);
|
|
3340
|
+
rb_define_method(cCursor,"pget",dbc_pget,3);
|
|
3341
|
+
rb_define_method(cCursor,"put",dbc_put,3);
|
|
3342
|
+
rb_define_method(cCursor,"close",dbc_close,0);
|
|
3343
|
+
rb_define_method(cCursor,"del",dbc_del,0);
|
|
3344
|
+
rb_define_method(cCursor,"count",dbc_count,0);
|
|
3345
|
+
|
|
3346
|
+
cEnv = rb_define_class_under(mBdb,"Env",rb_cObject);
|
|
3347
|
+
rb_define_singleton_method(cEnv,"new",env_new,1);
|
|
3348
|
+
rb_define_method(cEnv,"open",env_open,3);
|
|
3349
|
+
rb_define_method(cEnv,"close",env_close,0);
|
|
3350
|
+
rb_define_method(cEnv,"db",env_db,0);
|
|
3351
|
+
rb_define_method(cEnv,"cachesize=",env_set_cachesize,1);
|
|
3352
|
+
rb_define_method(cEnv,"cachesize",env_get_cachesize,0);
|
|
3353
|
+
rb_define_method(cEnv,"flags",env_get_flags,0);
|
|
3354
|
+
rb_define_method(cEnv,"flags_on=",env_set_flags_on,1);
|
|
3355
|
+
rb_define_method(cEnv,"flags_off=",env_set_flags_off,1);
|
|
3356
|
+
rb_define_method(cEnv,"list_dbs",env_list_dbs,0);
|
|
3357
|
+
rb_define_method(cEnv,"txn_begin",env_txn_begin,2);
|
|
3358
|
+
rb_define_method(cEnv,"txn_checkpoint",env_txn_checkpoint,3);
|
|
3359
|
+
rb_define_method(cEnv,"txn_stat",env_txn_stat,1);
|
|
3360
|
+
rb_define_method(cEnv,"timeout",env_set_timeout,2);
|
|
3361
|
+
rb_define_method(cEnv,"timeout",env_get_timeout,1);
|
|
3362
|
+
rb_define_method(cEnv,"mutex_get_max",env_mutex_get_max,0);
|
|
3363
|
+
rb_define_method(cEnv,"mutex_set_max",env_mutex_set_max,1);
|
|
3364
|
+
rb_define_method(cEnv,"tx_max=",env_set_tx_max,1);
|
|
3365
|
+
rb_define_method(cEnv,"tx_max",env_get_tx_max,0);
|
|
3366
|
+
rb_define_method(cEnv,"report_stderr",env_report_stderr,0);
|
|
3367
|
+
rb_define_method(cEnv,"lk_detect=",env_set_lk_detect,1);
|
|
3368
|
+
rb_define_method(cEnv,"lk_detect",env_get_lk_detect,0);
|
|
3369
|
+
rb_define_method(cEnv,"lk_max_locks=",env_set_lk_max_locks,1);
|
|
3370
|
+
rb_define_method(cEnv,"lk_max_locks",env_get_lk_max_locks,0);
|
|
3371
|
+
rb_define_method(cEnv,"lk_max_objects=",env_set_lk_max_objects,1);
|
|
3372
|
+
rb_define_method(cEnv,"lk_max_objects",env_get_lk_max_objects,0);
|
|
3373
|
+
rb_define_method(cEnv,"shm_key=",env_set_shm_key,1);
|
|
3374
|
+
rb_define_method(cEnv,"shm_key",env_get_shm_key,0);
|
|
3375
|
+
rb_define_method(cEnv,"log_config",env_log_set_config,2);
|
|
3376
|
+
#define ENV_LOG_CONFIG_FUNC(name,cnst) \
|
|
3377
|
+
rb_define_method(cEnv,"log_"#name "=",env_log_set_##cnst,1); \
|
|
3378
|
+
rb_define_method(cEnv,"log_"#name,env_log_get_##cnst,0);
|
|
3379
|
+
ENV_LOG_CONFIG_FUNCS
|
|
3380
|
+
|
|
3381
|
+
rb_define_method(cEnv,"data_dir=",env_set_data_dir,1);
|
|
3382
|
+
rb_define_method(cEnv,"data_dirs",env_get_data_dirs,0);
|
|
3383
|
+
rb_define_method(cEnv,"lg_dir=",env_set_lg_dir,1);
|
|
3384
|
+
rb_define_method(cEnv,"lg_dir",env_get_lg_dir,0);
|
|
3385
|
+
rb_define_method(cEnv,"tmp_dir=",env_set_tmp_dir,1);
|
|
3386
|
+
rb_define_method(cEnv,"tmp_dir",env_get_tmp_dir,0);
|
|
3387
|
+
rb_define_method(cEnv,"home",env_get_home,0);
|
|
3388
|
+
rb_define_method(cEnv,"set_verbose",env_set_verbose,2);
|
|
3389
|
+
|
|
3390
|
+
rb_define_method(cEnv,"rep_priority=", env_rep_set_priority, 1);
|
|
3391
|
+
rb_define_method(cEnv,"rep_priority", env_rep_get_priority, 0);
|
|
3392
|
+
rb_define_method(cEnv,"rep_nsites=", env_rep_set_nsites, 1);
|
|
3393
|
+
rb_define_method(cEnv,"rep_nsites", env_rep_get_nsites, 0);
|
|
3394
|
+
rb_define_method(cEnv,"repmgr_set_local_site", env_repmgr_set_local_site, 2);
|
|
3395
|
+
rb_define_method(cEnv,"repmgr_add_remote_site", env_repmgr_add_remote_site, 2);
|
|
3396
|
+
rb_define_method(cEnv,"repmgr_ack_policy=", env_repmgr_set_ack_policy, 1);
|
|
3397
|
+
rb_define_method(cEnv,"repmgr_ack_policy", env_repmgr_get_ack_policy, 0);
|
|
3398
|
+
rb_define_method(cEnv,"repmgr_start", env_repmgr_start, 2);
|
|
3399
|
+
rb_define_method(cEnv,"repmgr_stat_print", env_repmgr_stat_print, 1);
|
|
3400
|
+
|
|
3401
|
+
rb_define_method(cEnv,"lg_bsize=", env_set_lg_bsize, 1);
|
|
3402
|
+
rb_define_method(cEnv,"lg_bsize", env_get_lg_bsize, 0);
|
|
3403
|
+
rb_define_method(cEnv,"lg_max=", env_set_lg_max, 1);
|
|
3404
|
+
rb_define_method(cEnv,"lg_max", env_get_lg_max, 0);
|
|
3405
|
+
rb_define_method(cEnv,"lg_regionmax=", env_set_lg_regionmax, 1);
|
|
3406
|
+
rb_define_method(cEnv,"lg_regionmax", env_get_lg_regionmax, 0);
|
|
3407
|
+
|
|
3408
|
+
cTxnStat = rb_define_class_under(mBdb,"TxnStat",rb_cObject);
|
|
3409
|
+
rb_define_method(cTxnStat,"[]",stat_aref,1);
|
|
3410
|
+
|
|
3411
|
+
cTxnStatActive =
|
|
3412
|
+
rb_define_class_under(cTxnStat,"Active",rb_cObject);
|
|
3413
|
+
rb_define_method(cTxnStatActive,"[]",stat_aref,1);
|
|
3414
|
+
|
|
3415
|
+
cTxn = rb_define_class_under(mBdb,"Txn",rb_cObject);
|
|
3416
|
+
rb_define_method(cTxn,"commit",txn_commit,1);
|
|
3417
|
+
rb_define_method(cTxn,"abort",txn_abort,0);
|
|
3418
|
+
rb_define_method(cTxn,"discard",txn_discard,0);
|
|
3419
|
+
rb_define_method(cTxn,"tid",txn_id,0);
|
|
3420
|
+
rb_define_method(cTxn,"set_timeout",txn_set_timeout,2);
|
|
3421
|
+
}
|