ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/BDB/BDB.xs
Revision: 1.7
Committed: Thu Feb 8 22:14:01 2007 UTC (17 years, 3 months ago) by root
Branch: MAIN
Changes since 1.6: +3 -3 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 DB_ENV DB_ENV_ornull;
46 typedef DB_TXN DB_TXN_ornull;
47 typedef DBC DBC_ornull;
48 typedef DB DB_ornull;
49
50 typedef SV SV8; /* byte-sv, used for argument-checking */
51 typedef char *octetstring;
52
53 static SV *prepare_cb;
54
55 static inline char *
56 strdup_ornull (const char *s)
57 {
58 return s ? strdup (s) : 0;
59 }
60
61 static inline void
62 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 dbt->flags = DB_DBT_REALLOC;
71 }
72
73 static inline void
74 dbt_to_sv (SV *sv, DBT *dbt)
75 {
76 if (sv)
77 {
78 SvREADONLY_off (sv);
79 sv_setpvn_mg (sv, dbt->data, dbt->size);
80 SvREFCNT_dec (sv);
81 }
82
83 free (dbt->data);
84 }
85
86 enum {
87 REQ_QUIT,
88 REQ_ENV_OPEN, REQ_ENV_CLOSE,
89 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 REQ_TXN_COMMIT, REQ_TXN_ABORT,
91 REQ_C_CLOSE, REQ_C_COUNT, REQ_C_PUT, REQ_C_GET, REQ_C_PGET, REQ_C_DEL,
92 };
93
94 typedef struct aio_cb
95 {
96 struct aio_cb *volatile next;
97 SV *callback;
98 int type, pri, result;
99
100 DB_ENV *env;
101 DB *db;
102 DB_TXN *txn;
103 DBC *dbc;
104
105 UV uv1;
106 int int1, int2;
107 U32 uint1, uint2;
108 char *buf1, *buf2;
109 SV *sv1, *sv2, *sv3;
110
111 DBT dbt1, dbt2, dbt3;
112 } 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 case REQ_DB_CLOSE:
303 SvREFCNT_dec (req->sv1);
304 break;
305
306 case REQ_DB_GET:
307 case REQ_DB_PGET:
308 dbt_to_sv (req->sv3, &req->dbt3);
309 break;
310
311 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 break;
317 }
318
319 errno = req->result;
320
321 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 free (req->buf1);
335 free (req->buf2);
336 Safefree (req);
337 }
338
339 static void *aio_proc (void *arg);
340
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 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 ++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
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 }
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 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 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 case REQ_DB_DEL:
674 req->result = req->db->del (req->db, req->txn, &req->dbt1, req->uint1);
675 break;
676
677 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 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 default:
714 req->result = ENOSYS;
715 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 #define dREQ(reqtype) \
791 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 Newz (0, req, 1, aio_cb); \
799 if (!req) \
800 croak ("out of memory during aio_req allocation"); \
801 \
802 req->callback = newSVsv (callback); \
803 req->type = (reqtype); \
804 req->pri = req_pri
805
806 #define REQ_SEND \
807 req_send (req)
808
809 #define SvPTR(var, arg, type, class, nullok) \
810 if (!SvOK (arg)) \
811 { \
812 if (!nullok) \
813 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 croak (# var " is not a valid " # class " object anymore"); \
823 } \
824 else \
825 croak (# var " is not of type " # class); \
826 \
827
828 static void
829 ptr_nuke (SV *sv)
830 {
831 assert (SvROK (sv));
832 sv_setiv (SvRV (sv), 0);
833 }
834
835 MODULE = BDB PACKAGE = BDB
836
837 PROTOTYPES: ENABLE
838
839 BOOT:
840 {
841 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 const_iv (WRITECURSOR)
885 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 const_iv (READ_COMMITTED)
895 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 const_iv (GET_BOTH)
910 const_iv (GET_BOTH_RANGE)
911 //const_iv (SET_RECNO)
912 //const_iv (MULTIPLE)
913 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 const_iv (OLD_VERSION)
923 const_iv (REP_HANDLE_DEAD)
924 const_iv (REP_LOCKOUT)
925 const_iv (SECONDARY_BAD)
926
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 const_iv (TXN_NOWAIT)
935 const_iv (TXN_SNAPSHOT)
936 const_iv (TXN_SYNC)
937
938 const_iv (SET_LOCK_TIMEOUT)
939 const_iv (SET_TXN_TIMEOUT)
940
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 };
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
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 dbreq_pri (int pri = 0)
1003 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 dbreq_nice (int nice = 0)
1017 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 poll ()
1035 PROTOTYPE:
1036 CODE:
1037 poll_wait ();
1038 RETVAL = poll_cb ();
1039 OUTPUT:
1040 RETVAL
1041
1042 int
1043 poll_fileno ()
1044 PROTOTYPE:
1045 CODE:
1046 RETVAL = respipe [0];
1047 OUTPUT:
1048 RETVAL
1049
1050 int
1051 poll_cb (...)
1052 PROTOTYPE:
1053 CODE:
1054 RETVAL = poll_cb ();
1055 OUTPUT:
1056 RETVAL
1057
1058 void
1059 poll_wait ()
1060 PROTOTYPE:
1061 CODE:
1062 poll_wait ();
1063
1064 int
1065 nreqs ()
1066 PROTOTYPE:
1067 CODE:
1068 RETVAL = nreqs;
1069 OUTPUT:
1070 RETVAL
1071
1072 int
1073 nready ()
1074 PROTOTYPE:
1075 CODE:
1076 RETVAL = get_nready ();
1077 OUTPUT:
1078 RETVAL
1079
1080 int
1081 npending ()
1082 PROTOTYPE:
1083 CODE:
1084 RETVAL = get_npending ();
1085 OUTPUT:
1086 RETVAL
1087
1088 int
1089 nthreads ()
1090 PROTOTYPE:
1091 CODE:
1092 if (WORDACCESS_UNSAFE) LOCK (wrklock);
1093 RETVAL = started;
1094 if (WORDACCESS_UNSAFE) UNLOCK (wrklock);
1095 OUTPUT:
1096 RETVAL
1097
1098 void
1099 set_sync_prepare (SV *cb)
1100 PROTOTYPE: &
1101 CODE:
1102 SvREFCNT_dec (prepare_cb);
1103 prepare_cb = newSVsv (cb);
1104
1105 DB_ENV *
1106 db_env_create (U32 env_flags = 0)
1107 CODE:
1108 {
1109 errno = db_env_create (&RETVAL, env_flags);
1110 if (errno)
1111 croak ("db_env_create: %s", db_strerror (errno));
1112 }
1113 OUTPUT:
1114 RETVAL
1115
1116 void
1117 db_env_open (DB_ENV *env, octetstring db_home, U32 open_flags, int mode, SV *callback = &PL_sv_undef)
1118 CODE:
1119 {
1120 dREQ (REQ_ENV_OPEN);
1121 req->env = env;
1122 req->uint1 = open_flags | DB_THREAD;
1123 req->int1 = mode;
1124 req->buf1 = strdup_ornull (db_home);
1125 REQ_SEND;
1126 }
1127
1128 void
1129 db_env_close (DB_ENV *env, U32 flags = 0, SV *callback = &PL_sv_undef)
1130 CODE:
1131 {
1132 dREQ (REQ_ENV_CLOSE);
1133 req->env = env;
1134 req->uint1 = flags;
1135 REQ_SEND;
1136 ptr_nuke (ST (0));
1137 }
1138
1139 DB *
1140 db_create (DB_ENV *env = 0, U32 flags = 0)
1141 CODE:
1142 {
1143 errno = db_create (&RETVAL, env, flags);
1144 if (errno)
1145 croak ("db_create: %s", db_strerror (errno));
1146
1147 if (RETVAL)
1148 RETVAL->app_private = (void *)newSVsv (ST (0));
1149 }
1150 OUTPUT:
1151 RETVAL
1152
1153 void
1154 db_open (DB *db, DB_TXN_ornull *txnid, octetstring file, octetstring database, int type, U32 flags, int mode, SV *callback = &PL_sv_undef)
1155 CODE:
1156 {
1157 dREQ (REQ_DB_OPEN);
1158 req->db = db;
1159 req->txn = txnid;
1160 req->buf1 = strdup_ornull (file);
1161 req->buf2 = strdup_ornull (database);
1162 req->int1 = type;
1163 req->uint1 = flags | DB_THREAD;
1164 req->int2 = mode;
1165 REQ_SEND;
1166 }
1167
1168 void
1169 db_close (DB *db, U32 flags = 0, SV *callback = &PL_sv_undef)
1170 CODE:
1171 {
1172 dREQ (REQ_DB_CLOSE);
1173 req->db = db;
1174 req->uint1 = flags;
1175 req->sv1 = (SV *)db->app_private;
1176 REQ_SEND;
1177 ptr_nuke (ST (0));
1178 }
1179
1180 void
1181 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 CODE:
1183 {
1184 dREQ (REQ_DB_COMPACT);
1185 req->db = db;
1186 req->txn = txn;
1187 sv_to_dbt (&req->dbt1, start);
1188 sv_to_dbt (&req->dbt2, stop);
1189 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 db_put (DB *db, DB_TXN_ornull *txn, SV *key, SV *data, U32 flags = 0, SV *callback = &PL_sv_undef)
1205 CODE:
1206 {
1207 dREQ (REQ_DB_PUT);
1208 req->db = db;
1209 req->txn = txn;
1210 sv_to_dbt (&req->dbt1, key);
1211 sv_to_dbt (&req->dbt2, data);
1212 req->uint1 = flags;
1213 REQ_SEND;
1214 }
1215
1216 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 req->uint1 = flags;
1224 sv_to_dbt (&req->dbt1, key);
1225 req->dbt3.flags = DB_DBT_MALLOC;
1226 req->sv3 = SvREFCNT_inc (data); SvREADONLY_on (data);
1227 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 req->uint1 = flags;
1238 sv_to_dbt (&req->dbt1, key);
1239 sv_to_dbt (&req->dbt2, pkey);
1240 req->dbt3.flags = DB_DBT_MALLOC;
1241 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 req->uint1 = flags;
1253 sv_to_dbt (&req->dbt1, key);
1254 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 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
1374 MODULE = BDB PACKAGE = BDB::Env
1375
1376 void
1377 DESTROY (DB_ENV_ornull *env)
1378 CODE:
1379 if (env)
1380 env->close (env, 0);
1381
1382 int set_cachesize (DB_ENV *env, U32 gbytes, U32 bytes, int ncache = 0)
1383 CODE:
1384 RETVAL = env->set_cachesize (env, gbytes, bytes, ncache);
1385 OUTPUT:
1386 RETVAL
1387
1388 int set_flags (DB_ENV *env, U32 flags, int onoff)
1389 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
1406 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 croak ("DB_ENV->txn_begin: %s", db_strerror (errno));
1412 OUTPUT:
1413 RETVAL
1414
1415 MODULE = BDB PACKAGE = BDB::Db
1416
1417 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 int set_cachesize (DB *db, U32 gbytes, U32 bytes, int ncache = 0)
1428 CODE:
1429 RETVAL = db->set_cachesize (db, gbytes, bytes, ncache);
1430 OUTPUT:
1431 RETVAL
1432
1433 int set_flags (DB *db, U32 flags);
1434 CODE:
1435 RETVAL = db->set_flags (db, flags);
1436 OUTPUT:
1437 RETVAL
1438
1439 int set_encrypt (DB *db, const char *password, U32 flags)
1440 CODE:
1441 RETVAL = db->set_encrypt (db, password, flags);
1442 OUTPUT:
1443 RETVAL
1444
1445 int set_lorder (DB *db, int lorder)
1446 CODE:
1447 RETVAL = db->set_lorder (db, lorder);
1448 OUTPUT:
1449 RETVAL
1450
1451
1452 int set_bt_minkey (DB *db, U32 minkey)
1453 CODE:
1454 RETVAL = db->set_bt_minkey (db, minkey);
1455 OUTPUT:
1456 RETVAL
1457
1458 int set_re_delim(DB *db, int delim);
1459 CODE:
1460 RETVAL = db->set_re_delim (db, delim);
1461 OUTPUT:
1462 RETVAL
1463
1464 int set_re_pad (DB *db, int re_pad)
1465 CODE:
1466 RETVAL = db->set_re_pad (db, re_pad);
1467 OUTPUT:
1468 RETVAL
1469
1470 int set_re_source (DB *db, char *source)
1471 CODE:
1472 RETVAL = db->set_re_source (db, source);
1473 OUTPUT:
1474 RETVAL
1475
1476 int set_re_len (DB *db, U32 re_len)
1477 CODE:
1478 RETVAL = db->set_re_len (db, re_len);
1479 OUTPUT:
1480 RETVAL
1481
1482 int set_h_ffactor (DB *db, U32 h_ffactor)
1483 CODE:
1484 RETVAL = db->set_h_ffactor (db, h_ffactor);
1485 OUTPUT:
1486 RETVAL
1487
1488 int set_h_nelem (DB *db, U32 h_nelem)
1489 CODE:
1490 RETVAL = db->set_h_nelem (db, h_nelem);
1491 OUTPUT:
1492 RETVAL
1493
1494 int set_q_extentsize (DB *db, U32 extentsize)
1495 CODE:
1496 RETVAL = db->set_q_extentsize (db, extentsize);
1497 OUTPUT:
1498 RETVAL
1499
1500 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 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
1525 MODULE = BDB PACKAGE = BDB::Cursor
1526
1527 void
1528 DESTROY (DBC_ornull *dbc)
1529 CODE:
1530 if (dbc)
1531 dbc->c_close (dbc);
1532