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