ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/BDB/BDB.xs
Revision: 1.2
Committed: Mon Feb 5 20:21:38 2007 UTC (17 years, 3 months ago) by root
Branch: MAIN
Changes since 1.1: +215 -20 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     typedef SV SV8; /* byte-sv, used for argument-checking */
46    
47 root 1.2 enum
48     {
49 root 1.1 REQ_QUIT,
50 root 1.2 REQ_ENV_OPEN, REQ_ENV_CLOSE,
51     REQ_DB_OPEN, REQ_DB_CLOSE,
52 root 1.1 };
53    
54     typedef struct aio_cb
55     {
56 root 1.2 struct aio_cb *volatile next;
57     SV *callback;
58     int type, pri, errorno;
59    
60     DB_ENV *env;
61     DB *db;
62     DB_TXN *txn;
63     DBC *cursor;
64     int int1, int2;
65     U32 uint1, uint2;
66     char *buf1, *buf2;
67 root 1.1 } aio_cb;
68    
69     typedef aio_cb *aio_req;
70    
71     enum {
72     PRI_MIN = -4,
73     PRI_MAX = 4,
74    
75     DEFAULT_PRI = 0,
76     PRI_BIAS = -PRI_MIN,
77     NUM_PRI = PRI_MAX + PRI_BIAS + 1,
78     };
79    
80     #define AIO_TICKS ((1000000 + 1023) >> 10)
81    
82     static unsigned int max_poll_time = 0;
83     static unsigned int max_poll_reqs = 0;
84    
85     /* calculcate time difference in ~1/AIO_TICKS of a second */
86     static int tvdiff (struct timeval *tv1, struct timeval *tv2)
87     {
88     return (tv2->tv_sec - tv1->tv_sec ) * AIO_TICKS
89     + ((tv2->tv_usec - tv1->tv_usec) >> 10);
90     }
91    
92     static int next_pri = DEFAULT_PRI + PRI_BIAS;
93    
94     static unsigned int started, idle, wanted;
95    
96     #if __linux && defined (PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP)
97     # define AIO_MUTEX_INIT PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
98     #else
99     # define AIO_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
100     #endif
101    
102     #define LOCK(mutex) pthread_mutex_lock (&(mutex))
103     #define UNLOCK(mutex) pthread_mutex_unlock (&(mutex))
104    
105     /* worker threads management */
106     static pthread_mutex_t wrklock = AIO_MUTEX_INIT;
107    
108     typedef struct worker {
109     /* locked by wrklock */
110     struct worker *prev, *next;
111    
112     pthread_t tid;
113    
114     /* locked by reslock, reqlock or wrklock */
115     aio_req req; /* currently processed request */
116     void *dbuf;
117     DIR *dirp;
118     } worker;
119    
120     static worker wrk_first = { &wrk_first, &wrk_first, 0 };
121    
122     static void worker_clear (worker *wrk)
123     {
124     }
125    
126     static void worker_free (worker *wrk)
127     {
128     wrk->next->prev = wrk->prev;
129     wrk->prev->next = wrk->next;
130    
131     free (wrk);
132     }
133    
134     static volatile unsigned int nreqs, nready, npending;
135     static volatile unsigned int max_idle = 4;
136     static volatile unsigned int max_outstanding = 0xffffffff;
137     static int respipe [2];
138    
139     static pthread_mutex_t reslock = AIO_MUTEX_INIT;
140     static pthread_mutex_t reqlock = AIO_MUTEX_INIT;
141     static pthread_cond_t reqwait = PTHREAD_COND_INITIALIZER;
142    
143     #if WORDACCESS_UNSAFE
144    
145     static unsigned int get_nready ()
146     {
147     unsigned int retval;
148    
149     LOCK (reqlock);
150     retval = nready;
151     UNLOCK (reqlock);
152    
153     return retval;
154     }
155    
156     static unsigned int get_npending ()
157     {
158     unsigned int retval;
159    
160     LOCK (reslock);
161     retval = npending;
162     UNLOCK (reslock);
163    
164     return retval;
165     }
166    
167     static unsigned int get_nthreads ()
168     {
169     unsigned int retval;
170    
171     LOCK (wrklock);
172     retval = started;
173     UNLOCK (wrklock);
174    
175     return retval;
176     }
177    
178     #else
179    
180     # define get_nready() nready
181     # define get_npending() npending
182     # define get_nthreads() started
183    
184     #endif
185    
186     /*
187     * a somewhat faster data structure might be nice, but
188     * with 8 priorities this actually needs <20 insns
189     * per shift, the most expensive operation.
190     */
191     typedef struct {
192     aio_req qs[NUM_PRI], qe[NUM_PRI]; /* qstart, qend */
193     int size;
194     } reqq;
195    
196     static reqq req_queue;
197     static reqq res_queue;
198    
199     int reqq_push (reqq *q, aio_req req)
200     {
201     int pri = req->pri;
202     req->next = 0;
203    
204     if (q->qe[pri])
205     {
206     q->qe[pri]->next = req;
207     q->qe[pri] = req;
208     }
209     else
210     q->qe[pri] = q->qs[pri] = req;
211    
212     return q->size++;
213     }
214    
215     aio_req reqq_shift (reqq *q)
216     {
217     int pri;
218    
219     if (!q->size)
220     return 0;
221    
222     --q->size;
223    
224     for (pri = NUM_PRI; pri--; )
225     {
226     aio_req req = q->qs[pri];
227    
228     if (req)
229     {
230     if (!(q->qs[pri] = req->next))
231     q->qe[pri] = 0;
232    
233     return req;
234     }
235     }
236    
237     abort ();
238     }
239    
240     static int poll_cb ();
241     static void req_free (aio_req req);
242     static void req_cancel (aio_req req);
243    
244     static int req_invoke (aio_req req)
245     {
246     dSP;
247    
248     if (SvOK (req->callback))
249     {
250     ENTER;
251     SAVETMPS;
252     PUSHMARK (SP);
253     EXTEND (SP, 1);
254    
255     switch (req->type)
256     {
257     }
258    
259     PUTBACK;
260     call_sv (req->callback, G_VOID | G_EVAL);
261     SPAGAIN;
262    
263     FREETMPS;
264     LEAVE;
265     }
266    
267     return !SvTRUE (ERRSV);
268     }
269    
270     static void req_free (aio_req req)
271     {
272 root 1.2 free (req->buf1);
273     free (req->buf2);
274 root 1.1 Safefree (req);
275     }
276    
277     static void *aio_proc(void *arg);
278    
279     static void start_thread (void)
280     {
281     sigset_t fullsigset, oldsigset;
282     pthread_attr_t attr;
283    
284     worker *wrk = calloc (1, sizeof (worker));
285    
286     if (!wrk)
287     croak ("unable to allocate worker thread data");
288    
289     pthread_attr_init (&attr);
290     pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
291     #ifdef PTHREAD_SCOPE_PROCESS
292     pthread_attr_setscope (&attr, PTHREAD_SCOPE_PROCESS);
293     #endif
294    
295     sigfillset (&fullsigset);
296    
297     LOCK (wrklock);
298     pthread_sigmask (SIG_SETMASK, &fullsigset, &oldsigset);
299    
300     if (pthread_create (&wrk->tid, &attr, aio_proc, (void *)wrk) == 0)
301     {
302     wrk->prev = &wrk_first;
303     wrk->next = wrk_first.next;
304     wrk_first.next->prev = wrk;
305     wrk_first.next = wrk;
306     ++started;
307     }
308     else
309     free (wrk);
310    
311     pthread_sigmask (SIG_SETMASK, &oldsigset, 0);
312     UNLOCK (wrklock);
313     }
314    
315     static void maybe_start_thread ()
316     {
317     if (get_nthreads () >= wanted)
318     return;
319    
320     /* todo: maybe use idle here, but might be less exact */
321     if (0 <= (int)get_nthreads () + (int)get_npending () - (int)nreqs)
322     return;
323    
324     start_thread ();
325     }
326    
327     static void req_send (aio_req req)
328     {
329     ++nreqs;
330    
331     LOCK (reqlock);
332     ++nready;
333     reqq_push (&req_queue, req);
334     pthread_cond_signal (&reqwait);
335     UNLOCK (reqlock);
336    
337     maybe_start_thread ();
338     }
339    
340     static void end_thread (void)
341     {
342     aio_req req;
343    
344     Newz (0, req, 1, aio_cb);
345    
346     req->type = REQ_QUIT;
347     req->pri = PRI_MAX + PRI_BIAS;
348    
349     LOCK (reqlock);
350     reqq_push (&req_queue, req);
351     pthread_cond_signal (&reqwait);
352     UNLOCK (reqlock);
353    
354     LOCK (wrklock);
355     --started;
356     UNLOCK (wrklock);
357     }
358    
359     static void set_max_idle (int nthreads)
360     {
361     if (WORDACCESS_UNSAFE) LOCK (reqlock);
362     max_idle = nthreads <= 0 ? 1 : nthreads;
363     if (WORDACCESS_UNSAFE) UNLOCK (reqlock);
364     }
365    
366     static void min_parallel (int nthreads)
367     {
368     if (wanted < nthreads)
369     wanted = nthreads;
370     }
371    
372     static void max_parallel (int nthreads)
373     {
374     if (wanted > nthreads)
375     wanted = nthreads;
376    
377     while (started > wanted)
378     end_thread ();
379     }
380    
381     static void poll_wait ()
382     {
383     fd_set rfd;
384    
385     while (nreqs)
386     {
387     int size;
388     if (WORDACCESS_UNSAFE) LOCK (reslock);
389     size = res_queue.size;
390     if (WORDACCESS_UNSAFE) UNLOCK (reslock);
391    
392     if (size)
393     return;
394    
395     maybe_start_thread ();
396    
397     FD_ZERO(&rfd);
398     FD_SET(respipe [0], &rfd);
399    
400     select (respipe [0] + 1, &rfd, 0, 0, 0);
401     }
402     }
403    
404     static int poll_cb ()
405     {
406     dSP;
407     int count = 0;
408     int maxreqs = max_poll_reqs;
409     int do_croak = 0;
410     struct timeval tv_start, tv_now;
411     aio_req req;
412    
413     if (max_poll_time)
414     gettimeofday (&tv_start, 0);
415    
416     for (;;)
417     {
418     for (;;)
419     {
420     maybe_start_thread ();
421    
422     LOCK (reslock);
423     req = reqq_shift (&res_queue);
424    
425     if (req)
426     {
427     --npending;
428    
429     if (!res_queue.size)
430     {
431     /* read any signals sent by the worker threads */
432     char buf [4];
433     while (read (respipe [0], buf, 4) == 4)
434     ;
435     }
436     }
437    
438     UNLOCK (reslock);
439    
440     if (!req)
441     break;
442    
443     --nreqs;
444    
445     if (!req_invoke (req))
446     {
447     req_free (req);
448     croak (0);
449     }
450    
451     count++;
452    
453     req_free (req);
454    
455     if (maxreqs && !--maxreqs)
456     break;
457    
458     if (max_poll_time)
459     {
460     gettimeofday (&tv_now, 0);
461    
462     if (tvdiff (&tv_start, &tv_now) >= max_poll_time)
463     break;
464     }
465     }
466    
467     if (nreqs <= max_outstanding)
468     break;
469    
470     poll_wait ();
471    
472     ++maxreqs;
473     }
474    
475     return count;
476     }
477    
478     static void create_pipe ()
479     {
480     if (pipe (respipe))
481     croak ("unable to initialize result pipe");
482    
483     if (fcntl (respipe [0], F_SETFL, O_NONBLOCK))
484     croak ("cannot set result pipe to nonblocking mode");
485    
486     if (fcntl (respipe [1], F_SETFL, O_NONBLOCK))
487     croak ("cannot set result pipe to nonblocking mode");
488     }
489    
490     /*****************************************************************************/
491    
492     static void *aio_proc (void *thr_arg)
493     {
494     aio_req req;
495     struct timespec ts;
496     worker *self = (worker *)thr_arg;
497    
498     /* try to distribute timeouts somewhat evenly */
499     ts.tv_nsec = (((unsigned long)self + (unsigned long)ts.tv_sec) & 1023UL)
500     * (1000000000UL / 1024UL);
501    
502     for (;;)
503     {
504     ts.tv_sec = time (0) + IDLE_TIMEOUT;
505    
506     LOCK (reqlock);
507    
508     for (;;)
509     {
510     self->req = req = reqq_shift (&req_queue);
511    
512     if (req)
513     break;
514    
515     ++idle;
516    
517     if (pthread_cond_timedwait (&reqwait, &reqlock, &ts)
518     == ETIMEDOUT)
519     {
520     if (idle > max_idle)
521     {
522     --idle;
523     UNLOCK (reqlock);
524     LOCK (wrklock);
525     --started;
526     UNLOCK (wrklock);
527     goto quit;
528     }
529    
530     /* we are allowed to idle, so do so without any timeout */
531     pthread_cond_wait (&reqwait, &reqlock);
532     ts.tv_sec = time (0) + IDLE_TIMEOUT;
533     }
534    
535     --idle;
536     }
537    
538     --nready;
539    
540     UNLOCK (reqlock);
541    
542     errno = 0; /* strictly unnecessary */
543    
544     switch (req->type)
545     {
546     case REQ_QUIT:
547     goto quit;
548    
549     default:
550     //req->result = ENOSYS;
551     break;
552     }
553    
554     //req->errorno = errno;
555    
556     LOCK (reslock);
557    
558     ++npending;
559    
560     if (!reqq_push (&res_queue, req))
561     /* write a dummy byte to the pipe so fh becomes ready */
562     write (respipe [1], &respipe, 1);
563    
564     self->req = 0;
565     worker_clear (self);
566    
567     UNLOCK (reslock);
568     }
569    
570     quit:
571     LOCK (wrklock);
572     worker_free (self);
573     UNLOCK (wrklock);
574    
575     return 0;
576     }
577    
578     /*****************************************************************************/
579    
580     static void atfork_prepare (void)
581     {
582     LOCK (wrklock);
583     LOCK (reqlock);
584     LOCK (reslock);
585     }
586    
587     static void atfork_parent (void)
588     {
589     UNLOCK (reslock);
590     UNLOCK (reqlock);
591     UNLOCK (wrklock);
592     }
593    
594     static void atfork_child (void)
595     {
596     aio_req prv;
597    
598     while (prv = reqq_shift (&req_queue))
599     req_free (prv);
600    
601     while (prv = reqq_shift (&res_queue))
602     req_free (prv);
603    
604     while (wrk_first.next != &wrk_first)
605     {
606     worker *wrk = wrk_first.next;
607    
608     if (wrk->req)
609     req_free (wrk->req);
610    
611     worker_clear (wrk);
612     worker_free (wrk);
613     }
614    
615     started = 0;
616     idle = 0;
617     nreqs = 0;
618     nready = 0;
619     npending = 0;
620    
621     close (respipe [0]);
622     close (respipe [1]);
623     create_pipe ();
624    
625     atfork_parent ();
626     }
627    
628 root 1.2 #define dREQ(reqtype) \
629 root 1.1 aio_req req; \
630     int req_pri = next_pri; \
631     next_pri = DEFAULT_PRI + PRI_BIAS; \
632     \
633     if (SvOK (callback) && !SvROK (callback)) \
634     croak ("callback must be undef or of reference type"); \
635     \
636 root 1.2 Newz (0, req, 1, aio_cb); \
637 root 1.1 if (!req) \
638     croak ("out of memory during aio_req allocation"); \
639     \
640     req->callback = newSVsv (callback); \
641 root 1.2 req->type = (reqtype); \
642 root 1.1 req->pri = req_pri
643    
644     #define REQ_SEND \
645 root 1.2 req_send (req)
646    
647     #define SvPTR(var, arg, type, class) \
648     if (!SvOK (arg)) \
649     (var) = 0; \
650     else if (sv_derived_from ((arg), # class)) \
651     { \
652     IV tmp = SvIV ((SV*) SvRV (arg)); \
653     (var) = INT2PTR (type, tmp); \
654     } \
655     else \
656     Perl_croak (# var " is not of type " # type)
657 root 1.1
658 root 1.2 MODULE = BDB PACKAGE = BDB
659 root 1.1
660     PROTOTYPES: ENABLE
661    
662     BOOT:
663     {
664 root 1.2 HV *stash = gv_stashpv ("BDB", 1);
665    
666     static const struct {
667     const char *name;
668     IV iv;
669     } *civ, const_iv[] = {
670     #define const_iv(name) { # name, (IV)DB_ ## name },
671     const_iv (RPCCLIENT)
672     const_iv (INIT_CDB)
673     const_iv (INIT_LOCK)
674     const_iv (INIT_LOG)
675     const_iv (INIT_MPOOL)
676     const_iv (INIT_REP)
677     const_iv (INIT_TXN)
678     const_iv (RECOVER)
679     const_iv (INIT_TXN)
680     const_iv (RECOVER_FATAL)
681     const_iv (CREATE)
682     const_iv (USE_ENVIRON)
683     const_iv (USE_ENVIRON_ROOT)
684     const_iv (LOCKDOWN)
685     const_iv (PRIVATE)
686     const_iv (REGISTER)
687     const_iv (SYSTEM_MEM)
688     const_iv (AUTO_COMMIT)
689     const_iv (CDB_ALLDB)
690     const_iv (DIRECT_DB)
691     const_iv (DIRECT_LOG)
692     const_iv (DSYNC_DB)
693     const_iv (DSYNC_LOG)
694     const_iv (LOG_AUTOREMOVE)
695     const_iv (LOG_INMEMORY)
696     const_iv (NOLOCKING)
697     const_iv (MULTIVERSION)
698     const_iv (NOMMAP)
699     const_iv (NOPANIC)
700     const_iv (OVERWRITE)
701     const_iv (PANIC_ENVIRONMENT)
702     const_iv (REGION_INIT)
703     const_iv (TIME_NOTGRANTED)
704     const_iv (TXN_NOSYNC)
705     const_iv (TXN_SNAPSHOT)
706     const_iv (TXN_WRITE_NOSYNC)
707     const_iv (YIELDCPU)
708     const_iv (ENCRYPT_AES)
709     const_iv (XA_CREATE)
710     const_iv (BTREE)
711     const_iv (HASH)
712     const_iv (QUEUE)
713     const_iv (RECNO)
714     const_iv (UNKNOWN)
715     const_iv (EXCL)
716     const_iv (READ_UNCOMMITTED)
717     const_iv (TRUNCATE)
718     const_iv (NOSYNC)
719     const_iv (CHKSUM)
720     const_iv (ENCRYPT)
721     const_iv (TXN_NOT_DURABLE)
722     const_iv (DUP)
723     const_iv (DUPSORT)
724     const_iv (RECNUM)
725     const_iv (RENUMBER)
726     const_iv (REVSPLITOFF)
727     const_iv (INORDER)
728     const_iv (CONSUME)
729     const_iv (CONSUME_WAIT)
730     const_iv (SNAPSHOT)
731     const_iv (JOIN_ITEM)
732     const_iv (RMW)
733    
734     const_iv (NOTFOUND)
735     const_iv (KEYEMPTY)
736     const_iv (LOCK_DEADLOCK)
737     const_iv (LOCK_NOTGRANTED)
738     const_iv (RUNRECOVERY)
739     };
740    
741     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
742     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
743 root 1.1
744     create_pipe ();
745     pthread_atfork (atfork_prepare, atfork_parent, atfork_child);
746     }
747    
748     void
749     max_poll_reqs (int nreqs)
750     PROTOTYPE: $
751     CODE:
752     max_poll_reqs = nreqs;
753    
754     void
755     max_poll_time (double nseconds)
756     PROTOTYPE: $
757     CODE:
758     max_poll_time = nseconds * AIO_TICKS;
759    
760     void
761     min_parallel (int nthreads)
762     PROTOTYPE: $
763    
764     void
765     max_parallel (int nthreads)
766     PROTOTYPE: $
767    
768     void
769     max_idle (int nthreads)
770     PROTOTYPE: $
771     CODE:
772     set_max_idle (nthreads);
773    
774     int
775     max_outstanding (int maxreqs)
776     PROTOTYPE: $
777     CODE:
778     RETVAL = max_outstanding;
779     max_outstanding = maxreqs;
780     OUTPUT:
781     RETVAL
782    
783     int
784     bdbreq_pri (int pri = 0)
785     PROTOTYPE: ;$
786     CODE:
787     RETVAL = next_pri - PRI_BIAS;
788     if (items > 0)
789     {
790     if (pri < PRI_MIN) pri = PRI_MIN;
791     if (pri > PRI_MAX) pri = PRI_MAX;
792     next_pri = pri + PRI_BIAS;
793     }
794     OUTPUT:
795     RETVAL
796    
797     void
798     bdbreq_nice (int nice = 0)
799     CODE:
800     nice = next_pri - nice;
801     if (nice < PRI_MIN) nice = PRI_MIN;
802     if (nice > PRI_MAX) nice = PRI_MAX;
803     next_pri = nice + PRI_BIAS;
804    
805     void
806     flush ()
807     PROTOTYPE:
808     CODE:
809     while (nreqs)
810     {
811     poll_wait ();
812     poll_cb ();
813     }
814    
815     int
816     poll()
817     PROTOTYPE:
818     CODE:
819     poll_wait ();
820     RETVAL = poll_cb ();
821     OUTPUT:
822     RETVAL
823    
824     int
825     poll_fileno()
826     PROTOTYPE:
827     CODE:
828     RETVAL = respipe [0];
829     OUTPUT:
830     RETVAL
831    
832     int
833     poll_cb(...)
834     PROTOTYPE:
835     CODE:
836     RETVAL = poll_cb ();
837     OUTPUT:
838     RETVAL
839    
840     void
841     poll_wait()
842     PROTOTYPE:
843     CODE:
844     poll_wait ();
845    
846     int
847     nreqs()
848     PROTOTYPE:
849     CODE:
850     RETVAL = nreqs;
851     OUTPUT:
852     RETVAL
853    
854     int
855     nready()
856     PROTOTYPE:
857     CODE:
858     RETVAL = get_nready ();
859     OUTPUT:
860     RETVAL
861    
862     int
863     npending()
864     PROTOTYPE:
865     CODE:
866     RETVAL = get_npending ();
867     OUTPUT:
868     RETVAL
869    
870     int
871     nthreads()
872     PROTOTYPE:
873     CODE:
874     if (WORDACCESS_UNSAFE) LOCK (wrklock);
875     RETVAL = started;
876     if (WORDACCESS_UNSAFE) UNLOCK (wrklock);
877     OUTPUT:
878     RETVAL
879    
880 root 1.2 DB_ENV *
881     bdb_env_create (U32 env_flags = 0)
882     CODE:
883     {
884     int err = db_env_create (&RETVAL, env_flags);
885     if (err)
886     croak ("db_env_create: %s", db_strerror (err));
887     }
888    
889     void
890     bdb_env_open (DB_ENV *env, char *db_home, U32 open_flags, int mode, SV *callback = 0)
891     CODE:
892     {
893     dREQ (REQ_ENV_OPEN);
894     req->env = env;
895     req->uint1 = open_flags;
896     req->int1 = mode;
897     req->buf1 = strdup (db_home);
898     REQ_SEND;
899     }
900    
901     void
902     bdb_env_close (DB_ENV *env, U32 flags = 0, SV *callback = 0)
903     CODE:
904     {
905     dREQ (REQ_ENV_CLOSE);
906     req->env = env;
907     req->uint1 = flags;
908     REQ_SEND;
909     }
910    
911     DB *
912     bdb_db_create (DB_ENV *env = 0, U32 flags = 0)
913     CODE:
914     {
915     int err = db_create (&RETVAL, env, flags);
916     if (err)
917     croak ("db_env_create: %s", db_strerror (err));
918     }
919    
920     void
921     bdb_db_open (DB *db, DB_TXN *txnid, const char *file, const char *database, int type, U32 flags, int mode, SV *callback = 0)
922     CODE:
923     {
924     dREQ (REQ_DB_OPEN);
925     req->db = db;
926     req->txn = txnid;
927     req->buf1 = strdup (file);
928     req->buf2 = strdup (database);
929     req->int1 = type;
930     req->uint1 = flags;
931     req->int2 = mode;
932     REQ_SEND;
933     }
934    
935     void
936     bdb_db_close (DB *db, U32 flags = 0, SV *callback = 0)
937     CODE:
938     {
939     dREQ (REQ_DB_CLOSE);
940     req->db = db;
941     req->uint1 = flags;
942     REQ_SEND;
943     }
944    
945    
946     MODULE = BDB PACKAGE = BDB::Env
947    
948     int set_cachesize (DB_ENV *env, U32 gbytes, U32 bytes, int ncache = 0)
949    
950     int set_flags (DB_ENV *env, U32 flags, int onoff)
951    
952     int set_encrypt (DB_ENV *env, const char *password, U32 flags)
953    
954     MODULE = BDB PACKAGE = BDB::Db
955    
956     int set_cachesize (DB *db, U32 gbytes, U32 bytes, int ncache = 0)
957    
958     int set_flags (DB *env, U32 flags, int onoff)
959    
960     int set_encrypt (DB *db, const char *password, U32 flags)
961    
962     int set_lorder (DB *db, int lorder)
963    
964    
965     int set_bt_minkey (DB *db, U32 minkey)
966    
967     int set_re_delim(DB *db, int delim);
968    
969     int set_re_pad (DB *db, int re_pad)
970    
971     int set_re_source (DB *db, char *source)
972    
973     int set_re_len (DB *db, U32 re_len)
974    
975     int set_h_ffactor (DB *db, U32 h_ffactor)
976    
977     int set_h_nelem (DB *db, U32 h_nelem)
978    
979     int set_q_extentsize (DB *db, U32 extentsize)
980    
981 root 1.1