ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/BDB/BDB.xs
Revision: 1.6
Committed: Tue Feb 6 01:09:04 2007 UTC (17 years, 3 months ago) by root
Branch: MAIN
Changes since 1.5: +206 -18 lines
Log Message:
*** empty log message ***

File Contents

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