ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/BDB/BDB.xs
Revision: 1.15
Committed: Mon Aug 13 11:16:22 2007 UTC (16 years, 9 months ago) by root
Branch: MAIN
Changes since 1.14: +3 -0 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.15 #if DB_VERSION_MINOR >= 6
1079     const_iv (DB_PREV_DUP)
1080     #endif
1081 root 1.2 };
1082    
1083     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1084     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
1085 root 1.1
1086 root 1.14 newCONSTSUB (stash, "DB_VERSION", newSVnv (DB_VERSION_MAJOR + DB_VERSION_MINOR * .1));
1087     newCONSTSUB (stash, "DB_VERSION_STRING", newSVpv (DB_VERSION_STRING, 0));
1088    
1089 root 1.13 create_pipe (respipe);
1090 root 1.12
1091     X_THREAD_ATFORK (atfork_prepare, atfork_parent, atfork_child);
1092     #ifdef _WIN32
1093     X_MUTEX_CHECK (wrklock);
1094     X_MUTEX_CHECK (reslock);
1095     X_MUTEX_CHECK (reqlock);
1096    
1097     X_COND_CHECK (reqwait);
1098     #endif
1099 root 1.1 }
1100    
1101     void
1102     max_poll_reqs (int nreqs)
1103     PROTOTYPE: $
1104     CODE:
1105     max_poll_reqs = nreqs;
1106    
1107     void
1108     max_poll_time (double nseconds)
1109     PROTOTYPE: $
1110     CODE:
1111     max_poll_time = nseconds * AIO_TICKS;
1112    
1113     void
1114     min_parallel (int nthreads)
1115     PROTOTYPE: $
1116    
1117     void
1118     max_parallel (int nthreads)
1119     PROTOTYPE: $
1120    
1121     void
1122     max_idle (int nthreads)
1123     PROTOTYPE: $
1124     CODE:
1125     set_max_idle (nthreads);
1126    
1127     int
1128     max_outstanding (int maxreqs)
1129     PROTOTYPE: $
1130     CODE:
1131     RETVAL = max_outstanding;
1132     max_outstanding = maxreqs;
1133     OUTPUT:
1134     RETVAL
1135    
1136     int
1137 root 1.3 dbreq_pri (int pri = 0)
1138 root 1.1 PROTOTYPE: ;$
1139     CODE:
1140     RETVAL = next_pri - PRI_BIAS;
1141     if (items > 0)
1142     {
1143     if (pri < PRI_MIN) pri = PRI_MIN;
1144     if (pri > PRI_MAX) pri = PRI_MAX;
1145     next_pri = pri + PRI_BIAS;
1146     }
1147     OUTPUT:
1148     RETVAL
1149    
1150     void
1151 root 1.3 dbreq_nice (int nice = 0)
1152 root 1.1 CODE:
1153     nice = next_pri - nice;
1154     if (nice < PRI_MIN) nice = PRI_MIN;
1155     if (nice > PRI_MAX) nice = PRI_MAX;
1156     next_pri = nice + PRI_BIAS;
1157    
1158     void
1159     flush ()
1160     PROTOTYPE:
1161     CODE:
1162     while (nreqs)
1163     {
1164     poll_wait ();
1165     poll_cb ();
1166     }
1167    
1168     int
1169 root 1.3 poll ()
1170 root 1.1 PROTOTYPE:
1171     CODE:
1172     poll_wait ();
1173     RETVAL = poll_cb ();
1174     OUTPUT:
1175     RETVAL
1176    
1177     int
1178 root 1.3 poll_fileno ()
1179 root 1.1 PROTOTYPE:
1180     CODE:
1181     RETVAL = respipe [0];
1182     OUTPUT:
1183     RETVAL
1184    
1185     int
1186 root 1.3 poll_cb (...)
1187 root 1.1 PROTOTYPE:
1188     CODE:
1189     RETVAL = poll_cb ();
1190     OUTPUT:
1191     RETVAL
1192    
1193     void
1194 root 1.3 poll_wait ()
1195 root 1.1 PROTOTYPE:
1196     CODE:
1197     poll_wait ();
1198    
1199     int
1200 root 1.3 nreqs ()
1201 root 1.1 PROTOTYPE:
1202     CODE:
1203     RETVAL = nreqs;
1204     OUTPUT:
1205     RETVAL
1206    
1207     int
1208 root 1.3 nready ()
1209 root 1.1 PROTOTYPE:
1210     CODE:
1211     RETVAL = get_nready ();
1212     OUTPUT:
1213     RETVAL
1214    
1215     int
1216 root 1.3 npending ()
1217 root 1.1 PROTOTYPE:
1218     CODE:
1219     RETVAL = get_npending ();
1220     OUTPUT:
1221     RETVAL
1222    
1223     int
1224 root 1.3 nthreads ()
1225 root 1.1 PROTOTYPE:
1226     CODE:
1227 root 1.12 if (WORDACCESS_UNSAFE) X_LOCK (wrklock);
1228 root 1.1 RETVAL = started;
1229 root 1.12 if (WORDACCESS_UNSAFE) X_UNLOCK (wrklock);
1230 root 1.1 OUTPUT:
1231     RETVAL
1232    
1233 root 1.3 void
1234     set_sync_prepare (SV *cb)
1235     PROTOTYPE: &
1236     CODE:
1237     SvREFCNT_dec (prepare_cb);
1238     prepare_cb = newSVsv (cb);
1239    
1240 root 1.14 char *
1241     strerror (int errorno = errno)
1242     PROTOTYPE: ;$
1243     CODE:
1244     RETVAL = db_strerror (errorno);
1245     OUTPUT:
1246     RETVAL
1247 root 1.8
1248 root 1.2 DB_ENV *
1249 root 1.3 db_env_create (U32 env_flags = 0)
1250 root 1.2 CODE:
1251     {
1252 root 1.3 errno = db_env_create (&RETVAL, env_flags);
1253     if (errno)
1254     croak ("db_env_create: %s", db_strerror (errno));
1255 root 1.14
1256     if (0)
1257     {
1258     RETVAL->set_errcall (RETVAL, debug_errcall);
1259     RETVAL->set_msgcall (RETVAL, debug_msgcall);
1260     }
1261 root 1.2 }
1262 root 1.3 OUTPUT:
1263     RETVAL
1264 root 1.2
1265     void
1266 root 1.3 db_env_open (DB_ENV *env, octetstring db_home, U32 open_flags, int mode, SV *callback = &PL_sv_undef)
1267 root 1.2 CODE:
1268     {
1269 root 1.13 dREQ (REQ_ENV_OPEN);
1270    
1271 root 1.14 env->set_thread_count (env, wanted + 2);
1272 root 1.8
1273 root 1.2 req->env = env;
1274 root 1.3 req->uint1 = open_flags | DB_THREAD;
1275 root 1.2 req->int1 = mode;
1276 root 1.3 req->buf1 = strdup_ornull (db_home);
1277 root 1.2 REQ_SEND;
1278     }
1279    
1280     void
1281 root 1.3 db_env_close (DB_ENV *env, U32 flags = 0, SV *callback = &PL_sv_undef)
1282 root 1.2 CODE:
1283     {
1284     dREQ (REQ_ENV_CLOSE);
1285     req->env = env;
1286     req->uint1 = flags;
1287     REQ_SEND;
1288 root 1.5 ptr_nuke (ST (0));
1289 root 1.2 }
1290    
1291 root 1.8 void
1292     db_env_txn_checkpoint (DB_ENV *env, U32 kbyte = 0, U32 min = 0, U32 flags = 0, SV *callback = &PL_sv_undef)
1293     CODE:
1294     {
1295     dREQ (REQ_ENV_TXN_CHECKPOINT);
1296     req->env = env;
1297     req->uint1 = kbyte;
1298     req->int1 = min;
1299     req->uint2 = flags;
1300     REQ_SEND;
1301     }
1302    
1303     void
1304     db_env_lock_detect (DB_ENV *env, U32 flags = 0, U32 atype = DB_LOCK_DEFAULT, SV *dummy = 0, SV *callback = &PL_sv_undef)
1305     CODE:
1306     {
1307     dREQ (REQ_ENV_LOCK_DETECT);
1308     req->env = env;
1309     req->uint1 = flags;
1310     req->uint2 = atype;
1311     REQ_SEND;
1312     }
1313    
1314     void
1315     db_env_memp_sync (DB_ENV *env, SV *dummy = 0, SV *callback = &PL_sv_undef)
1316     CODE:
1317     {
1318     dREQ (REQ_ENV_MEMP_SYNC);
1319     req->env = env;
1320     REQ_SEND;
1321     }
1322    
1323     void
1324     db_env_memp_trickle (DB_ENV *env, int percent, SV *dummy = 0, SV *callback = &PL_sv_undef)
1325     CODE:
1326     {
1327     dREQ (REQ_ENV_MEMP_TRICKLE);
1328     req->env = env;
1329     req->int1 = percent;
1330     REQ_SEND;
1331     }
1332    
1333    
1334 root 1.2 DB *
1335 root 1.3 db_create (DB_ENV *env = 0, U32 flags = 0)
1336 root 1.2 CODE:
1337     {
1338 root 1.3 errno = db_create (&RETVAL, env, flags);
1339     if (errno)
1340 root 1.6 croak ("db_create: %s", db_strerror (errno));
1341 root 1.5
1342     if (RETVAL)
1343     RETVAL->app_private = (void *)newSVsv (ST (0));
1344 root 1.2 }
1345 root 1.3 OUTPUT:
1346     RETVAL
1347 root 1.2
1348     void
1349 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)
1350 root 1.2 CODE:
1351     {
1352     dREQ (REQ_DB_OPEN);
1353     req->db = db;
1354     req->txn = txnid;
1355 root 1.3 req->buf1 = strdup_ornull (file);
1356     req->buf2 = strdup_ornull (database);
1357 root 1.2 req->int1 = type;
1358 root 1.3 req->uint1 = flags | DB_THREAD;
1359 root 1.2 req->int2 = mode;
1360     REQ_SEND;
1361     }
1362    
1363     void
1364 root 1.3 db_close (DB *db, U32 flags = 0, SV *callback = &PL_sv_undef)
1365 root 1.2 CODE:
1366     {
1367     dREQ (REQ_DB_CLOSE);
1368     req->db = db;
1369     req->uint1 = flags;
1370 root 1.5 req->sv1 = (SV *)db->app_private;
1371 root 1.2 REQ_SEND;
1372 root 1.5 ptr_nuke (ST (0));
1373 root 1.2 }
1374    
1375 root 1.3 void
1376 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)
1377 root 1.3 CODE:
1378     {
1379     dREQ (REQ_DB_COMPACT);
1380     req->db = db;
1381     req->txn = txn;
1382 root 1.5 sv_to_dbt (&req->dbt1, start);
1383     sv_to_dbt (&req->dbt2, stop);
1384 root 1.3 req->uint1 = flags;
1385     REQ_SEND;
1386     }
1387    
1388     void
1389     db_sync (DB *db, U32 flags = 0, SV *callback = &PL_sv_undef)
1390     CODE:
1391     {
1392     dREQ (REQ_DB_SYNC);
1393     req->db = db;
1394     req->uint1 = flags;
1395     REQ_SEND;
1396     }
1397    
1398     void
1399 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)
1400     CODE:
1401     {
1402     dREQ (REQ_DB_KEY_RANGE);
1403     req->db = db;
1404     req->txn = txn;
1405     sv_to_dbt (&req->dbt1, key);
1406     req->uint1 = flags;
1407     req->sv1 = SvREFCNT_inc (key_range); SvREADONLY_on (key_range);
1408     REQ_SEND;
1409     }
1410    
1411     void
1412 root 1.5 db_put (DB *db, DB_TXN_ornull *txn, SV *key, SV *data, U32 flags = 0, SV *callback = &PL_sv_undef)
1413 root 1.3 CODE:
1414     {
1415     dREQ (REQ_DB_PUT);
1416     req->db = db;
1417 root 1.5 req->txn = txn;
1418     sv_to_dbt (&req->dbt1, key);
1419     sv_to_dbt (&req->dbt2, data);
1420 root 1.3 req->uint1 = flags;
1421     REQ_SEND;
1422     }
1423    
1424 root 1.5 void
1425     db_get (DB *db, DB_TXN_ornull *txn, SV *key, SV *data, U32 flags = 0, SV *callback = &PL_sv_undef)
1426     CODE:
1427     {
1428     dREQ (REQ_DB_GET);
1429     req->db = db;
1430     req->txn = txn;
1431 root 1.6 req->uint1 = flags;
1432 root 1.5 sv_to_dbt (&req->dbt1, key);
1433     req->dbt3.flags = DB_DBT_MALLOC;
1434 root 1.6 req->sv3 = SvREFCNT_inc (data); SvREADONLY_on (data);
1435 root 1.5 REQ_SEND;
1436     }
1437    
1438     void
1439     db_pget (DB *db, DB_TXN_ornull *txn, SV *key, SV *pkey, SV *data, U32 flags = 0, SV *callback = &PL_sv_undef)
1440     CODE:
1441     {
1442     dREQ (REQ_DB_PGET);
1443     req->db = db;
1444     req->txn = txn;
1445 root 1.6 req->uint1 = flags;
1446 root 1.5 sv_to_dbt (&req->dbt1, key);
1447     sv_to_dbt (&req->dbt2, pkey);
1448     req->dbt3.flags = DB_DBT_MALLOC;
1449 root 1.6 req->sv3 = SvREFCNT_inc (data); SvREADONLY_on (data);
1450     REQ_SEND;
1451     }
1452    
1453     void
1454     db_del (DB *db, DB_TXN_ornull *txn, SV *key, U32 flags = 0, SV *callback = &PL_sv_undef)
1455     CODE:
1456     {
1457     dREQ (REQ_DB_DEL);
1458     req->db = db;
1459     req->txn = txn;
1460 root 1.5 req->uint1 = flags;
1461 root 1.6 sv_to_dbt (&req->dbt1, key);
1462 root 1.5 REQ_SEND;
1463     }
1464    
1465     void
1466     db_txn_commit (DB_TXN *txn, U32 flags = 0, SV *callback = &PL_sv_undef)
1467     CODE:
1468     {
1469     dREQ (REQ_TXN_COMMIT);
1470     req->txn = txn;
1471     req->uint1 = flags;
1472     REQ_SEND;
1473     ptr_nuke (ST (0));
1474     }
1475    
1476     void
1477     db_txn_abort (DB_TXN *txn, SV *callback = &PL_sv_undef)
1478     CODE:
1479     {
1480     dREQ (REQ_TXN_ABORT);
1481     req->txn = txn;
1482     REQ_SEND;
1483     ptr_nuke (ST (0));
1484     }
1485    
1486 root 1.6 void
1487     db_c_close (DBC *dbc, SV *callback = &PL_sv_undef)
1488     CODE:
1489     {
1490     dREQ (REQ_C_CLOSE);
1491     req->dbc = dbc;
1492     REQ_SEND;
1493     ptr_nuke (ST (0));
1494     }
1495    
1496     void
1497     db_c_count (DBC *dbc, SV *count, U32 flags = 0, SV *callback = &PL_sv_undef)
1498     CODE:
1499     {
1500     dREQ (REQ_C_COUNT);
1501     req->dbc = dbc;
1502     req->sv1 = SvREFCNT_inc (count);
1503     REQ_SEND;
1504     }
1505    
1506     void
1507     db_c_put (DBC *dbc, SV *key, SV *data, U32 flags = 0, SV *callback = &PL_sv_undef)
1508     CODE:
1509     {
1510     dREQ (REQ_C_PUT);
1511     req->dbc = dbc;
1512     sv_to_dbt (&req->dbt1, key);
1513     sv_to_dbt (&req->dbt2, data);
1514     req->uint1 = flags;
1515     REQ_SEND;
1516     }
1517    
1518     void
1519     db_c_get (DBC *dbc, SV *key, SV *data, U32 flags = 0, SV *callback = &PL_sv_undef)
1520     CODE:
1521     {
1522     dREQ (REQ_C_GET);
1523     req->dbc = dbc;
1524     req->uint1 = flags;
1525     if ((flags & DB_SET) == DB_SET
1526     || (flags & DB_SET_RANGE) == DB_SET_RANGE)
1527     sv_to_dbt (&req->dbt1, key);
1528     else
1529     req->dbt1.flags = DB_DBT_MALLOC;
1530    
1531     req->sv1 = SvREFCNT_inc (key); SvREADONLY_on (key);
1532    
1533     if ((flags & DB_GET_BOTH) == DB_GET_BOTH
1534     || (flags & DB_GET_BOTH_RANGE) == DB_GET_BOTH_RANGE)
1535     sv_to_dbt (&req->dbt3, data);
1536     else
1537     req->dbt3.flags = DB_DBT_MALLOC;
1538    
1539     req->sv3 = SvREFCNT_inc (data); SvREADONLY_on (data);
1540     REQ_SEND;
1541     }
1542    
1543     void
1544     db_c_pget (DBC *dbc, SV *key, SV *pkey, SV *data, U32 flags = 0, SV *callback = &PL_sv_undef)
1545     CODE:
1546     {
1547     dREQ (REQ_C_PGET);
1548     req->dbc = dbc;
1549     req->uint1 = flags;
1550     if ((flags & DB_SET) == DB_SET
1551     || (flags & DB_SET_RANGE) == DB_SET_RANGE)
1552     sv_to_dbt (&req->dbt1, key);
1553     else
1554     req->dbt1.flags = DB_DBT_MALLOC;
1555    
1556     req->sv1 = SvREFCNT_inc (key); SvREADONLY_on (key);
1557    
1558     req->dbt2.flags = DB_DBT_MALLOC;
1559     req->sv2 = SvREFCNT_inc (pkey); SvREADONLY_on (pkey);
1560    
1561     if ((flags & DB_GET_BOTH) == DB_GET_BOTH
1562     || (flags & DB_GET_BOTH_RANGE) == DB_GET_BOTH_RANGE)
1563     sv_to_dbt (&req->dbt3, data);
1564     else
1565     req->dbt3.flags = DB_DBT_MALLOC;
1566    
1567     req->sv3 = SvREFCNT_inc (data); SvREADONLY_on (data);
1568     REQ_SEND;
1569     }
1570    
1571     void
1572     db_c_del (DBC *dbc, U32 flags = 0, SV *callback = &PL_sv_undef)
1573     CODE:
1574     {
1575     dREQ (REQ_C_DEL);
1576     req->dbc = dbc;
1577     req->uint1 = flags;
1578     REQ_SEND;
1579     }
1580    
1581 root 1.2
1582 root 1.8 void
1583     db_sequence_open (DB_SEQUENCE *seq, DB_TXN_ornull *txnid, SV *key, U32 flags = 0, SV *callback = &PL_sv_undef)
1584     CODE:
1585     {
1586     dREQ (REQ_SEQ_OPEN);
1587     req->seq = seq;
1588     req->txn = txnid;
1589     req->uint1 = flags | DB_THREAD;
1590     sv_to_dbt (&req->dbt1, key);
1591     REQ_SEND;
1592     }
1593    
1594     void
1595     db_sequence_close (DB_SEQUENCE *seq, U32 flags = 0, SV *callback = &PL_sv_undef)
1596     CODE:
1597     {
1598     dREQ (REQ_SEQ_CLOSE);
1599     req->seq = seq;
1600     req->uint1 = flags;
1601     REQ_SEND;
1602     ptr_nuke (ST (0));
1603     }
1604    
1605     void
1606     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)
1607     CODE:
1608     {
1609     dREQ (REQ_SEQ_GET);
1610     req->seq = seq;
1611     req->txn = txnid;
1612     req->int1 = delta;
1613     req->uint1 = flags;
1614     req->sv1 = SvREFCNT_inc (seq_value); SvREADONLY_on (seq_value);
1615     REQ_SEND;
1616     }
1617    
1618     void
1619     db_sequence_remove (DB_SEQUENCE *seq, DB_TXN_ornull *txnid = 0, U32 flags = 0, SV *callback = &PL_sv_undef)
1620     CODE:
1621     {
1622     dREQ (REQ_SEQ_REMOVE);
1623     req->seq = seq;
1624     req->txn = txnid;
1625     req->uint1 = flags;
1626     REQ_SEND;
1627     }
1628    
1629    
1630 root 1.2 MODULE = BDB PACKAGE = BDB::Env
1631    
1632 root 1.5 void
1633     DESTROY (DB_ENV_ornull *env)
1634     CODE:
1635     if (env)
1636     env->close (env, 0);
1637    
1638 root 1.8 int set_data_dir (DB_ENV *env, const char *dir)
1639     CODE:
1640     RETVAL = env->set_data_dir (env, dir);
1641     OUTPUT:
1642     RETVAL
1643    
1644     int set_tmp_dir (DB_ENV *env, const char *dir)
1645     CODE:
1646     RETVAL = env->set_tmp_dir (env, dir);
1647     OUTPUT:
1648     RETVAL
1649    
1650     int set_lg_dir (DB_ENV *env, const char *dir)
1651     CODE:
1652     RETVAL = env->set_lg_dir (env, dir);
1653     OUTPUT:
1654     RETVAL
1655    
1656     int set_shm_key (DB_ENV *env, long shm_key)
1657     CODE:
1658     RETVAL = env->set_shm_key (env, shm_key);
1659     OUTPUT:
1660     RETVAL
1661    
1662 root 1.2 int set_cachesize (DB_ENV *env, U32 gbytes, U32 bytes, int ncache = 0)
1663 root 1.3 CODE:
1664     RETVAL = env->set_cachesize (env, gbytes, bytes, ncache);
1665     OUTPUT:
1666     RETVAL
1667 root 1.2
1668     int set_flags (DB_ENV *env, U32 flags, int onoff)
1669 root 1.3 CODE:
1670     RETVAL = env->set_flags (env, flags, onoff);
1671     OUTPUT:
1672     RETVAL
1673    
1674 root 1.14 void set_errfile (DB_ENV *env, FILE *errfile)
1675     CODE:
1676     env->set_errfile (env, errfile);
1677    
1678     void set_msgfile (DB_ENV *env, FILE *msgfile)
1679     CODE:
1680     env->set_msgfile (env, msgfile);
1681    
1682     int set_verbose (DB_ENV *env, U32 which, int onoff = 1)
1683     CODE:
1684     RETVAL = env->set_verbose (env, which, onoff);
1685     OUTPUT:
1686     RETVAL
1687    
1688 root 1.3 int set_encrypt (DB_ENV *env, const char *password, U32 flags = 0)
1689     CODE:
1690     RETVAL = env->set_encrypt (env, password, flags);
1691     OUTPUT:
1692     RETVAL
1693    
1694     int set_timeout (DB_ENV *env, NV timeout, U32 flags)
1695     CODE:
1696     RETVAL = env->set_timeout (env, timeout * 1000000, flags);
1697     OUTPUT:
1698     RETVAL
1699 root 1.2
1700 root 1.8 int set_mp_max_openfd (DB_ENV *env, int maxopenfd);
1701     CODE:
1702     RETVAL = env->set_mp_max_openfd (env, maxopenfd);
1703     OUTPUT:
1704     RETVAL
1705    
1706     int set_mp_max_write (DB_ENV *env, int maxwrite, int maxwrite_sleep);
1707     CODE:
1708     RETVAL = env->set_mp_max_write (env, maxwrite, maxwrite_sleep);
1709     OUTPUT:
1710     RETVAL
1711    
1712     int set_mp_mmapsize (DB_ENV *env, int mmapsize_mb)
1713     CODE:
1714     RETVAL = env->set_mp_mmapsize (env, ((size_t)mmapsize_mb) << 20);
1715     OUTPUT:
1716     RETVAL
1717    
1718 root 1.9 int set_lk_detect (DB_ENV *env, U32 detect = DB_LOCK_DEFAULT)
1719 root 1.8 CODE:
1720     RETVAL = env->set_lk_detect (env, detect);
1721     OUTPUT:
1722     RETVAL
1723    
1724     int set_lk_max_lockers (DB_ENV *env, U32 max)
1725     CODE:
1726     RETVAL = env->set_lk_max_lockers (env, max);
1727     OUTPUT:
1728     RETVAL
1729    
1730     int set_lk_max_locks (DB_ENV *env, U32 max)
1731     CODE:
1732     RETVAL = env->set_lk_max_locks (env, max);
1733     OUTPUT:
1734     RETVAL
1735    
1736     int set_lk_max_objects (DB_ENV *env, U32 max)
1737     CODE:
1738     RETVAL = env->set_lk_max_objects (env, max);
1739     OUTPUT:
1740     RETVAL
1741    
1742     int set_lg_bsize (DB_ENV *env, U32 max)
1743     CODE:
1744     RETVAL = env->set_lg_bsize (env, max);
1745     OUTPUT:
1746     RETVAL
1747    
1748     int set_lg_max (DB_ENV *env, U32 max)
1749     CODE:
1750     RETVAL = env->set_lg_max (env, max);
1751     OUTPUT:
1752     RETVAL
1753    
1754 root 1.5 DB_TXN *
1755     txn_begin (DB_ENV *env, DB_TXN_ornull *parent = 0, U32 flags = 0)
1756     CODE:
1757     errno = env->txn_begin (env, parent, &RETVAL, flags);
1758     if (errno)
1759 root 1.6 croak ("DB_ENV->txn_begin: %s", db_strerror (errno));
1760 root 1.5 OUTPUT:
1761     RETVAL
1762 root 1.2
1763     MODULE = BDB PACKAGE = BDB::Db
1764    
1765 root 1.5 void
1766     DESTROY (DB_ornull *db)
1767     CODE:
1768     if (db)
1769     {
1770     SV *env = (SV *)db->app_private;
1771     db->close (db, 0);
1772     SvREFCNT_dec (env);
1773     }
1774    
1775 root 1.2 int set_cachesize (DB *db, U32 gbytes, U32 bytes, int ncache = 0)
1776 root 1.3 CODE:
1777     RETVAL = db->set_cachesize (db, gbytes, bytes, ncache);
1778     OUTPUT:
1779     RETVAL
1780 root 1.2
1781 root 1.3 int set_flags (DB *db, U32 flags);
1782     CODE:
1783     RETVAL = db->set_flags (db, flags);
1784     OUTPUT:
1785     RETVAL
1786 root 1.2
1787     int set_encrypt (DB *db, const char *password, U32 flags)
1788 root 1.3 CODE:
1789     RETVAL = db->set_encrypt (db, password, flags);
1790     OUTPUT:
1791     RETVAL
1792 root 1.2
1793     int set_lorder (DB *db, int lorder)
1794 root 1.3 CODE:
1795     RETVAL = db->set_lorder (db, lorder);
1796     OUTPUT:
1797     RETVAL
1798 root 1.2
1799     int set_bt_minkey (DB *db, U32 minkey)
1800 root 1.3 CODE:
1801     RETVAL = db->set_bt_minkey (db, minkey);
1802     OUTPUT:
1803     RETVAL
1804 root 1.2
1805     int set_re_delim(DB *db, int delim);
1806 root 1.3 CODE:
1807     RETVAL = db->set_re_delim (db, delim);
1808     OUTPUT:
1809     RETVAL
1810 root 1.2
1811     int set_re_pad (DB *db, int re_pad)
1812 root 1.3 CODE:
1813     RETVAL = db->set_re_pad (db, re_pad);
1814     OUTPUT:
1815     RETVAL
1816 root 1.2
1817     int set_re_source (DB *db, char *source)
1818 root 1.3 CODE:
1819     RETVAL = db->set_re_source (db, source);
1820     OUTPUT:
1821     RETVAL
1822 root 1.2
1823     int set_re_len (DB *db, U32 re_len)
1824 root 1.3 CODE:
1825     RETVAL = db->set_re_len (db, re_len);
1826     OUTPUT:
1827     RETVAL
1828 root 1.2
1829     int set_h_ffactor (DB *db, U32 h_ffactor)
1830 root 1.3 CODE:
1831     RETVAL = db->set_h_ffactor (db, h_ffactor);
1832     OUTPUT:
1833     RETVAL
1834 root 1.2
1835     int set_h_nelem (DB *db, U32 h_nelem)
1836 root 1.3 CODE:
1837     RETVAL = db->set_h_nelem (db, h_nelem);
1838     OUTPUT:
1839     RETVAL
1840 root 1.2
1841     int set_q_extentsize (DB *db, U32 extentsize)
1842 root 1.3 CODE:
1843     RETVAL = db->set_q_extentsize (db, extentsize);
1844     OUTPUT:
1845     RETVAL
1846 root 1.2
1847 root 1.6 DBC *
1848     cursor (DB *db, DB_TXN_ornull *txn = 0, U32 flags = 0)
1849     CODE:
1850     errno = db->cursor (db, txn, &RETVAL, flags);
1851     if (errno)
1852     croak ("DB->cursor: %s", db_strerror (errno));
1853     OUTPUT:
1854     RETVAL
1855    
1856 root 1.8 DB_SEQUENCE *
1857     sequence (DB *db, U32 flags = 0)
1858     CODE:
1859     {
1860     errno = db_sequence_create (&RETVAL, db, flags);
1861     if (errno)
1862     croak ("db_sequence_create: %s", db_strerror (errno));
1863     }
1864     OUTPUT:
1865     RETVAL
1866    
1867 root 1.6
1868 root 1.5 MODULE = BDB PACKAGE = BDB::Txn
1869    
1870     void
1871     DESTROY (DB_TXN_ornull *txn)
1872     CODE:
1873     if (txn)
1874     txn->abort (txn);
1875    
1876     int set_timeout (DB_TXN *txn, NV timeout, U32 flags)
1877     CODE:
1878     RETVAL = txn->set_timeout (txn, timeout * 1000000, flags);
1879     OUTPUT:
1880     RETVAL
1881    
1882 root 1.1
1883 root 1.6 MODULE = BDB PACKAGE = BDB::Cursor
1884    
1885     void
1886     DESTROY (DBC_ornull *dbc)
1887     CODE:
1888     if (dbc)
1889     dbc->c_close (dbc);
1890    
1891 root 1.8 MODULE = BDB PACKAGE = BDB::Sequence
1892    
1893     void
1894     DESTROY (DB_SEQUENCE_ornull *seq)
1895     CODE:
1896     if (seq)
1897     seq->close (seq, 0);
1898    
1899     int initial_value (DB_SEQUENCE *seq, db_seq_t value)
1900     CODE:
1901     RETVAL = seq->initial_value (seq, value);
1902     OUTPUT:
1903     RETVAL
1904    
1905     int set_cachesize (DB_SEQUENCE *seq, U32 size)
1906     CODE:
1907     RETVAL = seq->set_cachesize (seq, size);
1908     OUTPUT:
1909     RETVAL
1910    
1911     int set_flags (DB_SEQUENCE *seq, U32 flags)
1912     CODE:
1913     RETVAL = seq->set_flags (seq, flags);
1914     OUTPUT:
1915     RETVAL
1916    
1917     int set_range (DB_SEQUENCE *seq, db_seq_t min, db_seq_t max)
1918     CODE:
1919     RETVAL = seq->set_range (seq, min, max);
1920     OUTPUT:
1921     RETVAL
1922