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