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

# Content
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
28 #include <db.h>
29
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 enum
48 {
49 REQ_QUIT,
50 REQ_ENV_OPEN, REQ_ENV_CLOSE,
51 REQ_DB_OPEN, REQ_DB_CLOSE,
52 };
53
54 typedef struct aio_cb
55 {
56 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 } 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 free (req->buf1);
273 free (req->buf2);
274 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 #define dREQ(reqtype) \
629 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 Newz (0, req, 1, aio_cb); \
637 if (!req) \
638 croak ("out of memory during aio_req allocation"); \
639 \
640 req->callback = newSVsv (callback); \
641 req->type = (reqtype); \
642 req->pri = req_pri
643
644 #define REQ_SEND \
645 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
658 MODULE = BDB PACKAGE = BDB
659
660 PROTOTYPES: ENABLE
661
662 BOOT:
663 {
664 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
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 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