ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/BDB/BDB.xs
(Generate patch)

Comparing BDB/BDB.xs (file contents):
Revision 1.4 by root, Mon Feb 5 22:31:05 2007 UTC vs.
Revision 1.13 by root, Sun Jul 8 11:12:12 2007 UTC

1/* solaris */ 1#include "xthread.h"
2#define _POSIX_PTHREAD_SEMANTICS 1
3
4#if __linux && !defined(_GNU_SOURCE)
5# define _GNU_SOURCE
6#endif
7
8/* just in case */
9#define _REENTRANT 1
10 2
11#include <errno.h> 3#include <errno.h>
12 4
13#include "EXTERN.h" 5#include "EXTERN.h"
14#include "perl.h" 6#include "perl.h"
15#include "XSUB.h" 7#include "XSUB.h"
16 8
17#include <pthread.h> 9// perl stupidly defines these as macros, breaking
10// lots and lots of code.
11#undef open
12#undef close
13#undef abort
14#undef malloc
15#undef free
16#undef send
18 17
19#include <stddef.h> 18#include <stddef.h>
20#include <stdlib.h> 19#include <stdlib.h>
21#include <errno.h> 20#include <errno.h>
22#include <sys/time.h>
23#include <sys/types.h> 21#include <sys/types.h>
24#include <limits.h> 22#include <limits.h>
25#include <unistd.h>
26#include <fcntl.h> 23#include <fcntl.h>
27 24
25#ifndef _WIN32
26# include <sys/time.h>
27# include <unistd.h>
28#endif
29
28#include <db.h> 30#include <db.h>
31
32#if DB_VERSION_MAJOR < 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR < 4)
33# error you need Berkeley DB 4.4 or newer installed
34#endif
29 35
30/* number of seconds after which idle threads exit */ 36/* number of seconds after which idle threads exit */
31#define IDLE_TIMEOUT 10 37#define IDLE_TIMEOUT 10
32 38
33/* wether word reads are potentially non-atomic. 39typedef DB_ENV DB_ENV_ornull;
34 * this is conservatice, likely most arches this runs 40typedef DB_TXN DB_TXN_ornull;
35 * on have atomic word read/writes. 41typedef DBC DBC_ornull;
36 */ 42typedef DB DB_ornull;
37#ifndef WORDACCESS_UNSAFE 43typedef DB_SEQUENCE DB_SEQUENCE_ornull;
38# if __i386 || __x86_64
39# define WORDACCESS_UNSAFE 0
40# else
41# define WORDACCESS_UNSAFE 1
42# endif
43#endif
44 44
45typedef SV SV8; /* byte-sv, used for argument-checking */ 45typedef SV SV8; /* byte-sv, used for argument-checking */
46typedef char *octetstring; 46typedef char *octetstring;
47 47
48static SV *prepare_cb; 48static SV *prepare_cb;
49 49
50static inline char * 50static char *
51strdup_ornull (const char *s) 51strdup_ornull (const char *s)
52{ 52{
53 return s ? strdup (s) : 0; 53 return s ? strdup (s) : 0;
54} 54}
55 55
56static void
57sv_to_dbt (DBT *dbt, SV *sv)
58{
59 STRLEN len;
60 char *data = SvPVbyte (sv, len);
61
62 dbt->data = malloc (len);
63 memcpy (dbt->data, data, len);
64 dbt->size = len;
65 dbt->flags = DB_DBT_REALLOC;
66}
67
68static void
69dbt_to_sv (SV *sv, DBT *dbt)
70{
71 if (sv)
72 {
73 SvREADONLY_off (sv);
74 sv_setpvn_mg (sv, dbt->data, dbt->size);
75 SvREFCNT_dec (sv);
76 }
77
78 free (dbt->data);
79}
80
56enum { 81enum {
57 REQ_QUIT, 82 REQ_QUIT,
58 REQ_ENV_OPEN, REQ_ENV_CLOSE, 83 REQ_ENV_OPEN, REQ_ENV_CLOSE, REQ_ENV_TXN_CHECKPOINT, REQ_ENV_LOCK_DETECT,
84 REQ_ENV_MEMP_SYNC, REQ_ENV_MEMP_TRICKLE,
59 REQ_DB_OPEN, REQ_DB_CLOSE, REQ_DB_COMPACT, REQ_DB_SYNC, REQ_DB_PUT, 85 REQ_DB_OPEN, REQ_DB_CLOSE, REQ_DB_COMPACT, REQ_DB_SYNC,
86 REQ_DB_PUT, REQ_DB_GET, REQ_DB_PGET, REQ_DB_DEL, REQ_DB_KEY_RANGE,
87 REQ_TXN_COMMIT, REQ_TXN_ABORT,
88 REQ_C_CLOSE, REQ_C_COUNT, REQ_C_PUT, REQ_C_GET, REQ_C_PGET, REQ_C_DEL,
89 REQ_SEQ_OPEN, REQ_SEQ_CLOSE, REQ_SEQ_GET, REQ_SEQ_REMOVE,
60}; 90};
61 91
62typedef struct aio_cb 92typedef struct aio_cb
63{ 93{
64 struct aio_cb *volatile next; 94 struct aio_cb *volatile next;
66 int type, pri, result; 96 int type, pri, result;
67 97
68 DB_ENV *env; 98 DB_ENV *env;
69 DB *db; 99 DB *db;
70 DB_TXN *txn; 100 DB_TXN *txn;
71 DBC *cursor; 101 DBC *dbc;
102
103 UV uv1;
72 int int1, int2; 104 int int1, int2;
73 U32 uint1, uint2; 105 U32 uint1, uint2;
74 char *buf1, *buf2; 106 char *buf1, *buf2;
107 SV *sv1, *sv2, *sv3;
75 108
76 DBT dbt1, dbt2, dbt3; 109 DBT dbt1, dbt2, dbt3;
110 DB_KEY_RANGE key_range;
111 DB_SEQUENCE *seq;
112 db_seq_t seq_t;
77} aio_cb; 113} aio_cb;
78 114
79typedef aio_cb *aio_req; 115typedef aio_cb *aio_req;
80 116
81enum { 117enum {
101 137
102static int next_pri = DEFAULT_PRI + PRI_BIAS; 138static int next_pri = DEFAULT_PRI + PRI_BIAS;
103 139
104static unsigned int started, idle, wanted; 140static unsigned int started, idle, wanted;
105 141
106#if __linux && defined (PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP)
107# define AIO_MUTEX_INIT PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
108#else
109# define AIO_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
110#endif
111
112#define LOCK(mutex) pthread_mutex_lock (&(mutex))
113#define UNLOCK(mutex) pthread_mutex_unlock (&(mutex))
114
115/* worker threads management */ 142/* worker threads management */
116static pthread_mutex_t wrklock = AIO_MUTEX_INIT; 143static mutex_t wrklock = X_MUTEX_INIT;
117 144
118typedef struct worker { 145typedef struct worker {
119 /* locked by wrklock */ 146 /* locked by wrklock */
120 struct worker *prev, *next; 147 struct worker *prev, *next;
121 148
122 pthread_t tid; 149 thread_t tid;
123 150
124 /* locked by reslock, reqlock or wrklock */ 151 /* locked by reslock, reqlock or wrklock */
125 aio_req req; /* currently processed request */ 152 aio_req req; /* currently processed request */
126 void *dbuf; 153 void *dbuf;
127 DIR *dirp; 154 DIR *dirp;
142} 169}
143 170
144static volatile unsigned int nreqs, nready, npending; 171static volatile unsigned int nreqs, nready, npending;
145static volatile unsigned int max_idle = 4; 172static volatile unsigned int max_idle = 4;
146static volatile unsigned int max_outstanding = 0xffffffff; 173static volatile unsigned int max_outstanding = 0xffffffff;
147static int respipe [2]; 174static int respipe [2], respipe_osf [2];
148 175
149static pthread_mutex_t reslock = AIO_MUTEX_INIT; 176static mutex_t reslock = X_MUTEX_INIT;
150static pthread_mutex_t reqlock = AIO_MUTEX_INIT; 177static mutex_t reqlock = X_MUTEX_INIT;
151static pthread_cond_t reqwait = PTHREAD_COND_INITIALIZER; 178static cond_t reqwait = X_COND_INIT;
152 179
153#if WORDACCESS_UNSAFE 180#if WORDACCESS_UNSAFE
154 181
155static unsigned int get_nready () 182static unsigned int get_nready ()
156{ 183{
157 unsigned int retval; 184 unsigned int retval;
158 185
159 LOCK (reqlock); 186 X_LOCK (reqlock);
160 retval = nready; 187 retval = nready;
161 UNLOCK (reqlock); 188 X_UNLOCK (reqlock);
162 189
163 return retval; 190 return retval;
164} 191}
165 192
166static unsigned int get_npending () 193static unsigned int get_npending ()
167{ 194{
168 unsigned int retval; 195 unsigned int retval;
169 196
170 LOCK (reslock); 197 X_LOCK (reslock);
171 retval = npending; 198 retval = npending;
172 UNLOCK (reslock); 199 X_UNLOCK (reslock);
173 200
174 return retval; 201 return retval;
175} 202}
176 203
177static unsigned int get_nthreads () 204static unsigned int get_nthreads ()
178{ 205{
179 unsigned int retval; 206 unsigned int retval;
180 207
181 LOCK (wrklock); 208 X_LOCK (wrklock);
182 retval = started; 209 retval = started;
183 UNLOCK (wrklock); 210 X_UNLOCK (wrklock);
184 211
185 return retval; 212 return retval;
186} 213}
187 214
188#else 215#else
258 if (SvOK (req->callback)) 285 if (SvOK (req->callback))
259 { 286 {
260 ENTER; 287 ENTER;
261 SAVETMPS; 288 SAVETMPS;
262 PUSHMARK (SP); 289 PUSHMARK (SP);
263 EXTEND (SP, 1);
264 290
265 switch (req->type) 291 switch (req->type)
266 { 292 {
293 case REQ_DB_CLOSE:
294 SvREFCNT_dec (req->sv1);
295 break;
296
297 case REQ_DB_GET:
298 case REQ_DB_PGET:
299 dbt_to_sv (req->sv3, &req->dbt3);
300 break;
301
302 case REQ_C_GET:
303 case REQ_C_PGET:
304 dbt_to_sv (req->sv1, &req->dbt1);
305 dbt_to_sv (req->sv2, &req->dbt2);
306 dbt_to_sv (req->sv3, &req->dbt3);
307 break;
308
309 case REQ_DB_KEY_RANGE:
310 {
311 AV *av = newAV ();
312
313 av_push (av, newSVnv (req->key_range.less));
314 av_push (av, newSVnv (req->key_range.equal));
315 av_push (av, newSVnv (req->key_range.greater));
316
317 SvREADONLY_off (req->sv1);
318 sv_setsv_mg (req->sv1, newRV_noinc ((SV *)av));
319 SvREFCNT_dec (req->sv1);
320 }
321 break;
322
323 case REQ_SEQ_GET:
324 SvREADONLY_off (req->sv1);
325
326 if (sizeof (IV) > 4)
327 sv_setiv_mg (req->sv1, req->seq_t);
328 else
329 sv_setnv_mg (req->sv1, req->seq_t);
330
331 SvREFCNT_dec (req->sv1);
332 break;
267 } 333 }
268 334
269 errno = req->result; 335 errno = req->result;
270 336
271 PUTBACK; 337 PUTBACK;
284 free (req->buf1); 350 free (req->buf1);
285 free (req->buf2); 351 free (req->buf2);
286 Safefree (req); 352 Safefree (req);
287} 353}
288 354
289static void *aio_proc (void *arg); 355#ifdef USE_SOCKETS_AS_HANDLES
356# define TO_SOCKET(x) (win32_get_osfhandle (x))
357#else
358# define TO_SOCKET(x) (x)
359#endif
360
361static void
362create_pipe (int fd[2])
363{
364#ifdef _WIN32
365 int arg = 1;
366 if (PerlSock_socketpair (AF_UNIX, SOCK_STREAM, 0, fd)
367 || ioctlsocket (TO_SOCKET (fd [0]), FIONBIO, &arg)
368 || ioctlsocket (TO_SOCKET (fd [1]), FIONBIO, &arg))
369#else
370 if (pipe (fd)
371 || fcntl (fd [0], F_SETFL, O_NONBLOCK)
372 || fcntl (fd [1], F_SETFL, O_NONBLOCK))
373#endif
374 croak ("unable to initialize result pipe");
375
376 respipe_osf [0] = TO_SOCKET (respipe [0]);
377 respipe_osf [1] = TO_SOCKET (respipe [1]);
378}
379
380X_THREAD_PROC (bdb_proc);
290 381
291static void start_thread (void) 382static void start_thread (void)
292{ 383{
293 sigset_t fullsigset, oldsigset;
294 pthread_attr_t attr;
295
296 worker *wrk = calloc (1, sizeof (worker)); 384 worker *wrk = calloc (1, sizeof (worker));
297 385
298 if (!wrk) 386 if (!wrk)
299 croak ("unable to allocate worker thread data"); 387 croak ("unable to allocate worker thread data");
300 388
301 pthread_attr_init (&attr);
302 pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
303#ifdef PTHREAD_SCOPE_PROCESS
304 pthread_attr_setscope (&attr, PTHREAD_SCOPE_PROCESS);
305#endif
306
307 sigfillset (&fullsigset);
308
309 LOCK (wrklock); 389 X_LOCK (wrklock);
310 pthread_sigmask (SIG_SETMASK, &fullsigset, &oldsigset);
311
312 if (pthread_create (&wrk->tid, &attr, aio_proc, (void *)wrk) == 0) 390 if (thread_create (&wrk->tid, bdb_proc, (void *)wrk))
313 { 391 {
314 wrk->prev = &wrk_first; 392 wrk->prev = &wrk_first;
315 wrk->next = wrk_first.next; 393 wrk->next = wrk_first.next;
316 wrk_first.next->prev = wrk; 394 wrk_first.next->prev = wrk;
317 wrk_first.next = wrk; 395 wrk_first.next = wrk;
318 ++started; 396 ++started;
319 } 397 }
320 else 398 else
321 free (wrk); 399 free (wrk);
322 400
323 pthread_sigmask (SIG_SETMASK, &oldsigset, 0);
324 UNLOCK (wrklock); 401 X_UNLOCK (wrklock);
325} 402}
326 403
327static void maybe_start_thread () 404static void maybe_start_thread ()
328{ 405{
329 if (get_nthreads () >= wanted) 406 if (get_nthreads () >= wanted)
341 SV *wait_callback = 0; 418 SV *wait_callback = 0;
342 419
343 // synthesize callback if none given 420 // synthesize callback if none given
344 if (!SvOK (req->callback)) 421 if (!SvOK (req->callback))
345 { 422 {
423 int count;
424
346 dSP; 425 dSP;
347 PUSHMARK (SP); 426 PUSHMARK (SP);
348 PUTBACK; 427 PUTBACK;
349 int count = call_sv (prepare_cb, G_ARRAY); 428 count = call_sv (prepare_cb, G_ARRAY);
350 SPAGAIN; 429 SPAGAIN;
351 430
352 if (count != 2) 431 if (count != 2)
353 croak ("prepare callback must return exactly two values\n"); 432 croak ("prepare callback must return exactly two values\n");
354 433
357 req->callback = SvREFCNT_inc (POPs); 436 req->callback = SvREFCNT_inc (POPs);
358 } 437 }
359 438
360 ++nreqs; 439 ++nreqs;
361 440
362 LOCK (reqlock); 441 X_LOCK (reqlock);
363 ++nready; 442 ++nready;
364 reqq_push (&req_queue, req); 443 reqq_push (&req_queue, req);
365 pthread_cond_signal (&reqwait); 444 X_COND_SIGNAL (reqwait);
366 UNLOCK (reqlock); 445 X_UNLOCK (reqlock);
367 446
368 maybe_start_thread (); 447 maybe_start_thread ();
369 448
370 if (wait_callback) 449 if (wait_callback)
371 { 450 {
384 Newz (0, req, 1, aio_cb); 463 Newz (0, req, 1, aio_cb);
385 464
386 req->type = REQ_QUIT; 465 req->type = REQ_QUIT;
387 req->pri = PRI_MAX + PRI_BIAS; 466 req->pri = PRI_MAX + PRI_BIAS;
388 467
389 LOCK (reqlock); 468 X_LOCK (reqlock);
390 reqq_push (&req_queue, req); 469 reqq_push (&req_queue, req);
391 pthread_cond_signal (&reqwait); 470 X_COND_SIGNAL (reqwait);
392 UNLOCK (reqlock); 471 X_UNLOCK (reqlock);
393 472
394 LOCK (wrklock); 473 X_LOCK (wrklock);
395 --started; 474 --started;
396 UNLOCK (wrklock); 475 X_UNLOCK (wrklock);
397} 476}
398 477
399static void set_max_idle (int nthreads) 478static void set_max_idle (int nthreads)
400{ 479{
401 if (WORDACCESS_UNSAFE) LOCK (reqlock); 480 if (WORDACCESS_UNSAFE) X_LOCK (reqlock);
402 max_idle = nthreads <= 0 ? 1 : nthreads; 481 max_idle = nthreads <= 0 ? 1 : nthreads;
403 if (WORDACCESS_UNSAFE) UNLOCK (reqlock); 482 if (WORDACCESS_UNSAFE) X_UNLOCK (reqlock);
404} 483}
405 484
406static void min_parallel (int nthreads) 485static void min_parallel (int nthreads)
407{ 486{
408 if (wanted < nthreads) 487 if (wanted < nthreads)
423 fd_set rfd; 502 fd_set rfd;
424 503
425 while (nreqs) 504 while (nreqs)
426 { 505 {
427 int size; 506 int size;
428 if (WORDACCESS_UNSAFE) LOCK (reslock); 507 if (WORDACCESS_UNSAFE) X_LOCK (reslock);
429 size = res_queue.size; 508 size = res_queue.size;
430 if (WORDACCESS_UNSAFE) UNLOCK (reslock); 509 if (WORDACCESS_UNSAFE) X_UNLOCK (reslock);
431 510
432 if (size) 511 if (size)
433 return; 512 return;
434 513
435 maybe_start_thread (); 514 maybe_start_thread ();
436 515
437 FD_ZERO(&rfd); 516 FD_ZERO (&rfd);
438 FD_SET(respipe [0], &rfd); 517 FD_SET (respipe [0], &rfd);
439 518
440 select (respipe [0] + 1, &rfd, 0, 0, 0); 519 PerlSock_select (respipe [0] + 1, &rfd, 0, 0, 0);
441 } 520 }
442} 521}
443 522
444static int poll_cb () 523static int poll_cb ()
445{ 524{
457 { 536 {
458 for (;;) 537 for (;;)
459 { 538 {
460 maybe_start_thread (); 539 maybe_start_thread ();
461 540
462 LOCK (reslock); 541 X_LOCK (reslock);
463 req = reqq_shift (&res_queue); 542 req = reqq_shift (&res_queue);
464 543
465 if (req) 544 if (req)
466 { 545 {
467 --npending; 546 --npending;
468 547
469 if (!res_queue.size) 548 if (!res_queue.size)
470 { 549 {
471 /* read any signals sent by the worker threads */ 550 /* read any signals sent by the worker threads */
472 char buf [4]; 551 char buf [4];
473 while (read (respipe [0], buf, 4) == 4) 552 while (respipe_read (respipe [0], buf, 4) == 4)
474 ; 553 ;
475 } 554 }
476 } 555 }
477 556
478 UNLOCK (reslock); 557 X_UNLOCK (reslock);
479 558
480 if (!req) 559 if (!req)
481 break; 560 break;
482 561
483 --nreqs; 562 --nreqs;
513 } 592 }
514 593
515 return count; 594 return count;
516} 595}
517 596
518static void create_pipe ()
519{
520 if (pipe (respipe))
521 croak ("unable to initialize result pipe");
522
523 if (fcntl (respipe [0], F_SETFL, O_NONBLOCK))
524 croak ("cannot set result pipe to nonblocking mode");
525
526 if (fcntl (respipe [1], F_SETFL, O_NONBLOCK))
527 croak ("cannot set result pipe to nonblocking mode");
528}
529
530/*****************************************************************************/ 597/*****************************************************************************/
531 598
532static void *aio_proc (void *thr_arg) 599X_THREAD_PROC (bdb_proc)
533{ 600{
534 aio_req req; 601 aio_req req;
535 struct timespec ts; 602 struct timespec ts;
536 worker *self = (worker *)thr_arg; 603 worker *self = (worker *)thr_arg;
537 604
538 /* try to distribute timeouts somewhat evenly */ 605 /* try to distribute timeouts somewhat evenly */
539 ts.tv_nsec = (((unsigned long)self + (unsigned long)ts.tv_sec) & 1023UL) 606 ts.tv_nsec = ((unsigned long)self & 1023UL) * (1000000000UL / 1024UL);
540 * (1000000000UL / 1024UL);
541 607
542 for (;;) 608 for (;;)
543 { 609 {
544 ts.tv_sec = time (0) + IDLE_TIMEOUT; 610 ts.tv_sec = time (0) + IDLE_TIMEOUT;
545 611
546 LOCK (reqlock); 612 X_LOCK (reqlock);
547 613
548 for (;;) 614 for (;;)
549 { 615 {
550 self->req = req = reqq_shift (&req_queue); 616 self->req = req = reqq_shift (&req_queue);
551 617
552 if (req) 618 if (req)
553 break; 619 break;
554 620
555 ++idle; 621 ++idle;
556 622
557 if (pthread_cond_timedwait (&reqwait, &reqlock, &ts) 623 if (X_COND_TIMEDWAIT (reqwait, reqlock, ts)
558 == ETIMEDOUT) 624 == ETIMEDOUT)
559 { 625 {
560 if (idle > max_idle) 626 if (idle > max_idle)
561 { 627 {
562 --idle; 628 --idle;
563 UNLOCK (reqlock); 629 X_UNLOCK (reqlock);
564 LOCK (wrklock); 630 X_LOCK (wrklock);
565 --started; 631 --started;
566 UNLOCK (wrklock); 632 X_UNLOCK (wrklock);
567 goto quit; 633 goto quit;
568 } 634 }
569 635
570 /* we are allowed to idle, so do so without any timeout */ 636 /* we are allowed to idle, so do so without any timeout */
571 pthread_cond_wait (&reqwait, &reqlock); 637 X_COND_WAIT (reqwait, reqlock);
572 ts.tv_sec = time (0) + IDLE_TIMEOUT; 638 ts.tv_sec = time (0) + IDLE_TIMEOUT;
573 } 639 }
574 640
575 --idle; 641 --idle;
576 } 642 }
577 643
578 --nready; 644 --nready;
579 645
580 UNLOCK (reqlock); 646 X_UNLOCK (reqlock);
581 647
582 switch (req->type) 648 switch (req->type)
583 { 649 {
584 case REQ_QUIT: 650 case REQ_QUIT:
585 goto quit; 651 goto quit;
590 656
591 case REQ_ENV_CLOSE: 657 case REQ_ENV_CLOSE:
592 req->result = req->env->close (req->env, req->uint1); 658 req->result = req->env->close (req->env, req->uint1);
593 break; 659 break;
594 660
661 case REQ_ENV_TXN_CHECKPOINT:
662 req->result = req->env->txn_checkpoint (req->env, req->uint1, req->int1, req->uint2);
663 break;
664
665 case REQ_ENV_LOCK_DETECT:
666 req->result = req->env->lock_detect (req->env, req->uint1, req->uint2, &req->int1);
667 break;
668
669 case REQ_ENV_MEMP_SYNC:
670 req->result = req->env->memp_sync (req->env, 0);
671 break;
672
673 case REQ_ENV_MEMP_TRICKLE:
674 req->result = req->env->memp_trickle (req->env, req->int1, &req->int2);
675 break;
676
595 case REQ_DB_OPEN: 677 case REQ_DB_OPEN:
596 req->result = req->db->open (req->db, req->txn, req->buf1, req->buf2, req->int1, req->uint1, req->int2); 678 req->result = req->db->open (req->db, req->txn, req->buf1, req->buf2, req->int1, req->uint1, req->int2);
597 break; 679 break;
598 680
599 case REQ_DB_CLOSE: 681 case REQ_DB_CLOSE:
610 692
611 case REQ_DB_PUT: 693 case REQ_DB_PUT:
612 req->result = req->db->put (req->db, req->txn, &req->dbt1, &req->dbt2, req->uint1); 694 req->result = req->db->put (req->db, req->txn, &req->dbt1, &req->dbt2, req->uint1);
613 break; 695 break;
614 696
697 case REQ_DB_GET:
698 req->result = req->db->get (req->db, req->txn, &req->dbt1, &req->dbt3, req->uint1);
699 break;
700
701 case REQ_DB_PGET:
702 req->result = req->db->pget (req->db, req->txn, &req->dbt1, &req->dbt2, &req->dbt3, req->uint1);
703 break;
704
705 case REQ_DB_DEL:
706 req->result = req->db->del (req->db, req->txn, &req->dbt1, req->uint1);
707 break;
708
709 case REQ_DB_KEY_RANGE:
710 req->result = req->db->key_range (req->db, req->txn, &req->dbt1, &req->key_range, req->uint1);
711 break;
712
713 case REQ_TXN_COMMIT:
714 req->result = req->txn->commit (req->txn, req->uint1);
715 break;
716
717 case REQ_TXN_ABORT:
718 req->result = req->txn->abort (req->txn);
719 break;
720
721 case REQ_C_CLOSE:
722 req->result = req->dbc->c_close (req->dbc);
723 break;
724
725 case REQ_C_COUNT:
726 {
727 db_recno_t recno;
728 req->result = req->dbc->c_count (req->dbc, &recno, req->uint1);
729 req->uv1 = recno;
730 }
731 break;
732
733 case REQ_C_PUT:
734 req->result = req->dbc->c_put (req->dbc, &req->dbt1, &req->dbt2, req->uint1);
735 break;
736
737 case REQ_C_GET:
738 req->result = req->dbc->c_get (req->dbc, &req->dbt1, &req->dbt3, req->uint1);
739 break;
740
741 case REQ_C_PGET:
742 req->result = req->dbc->c_pget (req->dbc, &req->dbt1, &req->dbt2, &req->dbt3, req->uint1);
743 break;
744
745 case REQ_C_DEL:
746 req->result = req->dbc->c_del (req->dbc, req->uint1);
747 break;
748
749 case REQ_SEQ_OPEN:
750 req->result = req->seq->open (req->seq, req->txn, &req->dbt1, req->uint1);
751 break;
752
753 case REQ_SEQ_CLOSE:
754 req->result = req->seq->close (req->seq, req->uint1);
755 break;
756
757 case REQ_SEQ_GET:
758 req->result = req->seq->get (req->seq, req->txn, req->int1, &req->seq_t, req->uint1);
759 break;
760
761 case REQ_SEQ_REMOVE:
762 req->result = req->seq->remove (req->seq, req->txn, req->uint1);
763 break;
764
615 default: 765 default:
616 req->result = ENOSYS; 766 req->result = ENOSYS;
617 break; 767 break;
618 } 768 }
619 769
620 LOCK (reslock); 770 X_LOCK (reslock);
621 771
622 ++npending; 772 ++npending;
623 773
624 if (!reqq_push (&res_queue, req)) 774 if (!reqq_push (&res_queue, req))
625 /* write a dummy byte to the pipe so fh becomes ready */ 775 /* write a dummy byte to the pipe so fh becomes ready */
626 write (respipe [1], &respipe, 1); 776 respipe_write (respipe_osf [1], (const void *)&respipe_osf, 1);
627 777
628 self->req = 0; 778 self->req = 0;
629 worker_clear (self); 779 worker_clear (self);
630 780
631 UNLOCK (reslock); 781 X_UNLOCK (reslock);
632 } 782 }
633 783
634quit: 784quit:
635 LOCK (wrklock); 785 X_LOCK (wrklock);
636 worker_free (self); 786 worker_free (self);
637 UNLOCK (wrklock); 787 X_UNLOCK (wrklock);
638 788
639 return 0; 789 return 0;
640} 790}
641 791
642/*****************************************************************************/ 792/*****************************************************************************/
643 793
644static void atfork_prepare (void) 794static void atfork_prepare (void)
645{ 795{
646 LOCK (wrklock); 796 X_LOCK (wrklock);
647 LOCK (reqlock); 797 X_LOCK (reqlock);
648 LOCK (reslock); 798 X_LOCK (reslock);
649} 799}
650 800
651static void atfork_parent (void) 801static void atfork_parent (void)
652{ 802{
653 UNLOCK (reslock); 803 X_UNLOCK (reslock);
654 UNLOCK (reqlock); 804 X_UNLOCK (reqlock);
655 UNLOCK (wrklock); 805 X_UNLOCK (wrklock);
656} 806}
657 807
658static void atfork_child (void) 808static void atfork_child (void)
659{ 809{
660 aio_req prv; 810 aio_req prv;
680 idle = 0; 830 idle = 0;
681 nreqs = 0; 831 nreqs = 0;
682 nready = 0; 832 nready = 0;
683 npending = 0; 833 npending = 0;
684 834
685 close (respipe [0]); 835 respipe_close (respipe [0]);
686 close (respipe [1]); 836 respipe_close (respipe [1]);
837
687 create_pipe (); 838 create_pipe (respipe);
688 839
689 atfork_parent (); 840 atfork_parent ();
690} 841}
691 842
692#define dREQ(reqtype) \ 843#define dREQ(reqtype) \
706 req->pri = req_pri 857 req->pri = req_pri
707 858
708#define REQ_SEND \ 859#define REQ_SEND \
709 req_send (req) 860 req_send (req)
710 861
711#define SvPTR(var, arg, type, class) \ 862#define SvPTR(var, arg, type, class, nullok) \
712 if (!SvOK (arg)) \ 863 if (!SvOK (arg)) \
864 { \
865 if (!nullok) \
866 croak (# var " must be a " # class " object, not undef"); \
867 \
713 (var) = 0; \ 868 (var) = 0; \
869 } \
714 else if (sv_derived_from ((arg), # class)) \ 870 else if (sv_derived_from ((arg), # class)) \
715 { \ 871 { \
716 IV tmp = SvIV ((SV*) SvRV (arg)); \ 872 IV tmp = SvIV ((SV*) SvRV (arg)); \
717 (var) = INT2PTR (type, tmp); \ 873 (var) = INT2PTR (type, tmp); \
874 if (!var) \
875 croak (# var " is not a valid " # class " object anymore"); \
718 } \ 876 } \
719 else \ 877 else \
720 Perl_croak (# var " is not of type " # class) 878 croak (# var " is not of type " # class); \
879 \
721 880
722inline void 881static void
723set_dbt (DBT *dbt, SV *sv) 882ptr_nuke (SV *sv)
724{ 883{
725 STRLEN len; 884 assert (SvROK (sv));
726 char *data = SvPVbyte (sv, len); 885 sv_setiv (SvRV (sv), 0);
727
728 dbt->data = malloc (len);
729 memcpy (dbt->data, data, len);
730 dbt->size = len;
731} 886}
732 887
733MODULE = BDB PACKAGE = BDB 888MODULE = BDB PACKAGE = BDB
734 889
735PROTOTYPES: ENABLE 890PROTOTYPES: ENABLE
736 891
737BOOT: 892BOOT:
767 const_iv (DSYNC_DB) 922 const_iv (DSYNC_DB)
768 const_iv (DSYNC_LOG) 923 const_iv (DSYNC_LOG)
769 const_iv (LOG_AUTOREMOVE) 924 const_iv (LOG_AUTOREMOVE)
770 const_iv (LOG_INMEMORY) 925 const_iv (LOG_INMEMORY)
771 const_iv (NOLOCKING) 926 const_iv (NOLOCKING)
772 const_iv (MULTIVERSION)
773 const_iv (NOMMAP) 927 const_iv (NOMMAP)
774 const_iv (NOPANIC) 928 const_iv (NOPANIC)
775 const_iv (OVERWRITE) 929 const_iv (OVERWRITE)
776 const_iv (PANIC_ENVIRONMENT) 930 const_iv (PANIC_ENVIRONMENT)
777 const_iv (REGION_INIT) 931 const_iv (REGION_INIT)
778 const_iv (TIME_NOTGRANTED) 932 const_iv (TIME_NOTGRANTED)
779 const_iv (TXN_NOSYNC) 933 const_iv (TXN_NOSYNC)
780 const_iv (TXN_SNAPSHOT)
781 const_iv (TXN_WRITE_NOSYNC) 934 const_iv (TXN_WRITE_NOSYNC)
935 const_iv (WRITECURSOR)
782 const_iv (YIELDCPU) 936 const_iv (YIELDCPU)
783 const_iv (ENCRYPT_AES) 937 const_iv (ENCRYPT_AES)
784 const_iv (XA_CREATE) 938 const_iv (XA_CREATE)
785 const_iv (BTREE) 939 const_iv (BTREE)
786 const_iv (HASH) 940 const_iv (HASH)
801 const_iv (RENUMBER) 955 const_iv (RENUMBER)
802 const_iv (REVSPLITOFF) 956 const_iv (REVSPLITOFF)
803 const_iv (INORDER) 957 const_iv (INORDER)
804 const_iv (CONSUME) 958 const_iv (CONSUME)
805 const_iv (CONSUME_WAIT) 959 const_iv (CONSUME_WAIT)
960 const_iv (GET_BOTH)
961 const_iv (GET_BOTH_RANGE)
962 //const_iv (SET_RECNO)
963 //const_iv (MULTIPLE)
806 const_iv (SNAPSHOT) 964 const_iv (SNAPSHOT)
807 const_iv (JOIN_ITEM) 965 const_iv (JOIN_ITEM)
808 const_iv (RMW) 966 const_iv (RMW)
809 967
810 const_iv (NOTFOUND) 968 const_iv (NOTFOUND)
813 const_iv (LOCK_NOTGRANTED) 971 const_iv (LOCK_NOTGRANTED)
814 const_iv (RUNRECOVERY) 972 const_iv (RUNRECOVERY)
815 const_iv (OLD_VERSION) 973 const_iv (OLD_VERSION)
816 const_iv (REP_HANDLE_DEAD) 974 const_iv (REP_HANDLE_DEAD)
817 const_iv (REP_LOCKOUT) 975 const_iv (REP_LOCKOUT)
976 const_iv (SECONDARY_BAD)
818 977
819 const_iv (FREE_SPACE) 978 const_iv (FREE_SPACE)
820 const_iv (FREELIST_ONLY) 979 const_iv (FREELIST_ONLY)
821 980
822 const_iv (APPEND) 981 const_iv (APPEND)
823 const_iv (NODUPDATA) 982 const_iv (NODUPDATA)
824 const_iv (NOOVERWRITE) 983 const_iv (NOOVERWRITE)
825 984
826 const_iv (TXN_NOWAIT) 985 const_iv (TXN_NOWAIT)
827 const_iv (TXN_SNAPSHOT)
828 const_iv (TXN_SYNC) 986 const_iv (TXN_SYNC)
829 987
830 const_iv (SET_LOCK_TIMEOUT) 988 const_iv (SET_LOCK_TIMEOUT)
831 const_iv (SET_TXN_TIMEOUT) 989 const_iv (SET_TXN_TIMEOUT)
990
991 const_iv (JOIN_ITEM)
992 const_iv (FIRST)
993 const_iv (NEXT)
994 const_iv (NEXT_DUP)
995 const_iv (NEXT_NODUP)
996 const_iv (PREV)
997 const_iv (PREV_NODUP)
998 const_iv (SET)
999 const_iv (SET_RANGE)
1000 const_iv (LAST)
1001 const_iv (BEFORE)
1002 const_iv (AFTER)
1003 const_iv (CURRENT)
1004 const_iv (KEYFIRST)
1005 const_iv (KEYLAST)
1006 const_iv (NODUPDATA)
1007
1008 const_iv (FORCE)
1009
1010 const_iv (LOCK_DEFAULT)
1011 const_iv (LOCK_EXPIRE)
1012 const_iv (LOCK_MAXLOCKS)
1013 const_iv (LOCK_MAXWRITE)
1014 const_iv (LOCK_MINLOCKS)
1015 const_iv (LOCK_MINWRITE)
1016 const_iv (LOCK_OLDEST)
1017 const_iv (LOCK_RANDOM)
1018 const_iv (LOCK_YOUNGEST)
1019
1020 const_iv (SEQ_DEC)
1021 const_iv (SEQ_INC)
1022 const_iv (SEQ_WRAP)
1023#if DB_VERSION_MINOR >= 5
1024 const_iv (MULTIVERSION)
1025 const_iv (TXN_SNAPSHOT)
1026#endif
832 }; 1027 };
833 1028
834 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; ) 1029 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
835 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv)); 1030 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
836 1031
837 create_pipe (); 1032 create_pipe (respipe);
1033
838 pthread_atfork (atfork_prepare, atfork_parent, atfork_child); 1034 X_THREAD_ATFORK (atfork_prepare, atfork_parent, atfork_child);
1035#ifdef _WIN32
1036 X_MUTEX_CHECK (wrklock);
1037 X_MUTEX_CHECK (reslock);
1038 X_MUTEX_CHECK (reqlock);
1039
1040 X_COND_CHECK (reqwait);
1041#endif
839} 1042}
840 1043
841void 1044void
842max_poll_reqs (int nreqs) 1045max_poll_reqs (int nreqs)
843 PROTOTYPE: $ 1046 PROTOTYPE: $
962 1165
963int 1166int
964nthreads () 1167nthreads ()
965 PROTOTYPE: 1168 PROTOTYPE:
966 CODE: 1169 CODE:
967 if (WORDACCESS_UNSAFE) LOCK (wrklock); 1170 if (WORDACCESS_UNSAFE) X_LOCK (wrklock);
968 RETVAL = started; 1171 RETVAL = started;
969 if (WORDACCESS_UNSAFE) UNLOCK (wrklock); 1172 if (WORDACCESS_UNSAFE) X_UNLOCK (wrklock);
970 OUTPUT: 1173 OUTPUT:
971 RETVAL 1174 RETVAL
972 1175
973void 1176void
974set_sync_prepare (SV *cb) 1177set_sync_prepare (SV *cb)
975 PROTOTYPE: & 1178 PROTOTYPE: &
976 CODE: 1179 CODE:
977 SvREFCNT_dec (prepare_cb); 1180 SvREFCNT_dec (prepare_cb);
978 prepare_cb = newSVsv (cb); 1181 prepare_cb = newSVsv (cb);
1182
979 1183
980DB_ENV * 1184DB_ENV *
981db_env_create (U32 env_flags = 0) 1185db_env_create (U32 env_flags = 0)
982 CODE: 1186 CODE:
983{ 1187{
991void 1195void
992db_env_open (DB_ENV *env, octetstring db_home, U32 open_flags, int mode, SV *callback = &PL_sv_undef) 1196db_env_open (DB_ENV *env, octetstring db_home, U32 open_flags, int mode, SV *callback = &PL_sv_undef)
993 CODE: 1197 CODE:
994{ 1198{
995 dREQ (REQ_ENV_OPEN); 1199 dREQ (REQ_ENV_OPEN);
1200
1201 env->set_thread_count (env, get_nthreads ());
1202
996 req->env = env; 1203 req->env = env;
997 req->uint1 = open_flags | DB_THREAD; 1204 req->uint1 = open_flags | DB_THREAD;
998 req->int1 = mode; 1205 req->int1 = mode;
999 req->buf1 = strdup_ornull (db_home); 1206 req->buf1 = strdup_ornull (db_home);
1000 REQ_SEND; 1207 REQ_SEND;
1006{ 1213{
1007 dREQ (REQ_ENV_CLOSE); 1214 dREQ (REQ_ENV_CLOSE);
1008 req->env = env; 1215 req->env = env;
1009 req->uint1 = flags; 1216 req->uint1 = flags;
1010 REQ_SEND; 1217 REQ_SEND;
1218 ptr_nuke (ST (0));
1011} 1219}
1220
1221void
1222db_env_txn_checkpoint (DB_ENV *env, U32 kbyte = 0, U32 min = 0, U32 flags = 0, SV *callback = &PL_sv_undef)
1223 CODE:
1224{
1225 dREQ (REQ_ENV_TXN_CHECKPOINT);
1226 req->env = env;
1227 req->uint1 = kbyte;
1228 req->int1 = min;
1229 req->uint2 = flags;
1230 REQ_SEND;
1231}
1232
1233void
1234db_env_lock_detect (DB_ENV *env, U32 flags = 0, U32 atype = DB_LOCK_DEFAULT, SV *dummy = 0, SV *callback = &PL_sv_undef)
1235 CODE:
1236{
1237 dREQ (REQ_ENV_LOCK_DETECT);
1238 req->env = env;
1239 req->uint1 = flags;
1240 req->uint2 = atype;
1241 REQ_SEND;
1242}
1243
1244void
1245db_env_memp_sync (DB_ENV *env, SV *dummy = 0, SV *callback = &PL_sv_undef)
1246 CODE:
1247{
1248 dREQ (REQ_ENV_MEMP_SYNC);
1249 req->env = env;
1250 REQ_SEND;
1251}
1252
1253void
1254db_env_memp_trickle (DB_ENV *env, int percent, SV *dummy = 0, SV *callback = &PL_sv_undef)
1255 CODE:
1256{
1257 dREQ (REQ_ENV_MEMP_TRICKLE);
1258 req->env = env;
1259 req->int1 = percent;
1260 REQ_SEND;
1261}
1262
1012 1263
1013DB * 1264DB *
1014db_create (DB_ENV *env = 0, U32 flags = 0) 1265db_create (DB_ENV *env = 0, U32 flags = 0)
1015 CODE: 1266 CODE:
1016{ 1267{
1017 errno = db_create (&RETVAL, env, flags); 1268 errno = db_create (&RETVAL, env, flags);
1018 if (errno) 1269 if (errno)
1019 croak ("db_env_create: %s", db_strerror (errno)); 1270 croak ("db_create: %s", db_strerror (errno));
1271
1272 if (RETVAL)
1273 RETVAL->app_private = (void *)newSVsv (ST (0));
1020} 1274}
1021 OUTPUT: 1275 OUTPUT:
1022 RETVAL 1276 RETVAL
1023 1277
1024void 1278void
1025db_open (DB *db, DB_TXN *txnid, octetstring file, octetstring database, int type, U32 flags, int mode, SV *callback = &PL_sv_undef) 1279db_open (DB *db, DB_TXN_ornull *txnid, octetstring file, octetstring database, int type, U32 flags, int mode, SV *callback = &PL_sv_undef)
1026 CODE: 1280 CODE:
1027{ 1281{
1028 dREQ (REQ_DB_OPEN); 1282 dREQ (REQ_DB_OPEN);
1029 req->db = db; 1283 req->db = db;
1030 req->txn = txnid; 1284 req->txn = txnid;
1041 CODE: 1295 CODE:
1042{ 1296{
1043 dREQ (REQ_DB_CLOSE); 1297 dREQ (REQ_DB_CLOSE);
1044 req->db = db; 1298 req->db = db;
1045 req->uint1 = flags; 1299 req->uint1 = flags;
1300 req->sv1 = (SV *)db->app_private;
1046 REQ_SEND; 1301 REQ_SEND;
1302 ptr_nuke (ST (0));
1047} 1303}
1048 1304
1049void 1305void
1050db_compact (DB *db, DB_TXN *txn = 0, SV *start = 0, SV *stop = 0, SV *unused1 = 0, U32 flags = DB_FREE_SPACE, SV *unused2 = 0, SV *callback = &PL_sv_undef) 1306db_compact (DB *db, DB_TXN_ornull *txn = 0, SV *start = 0, SV *stop = 0, SV *unused1 = 0, U32 flags = DB_FREE_SPACE, SV *unused2 = 0, SV *callback = &PL_sv_undef)
1051 CODE: 1307 CODE:
1052{ 1308{
1053 dREQ (REQ_DB_COMPACT); 1309 dREQ (REQ_DB_COMPACT);
1054 req->db = db; 1310 req->db = db;
1055 req->txn = txn; 1311 req->txn = txn;
1056 set_dbt (&req->dbt1, start); 1312 sv_to_dbt (&req->dbt1, start);
1057 set_dbt (&req->dbt2, stop); 1313 sv_to_dbt (&req->dbt2, stop);
1058 req->uint1 = flags; 1314 req->uint1 = flags;
1059 REQ_SEND; 1315 REQ_SEND;
1060} 1316}
1061 1317
1062void 1318void
1068 req->uint1 = flags; 1324 req->uint1 = flags;
1069 REQ_SEND; 1325 REQ_SEND;
1070} 1326}
1071 1327
1072void 1328void
1329db_key_range (DB *db, DB_TXN_ornull *txn, SV *key, SV *key_range, U32 flags = 0, SV *callback = &PL_sv_undef)
1330 CODE:
1331{
1332 dREQ (REQ_DB_KEY_RANGE);
1333 req->db = db;
1334 req->txn = txn;
1335 sv_to_dbt (&req->dbt1, key);
1336 req->uint1 = flags;
1337 req->sv1 = SvREFCNT_inc (key_range); SvREADONLY_on (key_range);
1338 REQ_SEND;
1339}
1340
1341void
1073db_put (DB *db, DB_TXN *txn, SV *key, SV *data, U32 flags = 0, SV *callback = &PL_sv_undef) 1342db_put (DB *db, DB_TXN_ornull *txn, SV *key, SV *data, U32 flags = 0, SV *callback = &PL_sv_undef)
1074 CODE: 1343 CODE:
1075{ 1344{
1076 dREQ (REQ_DB_PUT); 1345 dREQ (REQ_DB_PUT);
1077 req->db = db; 1346 req->db = db;
1078 req->txn = 0; 1347 req->txn = txn;
1079 set_dbt (&req->dbt1, key); 1348 sv_to_dbt (&req->dbt1, key);
1080 set_dbt (&req->dbt2, data); 1349 sv_to_dbt (&req->dbt2, data);
1081 req->uint1 = flags; 1350 req->uint1 = flags;
1082 REQ_SEND; 1351 REQ_SEND;
1083} 1352}
1084 1353
1354void
1355db_get (DB *db, DB_TXN_ornull *txn, SV *key, SV *data, U32 flags = 0, SV *callback = &PL_sv_undef)
1356 CODE:
1357{
1358 dREQ (REQ_DB_GET);
1359 req->db = db;
1360 req->txn = txn;
1361 req->uint1 = flags;
1362 sv_to_dbt (&req->dbt1, key);
1363 req->dbt3.flags = DB_DBT_MALLOC;
1364 req->sv3 = SvREFCNT_inc (data); SvREADONLY_on (data);
1365 REQ_SEND;
1366}
1367
1368void
1369db_pget (DB *db, DB_TXN_ornull *txn, SV *key, SV *pkey, SV *data, U32 flags = 0, SV *callback = &PL_sv_undef)
1370 CODE:
1371{
1372 dREQ (REQ_DB_PGET);
1373 req->db = db;
1374 req->txn = txn;
1375 req->uint1 = flags;
1376 sv_to_dbt (&req->dbt1, key);
1377 sv_to_dbt (&req->dbt2, pkey);
1378 req->dbt3.flags = DB_DBT_MALLOC;
1379 req->sv3 = SvREFCNT_inc (data); SvREADONLY_on (data);
1380 REQ_SEND;
1381}
1382
1383void
1384db_del (DB *db, DB_TXN_ornull *txn, SV *key, U32 flags = 0, SV *callback = &PL_sv_undef)
1385 CODE:
1386{
1387 dREQ (REQ_DB_DEL);
1388 req->db = db;
1389 req->txn = txn;
1390 req->uint1 = flags;
1391 sv_to_dbt (&req->dbt1, key);
1392 REQ_SEND;
1393}
1394
1395void
1396db_txn_commit (DB_TXN *txn, U32 flags = 0, SV *callback = &PL_sv_undef)
1397 CODE:
1398{
1399 dREQ (REQ_TXN_COMMIT);
1400 req->txn = txn;
1401 req->uint1 = flags;
1402 REQ_SEND;
1403 ptr_nuke (ST (0));
1404}
1405
1406void
1407db_txn_abort (DB_TXN *txn, SV *callback = &PL_sv_undef)
1408 CODE:
1409{
1410 dREQ (REQ_TXN_ABORT);
1411 req->txn = txn;
1412 REQ_SEND;
1413 ptr_nuke (ST (0));
1414}
1415
1416void
1417db_c_close (DBC *dbc, SV *callback = &PL_sv_undef)
1418 CODE:
1419{
1420 dREQ (REQ_C_CLOSE);
1421 req->dbc = dbc;
1422 REQ_SEND;
1423 ptr_nuke (ST (0));
1424}
1425
1426void
1427db_c_count (DBC *dbc, SV *count, U32 flags = 0, SV *callback = &PL_sv_undef)
1428 CODE:
1429{
1430 dREQ (REQ_C_COUNT);
1431 req->dbc = dbc;
1432 req->sv1 = SvREFCNT_inc (count);
1433 REQ_SEND;
1434}
1435
1436void
1437db_c_put (DBC *dbc, SV *key, SV *data, U32 flags = 0, SV *callback = &PL_sv_undef)
1438 CODE:
1439{
1440 dREQ (REQ_C_PUT);
1441 req->dbc = dbc;
1442 sv_to_dbt (&req->dbt1, key);
1443 sv_to_dbt (&req->dbt2, data);
1444 req->uint1 = flags;
1445 REQ_SEND;
1446}
1447
1448void
1449db_c_get (DBC *dbc, SV *key, SV *data, U32 flags = 0, SV *callback = &PL_sv_undef)
1450 CODE:
1451{
1452 dREQ (REQ_C_GET);
1453 req->dbc = dbc;
1454 req->uint1 = flags;
1455 if ((flags & DB_SET) == DB_SET
1456 || (flags & DB_SET_RANGE) == DB_SET_RANGE)
1457 sv_to_dbt (&req->dbt1, key);
1458 else
1459 req->dbt1.flags = DB_DBT_MALLOC;
1460
1461 req->sv1 = SvREFCNT_inc (key); SvREADONLY_on (key);
1462
1463 if ((flags & DB_GET_BOTH) == DB_GET_BOTH
1464 || (flags & DB_GET_BOTH_RANGE) == DB_GET_BOTH_RANGE)
1465 sv_to_dbt (&req->dbt3, data);
1466 else
1467 req->dbt3.flags = DB_DBT_MALLOC;
1468
1469 req->sv3 = SvREFCNT_inc (data); SvREADONLY_on (data);
1470 REQ_SEND;
1471}
1472
1473void
1474db_c_pget (DBC *dbc, SV *key, SV *pkey, SV *data, U32 flags = 0, SV *callback = &PL_sv_undef)
1475 CODE:
1476{
1477 dREQ (REQ_C_PGET);
1478 req->dbc = dbc;
1479 req->uint1 = flags;
1480 if ((flags & DB_SET) == DB_SET
1481 || (flags & DB_SET_RANGE) == DB_SET_RANGE)
1482 sv_to_dbt (&req->dbt1, key);
1483 else
1484 req->dbt1.flags = DB_DBT_MALLOC;
1485
1486 req->sv1 = SvREFCNT_inc (key); SvREADONLY_on (key);
1487
1488 req->dbt2.flags = DB_DBT_MALLOC;
1489 req->sv2 = SvREFCNT_inc (pkey); SvREADONLY_on (pkey);
1490
1491 if ((flags & DB_GET_BOTH) == DB_GET_BOTH
1492 || (flags & DB_GET_BOTH_RANGE) == DB_GET_BOTH_RANGE)
1493 sv_to_dbt (&req->dbt3, data);
1494 else
1495 req->dbt3.flags = DB_DBT_MALLOC;
1496
1497 req->sv3 = SvREFCNT_inc (data); SvREADONLY_on (data);
1498 REQ_SEND;
1499}
1500
1501void
1502db_c_del (DBC *dbc, U32 flags = 0, SV *callback = &PL_sv_undef)
1503 CODE:
1504{
1505 dREQ (REQ_C_DEL);
1506 req->dbc = dbc;
1507 req->uint1 = flags;
1508 REQ_SEND;
1509}
1510
1511
1512void
1513db_sequence_open (DB_SEQUENCE *seq, DB_TXN_ornull *txnid, SV *key, U32 flags = 0, SV *callback = &PL_sv_undef)
1514 CODE:
1515{
1516 dREQ (REQ_SEQ_OPEN);
1517 req->seq = seq;
1518 req->txn = txnid;
1519 req->uint1 = flags | DB_THREAD;
1520 sv_to_dbt (&req->dbt1, key);
1521 REQ_SEND;
1522}
1523
1524void
1525db_sequence_close (DB_SEQUENCE *seq, U32 flags = 0, SV *callback = &PL_sv_undef)
1526 CODE:
1527{
1528 dREQ (REQ_SEQ_CLOSE);
1529 req->seq = seq;
1530 req->uint1 = flags;
1531 REQ_SEND;
1532 ptr_nuke (ST (0));
1533}
1534
1535void
1536db_sequence_get (DB_SEQUENCE *seq, DB_TXN_ornull *txnid, int delta, SV *seq_value, U32 flags = DB_TXN_NOSYNC, SV *callback = &PL_sv_undef)
1537 CODE:
1538{
1539 dREQ (REQ_SEQ_GET);
1540 req->seq = seq;
1541 req->txn = txnid;
1542 req->int1 = delta;
1543 req->uint1 = flags;
1544 req->sv1 = SvREFCNT_inc (seq_value); SvREADONLY_on (seq_value);
1545 REQ_SEND;
1546}
1547
1548void
1549db_sequence_remove (DB_SEQUENCE *seq, DB_TXN_ornull *txnid = 0, U32 flags = 0, SV *callback = &PL_sv_undef)
1550 CODE:
1551{
1552 dREQ (REQ_SEQ_REMOVE);
1553 req->seq = seq;
1554 req->txn = txnid;
1555 req->uint1 = flags;
1556 REQ_SEND;
1557}
1558
1085 1559
1086MODULE = BDB PACKAGE = BDB::Env 1560MODULE = BDB PACKAGE = BDB::Env
1087 1561
1562void
1563DESTROY (DB_ENV_ornull *env)
1564 CODE:
1565 if (env)
1566 env->close (env, 0);
1567
1568int set_data_dir (DB_ENV *env, const char *dir)
1569 CODE:
1570 RETVAL = env->set_data_dir (env, dir);
1571 OUTPUT:
1572 RETVAL
1573
1574int set_tmp_dir (DB_ENV *env, const char *dir)
1575 CODE:
1576 RETVAL = env->set_tmp_dir (env, dir);
1577 OUTPUT:
1578 RETVAL
1579
1580int set_lg_dir (DB_ENV *env, const char *dir)
1581 CODE:
1582 RETVAL = env->set_lg_dir (env, dir);
1583 OUTPUT:
1584 RETVAL
1585
1586int set_shm_key (DB_ENV *env, long shm_key)
1587 CODE:
1588 RETVAL = env->set_shm_key (env, shm_key);
1589 OUTPUT:
1590 RETVAL
1591
1088int set_cachesize (DB_ENV *env, U32 gbytes, U32 bytes, int ncache = 0) 1592int set_cachesize (DB_ENV *env, U32 gbytes, U32 bytes, int ncache = 0)
1089 CODE: 1593 CODE:
1090 RETVAL = env->set_cachesize (env, gbytes, bytes, ncache); 1594 RETVAL = env->set_cachesize (env, gbytes, bytes, ncache);
1091 OUTPUT: 1595 OUTPUT:
1092 RETVAL 1596 RETVAL
1107 CODE: 1611 CODE:
1108 RETVAL = env->set_timeout (env, timeout * 1000000, flags); 1612 RETVAL = env->set_timeout (env, timeout * 1000000, flags);
1109 OUTPUT: 1613 OUTPUT:
1110 RETVAL 1614 RETVAL
1111 1615
1616int set_mp_max_openfd (DB_ENV *env, int maxopenfd);
1617 CODE:
1618 RETVAL = env->set_mp_max_openfd (env, maxopenfd);
1619 OUTPUT:
1620 RETVAL
1621
1622int set_mp_max_write (DB_ENV *env, int maxwrite, int maxwrite_sleep);
1623 CODE:
1624 RETVAL = env->set_mp_max_write (env, maxwrite, maxwrite_sleep);
1625 OUTPUT:
1626 RETVAL
1627
1628int set_mp_mmapsize (DB_ENV *env, int mmapsize_mb)
1629 CODE:
1630 RETVAL = env->set_mp_mmapsize (env, ((size_t)mmapsize_mb) << 20);
1631 OUTPUT:
1632 RETVAL
1633
1634int set_lk_detect (DB_ENV *env, U32 detect = DB_LOCK_DEFAULT)
1635 CODE:
1636 RETVAL = env->set_lk_detect (env, detect);
1637 OUTPUT:
1638 RETVAL
1639
1640int set_lk_max_lockers (DB_ENV *env, U32 max)
1641 CODE:
1642 RETVAL = env->set_lk_max_lockers (env, max);
1643 OUTPUT:
1644 RETVAL
1645
1646int set_lk_max_locks (DB_ENV *env, U32 max)
1647 CODE:
1648 RETVAL = env->set_lk_max_locks (env, max);
1649 OUTPUT:
1650 RETVAL
1651
1652int set_lk_max_objects (DB_ENV *env, U32 max)
1653 CODE:
1654 RETVAL = env->set_lk_max_objects (env, max);
1655 OUTPUT:
1656 RETVAL
1657
1658int set_lg_bsize (DB_ENV *env, U32 max)
1659 CODE:
1660 RETVAL = env->set_lg_bsize (env, max);
1661 OUTPUT:
1662 RETVAL
1663
1664int set_lg_max (DB_ENV *env, U32 max)
1665 CODE:
1666 RETVAL = env->set_lg_max (env, max);
1667 OUTPUT:
1668 RETVAL
1669
1670DB_TXN *
1671txn_begin (DB_ENV *env, DB_TXN_ornull *parent = 0, U32 flags = 0)
1672 CODE:
1673 errno = env->txn_begin (env, parent, &RETVAL, flags);
1674 if (errno)
1675 croak ("DB_ENV->txn_begin: %s", db_strerror (errno));
1676 OUTPUT:
1677 RETVAL
1112 1678
1113MODULE = BDB PACKAGE = BDB::Db 1679MODULE = BDB PACKAGE = BDB::Db
1114 1680
1681void
1682DESTROY (DB_ornull *db)
1683 CODE:
1684 if (db)
1685 {
1686 SV *env = (SV *)db->app_private;
1687 db->close (db, 0);
1688 SvREFCNT_dec (env);
1689 }
1690
1115int set_cachesize (DB *db, U32 gbytes, U32 bytes, int ncache = 0) 1691int set_cachesize (DB *db, U32 gbytes, U32 bytes, int ncache = 0)
1116 CODE: 1692 CODE:
1117 RETVAL = db->set_cachesize (db, gbytes, bytes, ncache); 1693 RETVAL = db->set_cachesize (db, gbytes, bytes, ncache);
1118 OUTPUT: 1694 OUTPUT:
1119 RETVAL 1695 RETVAL
1134 CODE: 1710 CODE:
1135 RETVAL = db->set_lorder (db, lorder); 1711 RETVAL = db->set_lorder (db, lorder);
1136 OUTPUT: 1712 OUTPUT:
1137 RETVAL 1713 RETVAL
1138 1714
1139
1140int set_bt_minkey (DB *db, U32 minkey) 1715int set_bt_minkey (DB *db, U32 minkey)
1141 CODE: 1716 CODE:
1142 RETVAL = db->set_bt_minkey (db, minkey); 1717 RETVAL = db->set_bt_minkey (db, minkey);
1143 OUTPUT: 1718 OUTPUT:
1144 RETVAL 1719 RETVAL
1183 CODE: 1758 CODE:
1184 RETVAL = db->set_q_extentsize (db, extentsize); 1759 RETVAL = db->set_q_extentsize (db, extentsize);
1185 OUTPUT: 1760 OUTPUT:
1186 RETVAL 1761 RETVAL
1187 1762
1763DBC *
1764cursor (DB *db, DB_TXN_ornull *txn = 0, U32 flags = 0)
1765 CODE:
1766 errno = db->cursor (db, txn, &RETVAL, flags);
1767 if (errno)
1768 croak ("DB->cursor: %s", db_strerror (errno));
1769 OUTPUT:
1770 RETVAL
1188 1771
1772DB_SEQUENCE *
1773sequence (DB *db, U32 flags = 0)
1774 CODE:
1775{
1776 errno = db_sequence_create (&RETVAL, db, flags);
1777 if (errno)
1778 croak ("db_sequence_create: %s", db_strerror (errno));
1779}
1780 OUTPUT:
1781 RETVAL
1782
1783
1784MODULE = BDB PACKAGE = BDB::Txn
1785
1786void
1787DESTROY (DB_TXN_ornull *txn)
1788 CODE:
1789 if (txn)
1790 txn->abort (txn);
1791
1792int set_timeout (DB_TXN *txn, NV timeout, U32 flags)
1793 CODE:
1794 RETVAL = txn->set_timeout (txn, timeout * 1000000, flags);
1795 OUTPUT:
1796 RETVAL
1797
1798
1799MODULE = BDB PACKAGE = BDB::Cursor
1800
1801void
1802DESTROY (DBC_ornull *dbc)
1803 CODE:
1804 if (dbc)
1805 dbc->c_close (dbc);
1806
1807MODULE = BDB PACKAGE = BDB::Sequence
1808
1809void
1810DESTROY (DB_SEQUENCE_ornull *seq)
1811 CODE:
1812 if (seq)
1813 seq->close (seq, 0);
1814
1815int initial_value (DB_SEQUENCE *seq, db_seq_t value)
1816 CODE:
1817 RETVAL = seq->initial_value (seq, value);
1818 OUTPUT:
1819 RETVAL
1820
1821int set_cachesize (DB_SEQUENCE *seq, U32 size)
1822 CODE:
1823 RETVAL = seq->set_cachesize (seq, size);
1824 OUTPUT:
1825 RETVAL
1826
1827int set_flags (DB_SEQUENCE *seq, U32 flags)
1828 CODE:
1829 RETVAL = seq->set_flags (seq, flags);
1830 OUTPUT:
1831 RETVAL
1832
1833int set_range (DB_SEQUENCE *seq, db_seq_t min, db_seq_t max)
1834 CODE:
1835 RETVAL = seq->set_range (seq, min, max);
1836 OUTPUT:
1837 RETVAL
1838

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines