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