ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/BDB/BDB.xs
Revision: 1.14
Committed: Sun Jul 8 13:41:03 2007 UTC (16 years, 10 months ago) by root
Branch: MAIN
CVS Tags: rel-0_5
Changes since 1.13: +82 -1 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.11 #include "xthread.h"
2 root 1.1
3     #include <errno.h>
4    
5     #include "EXTERN.h"
6     #include "perl.h"
7     #include "XSUB.h"
8    
9 root 1.13 // 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
17    
18 root 1.1 #include <stddef.h>
19     #include <stdlib.h>
20     #include <errno.h>
21     #include <sys/types.h>
22     #include <limits.h>
23     #include <fcntl.h>
24 root 1.2
25 root 1.13 #ifndef _WIN32
26     # include <sys/time.h>
27     # include <unistd.h>
28     #endif
29    
30 root 1.2 #include <db.h>
31 root 1.1
32 root 1.13 #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 root 1.10 #endif
35    
36 root 1.1 /* number of seconds after which idle threads exit */
37     #define IDLE_TIMEOUT 10
38    
39 root 1.8 typedef DB_ENV DB_ENV_ornull;
40     typedef DB_TXN DB_TXN_ornull;
41     typedef DBC DBC_ornull;
42     typedef DB DB_ornull;
43     typedef DB_SEQUENCE DB_SEQUENCE_ornull;
44 root 1.5
45 root 1.1 typedef SV SV8; /* byte-sv, used for argument-checking */
46 root 1.3 typedef char *octetstring;
47 root 1.1
48 root 1.3 static SV *prepare_cb;
49    
50 root 1.14 static void
51     debug_errcall (const DB_ENV *dbenv, const char *errpfx, const char *msg)
52     {
53     printf ("err[%s]\n", msg);
54     }
55    
56     static void
57     debug_msgcall (const DB_ENV *dbenv, const char *msg)
58     {
59     printf ("msg[%s]\n", msg);
60     }
61    
62 root 1.13 static char *
63 root 1.3 strdup_ornull (const char *s)
64 root 1.2 {
65 root 1.3 return s ? strdup (s) : 0;
66     }
67    
68 root 1.13 static void
69 root 1.5 sv_to_dbt (DBT *dbt, SV *sv)
70     {
71     STRLEN len;
72     char *data = SvPVbyte (sv, len);
73    
74     dbt->data = malloc (len);
75     memcpy (dbt->data, data, len);
76     dbt->size = len;
77 root 1.6 dbt->flags = DB_DBT_REALLOC;
78 root 1.5 }
79    
80 root 1.13 static void
81 root 1.5 dbt_to_sv (SV *sv, DBT *dbt)
82     {
83 root 1.6 if (sv)
84     {
85     SvREADONLY_off (sv);
86     sv_setpvn_mg (sv, dbt->data, dbt->size);
87     SvREFCNT_dec (sv);
88     }
89 root 1.5
90     free (dbt->data);
91     }
92    
93 root 1.3 enum {
94 root 1.1 REQ_QUIT,
95 root 1.8 REQ_ENV_OPEN, REQ_ENV_CLOSE, REQ_ENV_TXN_CHECKPOINT, REQ_ENV_LOCK_DETECT,
96     REQ_ENV_MEMP_SYNC, REQ_ENV_MEMP_TRICKLE,
97     REQ_DB_OPEN, REQ_DB_CLOSE, REQ_DB_COMPACT, REQ_DB_SYNC,
98     REQ_DB_PUT, REQ_DB_GET, REQ_DB_PGET, REQ_DB_DEL, REQ_DB_KEY_RANGE,
99 root 1.5 REQ_TXN_COMMIT, REQ_TXN_ABORT,
100 root 1.6 REQ_C_CLOSE, REQ_C_COUNT, REQ_C_PUT, REQ_C_GET, REQ_C_PGET, REQ_C_DEL,
101 root 1.8 REQ_SEQ_OPEN, REQ_SEQ_CLOSE, REQ_SEQ_GET, REQ_SEQ_REMOVE,
102 root 1.1 };
103    
104     typedef struct aio_cb
105     {
106 root 1.2 struct aio_cb *volatile next;
107     SV *callback;
108 root 1.3 int type, pri, result;
109 root 1.2
110     DB_ENV *env;
111     DB *db;
112     DB_TXN *txn;
113 root 1.6 DBC *dbc;
114    
115     UV uv1;
116 root 1.2 int int1, int2;
117     U32 uint1, uint2;
118     char *buf1, *buf2;
119 root 1.6 SV *sv1, *sv2, *sv3;
120 root 1.3
121     DBT dbt1, dbt2, dbt3;
122 root 1.8 DB_KEY_RANGE key_range;
123     DB_SEQUENCE *seq;
124     db_seq_t seq_t;
125 root 1.1 } aio_cb;
126    
127     typedef aio_cb *aio_req;
128    
129     enum {
130     PRI_MIN = -4,
131     PRI_MAX = 4,
132    
133     DEFAULT_PRI = 0,
134     PRI_BIAS = -PRI_MIN,
135     NUM_PRI = PRI_MAX + PRI_BIAS + 1,
136     };
137    
138     #define AIO_TICKS ((1000000 + 1023) >> 10)
139    
140     static unsigned int max_poll_time = 0;
141     static unsigned int max_poll_reqs = 0;
142    
143     /* calculcate time difference in ~1/AIO_TICKS of a second */
144     static int tvdiff (struct timeval *tv1, struct timeval *tv2)
145     {
146     return (tv2->tv_sec - tv1->tv_sec ) * AIO_TICKS
147     + ((tv2->tv_usec - tv1->tv_usec) >> 10);
148     }
149    
150     static int next_pri = DEFAULT_PRI + PRI_BIAS;
151    
152     static unsigned int started, idle, wanted;
153    
154     /* worker threads management */
155 root 1.12 static mutex_t wrklock = X_MUTEX_INIT;
156 root 1.1
157     typedef struct worker {
158     /* locked by wrklock */
159     struct worker *prev, *next;
160    
161 root 1.11 thread_t tid;
162 root 1.1
163     /* locked by reslock, reqlock or wrklock */
164     aio_req req; /* currently processed request */
165     void *dbuf;
166     DIR *dirp;
167     } worker;
168    
169     static worker wrk_first = { &wrk_first, &wrk_first, 0 };
170    
171     static void worker_clear (worker *wrk)
172     {
173     }
174    
175     static void worker_free (worker *wrk)
176     {
177     wrk->next->prev = wrk->prev;
178     wrk->prev->next = wrk->next;
179    
180     free (wrk);
181     }
182    
183     static volatile unsigned int nreqs, nready, npending;
184     static volatile unsigned int max_idle = 4;
185     static volatile unsigned int max_outstanding = 0xffffffff;
186 root 1.13 static int respipe [2], respipe_osf [2];
187 root 1.1
188 root 1.12 static mutex_t reslock = X_MUTEX_INIT;
189     static mutex_t reqlock = X_MUTEX_INIT;
190     static cond_t reqwait = X_COND_INIT;
191 root 1.1
192     #if WORDACCESS_UNSAFE
193    
194     static unsigned int get_nready ()
195     {
196     unsigned int retval;
197    
198 root 1.12 X_LOCK (reqlock);
199 root 1.1 retval = nready;
200 root 1.12 X_UNLOCK (reqlock);
201 root 1.1
202     return retval;
203     }
204    
205     static unsigned int get_npending ()
206     {
207     unsigned int retval;
208    
209 root 1.12 X_LOCK (reslock);
210 root 1.1 retval = npending;
211 root 1.12 X_UNLOCK (reslock);
212 root 1.1
213     return retval;
214     }
215    
216     static unsigned int get_nthreads ()
217     {
218     unsigned int retval;
219    
220 root 1.12 X_LOCK (wrklock);
221 root 1.1 retval = started;
222 root 1.12 X_UNLOCK (wrklock);
223 root 1.1
224     return retval;
225     }
226    
227     #else
228    
229     # define get_nready() nready
230     # define get_npending() npending
231     # define get_nthreads() started
232    
233     #endif
234    
235     /*
236     * a somewhat faster data structure might be nice, but
237     * with 8 priorities this actually needs <20 insns
238     * per shift, the most expensive operation.
239     */
240     typedef struct {
241     aio_req qs[NUM_PRI], qe[NUM_PRI]; /* qstart, qend */
242     int size;
243     } reqq;
244    
245     static reqq req_queue;
246     static reqq res_queue;
247    
248     int reqq_push (reqq *q, aio_req req)
249     {
250     int pri = req->pri;
251     req->next = 0;
252    
253     if (q->qe[pri])
254     {
255     q->qe[pri]->next = req;
256     q->qe[pri] = req;
257     }
258     else
259     q->qe[pri] = q->qs[pri] = req;
260    
261     return q->size++;
262     }
263    
264     aio_req reqq_shift (reqq *q)
265     {
266     int pri;
267    
268     if (!q->size)
269     return 0;
270    
271     --q->size;
272    
273     for (pri = NUM_PRI; pri--; )
274     {
275     aio_req req = q->qs[pri];
276    
277     if (req)
278     {
279     if (!(q->qs[pri] = req->next))
280     q->qe[pri] = 0;
281    
282     return req;
283     }
284     }
285    
286     abort ();
287     }
288    
289     static int poll_cb ();
290     static void req_free (aio_req req);
291     static void req_cancel (aio_req req);
292    
293     static int req_invoke (aio_req req)
294     {
295     dSP;
296    
297     if (SvOK (req->callback))
298     {
299     ENTER;
300     SAVETMPS;
301     PUSHMARK (SP);
302    
303     switch (req->type)
304     {
305 root 1.6 case REQ_DB_CLOSE:
306     SvREFCNT_dec (req->sv1);
307     break;
308    
309 root 1.5 case REQ_DB_GET:
310     case REQ_DB_PGET:
311 root 1.6 dbt_to_sv (req->sv3, &req->dbt3);
312 root 1.5 break;
313    
314 root 1.6 case REQ_C_GET:
315     case REQ_C_PGET:
316     dbt_to_sv (req->sv1, &req->dbt1);
317     dbt_to_sv (req->sv2, &req->dbt2);
318     dbt_to_sv (req->sv3, &req->dbt3);
319 root 1.5 break;
320 root 1.8
321     case REQ_DB_KEY_RANGE:
322     {
323     AV *av = newAV ();
324    
325     av_push (av, newSVnv (req->key_range.less));
326     av_push (av, newSVnv (req->key_range.equal));
327     av_push (av, newSVnv (req->key_range.greater));
328    
329     SvREADONLY_off (req->sv1);
330     sv_setsv_mg (req->sv1, newRV_noinc ((SV *)av));
331     SvREFCNT_dec (req->sv1);
332     }
333     break;
334    
335     case REQ_SEQ_GET:
336     SvREADONLY_off (req->sv1);
337    
338     if (sizeof (IV) > 4)
339     sv_setiv_mg (req->sv1, req->seq_t);
340     else
341     sv_setnv_mg (req->sv1, req->seq_t);
342    
343     SvREFCNT_dec (req->sv1);
344     break;
345 root 1.1 }
346    
347 root 1.3 errno = req->result;
348    
349 root 1.1 PUTBACK;
350     call_sv (req->callback, G_VOID | G_EVAL);
351     SPAGAIN;
352    
353     FREETMPS;
354     LEAVE;
355     }
356    
357     return !SvTRUE (ERRSV);
358     }
359    
360     static void req_free (aio_req req)
361     {
362 root 1.2 free (req->buf1);
363     free (req->buf2);
364 root 1.1 Safefree (req);
365     }
366    
367 root 1.13 #ifdef USE_SOCKETS_AS_HANDLES
368     # define TO_SOCKET(x) (win32_get_osfhandle (x))
369     #else
370     # define TO_SOCKET(x) (x)
371     #endif
372    
373     static void
374     create_pipe (int fd[2])
375     {
376     #ifdef _WIN32
377     int arg = 1;
378     if (PerlSock_socketpair (AF_UNIX, SOCK_STREAM, 0, fd)
379     || ioctlsocket (TO_SOCKET (fd [0]), FIONBIO, &arg)
380     || ioctlsocket (TO_SOCKET (fd [1]), FIONBIO, &arg))
381     #else
382     if (pipe (fd)
383     || fcntl (fd [0], F_SETFL, O_NONBLOCK)
384     || fcntl (fd [1], F_SETFL, O_NONBLOCK))
385     #endif
386     croak ("unable to initialize result pipe");
387    
388     respipe_osf [0] = TO_SOCKET (respipe [0]);
389     respipe_osf [1] = TO_SOCKET (respipe [1]);
390     }
391    
392     X_THREAD_PROC (bdb_proc);
393 root 1.1
394     static void start_thread (void)
395     {
396     worker *wrk = calloc (1, sizeof (worker));
397    
398     if (!wrk)
399     croak ("unable to allocate worker thread data");
400    
401 root 1.12 X_LOCK (wrklock);
402 root 1.13 if (thread_create (&wrk->tid, bdb_proc, (void *)wrk))
403 root 1.1 {
404     wrk->prev = &wrk_first;
405     wrk->next = wrk_first.next;
406     wrk_first.next->prev = wrk;
407     wrk_first.next = wrk;
408     ++started;
409     }
410     else
411     free (wrk);
412    
413 root 1.12 X_UNLOCK (wrklock);
414 root 1.1 }
415    
416     static void maybe_start_thread ()
417     {
418     if (get_nthreads () >= wanted)
419     return;
420    
421     /* todo: maybe use idle here, but might be less exact */
422     if (0 <= (int)get_nthreads () + (int)get_npending () - (int)nreqs)
423     return;
424    
425     start_thread ();
426     }
427    
428     static void req_send (aio_req req)
429     {
430 root 1.3 SV *wait_callback = 0;
431    
432     // synthesize callback if none given
433     if (!SvOK (req->callback))
434     {
435 root 1.13 int count;
436    
437 root 1.3 dSP;
438     PUSHMARK (SP);
439     PUTBACK;
440 root 1.13 count = call_sv (prepare_cb, G_ARRAY);
441 root 1.3 SPAGAIN;
442    
443     if (count != 2)
444     croak ("prepare callback must return exactly two values\n");
445    
446     wait_callback = SvREFCNT_inc (POPs);
447     SvREFCNT_dec (req->callback);
448     req->callback = SvREFCNT_inc (POPs);
449     }
450    
451 root 1.1 ++nreqs;
452    
453 root 1.12 X_LOCK (reqlock);
454 root 1.1 ++nready;
455     reqq_push (&req_queue, req);
456 root 1.12 X_COND_SIGNAL (reqwait);
457     X_UNLOCK (reqlock);
458 root 1.1
459     maybe_start_thread ();
460 root 1.3
461     if (wait_callback)
462     {
463     dSP;
464     PUSHMARK (SP);
465     PUTBACK;
466     call_sv (wait_callback, G_DISCARD);
467     SvREFCNT_dec (wait_callback);
468     }
469 root 1.1 }
470    
471     static void end_thread (void)
472     {
473     aio_req req;
474    
475     Newz (0, req, 1, aio_cb);
476    
477     req->type = REQ_QUIT;
478     req->pri = PRI_MAX + PRI_BIAS;
479    
480 root 1.12 X_LOCK (reqlock);
481 root 1.1 reqq_push (&req_queue, req);
482 root 1.12 X_COND_SIGNAL (reqwait);
483     X_UNLOCK (reqlock);
484 root 1.1
485 root 1.12 X_LOCK (wrklock);
486 root 1.1 --started;
487 root 1.12 X_UNLOCK (wrklock);
488 root 1.1 }
489    
490     static void set_max_idle (int nthreads)
491     {
492 root 1.12 if (WORDACCESS_UNSAFE) X_LOCK (reqlock);
493 root 1.1 max_idle = nthreads <= 0 ? 1 : nthreads;
494 root 1.12 if (WORDACCESS_UNSAFE) X_UNLOCK (reqlock);
495 root 1.1 }
496    
497     static void min_parallel (int nthreads)
498     {
499     if (wanted < nthreads)
500     wanted = nthreads;
501     }
502    
503     static void max_parallel (int nthreads)
504     {
505     if (wanted > nthreads)
506     wanted = nthreads;
507    
508     while (started > wanted)
509     end_thread ();
510     }
511    
512     static void poll_wait ()
513     {
514     fd_set rfd;
515    
516     while (nreqs)
517     {
518     int size;
519 root 1.12 if (WORDACCESS_UNSAFE) X_LOCK (reslock);
520 root 1.1 size = res_queue.size;
521 root 1.12 if (WORDACCESS_UNSAFE) X_UNLOCK (reslock);
522 root 1.1
523     if (size)
524     return;
525    
526     maybe_start_thread ();
527    
528 root 1.13 FD_ZERO (&rfd);
529     FD_SET (respipe [0], &rfd);
530 root 1.1
531 root 1.13 PerlSock_select (respipe [0] + 1, &rfd, 0, 0, 0);
532 root 1.1 }
533     }
534    
535     static int poll_cb ()
536     {
537     dSP;
538     int count = 0;
539     int maxreqs = max_poll_reqs;
540     int do_croak = 0;
541     struct timeval tv_start, tv_now;
542     aio_req req;
543    
544     if (max_poll_time)
545     gettimeofday (&tv_start, 0);
546    
547     for (;;)
548     {
549     for (;;)
550     {
551     maybe_start_thread ();
552    
553 root 1.12 X_LOCK (reslock);
554 root 1.1 req = reqq_shift (&res_queue);
555    
556     if (req)
557     {
558     --npending;
559    
560     if (!res_queue.size)
561     {
562     /* read any signals sent by the worker threads */
563     char buf [4];
564 root 1.13 while (respipe_read (respipe [0], buf, 4) == 4)
565 root 1.1 ;
566     }
567     }
568    
569 root 1.12 X_UNLOCK (reslock);
570 root 1.1
571     if (!req)
572     break;
573    
574     --nreqs;
575    
576     if (!req_invoke (req))
577     {
578     req_free (req);
579     croak (0);
580     }
581    
582     count++;
583    
584     req_free (req);
585    
586     if (maxreqs && !--maxreqs)
587     break;
588    
589     if (max_poll_time)
590     {
591     gettimeofday (&tv_now, 0);
592    
593     if (tvdiff (&tv_start, &tv_now) >= max_poll_time)
594     break;
595     }
596     }
597    
598     if (nreqs <= max_outstanding)
599     break;
600    
601     poll_wait ();
602    
603     ++maxreqs;
604     }
605    
606     return count;
607     }
608    
609     /*****************************************************************************/
610    
611 root 1.13 X_THREAD_PROC (bdb_proc)
612 root 1.1 {
613     aio_req req;
614     struct timespec ts;
615     worker *self = (worker *)thr_arg;
616    
617     /* try to distribute timeouts somewhat evenly */
618 root 1.13 ts.tv_nsec = ((unsigned long)self & 1023UL) * (1000000000UL / 1024UL);
619 root 1.1
620     for (;;)
621     {
622     ts.tv_sec = time (0) + IDLE_TIMEOUT;
623    
624 root 1.12 X_LOCK (reqlock);
625 root 1.1
626     for (;;)
627     {
628     self->req = req = reqq_shift (&req_queue);
629    
630     if (req)
631     break;
632    
633     ++idle;
634    
635 root 1.12 if (X_COND_TIMEDWAIT (reqwait, reqlock, ts)
636 root 1.1 == ETIMEDOUT)
637     {
638     if (idle > max_idle)
639     {
640     --idle;
641 root 1.12 X_UNLOCK (reqlock);
642     X_LOCK (wrklock);
643 root 1.1 --started;
644 root 1.12 X_UNLOCK (wrklock);
645 root 1.1 goto quit;
646     }
647    
648     /* we are allowed to idle, so do so without any timeout */
649 root 1.12 X_COND_WAIT (reqwait, reqlock);
650 root 1.1 ts.tv_sec = time (0) + IDLE_TIMEOUT;
651     }
652    
653     --idle;
654     }
655    
656     --nready;
657    
658 root 1.12 X_UNLOCK (reqlock);
659 root 1.1
660     switch (req->type)
661     {
662     case REQ_QUIT:
663     goto quit;
664    
665 root 1.3 case REQ_ENV_OPEN:
666     req->result = req->env->open (req->env, req->buf1, req->uint1, req->int1);
667     break;
668    
669     case REQ_ENV_CLOSE:
670     req->result = req->env->close (req->env, req->uint1);
671     break;
672    
673 root 1.8 case REQ_ENV_TXN_CHECKPOINT:
674     req->result = req->env->txn_checkpoint (req->env, req->uint1, req->int1, req->uint2);
675     break;
676    
677     case REQ_ENV_LOCK_DETECT:
678     req->result = req->env->lock_detect (req->env, req->uint1, req->uint2, &req->int1);
679     break;
680    
681     case REQ_ENV_MEMP_SYNC:
682     req->result = req->env->memp_sync (req->env, 0);
683     break;
684    
685     case REQ_ENV_MEMP_TRICKLE:
686     req->result = req->env->memp_trickle (req->env, req->int1, &req->int2);
687     break;
688    
689 root 1.3 case REQ_DB_OPEN:
690     req->result = req->db->open (req->db, req->txn, req->buf1, req->buf2, req->int1, req->uint1, req->int2);
691     break;
692    
693     case REQ_DB_CLOSE:
694     req->result = req->db->close (req->db, req->uint1);
695     break;
696    
697     case REQ_DB_COMPACT:
698     req->result = req->db->compact (req->db, req->txn, &req->dbt1, &req->dbt2, 0, req->uint1, 0);
699     break;
700    
701     case REQ_DB_SYNC:
702     req->result = req->db->sync (req->db, req->uint1);
703     break;
704    
705     case REQ_DB_PUT:
706     req->result = req->db->put (req->db, req->txn, &req->dbt1, &req->dbt2, req->uint1);
707     break;
708    
709 root 1.5 case REQ_DB_GET:
710     req->result = req->db->get (req->db, req->txn, &req->dbt1, &req->dbt3, req->uint1);
711     break;
712    
713     case REQ_DB_PGET:
714     req->result = req->db->pget (req->db, req->txn, &req->dbt1, &req->dbt2, &req->dbt3, req->uint1);
715     break;
716    
717 root 1.6 case REQ_DB_DEL:
718     req->result = req->db->del (req->db, req->txn, &req->dbt1, req->uint1);
719     break;
720    
721 root 1.8 case REQ_DB_KEY_RANGE:
722     req->result = req->db->key_range (req->db, req->txn, &req->dbt1, &req->key_range, req->uint1);
723     break;
724    
725 root 1.5 case REQ_TXN_COMMIT:
726     req->result = req->txn->commit (req->txn, req->uint1);
727     break;
728    
729     case REQ_TXN_ABORT:
730     req->result = req->txn->abort (req->txn);
731     break;
732    
733 root 1.6 case REQ_C_CLOSE:
734     req->result = req->dbc->c_close (req->dbc);
735     break;
736    
737     case REQ_C_COUNT:
738     {
739     db_recno_t recno;
740     req->result = req->dbc->c_count (req->dbc, &recno, req->uint1);
741     req->uv1 = recno;
742     }
743     break;
744    
745     case REQ_C_PUT:
746     req->result = req->dbc->c_put (req->dbc, &req->dbt1, &req->dbt2, req->uint1);
747     break;
748    
749     case REQ_C_GET:
750     req->result = req->dbc->c_get (req->dbc, &req->dbt1, &req->dbt3, req->uint1);
751     break;
752    
753     case REQ_C_PGET:
754     req->result = req->dbc->c_pget (req->dbc, &req->dbt1, &req->dbt2, &req->dbt3, req->uint1);
755     break;
756    
757     case REQ_C_DEL:
758     req->result = req->dbc->c_del (req->dbc, req->uint1);
759     break;
760    
761 root 1.8 case REQ_SEQ_OPEN:
762     req->result = req->seq->open (req->seq, req->txn, &req->dbt1, req->uint1);
763     break;
764    
765     case REQ_SEQ_CLOSE:
766     req->result = req->seq->close (req->seq, req->uint1);
767     break;
768    
769     case REQ_SEQ_GET:
770     req->result = req->seq->get (req->seq, req->txn, req->int1, &req->seq_t, req->uint1);
771     break;
772    
773     case REQ_SEQ_REMOVE:
774     req->result = req->seq->remove (req->seq, req->txn, req->uint1);
775     break;
776    
777 root 1.1 default:
778 root 1.3 req->result = ENOSYS;
779 root 1.1 break;
780     }
781    
782 root 1.12 X_LOCK (reslock);
783 root 1.1
784     ++npending;
785    
786     if (!reqq_push (&res_queue, req))
787     /* write a dummy byte to the pipe so fh becomes ready */
788 root 1.13 respipe_write (respipe_osf [1], (const void *)&respipe_osf, 1);
789 root 1.1
790     self->req = 0;
791     worker_clear (self);
792    
793 root 1.12 X_UNLOCK (reslock);
794 root 1.1 }
795    
796     quit:
797 root 1.12 X_LOCK (wrklock);
798 root 1.1 worker_free (self);
799 root 1.12 X_UNLOCK (wrklock);
800 root 1.1
801     return 0;
802     }
803    
804     /*****************************************************************************/
805    
806     static void atfork_prepare (void)
807     {
808 root 1.12 X_LOCK (wrklock);
809     X_LOCK (reqlock);
810     X_LOCK (reslock);
811 root 1.1 }
812    
813     static void atfork_parent (void)
814     {
815 root 1.12 X_UNLOCK (reslock);
816     X_UNLOCK (reqlock);
817     X_UNLOCK (wrklock);
818 root 1.1 }
819    
820     static void atfork_child (void)
821     {
822     aio_req prv;
823    
824     while (prv = reqq_shift (&req_queue))
825     req_free (prv);
826    
827     while (prv = reqq_shift (&res_queue))
828     req_free (prv);
829    
830     while (wrk_first.next != &wrk_first)
831     {
832     worker *wrk = wrk_first.next;
833    
834     if (wrk->req)
835     req_free (wrk->req);
836    
837     worker_clear (wrk);
838     worker_free (wrk);
839     }
840    
841     started = 0;
842     idle = 0;
843     nreqs = 0;
844     nready = 0;
845     npending = 0;
846    
847 root 1.13 respipe_close (respipe [0]);
848     respipe_close (respipe [1]);
849 root 1.12
850 root 1.13 create_pipe (respipe);
851 root 1.1
852     atfork_parent ();
853     }
854    
855 root 1.2 #define dREQ(reqtype) \
856 root 1.1 aio_req req; \
857     int req_pri = next_pri; \
858     next_pri = DEFAULT_PRI + PRI_BIAS; \
859     \
860     if (SvOK (callback) && !SvROK (callback)) \
861     croak ("callback must be undef or of reference type"); \
862     \
863 root 1.2 Newz (0, req, 1, aio_cb); \
864 root 1.1 if (!req) \
865     croak ("out of memory during aio_req allocation"); \
866     \
867     req->callback = newSVsv (callback); \
868 root 1.2 req->type = (reqtype); \
869 root 1.1 req->pri = req_pri
870    
871     #define REQ_SEND \
872 root 1.2 req_send (req)
873    
874 root 1.5 #define SvPTR(var, arg, type, class, nullok) \
875     if (!SvOK (arg)) \
876     { \
877     if (!nullok) \
878 root 1.7 croak (# var " must be a " # class " object, not undef"); \
879 root 1.5 \
880     (var) = 0; \
881     } \
882     else if (sv_derived_from ((arg), # class)) \
883     { \
884     IV tmp = SvIV ((SV*) SvRV (arg)); \
885     (var) = INT2PTR (type, tmp); \
886     if (!var) \
887 root 1.7 croak (# var " is not a valid " # class " object anymore"); \
888 root 1.5 } \
889     else \
890 root 1.7 croak (# var " is not of type " # class); \
891 root 1.5 \
892 root 1.3
893 root 1.5 static void
894     ptr_nuke (SV *sv)
895 root 1.3 {
896 root 1.5 assert (SvROK (sv));
897     sv_setiv (SvRV (sv), 0);
898     }
899 root 1.3
900 root 1.2 MODULE = BDB PACKAGE = BDB
901 root 1.1
902     PROTOTYPES: ENABLE
903    
904     BOOT:
905     {
906 root 1.2 HV *stash = gv_stashpv ("BDB", 1);
907    
908     static const struct {
909     const char *name;
910     IV iv;
911     } *civ, const_iv[] = {
912     #define const_iv(name) { # name, (IV)DB_ ## name },
913     const_iv (RPCCLIENT)
914     const_iv (INIT_CDB)
915     const_iv (INIT_LOCK)
916     const_iv (INIT_LOG)
917     const_iv (INIT_MPOOL)
918     const_iv (INIT_REP)
919     const_iv (INIT_TXN)
920     const_iv (RECOVER)
921     const_iv (INIT_TXN)
922     const_iv (RECOVER_FATAL)
923     const_iv (CREATE)
924     const_iv (USE_ENVIRON)
925     const_iv (USE_ENVIRON_ROOT)
926     const_iv (LOCKDOWN)
927     const_iv (PRIVATE)
928     const_iv (REGISTER)
929     const_iv (SYSTEM_MEM)
930     const_iv (AUTO_COMMIT)
931     const_iv (CDB_ALLDB)
932     const_iv (DIRECT_DB)
933     const_iv (DIRECT_LOG)
934     const_iv (DSYNC_DB)
935     const_iv (DSYNC_LOG)
936     const_iv (LOG_AUTOREMOVE)
937     const_iv (LOG_INMEMORY)
938     const_iv (NOLOCKING)
939     const_iv (NOMMAP)
940     const_iv (NOPANIC)
941     const_iv (OVERWRITE)
942     const_iv (PANIC_ENVIRONMENT)
943     const_iv (REGION_INIT)
944     const_iv (TIME_NOTGRANTED)
945     const_iv (TXN_NOSYNC)
946     const_iv (TXN_WRITE_NOSYNC)
947 root 1.5 const_iv (WRITECURSOR)
948 root 1.2 const_iv (YIELDCPU)
949     const_iv (ENCRYPT_AES)
950     const_iv (XA_CREATE)
951     const_iv (BTREE)
952     const_iv (HASH)
953     const_iv (QUEUE)
954     const_iv (RECNO)
955     const_iv (UNKNOWN)
956     const_iv (EXCL)
957 root 1.4 const_iv (READ_COMMITTED)
958 root 1.2 const_iv (READ_UNCOMMITTED)
959     const_iv (TRUNCATE)
960     const_iv (NOSYNC)
961     const_iv (CHKSUM)
962     const_iv (ENCRYPT)
963     const_iv (TXN_NOT_DURABLE)
964     const_iv (DUP)
965     const_iv (DUPSORT)
966     const_iv (RECNUM)
967     const_iv (RENUMBER)
968     const_iv (REVSPLITOFF)
969     const_iv (INORDER)
970     const_iv (CONSUME)
971     const_iv (CONSUME_WAIT)
972 root 1.5 const_iv (GET_BOTH)
973 root 1.6 const_iv (GET_BOTH_RANGE)
974 root 1.5 //const_iv (SET_RECNO)
975     //const_iv (MULTIPLE)
976 root 1.2 const_iv (SNAPSHOT)
977     const_iv (JOIN_ITEM)
978     const_iv (RMW)
979    
980     const_iv (NOTFOUND)
981     const_iv (KEYEMPTY)
982     const_iv (LOCK_DEADLOCK)
983     const_iv (LOCK_NOTGRANTED)
984     const_iv (RUNRECOVERY)
985 root 1.3 const_iv (OLD_VERSION)
986     const_iv (REP_HANDLE_DEAD)
987     const_iv (REP_LOCKOUT)
988 root 1.6 const_iv (SECONDARY_BAD)
989 root 1.3
990     const_iv (FREE_SPACE)
991     const_iv (FREELIST_ONLY)
992    
993     const_iv (APPEND)
994     const_iv (NODUPDATA)
995     const_iv (NOOVERWRITE)
996    
997 root 1.4 const_iv (TXN_NOWAIT)
998     const_iv (TXN_SYNC)
999    
1000 root 1.3 const_iv (SET_LOCK_TIMEOUT)
1001     const_iv (SET_TXN_TIMEOUT)
1002 root 1.6
1003     const_iv (JOIN_ITEM)
1004     const_iv (FIRST)
1005     const_iv (NEXT)
1006     const_iv (NEXT_DUP)
1007     const_iv (NEXT_NODUP)
1008     const_iv (PREV)
1009     const_iv (PREV_NODUP)
1010     const_iv (SET)
1011     const_iv (SET_RANGE)
1012     const_iv (LAST)
1013     const_iv (BEFORE)
1014     const_iv (AFTER)
1015     const_iv (CURRENT)
1016     const_iv (KEYFIRST)
1017     const_iv (KEYLAST)
1018     const_iv (NODUPDATA)
1019 root 1.8
1020     const_iv (FORCE)
1021    
1022     const_iv (LOCK_DEFAULT)
1023     const_iv (LOCK_EXPIRE)
1024     const_iv (LOCK_MAXLOCKS)
1025     const_iv (LOCK_MAXWRITE)
1026     const_iv (LOCK_MINLOCKS)
1027     const_iv (LOCK_MINWRITE)
1028     const_iv (LOCK_OLDEST)
1029     const_iv (LOCK_RANDOM)
1030     const_iv (LOCK_YOUNGEST)
1031    
1032     const_iv (SEQ_DEC)
1033     const_iv (SEQ_INC)
1034     const_iv (SEQ_WRAP)
1035 root 1.14
1036     const_iv (BUFFER_SMALL)
1037     const_iv (DONOTINDEX)
1038     const_iv (KEYEMPTY )
1039     const_iv (KEYEXIST )
1040     const_iv (LOCK_DEADLOCK)
1041     const_iv (LOCK_NOTGRANTED)
1042     const_iv (LOG_BUFFER_FULL)
1043     const_iv (NOSERVER)
1044     const_iv (NOSERVER_HOME)
1045     const_iv (NOSERVER_ID)
1046     const_iv (NOTFOUND)
1047     const_iv (OLD_VERSION)
1048     const_iv (PAGE_NOTFOUND)
1049     const_iv (REP_DUPMASTER)
1050     const_iv (REP_HANDLE_DEAD)
1051     const_iv (REP_HOLDELECTION)
1052     const_iv (REP_IGNORE)
1053     const_iv (REP_ISPERM)
1054     const_iv (REP_JOIN_FAILURE)
1055     const_iv (REP_LOCKOUT)
1056     const_iv (REP_NEWMASTER)
1057     const_iv (REP_NEWSITE)
1058     const_iv (REP_NOTPERM)
1059     const_iv (REP_UNAVAIL)
1060     const_iv (RUNRECOVERY)
1061     const_iv (SECONDARY_BAD)
1062     const_iv (VERIFY_BAD)
1063     const_iv (VERSION_MISMATCH)
1064    
1065     const_iv (VERB_DEADLOCK)
1066     const_iv (VERB_RECOVERY)
1067     const_iv (VERB_REGISTER)
1068     const_iv (VERB_REPLICATION)
1069     const_iv (VERB_WAITSFOR)
1070    
1071     const_iv (VERSION_MAJOR)
1072     const_iv (VERSION_MINOR)
1073     const_iv (VERSION_PATCH)
1074 root 1.13 #if DB_VERSION_MINOR >= 5
1075     const_iv (MULTIVERSION)
1076     const_iv (TXN_SNAPSHOT)
1077     #endif
1078 root 1.2 };
1079    
1080     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1081     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
1082 root 1.1
1083 root 1.14 newCONSTSUB (stash, "DB_VERSION", newSVnv (DB_VERSION_MAJOR + DB_VERSION_MINOR * .1));
1084     newCONSTSUB (stash, "DB_VERSION_STRING", newSVpv (DB_VERSION_STRING, 0));
1085    
1086 root 1.13 create_pipe (respipe);
1087 root 1.12
1088     X_THREAD_ATFORK (atfork_prepare, atfork_parent, atfork_child);
1089     #ifdef _WIN32
1090     X_MUTEX_CHECK (wrklock);
1091     X_MUTEX_CHECK (reslock);
1092     X_MUTEX_CHECK (reqlock);
1093    
1094     X_COND_CHECK (reqwait);
1095     #endif
1096 root 1.1 }
1097    
1098     void
1099     max_poll_reqs (int nreqs)
1100     PROTOTYPE: $
1101     CODE:
1102     max_poll_reqs = nreqs;
1103    
1104     void
1105     max_poll_time (double nseconds)
1106     PROTOTYPE: $
1107     CODE:
1108     max_poll_time = nseconds * AIO_TICKS;
1109    
1110     void
1111     min_parallel (int nthreads)
1112     PROTOTYPE: $
1113    
1114     void
1115     max_parallel (int nthreads)
1116     PROTOTYPE: $
1117    
1118     void
1119     max_idle (int nthreads)
1120     PROTOTYPE: $
1121     CODE:
1122     set_max_idle (nthreads);
1123    
1124     int
1125     max_outstanding (int maxreqs)
1126     PROTOTYPE: $
1127     CODE:
1128     RETVAL = max_outstanding;
1129     max_outstanding = maxreqs;
1130     OUTPUT:
1131     RETVAL
1132    
1133     int
1134 root 1.3 dbreq_pri (int pri = 0)
1135 root 1.1 PROTOTYPE: ;$
1136     CODE:
1137     RETVAL = next_pri - PRI_BIAS;
1138     if (items > 0)
1139     {
1140     if (pri < PRI_MIN) pri = PRI_MIN;
1141     if (pri > PRI_MAX) pri = PRI_MAX;
1142     next_pri = pri + PRI_BIAS;
1143     }
1144     OUTPUT:
1145     RETVAL
1146    
1147     void
1148 root 1.3 dbreq_nice (int nice = 0)
1149 root 1.1 CODE:
1150     nice = next_pri - nice;
1151     if (nice < PRI_MIN) nice = PRI_MIN;
1152     if (nice > PRI_MAX) nice = PRI_MAX;
1153     next_pri = nice + PRI_BIAS;
1154    
1155     void
1156     flush ()
1157     PROTOTYPE:
1158     CODE:
1159     while (nreqs)
1160     {
1161     poll_wait ();
1162     poll_cb ();
1163     }
1164    
1165     int
1166 root 1.3 poll ()
1167 root 1.1 PROTOTYPE:
1168     CODE:
1169     poll_wait ();
1170     RETVAL = poll_cb ();
1171     OUTPUT:
1172     RETVAL
1173    
1174     int
1175 root 1.3 poll_fileno ()
1176 root 1.1 PROTOTYPE:
1177     CODE:
1178     RETVAL = respipe [0];
1179     OUTPUT:
1180     RETVAL
1181    
1182     int
1183 root 1.3 poll_cb (...)
1184 root 1.1 PROTOTYPE:
1185     CODE:
1186     RETVAL = poll_cb ();
1187     OUTPUT:
1188     RETVAL
1189    
1190     void
1191 root 1.3 poll_wait ()
1192 root 1.1 PROTOTYPE:
1193     CODE:
1194     poll_wait ();
1195    
1196     int
1197 root 1.3 nreqs ()
1198 root 1.1 PROTOTYPE:
1199     CODE:
1200     RETVAL = nreqs;
1201     OUTPUT:
1202     RETVAL
1203    
1204     int
1205 root 1.3 nready ()
1206 root 1.1 PROTOTYPE:
1207     CODE:
1208     RETVAL = get_nready ();
1209     OUTPUT:
1210     RETVAL
1211    
1212     int
1213 root 1.3 npending ()
1214 root 1.1 PROTOTYPE:
1215     CODE:
1216     RETVAL = get_npending ();
1217     OUTPUT:
1218     RETVAL
1219    
1220     int
1221 root 1.3 nthreads ()
1222 root 1.1 PROTOTYPE:
1223     CODE:
1224 root 1.12 if (WORDACCESS_UNSAFE) X_LOCK (wrklock);
1225 root 1.1 RETVAL = started;
1226 root 1.12 if (WORDACCESS_UNSAFE) X_UNLOCK (wrklock);
1227 root 1.1 OUTPUT:
1228     RETVAL
1229    
1230 root 1.3 void
1231     set_sync_prepare (SV *cb)
1232     PROTOTYPE: &
1233     CODE:
1234     SvREFCNT_dec (prepare_cb);
1235     prepare_cb = newSVsv (cb);
1236    
1237 root 1.14 char *
1238     strerror (int errorno = errno)
1239     PROTOTYPE: ;$
1240     CODE:
1241     RETVAL = db_strerror (errorno);
1242     OUTPUT:
1243     RETVAL
1244 root 1.8
1245 root 1.2 DB_ENV *
1246 root 1.3 db_env_create (U32 env_flags = 0)
1247 root 1.2 CODE:
1248     {
1249 root 1.3 errno = db_env_create (&RETVAL, env_flags);
1250     if (errno)
1251     croak ("db_env_create: %s", db_strerror (errno));
1252 root 1.14
1253     if (0)
1254     {
1255     RETVAL->set_errcall (RETVAL, debug_errcall);
1256     RETVAL->set_msgcall (RETVAL, debug_msgcall);
1257     }
1258 root 1.2 }
1259 root 1.3 OUTPUT:
1260     RETVAL
1261 root 1.2
1262     void
1263 root 1.3 db_env_open (DB_ENV *env, octetstring db_home, U32 open_flags, int mode, SV *callback = &PL_sv_undef)
1264 root 1.2 CODE:
1265     {
1266 root 1.13 dREQ (REQ_ENV_OPEN);
1267    
1268 root 1.14 env->set_thread_count (env, wanted + 2);
1269 root 1.8
1270 root 1.2 req->env = env;
1271 root 1.3 req->uint1 = open_flags | DB_THREAD;
1272 root 1.2 req->int1 = mode;
1273 root 1.3 req->buf1 = strdup_ornull (db_home);
1274 root 1.2 REQ_SEND;
1275     }
1276    
1277     void
1278 root 1.3 db_env_close (DB_ENV *env, U32 flags = 0, SV *callback = &PL_sv_undef)
1279 root 1.2 CODE:
1280     {
1281     dREQ (REQ_ENV_CLOSE);
1282     req->env = env;
1283     req->uint1 = flags;
1284     REQ_SEND;
1285 root 1.5 ptr_nuke (ST (0));
1286 root 1.2 }
1287    
1288 root 1.8 void
1289     db_env_txn_checkpoint (DB_ENV *env, U32 kbyte = 0, U32 min = 0, U32 flags = 0, SV *callback = &PL_sv_undef)
1290     CODE:
1291     {
1292     dREQ (REQ_ENV_TXN_CHECKPOINT);
1293     req->env = env;
1294     req->uint1 = kbyte;
1295     req->int1 = min;
1296     req->uint2 = flags;
1297     REQ_SEND;
1298     }
1299    
1300     void
1301     db_env_lock_detect (DB_ENV *env, U32 flags = 0, U32 atype = DB_LOCK_DEFAULT, SV *dummy = 0, SV *callback = &PL_sv_undef)
1302     CODE:
1303     {
1304     dREQ (REQ_ENV_LOCK_DETECT);
1305     req->env = env;
1306     req->uint1 = flags;
1307     req->uint2 = atype;
1308     REQ_SEND;
1309     }
1310    
1311     void
1312     db_env_memp_sync (DB_ENV *env, SV *dummy = 0, SV *callback = &PL_sv_undef)
1313     CODE:
1314     {
1315     dREQ (REQ_ENV_MEMP_SYNC);
1316     req->env = env;
1317     REQ_SEND;
1318     }
1319    
1320     void
1321     db_env_memp_trickle (DB_ENV *env, int percent, SV *dummy = 0, SV *callback = &PL_sv_undef)
1322     CODE:
1323     {
1324     dREQ (REQ_ENV_MEMP_TRICKLE);
1325     req->env = env;
1326     req->int1 = percent;
1327     REQ_SEND;
1328     }
1329    
1330    
1331 root 1.2 DB *
1332 root 1.3 db_create (DB_ENV *env = 0, U32 flags = 0)
1333 root 1.2 CODE:
1334     {
1335 root 1.3 errno = db_create (&RETVAL, env, flags);
1336     if (errno)
1337 root 1.6 croak ("db_create: %s", db_strerror (errno));
1338 root 1.5
1339     if (RETVAL)
1340     RETVAL->app_private = (void *)newSVsv (ST (0));
1341 root 1.2 }
1342 root 1.3 OUTPUT:
1343     RETVAL
1344 root 1.2
1345     void
1346 root 1.5 db_open (DB *db, DB_TXN_ornull *txnid, octetstring file, octetstring database, int type, U32 flags, int mode, SV *callback = &PL_sv_undef)
1347 root 1.2 CODE:
1348     {
1349     dREQ (REQ_DB_OPEN);
1350     req->db = db;
1351     req->txn = txnid;
1352 root 1.3 req->buf1 = strdup_ornull (file);
1353     req->buf2 = strdup_ornull (database);
1354 root 1.2 req->int1 = type;
1355 root 1.3 req->uint1 = flags | DB_THREAD;
1356 root 1.2 req->int2 = mode;
1357     REQ_SEND;
1358     }
1359    
1360     void
1361 root 1.3 db_close (DB *db, U32 flags = 0, SV *callback = &PL_sv_undef)
1362 root 1.2 CODE:
1363     {
1364     dREQ (REQ_DB_CLOSE);
1365     req->db = db;
1366     req->uint1 = flags;
1367 root 1.5 req->sv1 = (SV *)db->app_private;
1368 root 1.2 REQ_SEND;
1369 root 1.5 ptr_nuke (ST (0));
1370 root 1.2 }
1371    
1372 root 1.3 void
1373 root 1.5 db_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)
1374 root 1.3 CODE:
1375     {
1376     dREQ (REQ_DB_COMPACT);
1377     req->db = db;
1378     req->txn = txn;
1379 root 1.5 sv_to_dbt (&req->dbt1, start);
1380     sv_to_dbt (&req->dbt2, stop);
1381 root 1.3 req->uint1 = flags;
1382     REQ_SEND;
1383     }
1384    
1385     void
1386     db_sync (DB *db, U32 flags = 0, SV *callback = &PL_sv_undef)
1387     CODE:
1388     {
1389     dREQ (REQ_DB_SYNC);
1390     req->db = db;
1391     req->uint1 = flags;
1392     REQ_SEND;
1393     }
1394    
1395     void
1396 root 1.8 db_key_range (DB *db, DB_TXN_ornull *txn, SV *key, SV *key_range, U32 flags = 0, SV *callback = &PL_sv_undef)
1397     CODE:
1398     {
1399     dREQ (REQ_DB_KEY_RANGE);
1400     req->db = db;
1401     req->txn = txn;
1402     sv_to_dbt (&req->dbt1, key);
1403     req->uint1 = flags;
1404     req->sv1 = SvREFCNT_inc (key_range); SvREADONLY_on (key_range);
1405     REQ_SEND;
1406     }
1407    
1408     void
1409 root 1.5 db_put (DB *db, DB_TXN_ornull *txn, SV *key, SV *data, U32 flags = 0, SV *callback = &PL_sv_undef)
1410 root 1.3 CODE:
1411     {
1412     dREQ (REQ_DB_PUT);
1413     req->db = db;
1414 root 1.5 req->txn = txn;
1415     sv_to_dbt (&req->dbt1, key);
1416     sv_to_dbt (&req->dbt2, data);
1417 root 1.3 req->uint1 = flags;
1418     REQ_SEND;
1419     }
1420    
1421 root 1.5 void
1422     db_get (DB *db, DB_TXN_ornull *txn, SV *key, SV *data, U32 flags = 0, SV *callback = &PL_sv_undef)
1423     CODE:
1424     {
1425     dREQ (REQ_DB_GET);
1426     req->db = db;
1427     req->txn = txn;
1428 root 1.6 req->uint1 = flags;
1429 root 1.5 sv_to_dbt (&req->dbt1, key);
1430     req->dbt3.flags = DB_DBT_MALLOC;
1431 root 1.6 req->sv3 = SvREFCNT_inc (data); SvREADONLY_on (data);
1432 root 1.5 REQ_SEND;
1433     }
1434    
1435     void
1436     db_pget (DB *db, DB_TXN_ornull *txn, SV *key, SV *pkey, SV *data, U32 flags = 0, SV *callback = &PL_sv_undef)
1437     CODE:
1438     {
1439     dREQ (REQ_DB_PGET);
1440     req->db = db;
1441     req->txn = txn;
1442 root 1.6 req->uint1 = flags;
1443 root 1.5 sv_to_dbt (&req->dbt1, key);
1444     sv_to_dbt (&req->dbt2, pkey);
1445     req->dbt3.flags = DB_DBT_MALLOC;
1446 root 1.6 req->sv3 = SvREFCNT_inc (data); SvREADONLY_on (data);
1447     REQ_SEND;
1448     }
1449    
1450     void
1451     db_del (DB *db, DB_TXN_ornull *txn, SV *key, U32 flags = 0, SV *callback = &PL_sv_undef)
1452     CODE:
1453     {
1454     dREQ (REQ_DB_DEL);
1455     req->db = db;
1456     req->txn = txn;
1457 root 1.5 req->uint1 = flags;
1458 root 1.6 sv_to_dbt (&req->dbt1, key);
1459 root 1.5 REQ_SEND;
1460     }
1461    
1462     void
1463     db_txn_commit (DB_TXN *txn, U32 flags = 0, SV *callback = &PL_sv_undef)
1464     CODE:
1465     {
1466     dREQ (REQ_TXN_COMMIT);
1467     req->txn = txn;
1468     req->uint1 = flags;
1469     REQ_SEND;
1470     ptr_nuke (ST (0));
1471     }
1472    
1473     void
1474     db_txn_abort (DB_TXN *txn, SV *callback = &PL_sv_undef)
1475     CODE:
1476     {
1477     dREQ (REQ_TXN_ABORT);
1478     req->txn = txn;
1479     REQ_SEND;
1480     ptr_nuke (ST (0));
1481     }
1482    
1483 root 1.6 void
1484     db_c_close (DBC *dbc, SV *callback = &PL_sv_undef)
1485     CODE:
1486     {
1487     dREQ (REQ_C_CLOSE);
1488     req->dbc = dbc;
1489     REQ_SEND;
1490     ptr_nuke (ST (0));
1491     }
1492    
1493     void
1494     db_c_count (DBC *dbc, SV *count, U32 flags = 0, SV *callback = &PL_sv_undef)
1495     CODE:
1496     {
1497     dREQ (REQ_C_COUNT);
1498     req->dbc = dbc;
1499     req->sv1 = SvREFCNT_inc (count);
1500     REQ_SEND;
1501     }
1502    
1503     void
1504     db_c_put (DBC *dbc, SV *key, SV *data, U32 flags = 0, SV *callback = &PL_sv_undef)
1505     CODE:
1506     {
1507     dREQ (REQ_C_PUT);
1508     req->dbc = dbc;
1509     sv_to_dbt (&req->dbt1, key);
1510     sv_to_dbt (&req->dbt2, data);
1511     req->uint1 = flags;
1512     REQ_SEND;
1513     }
1514    
1515     void
1516     db_c_get (DBC *dbc, SV *key, SV *data, U32 flags = 0, SV *callback = &PL_sv_undef)
1517     CODE:
1518     {
1519     dREQ (REQ_C_GET);
1520     req->dbc = dbc;
1521     req->uint1 = flags;
1522     if ((flags & DB_SET) == DB_SET
1523     || (flags & DB_SET_RANGE) == DB_SET_RANGE)
1524     sv_to_dbt (&req->dbt1, key);
1525     else
1526     req->dbt1.flags = DB_DBT_MALLOC;
1527    
1528     req->sv1 = SvREFCNT_inc (key); SvREADONLY_on (key);
1529    
1530     if ((flags & DB_GET_BOTH) == DB_GET_BOTH
1531     || (flags & DB_GET_BOTH_RANGE) == DB_GET_BOTH_RANGE)
1532     sv_to_dbt (&req->dbt3, data);
1533     else
1534     req->dbt3.flags = DB_DBT_MALLOC;
1535    
1536     req->sv3 = SvREFCNT_inc (data); SvREADONLY_on (data);
1537     REQ_SEND;
1538     }
1539    
1540     void
1541     db_c_pget (DBC *dbc, SV *key, SV *pkey, SV *data, U32 flags = 0, SV *callback = &PL_sv_undef)
1542     CODE:
1543     {
1544     dREQ (REQ_C_PGET);
1545     req->dbc = dbc;
1546     req->uint1 = flags;
1547     if ((flags & DB_SET) == DB_SET
1548     || (flags & DB_SET_RANGE) == DB_SET_RANGE)
1549     sv_to_dbt (&req->dbt1, key);
1550     else
1551     req->dbt1.flags = DB_DBT_MALLOC;
1552    
1553     req->sv1 = SvREFCNT_inc (key); SvREADONLY_on (key);
1554    
1555     req->dbt2.flags = DB_DBT_MALLOC;
1556     req->sv2 = SvREFCNT_inc (pkey); SvREADONLY_on (pkey);
1557    
1558     if ((flags & DB_GET_BOTH) == DB_GET_BOTH
1559     || (flags & DB_GET_BOTH_RANGE) == DB_GET_BOTH_RANGE)
1560     sv_to_dbt (&req->dbt3, data);
1561     else
1562     req->dbt3.flags = DB_DBT_MALLOC;
1563    
1564     req->sv3 = SvREFCNT_inc (data); SvREADONLY_on (data);
1565     REQ_SEND;
1566     }
1567    
1568     void
1569     db_c_del (DBC *dbc, U32 flags = 0, SV *callback = &PL_sv_undef)
1570     CODE:
1571     {
1572     dREQ (REQ_C_DEL);
1573     req->dbc = dbc;
1574     req->uint1 = flags;
1575     REQ_SEND;
1576     }
1577    
1578 root 1.2
1579 root 1.8 void
1580     db_sequence_open (DB_SEQUENCE *seq, DB_TXN_ornull *txnid, SV *key, U32 flags = 0, SV *callback = &PL_sv_undef)
1581     CODE:
1582     {
1583     dREQ (REQ_SEQ_OPEN);
1584     req->seq = seq;
1585     req->txn = txnid;
1586     req->uint1 = flags | DB_THREAD;
1587     sv_to_dbt (&req->dbt1, key);
1588     REQ_SEND;
1589     }
1590    
1591     void
1592     db_sequence_close (DB_SEQUENCE *seq, U32 flags = 0, SV *callback = &PL_sv_undef)
1593     CODE:
1594     {
1595     dREQ (REQ_SEQ_CLOSE);
1596     req->seq = seq;
1597     req->uint1 = flags;
1598     REQ_SEND;
1599     ptr_nuke (ST (0));
1600     }
1601    
1602     void
1603     db_sequence_get (DB_SEQUENCE *seq, DB_TXN_ornull *txnid, int delta, SV *seq_value, U32 flags = DB_TXN_NOSYNC, SV *callback = &PL_sv_undef)
1604     CODE:
1605     {
1606     dREQ (REQ_SEQ_GET);
1607     req->seq = seq;
1608     req->txn = txnid;
1609     req->int1 = delta;
1610     req->uint1 = flags;
1611     req->sv1 = SvREFCNT_inc (seq_value); SvREADONLY_on (seq_value);
1612     REQ_SEND;
1613     }
1614    
1615     void
1616     db_sequence_remove (DB_SEQUENCE *seq, DB_TXN_ornull *txnid = 0, U32 flags = 0, SV *callback = &PL_sv_undef)
1617     CODE:
1618     {
1619     dREQ (REQ_SEQ_REMOVE);
1620     req->seq = seq;
1621     req->txn = txnid;
1622     req->uint1 = flags;
1623     REQ_SEND;
1624     }
1625    
1626    
1627 root 1.2 MODULE = BDB PACKAGE = BDB::Env
1628    
1629 root 1.5 void
1630     DESTROY (DB_ENV_ornull *env)
1631     CODE:
1632     if (env)
1633     env->close (env, 0);
1634    
1635 root 1.8 int set_data_dir (DB_ENV *env, const char *dir)
1636     CODE:
1637     RETVAL = env->set_data_dir (env, dir);
1638     OUTPUT:
1639     RETVAL
1640    
1641     int set_tmp_dir (DB_ENV *env, const char *dir)
1642     CODE:
1643     RETVAL = env->set_tmp_dir (env, dir);
1644     OUTPUT:
1645     RETVAL
1646    
1647     int set_lg_dir (DB_ENV *env, const char *dir)
1648     CODE:
1649     RETVAL = env->set_lg_dir (env, dir);
1650     OUTPUT:
1651     RETVAL
1652    
1653     int set_shm_key (DB_ENV *env, long shm_key)
1654     CODE:
1655     RETVAL = env->set_shm_key (env, shm_key);
1656     OUTPUT:
1657     RETVAL
1658    
1659 root 1.2 int set_cachesize (DB_ENV *env, U32 gbytes, U32 bytes, int ncache = 0)
1660 root 1.3 CODE:
1661     RETVAL = env->set_cachesize (env, gbytes, bytes, ncache);
1662     OUTPUT:
1663     RETVAL
1664 root 1.2
1665     int set_flags (DB_ENV *env, U32 flags, int onoff)
1666 root 1.3 CODE:
1667     RETVAL = env->set_flags (env, flags, onoff);
1668     OUTPUT:
1669     RETVAL
1670    
1671 root 1.14 void set_errfile (DB_ENV *env, FILE *errfile)
1672     CODE:
1673     env->set_errfile (env, errfile);
1674    
1675     void set_msgfile (DB_ENV *env, FILE *msgfile)
1676     CODE:
1677     env->set_msgfile (env, msgfile);
1678    
1679     int set_verbose (DB_ENV *env, U32 which, int onoff = 1)
1680     CODE:
1681     RETVAL = env->set_verbose (env, which, onoff);
1682     OUTPUT:
1683     RETVAL
1684    
1685 root 1.3 int set_encrypt (DB_ENV *env, const char *password, U32 flags = 0)
1686     CODE:
1687     RETVAL = env->set_encrypt (env, password, flags);
1688     OUTPUT:
1689     RETVAL
1690    
1691     int set_timeout (DB_ENV *env, NV timeout, U32 flags)
1692     CODE:
1693     RETVAL = env->set_timeout (env, timeout * 1000000, flags);
1694     OUTPUT:
1695     RETVAL
1696 root 1.2
1697 root 1.8 int set_mp_max_openfd (DB_ENV *env, int maxopenfd);
1698     CODE:
1699     RETVAL = env->set_mp_max_openfd (env, maxopenfd);
1700     OUTPUT:
1701     RETVAL
1702    
1703     int set_mp_max_write (DB_ENV *env, int maxwrite, int maxwrite_sleep);
1704     CODE:
1705     RETVAL = env->set_mp_max_write (env, maxwrite, maxwrite_sleep);
1706     OUTPUT:
1707     RETVAL
1708    
1709     int set_mp_mmapsize (DB_ENV *env, int mmapsize_mb)
1710     CODE:
1711     RETVAL = env->set_mp_mmapsize (env, ((size_t)mmapsize_mb) << 20);
1712     OUTPUT:
1713     RETVAL
1714    
1715 root 1.9 int set_lk_detect (DB_ENV *env, U32 detect = DB_LOCK_DEFAULT)
1716 root 1.8 CODE:
1717     RETVAL = env->set_lk_detect (env, detect);
1718     OUTPUT:
1719     RETVAL
1720    
1721     int set_lk_max_lockers (DB_ENV *env, U32 max)
1722     CODE:
1723     RETVAL = env->set_lk_max_lockers (env, max);
1724     OUTPUT:
1725     RETVAL
1726    
1727     int set_lk_max_locks (DB_ENV *env, U32 max)
1728     CODE:
1729     RETVAL = env->set_lk_max_locks (env, max);
1730     OUTPUT:
1731     RETVAL
1732    
1733     int set_lk_max_objects (DB_ENV *env, U32 max)
1734     CODE:
1735     RETVAL = env->set_lk_max_objects (env, max);
1736     OUTPUT:
1737     RETVAL
1738    
1739     int set_lg_bsize (DB_ENV *env, U32 max)
1740     CODE:
1741     RETVAL = env->set_lg_bsize (env, max);
1742     OUTPUT:
1743     RETVAL
1744    
1745     int set_lg_max (DB_ENV *env, U32 max)
1746     CODE:
1747     RETVAL = env->set_lg_max (env, max);
1748     OUTPUT:
1749     RETVAL
1750    
1751 root 1.5 DB_TXN *
1752     txn_begin (DB_ENV *env, DB_TXN_ornull *parent = 0, U32 flags = 0)
1753     CODE:
1754     errno = env->txn_begin (env, parent, &RETVAL, flags);
1755     if (errno)
1756 root 1.6 croak ("DB_ENV->txn_begin: %s", db_strerror (errno));
1757 root 1.5 OUTPUT:
1758     RETVAL
1759 root 1.2
1760     MODULE = BDB PACKAGE = BDB::Db
1761    
1762 root 1.5 void
1763     DESTROY (DB_ornull *db)
1764     CODE:
1765     if (db)
1766     {
1767     SV *env = (SV *)db->app_private;
1768     db->close (db, 0);
1769     SvREFCNT_dec (env);
1770     }
1771    
1772 root 1.2 int set_cachesize (DB *db, U32 gbytes, U32 bytes, int ncache = 0)
1773 root 1.3 CODE:
1774     RETVAL = db->set_cachesize (db, gbytes, bytes, ncache);
1775     OUTPUT:
1776     RETVAL
1777 root 1.2
1778 root 1.3 int set_flags (DB *db, U32 flags);
1779     CODE:
1780     RETVAL = db->set_flags (db, flags);
1781     OUTPUT:
1782     RETVAL
1783 root 1.2
1784     int set_encrypt (DB *db, const char *password, U32 flags)
1785 root 1.3 CODE:
1786     RETVAL = db->set_encrypt (db, password, flags);
1787     OUTPUT:
1788     RETVAL
1789 root 1.2
1790     int set_lorder (DB *db, int lorder)
1791 root 1.3 CODE:
1792     RETVAL = db->set_lorder (db, lorder);
1793     OUTPUT:
1794     RETVAL
1795 root 1.2
1796     int set_bt_minkey (DB *db, U32 minkey)
1797 root 1.3 CODE:
1798     RETVAL = db->set_bt_minkey (db, minkey);
1799     OUTPUT:
1800     RETVAL
1801 root 1.2
1802     int set_re_delim(DB *db, int delim);
1803 root 1.3 CODE:
1804     RETVAL = db->set_re_delim (db, delim);
1805     OUTPUT:
1806     RETVAL
1807 root 1.2
1808     int set_re_pad (DB *db, int re_pad)
1809 root 1.3 CODE:
1810     RETVAL = db->set_re_pad (db, re_pad);
1811     OUTPUT:
1812     RETVAL
1813 root 1.2
1814     int set_re_source (DB *db, char *source)
1815 root 1.3 CODE:
1816     RETVAL = db->set_re_source (db, source);
1817     OUTPUT:
1818     RETVAL
1819 root 1.2
1820     int set_re_len (DB *db, U32 re_len)
1821 root 1.3 CODE:
1822     RETVAL = db->set_re_len (db, re_len);
1823     OUTPUT:
1824     RETVAL
1825 root 1.2
1826     int set_h_ffactor (DB *db, U32 h_ffactor)
1827 root 1.3 CODE:
1828     RETVAL = db->set_h_ffactor (db, h_ffactor);
1829     OUTPUT:
1830     RETVAL
1831 root 1.2
1832     int set_h_nelem (DB *db, U32 h_nelem)
1833 root 1.3 CODE:
1834     RETVAL = db->set_h_nelem (db, h_nelem);
1835     OUTPUT:
1836     RETVAL
1837 root 1.2
1838     int set_q_extentsize (DB *db, U32 extentsize)
1839 root 1.3 CODE:
1840     RETVAL = db->set_q_extentsize (db, extentsize);
1841     OUTPUT:
1842     RETVAL
1843 root 1.2
1844 root 1.6 DBC *
1845     cursor (DB *db, DB_TXN_ornull *txn = 0, U32 flags = 0)
1846     CODE:
1847     errno = db->cursor (db, txn, &RETVAL, flags);
1848     if (errno)
1849     croak ("DB->cursor: %s", db_strerror (errno));
1850     OUTPUT:
1851     RETVAL
1852    
1853 root 1.8 DB_SEQUENCE *
1854     sequence (DB *db, U32 flags = 0)
1855     CODE:
1856     {
1857     errno = db_sequence_create (&RETVAL, db, flags);
1858     if (errno)
1859     croak ("db_sequence_create: %s", db_strerror (errno));
1860     }
1861     OUTPUT:
1862     RETVAL
1863    
1864 root 1.6
1865 root 1.5 MODULE = BDB PACKAGE = BDB::Txn
1866    
1867     void
1868     DESTROY (DB_TXN_ornull *txn)
1869     CODE:
1870     if (txn)
1871     txn->abort (txn);
1872    
1873     int set_timeout (DB_TXN *txn, NV timeout, U32 flags)
1874     CODE:
1875     RETVAL = txn->set_timeout (txn, timeout * 1000000, flags);
1876     OUTPUT:
1877     RETVAL
1878    
1879 root 1.1
1880 root 1.6 MODULE = BDB PACKAGE = BDB::Cursor
1881    
1882     void
1883     DESTROY (DBC_ornull *dbc)
1884     CODE:
1885     if (dbc)
1886     dbc->c_close (dbc);
1887    
1888 root 1.8 MODULE = BDB PACKAGE = BDB::Sequence
1889    
1890     void
1891     DESTROY (DB_SEQUENCE_ornull *seq)
1892     CODE:
1893     if (seq)
1894     seq->close (seq, 0);
1895    
1896     int initial_value (DB_SEQUENCE *seq, db_seq_t value)
1897     CODE:
1898     RETVAL = seq->initial_value (seq, value);
1899     OUTPUT:
1900     RETVAL
1901    
1902     int set_cachesize (DB_SEQUENCE *seq, U32 size)
1903     CODE:
1904     RETVAL = seq->set_cachesize (seq, size);
1905     OUTPUT:
1906     RETVAL
1907    
1908     int set_flags (DB_SEQUENCE *seq, U32 flags)
1909     CODE:
1910     RETVAL = seq->set_flags (seq, flags);
1911     OUTPUT:
1912     RETVAL
1913    
1914     int set_range (DB_SEQUENCE *seq, db_seq_t min, db_seq_t max)
1915     CODE:
1916     RETVAL = seq->set_range (seq, min, max);
1917     OUTPUT:
1918     RETVAL
1919