ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/BDB/BDB.xs
Revision: 1.65
Committed: Fri Jan 2 22:37:51 2009 UTC (15 years, 4 months ago) by root
Branch: MAIN
Changes since 1.64: +88 -1 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.48 #define X_STACKSIZE 1024 * 128 + sizeof (long) * 64 * 1024 / 4
2    
3 root 1.11 #include "xthread.h"
4 root 1.1
5     #include <errno.h>
6    
7     #include "EXTERN.h"
8     #include "perl.h"
9     #include "XSUB.h"
10    
11 root 1.13 // perl stupidly defines these as macros, breaking
12     // lots and lots of code.
13     #undef open
14     #undef close
15     #undef abort
16     #undef malloc
17     #undef free
18     #undef send
19    
20 root 1.1 #include <stddef.h>
21     #include <stdlib.h>
22     #include <errno.h>
23     #include <sys/types.h>
24     #include <limits.h>
25     #include <fcntl.h>
26 root 1.2
27 root 1.13 #ifndef _WIN32
28     # include <sys/time.h>
29     # include <unistd.h>
30     #endif
31    
32 root 1.2 #include <db.h>
33 root 1.1
34 root 1.47 #if DB_VERSION_MAJOR != 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR < 3)
35     # error you need Berkeley DB 4.3 or a newer 4.x version installed
36 root 1.10 #endif
37    
38 root 1.1 /* number of seconds after which idle threads exit */
39     #define IDLE_TIMEOUT 10
40    
41 root 1.54 typedef SV SV_mutable;
42    
43 root 1.8 typedef DB_ENV DB_ENV_ornull;
44     typedef DB_TXN DB_TXN_ornull;
45     typedef DBC DBC_ornull;
46     typedef DB DB_ornull;
47 root 1.5
48 root 1.30 typedef DB_ENV DB_ENV_ornuked;
49     typedef DB_TXN DB_TXN_ornuked;
50     typedef DBC DBC_ornuked;
51     typedef DB DB_ornuked;
52 root 1.47
53     #if DB_VERSION_MINOR >= 3
54     typedef DB_SEQUENCE DB_SEQUENCE_ornull;
55 root 1.30 typedef DB_SEQUENCE DB_SEQUENCE_ornuked;
56 root 1.47 #endif
57 root 1.30
58 root 1.33 typedef char *bdb_filename;
59 root 1.1
60 root 1.3 static SV *prepare_cb;
61    
62 root 1.16 #if DB_VERSION_MINOR >= 6
63     # define c_close close
64     # define c_count count
65     # define c_del del
66     # define c_dup dup
67     # define c_get get
68     # define c_pget pget
69     # define c_put put
70     #endif
71    
72 root 1.34 static char *
73     get_bdb_filename (SV *sv)
74     {
75 root 1.36 if (!SvOK (sv))
76     return 0;
77    
78 root 1.35 #if _WIN32
79 root 1.36 /* win32 madness + win32 perl absolutely brokenness make for horrible hacks */
80     {
81     STRLEN len;
82     char *src = SvPVbyte (sv, len);
83     SV *t1 = sv_newmortal ();
84     SV *t2 = sv_newmortal ();
85    
86     sv_upgrade (t1, SVt_PV); SvPOK_only (t1); SvGROW (t1, len * 16 + 1);
87     sv_upgrade (t2, SVt_PV); SvPOK_only (t2); SvGROW (t2, len * 16 + 1);
88    
89     len = MultiByteToWideChar (CP_ACP, 0, src, len, (WCHAR *)SvPVX (t1), SvLEN (t1) / sizeof (WCHAR));
90     len = WideCharToMultiByte (CP_UTF8, 0, (WCHAR *)SvPVX (t1), len, SvPVX (t2), SvLEN (t2), 0, 0);
91     SvPOK_only (t2);
92     SvPVX (t2)[len] = 0;
93     SvCUR_set (t2, len);
94    
95     return SvPVX (t2);
96     }
97 root 1.34 #else
98 root 1.36 return SvPVbyte_nolen (sv);
99 root 1.34 #endif
100     }
101    
102 root 1.14 static void
103     debug_errcall (const DB_ENV *dbenv, const char *errpfx, const char *msg)
104     {
105     printf ("err[%s]\n", msg);
106     }
107    
108     static void
109     debug_msgcall (const DB_ENV *dbenv, const char *msg)
110     {
111     printf ("msg[%s]\n", msg);
112     }
113    
114 root 1.13 static char *
115 root 1.3 strdup_ornull (const char *s)
116 root 1.2 {
117 root 1.3 return s ? strdup (s) : 0;
118     }
119    
120 root 1.13 static void
121 root 1.5 sv_to_dbt (DBT *dbt, SV *sv)
122     {
123     STRLEN len;
124     char *data = SvPVbyte (sv, len);
125    
126     dbt->data = malloc (len);
127     memcpy (dbt->data, data, len);
128     dbt->size = len;
129 root 1.6 dbt->flags = DB_DBT_REALLOC;
130 root 1.5 }
131    
132 root 1.13 static void
133 root 1.5 dbt_to_sv (SV *sv, DBT *dbt)
134     {
135 root 1.6 if (sv)
136     {
137     SvREADONLY_off (sv);
138 root 1.55
139     if (dbt->data)
140     sv_setpvn_mg (sv, dbt->data, dbt->size);
141     else
142     sv_setsv_mg (sv, &PL_sv_undef);
143    
144 root 1.6 SvREFCNT_dec (sv);
145     }
146 root 1.5
147 root 1.55 free (dbt->data);
148 root 1.5 }
149    
150 root 1.3 enum {
151 root 1.1 REQ_QUIT,
152 root 1.8 REQ_ENV_OPEN, REQ_ENV_CLOSE, REQ_ENV_TXN_CHECKPOINT, REQ_ENV_LOCK_DETECT,
153 root 1.39 REQ_ENV_MEMP_SYNC, REQ_ENV_MEMP_TRICKLE, REQ_ENV_DBREMOVE, REQ_ENV_DBRENAME,
154 root 1.63 REQ_ENV_LOG_ARCHIVE,
155 root 1.26 REQ_DB_OPEN, REQ_DB_CLOSE, REQ_DB_COMPACT, REQ_DB_SYNC, REQ_DB_UPGRADE,
156 root 1.45 REQ_DB_PUT, REQ_DB_EXISTS, REQ_DB_GET, REQ_DB_PGET, REQ_DB_DEL, REQ_DB_KEY_RANGE,
157 root 1.17 REQ_TXN_COMMIT, REQ_TXN_ABORT, REQ_TXN_FINISH,
158 root 1.6 REQ_C_CLOSE, REQ_C_COUNT, REQ_C_PUT, REQ_C_GET, REQ_C_PGET, REQ_C_DEL,
159 root 1.8 REQ_SEQ_OPEN, REQ_SEQ_CLOSE, REQ_SEQ_GET, REQ_SEQ_REMOVE,
160 root 1.1 };
161    
162 root 1.28 typedef struct bdb_cb
163 root 1.1 {
164 root 1.28 struct bdb_cb *volatile next;
165 root 1.2 SV *callback;
166 root 1.3 int type, pri, result;
167 root 1.2
168     DB_ENV *env;
169     DB *db;
170     DB_TXN *txn;
171 root 1.6 DBC *dbc;
172    
173     UV uv1;
174 root 1.2 int int1, int2;
175     U32 uint1, uint2;
176 root 1.39 char *buf1, *buf2, *buf3;
177 root 1.6 SV *sv1, *sv2, *sv3;
178 root 1.3
179     DBT dbt1, dbt2, dbt3;
180 root 1.8 DB_KEY_RANGE key_range;
181 root 1.47 #if DB_VERSION_MINOR >= 3
182 root 1.8 DB_SEQUENCE *seq;
183     db_seq_t seq_t;
184 root 1.47 #endif
185 root 1.50
186     SV *rsv1, *rsv2; // keep some request objects alive
187 root 1.28 } bdb_cb;
188 root 1.1
189 root 1.28 typedef bdb_cb *bdb_req;
190 root 1.1
191     enum {
192     PRI_MIN = -4,
193     PRI_MAX = 4,
194    
195     DEFAULT_PRI = 0,
196     PRI_BIAS = -PRI_MIN,
197     NUM_PRI = PRI_MAX + PRI_BIAS + 1,
198     };
199    
200     #define AIO_TICKS ((1000000 + 1023) >> 10)
201    
202 root 1.37 static SV *on_next_submit;
203    
204 root 1.1 static unsigned int max_poll_time = 0;
205     static unsigned int max_poll_reqs = 0;
206    
207     /* calculcate time difference in ~1/AIO_TICKS of a second */
208     static int tvdiff (struct timeval *tv1, struct timeval *tv2)
209     {
210     return (tv2->tv_sec - tv1->tv_sec ) * AIO_TICKS
211     + ((tv2->tv_usec - tv1->tv_usec) >> 10);
212     }
213    
214     static int next_pri = DEFAULT_PRI + PRI_BIAS;
215    
216     static unsigned int started, idle, wanted;
217    
218     /* worker threads management */
219 root 1.12 static mutex_t wrklock = X_MUTEX_INIT;
220 root 1.1
221     typedef struct worker {
222     /* locked by wrklock */
223     struct worker *prev, *next;
224    
225 root 1.11 thread_t tid;
226 root 1.1
227     /* locked by reslock, reqlock or wrklock */
228 root 1.28 bdb_req req; /* currently processed request */
229 root 1.1 void *dbuf;
230     DIR *dirp;
231     } worker;
232    
233     static worker wrk_first = { &wrk_first, &wrk_first, 0 };
234    
235     static void worker_clear (worker *wrk)
236     {
237     }
238    
239     static void worker_free (worker *wrk)
240     {
241     wrk->next->prev = wrk->prev;
242     wrk->prev->next = wrk->next;
243    
244     free (wrk);
245     }
246    
247     static volatile unsigned int nreqs, nready, npending;
248     static volatile unsigned int max_idle = 4;
249     static volatile unsigned int max_outstanding = 0xffffffff;
250 root 1.19 static int respipe_osf [2], respipe [2] = { -1, -1 };
251 root 1.1
252 root 1.12 static mutex_t reslock = X_MUTEX_INIT;
253     static mutex_t reqlock = X_MUTEX_INIT;
254     static cond_t reqwait = X_COND_INIT;
255 root 1.1
256     #if WORDACCESS_UNSAFE
257    
258 root 1.34 static unsigned int get_nready (void)
259 root 1.1 {
260     unsigned int retval;
261    
262 root 1.12 X_LOCK (reqlock);
263 root 1.1 retval = nready;
264 root 1.12 X_UNLOCK (reqlock);
265 root 1.1
266     return retval;
267     }
268    
269 root 1.34 static unsigned int get_npending (void)
270 root 1.1 {
271     unsigned int retval;
272    
273 root 1.12 X_LOCK (reslock);
274 root 1.1 retval = npending;
275 root 1.12 X_UNLOCK (reslock);
276 root 1.1
277     return retval;
278     }
279    
280 root 1.34 static unsigned int get_nthreads (void)
281 root 1.1 {
282     unsigned int retval;
283    
284 root 1.12 X_LOCK (wrklock);
285 root 1.1 retval = started;
286 root 1.12 X_UNLOCK (wrklock);
287 root 1.1
288     return retval;
289     }
290    
291     #else
292    
293     # define get_nready() nready
294     # define get_npending() npending
295     # define get_nthreads() started
296    
297     #endif
298    
299     /*
300     * a somewhat faster data structure might be nice, but
301     * with 8 priorities this actually needs <20 insns
302     * per shift, the most expensive operation.
303     */
304     typedef struct {
305 root 1.28 bdb_req qs[NUM_PRI], qe[NUM_PRI]; /* qstart, qend */
306 root 1.1 int size;
307     } reqq;
308    
309     static reqq req_queue;
310     static reqq res_queue;
311    
312 root 1.28 int reqq_push (reqq *q, bdb_req req)
313 root 1.1 {
314     int pri = req->pri;
315     req->next = 0;
316    
317     if (q->qe[pri])
318     {
319     q->qe[pri]->next = req;
320     q->qe[pri] = req;
321     }
322     else
323     q->qe[pri] = q->qs[pri] = req;
324    
325     return q->size++;
326     }
327    
328 root 1.28 bdb_req reqq_shift (reqq *q)
329 root 1.1 {
330     int pri;
331    
332     if (!q->size)
333     return 0;
334    
335     --q->size;
336    
337     for (pri = NUM_PRI; pri--; )
338     {
339 root 1.28 bdb_req req = q->qs[pri];
340 root 1.1
341     if (req)
342     {
343     if (!(q->qs[pri] = req->next))
344     q->qe[pri] = 0;
345    
346     return req;
347     }
348     }
349    
350     abort ();
351     }
352    
353 root 1.34 static int poll_cb (void);
354 root 1.28 static void req_free (bdb_req req);
355 root 1.1
356 root 1.28 static int req_invoke (bdb_req req)
357 root 1.1 {
358 root 1.53 switch (req->type)
359 root 1.1 {
360 root 1.53 case REQ_DB_CLOSE:
361     SvREFCNT_dec (req->sv1);
362     break;
363 root 1.1
364 root 1.53 case REQ_DB_GET:
365     case REQ_DB_PGET:
366     case REQ_C_GET:
367     case REQ_C_PGET:
368 root 1.54 case REQ_DB_PUT:
369     case REQ_C_PUT:
370 root 1.53 dbt_to_sv (req->sv1, &req->dbt1);
371     dbt_to_sv (req->sv2, &req->dbt2);
372     dbt_to_sv (req->sv3, &req->dbt3);
373     break;
374 root 1.5
375 root 1.53 case REQ_DB_KEY_RANGE:
376     {
377     AV *av = newAV ();
378 root 1.23
379 root 1.53 av_push (av, newSVnv (req->key_range.less));
380     av_push (av, newSVnv (req->key_range.equal));
381     av_push (av, newSVnv (req->key_range.greater));
382    
383 root 1.63 av = (AV *)newRV_noinc ((SV *)av);
384    
385 root 1.53 SvREADONLY_off (req->sv1);
386     sv_setsv_mg (req->sv1, newRV_noinc ((SV *)av));
387 root 1.63 SvREFCNT_dec (av);
388 root 1.53 SvREFCNT_dec (req->sv1);
389     }
390     break;
391 root 1.8
392 root 1.47 #if DB_VERSION_MINOR >= 3
393 root 1.53 case REQ_SEQ_GET:
394     SvREADONLY_off (req->sv1);
395 root 1.8
396 root 1.53 if (sizeof (IV) > 4)
397     sv_setiv_mg (req->sv1, (IV)req->seq_t);
398     else
399     sv_setnv_mg (req->sv1, (NV)req->seq_t);
400 root 1.8
401 root 1.53 SvREFCNT_dec (req->sv1);
402     break;
403 root 1.47 #endif
404 root 1.63
405     case REQ_ENV_LOG_ARCHIVE:
406     {
407     AV *av = newAV ();
408     char **listp = (char **)req->buf1;
409    
410     if (listp)
411     while (*listp)
412     av_push (av, newSVpv (*listp, 0)), ++listp;
413    
414     av = (AV *)newRV_noinc ((SV *)av);
415    
416     SvREADONLY_off (req->sv1);
417     sv_setsv_mg (req->sv1, (SV *)av);
418     SvREFCNT_dec (av);
419     SvREFCNT_dec (req->sv1);
420     }
421     break;
422 root 1.53 }
423    
424     errno = req->result;
425    
426     if (req->callback)
427     {
428     dSP;
429 root 1.1
430 root 1.53 ENTER;
431     SAVETMPS;
432     PUSHMARK (SP);
433 root 1.3
434 root 1.1 PUTBACK;
435     call_sv (req->callback, G_VOID | G_EVAL);
436     SPAGAIN;
437    
438     FREETMPS;
439     LEAVE;
440 root 1.53
441     return !SvTRUE (ERRSV);
442 root 1.1 }
443    
444 root 1.53 return 1;
445 root 1.1 }
446    
447 root 1.28 static void req_free (bdb_req req)
448 root 1.1 {
449 root 1.43 SvREFCNT_dec (req->callback);
450    
451 root 1.50 SvREFCNT_dec (req->rsv1);
452     SvREFCNT_dec (req->rsv2);
453    
454 root 1.2 free (req->buf1);
455     free (req->buf2);
456 root 1.39 free (req->buf3);
457 root 1.43
458 root 1.1 Safefree (req);
459     }
460    
461 root 1.13 #ifdef USE_SOCKETS_AS_HANDLES
462     # define TO_SOCKET(x) (win32_get_osfhandle (x))
463     #else
464 root 1.65 # define EV_SELECT_IS_WINSOCKET 1
465 root 1.13 # define TO_SOCKET(x) (x)
466     #endif
467    
468 root 1.65 #ifdef _WIN32
469     /* taken verbatim from libev's ev_win32.c */
470     /* oh, the humanity! */
471     static int
472     ev_pipe (int filedes [2])
473     {
474     struct sockaddr_in addr = { 0 };
475     int addr_size = sizeof (addr);
476     struct sockaddr_in adr2;
477     int adr2_size;
478     SOCKET listener;
479     SOCKET sock [2] = { -1, -1 };
480    
481     if ((listener = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
482     return -1;
483    
484     addr.sin_family = AF_INET;
485     addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
486     addr.sin_port = 0;
487    
488     if (bind (listener, (struct sockaddr *)&addr, addr_size))
489     goto fail;
490    
491     if (getsockname (listener, (struct sockaddr *)&addr, &addr_size))
492     goto fail;
493    
494     if (listen (listener, 1))
495     goto fail;
496    
497     if ((sock [0] = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
498     goto fail;
499    
500     if (connect (sock [0], (struct sockaddr *)&addr, addr_size))
501     goto fail;
502    
503     if ((sock [1] = accept (listener, 0, 0)) < 0)
504     goto fail;
505    
506     /* windows vista returns fantasy port numbers for getpeername.
507     * example for two interconnected tcp sockets:
508     *
509     * (Socket::unpack_sockaddr_in getsockname $sock0)[0] == 53364
510     * (Socket::unpack_sockaddr_in getpeername $sock0)[0] == 53363
511     * (Socket::unpack_sockaddr_in getsockname $sock1)[0] == 53363
512     * (Socket::unpack_sockaddr_in getpeername $sock1)[0] == 53365
513     *
514     * wow! tridirectional sockets!
515     *
516     * this way of checking ports seems to work:
517     */
518     if (getpeername (sock [0], (struct sockaddr *)&addr, &addr_size))
519     goto fail;
520    
521     if (getsockname (sock [1], (struct sockaddr *)&adr2, &adr2_size))
522     goto fail;
523    
524     errno = WSAEINVAL;
525     if (addr_size != adr2_size
526     || addr.sin_addr.s_addr != adr2.sin_addr.s_addr /* just to be sure, I mean, it's windows */
527     || addr.sin_port != adr2.sin_port)
528     goto fail;
529    
530     closesocket (listener);
531    
532     #if EV_SELECT_IS_WINSOCKET
533     filedes [0] = _open_osfhandle (sock [0], 0);
534     filedes [1] = _open_osfhandle (sock [1], 0);
535     #else
536     /* when select isn't winsocket, we also expect socket, connect, accept etc.
537     * to work on fds */
538     filedes [0] = sock [0];
539     filedes [1] = sock [1];
540     #endif
541    
542     return 0;
543    
544     fail:
545     closesocket (listener);
546    
547     if (sock [0] != INVALID_SOCKET) closesocket (sock [0]);
548     if (sock [1] != INVALID_SOCKET) closesocket (sock [1]);
549    
550     return -1;
551     }
552     #endif
553    
554 root 1.13 static void
555 root 1.34 create_respipe (void)
556 root 1.13 {
557 root 1.21 #ifdef _WIN32
558     int arg; /* argg */
559     #endif
560 root 1.19 int old_readfd = respipe [0];
561    
562     if (respipe [1] >= 0)
563     respipe_close (TO_SOCKET (respipe [1]));
564    
565     #ifdef _WIN32
566 root 1.65 if (ev_pipe (respipe))
567 root 1.19 #else
568     if (pipe (respipe))
569     #endif
570     croak ("unable to initialize result pipe");
571    
572     if (old_readfd >= 0)
573     {
574     if (dup2 (TO_SOCKET (respipe [0]), TO_SOCKET (old_readfd)) < 0)
575     croak ("unable to initialize result pipe(2)");
576    
577     respipe_close (respipe [0]);
578     respipe [0] = old_readfd;
579     }
580    
581 root 1.13 #ifdef _WIN32
582 root 1.21 arg = 1;
583 root 1.19 if (ioctlsocket (TO_SOCKET (respipe [0]), FIONBIO, &arg)
584     || ioctlsocket (TO_SOCKET (respipe [1]), FIONBIO, &arg))
585 root 1.13 #else
586 root 1.19 if (fcntl (respipe [0], F_SETFL, O_NONBLOCK)
587     || fcntl (respipe [1], F_SETFL, O_NONBLOCK))
588 root 1.13 #endif
589 root 1.19 croak ("unable to initialize result pipe(3)");
590 root 1.13
591     respipe_osf [0] = TO_SOCKET (respipe [0]);
592     respipe_osf [1] = TO_SOCKET (respipe [1]);
593     }
594    
595 root 1.53 static void bdb_request (bdb_req req);
596 root 1.13 X_THREAD_PROC (bdb_proc);
597 root 1.1
598     static void start_thread (void)
599     {
600     worker *wrk = calloc (1, sizeof (worker));
601    
602     if (!wrk)
603     croak ("unable to allocate worker thread data");
604    
605 root 1.12 X_LOCK (wrklock);
606 root 1.13 if (thread_create (&wrk->tid, bdb_proc, (void *)wrk))
607 root 1.1 {
608     wrk->prev = &wrk_first;
609     wrk->next = wrk_first.next;
610     wrk_first.next->prev = wrk;
611     wrk_first.next = wrk;
612     ++started;
613     }
614     else
615     free (wrk);
616    
617 root 1.12 X_UNLOCK (wrklock);
618 root 1.1 }
619    
620 root 1.34 static void maybe_start_thread (void)
621 root 1.1 {
622     if (get_nthreads () >= wanted)
623     return;
624    
625     /* todo: maybe use idle here, but might be less exact */
626     if (0 <= (int)get_nthreads () + (int)get_npending () - (int)nreqs)
627     return;
628    
629     start_thread ();
630     }
631    
632 root 1.28 static void req_send (bdb_req req)
633 root 1.1 {
634 root 1.3 SV *wait_callback = 0;
635    
636 root 1.37 if (on_next_submit)
637     {
638     dSP;
639     SV *cb = sv_2mortal (on_next_submit);
640    
641     on_next_submit = 0;
642    
643     PUSHMARK (SP);
644     PUTBACK;
645     call_sv (cb, G_DISCARD | G_EVAL);
646 root 1.49 SPAGAIN;
647 root 1.37 }
648    
649 root 1.3 // synthesize callback if none given
650 root 1.41 if (!req->callback)
651 root 1.3 {
652 root 1.53 if (SvOK (prepare_cb))
653     {
654     int count;
655 root 1.13
656 root 1.53 dSP;
657     PUSHMARK (SP);
658     PUTBACK;
659     count = call_sv (prepare_cb, G_ARRAY);
660     SPAGAIN;
661 root 1.3
662 root 1.53 if (count != 2)
663 root 1.54 croak ("sync prepare callback must return exactly two values\n");
664 root 1.3
665 root 1.53 wait_callback = POPs;
666     req->callback = SvREFCNT_inc (POPs);
667     }
668     else
669     {
670     // execute request synchronously
671     bdb_request (req);
672     req_invoke (req);
673     req_free (req);
674     return;
675     }
676 root 1.3 }
677    
678 root 1.1 ++nreqs;
679    
680 root 1.12 X_LOCK (reqlock);
681 root 1.1 ++nready;
682     reqq_push (&req_queue, req);
683 root 1.12 X_COND_SIGNAL (reqwait);
684     X_UNLOCK (reqlock);
685 root 1.1
686     maybe_start_thread ();
687 root 1.3
688     if (wait_callback)
689     {
690     dSP;
691     PUSHMARK (SP);
692     PUTBACK;
693     call_sv (wait_callback, G_DISCARD);
694     }
695 root 1.1 }
696    
697     static void end_thread (void)
698     {
699 root 1.52 bdb_req req = calloc (1, sizeof (bdb_cb));
700 root 1.1
701     req->type = REQ_QUIT;
702     req->pri = PRI_MAX + PRI_BIAS;
703    
704 root 1.12 X_LOCK (reqlock);
705 root 1.1 reqq_push (&req_queue, req);
706 root 1.12 X_COND_SIGNAL (reqwait);
707     X_UNLOCK (reqlock);
708 root 1.1
709 root 1.12 X_LOCK (wrklock);
710 root 1.1 --started;
711 root 1.12 X_UNLOCK (wrklock);
712 root 1.1 }
713    
714     static void set_max_idle (int nthreads)
715     {
716 root 1.12 if (WORDACCESS_UNSAFE) X_LOCK (reqlock);
717 root 1.1 max_idle = nthreads <= 0 ? 1 : nthreads;
718 root 1.12 if (WORDACCESS_UNSAFE) X_UNLOCK (reqlock);
719 root 1.1 }
720    
721     static void min_parallel (int nthreads)
722     {
723     if (wanted < nthreads)
724     wanted = nthreads;
725     }
726    
727     static void max_parallel (int nthreads)
728     {
729     if (wanted > nthreads)
730     wanted = nthreads;
731    
732     while (started > wanted)
733     end_thread ();
734     }
735    
736 root 1.34 static void poll_wait (void)
737 root 1.1 {
738     fd_set rfd;
739    
740     while (nreqs)
741     {
742     int size;
743 root 1.12 if (WORDACCESS_UNSAFE) X_LOCK (reslock);
744 root 1.1 size = res_queue.size;
745 root 1.12 if (WORDACCESS_UNSAFE) X_UNLOCK (reslock);
746 root 1.1
747     if (size)
748     return;
749    
750     maybe_start_thread ();
751    
752 root 1.13 FD_ZERO (&rfd);
753     FD_SET (respipe [0], &rfd);
754 root 1.1
755 root 1.13 PerlSock_select (respipe [0] + 1, &rfd, 0, 0, 0);
756 root 1.1 }
757     }
758    
759 root 1.34 static int poll_cb (void)
760 root 1.1 {
761     dSP;
762     int count = 0;
763     int maxreqs = max_poll_reqs;
764     int do_croak = 0;
765     struct timeval tv_start, tv_now;
766 root 1.28 bdb_req req;
767 root 1.1
768     if (max_poll_time)
769     gettimeofday (&tv_start, 0);
770    
771     for (;;)
772     {
773     for (;;)
774     {
775     maybe_start_thread ();
776    
777 root 1.12 X_LOCK (reslock);
778 root 1.1 req = reqq_shift (&res_queue);
779    
780     if (req)
781     {
782     --npending;
783    
784     if (!res_queue.size)
785     {
786     /* read any signals sent by the worker threads */
787     char buf [4];
788 root 1.13 while (respipe_read (respipe [0], buf, 4) == 4)
789 root 1.1 ;
790     }
791     }
792    
793 root 1.12 X_UNLOCK (reslock);
794 root 1.1
795     if (!req)
796     break;
797    
798     --nreqs;
799    
800     if (!req_invoke (req))
801     {
802     req_free (req);
803     croak (0);
804     }
805    
806     count++;
807    
808     req_free (req);
809    
810     if (maxreqs && !--maxreqs)
811     break;
812    
813     if (max_poll_time)
814     {
815     gettimeofday (&tv_now, 0);
816    
817     if (tvdiff (&tv_start, &tv_now) >= max_poll_time)
818     break;
819     }
820     }
821    
822     if (nreqs <= max_outstanding)
823     break;
824    
825     poll_wait ();
826    
827     ++maxreqs;
828     }
829    
830     return count;
831     }
832    
833     /*****************************************************************************/
834    
835 root 1.51 static void
836     bdb_request (bdb_req req)
837     {
838     switch (req->type)
839     {
840     case REQ_ENV_OPEN:
841     req->result = req->env->open (req->env, req->buf1, req->uint1, req->int1);
842     break;
843    
844     case REQ_ENV_CLOSE:
845     req->result = req->env->close (req->env, req->uint1);
846     break;
847    
848     case REQ_ENV_TXN_CHECKPOINT:
849     req->result = req->env->txn_checkpoint (req->env, req->uint1, req->int1, req->uint2);
850     break;
851    
852     case REQ_ENV_LOCK_DETECT:
853     req->result = req->env->lock_detect (req->env, req->uint1, req->uint2, &req->int1);
854     break;
855    
856     case REQ_ENV_MEMP_SYNC:
857     req->result = req->env->memp_sync (req->env, 0);
858     break;
859    
860     case REQ_ENV_MEMP_TRICKLE:
861     req->result = req->env->memp_trickle (req->env, req->int1, &req->int2);
862     break;
863    
864     case REQ_ENV_DBREMOVE:
865     req->result = req->env->dbremove (req->env, req->txn, req->buf1, req->buf2, req->uint1);
866     break;
867    
868     case REQ_ENV_DBRENAME:
869     req->result = req->env->dbrename (req->env, req->txn, req->buf1, req->buf2, req->buf3, req->uint1);
870     break;
871    
872     case REQ_DB_OPEN:
873     req->result = req->db->open (req->db, req->txn, req->buf1, req->buf2, req->int1, req->uint1, req->int2);
874     break;
875    
876     case REQ_DB_CLOSE:
877     req->result = req->db->close (req->db, req->uint1);
878     break;
879    
880     #if DB_VERSION_MINOR >= 4
881     case REQ_DB_COMPACT:
882 root 1.62 req->result = req->db->compact (req->db, req->txn, req->dbt1.data ? &req->dbt1 : 0, req->dbt2.data ? &req->dbt2 : 0, 0, req->uint1, 0);
883 root 1.51 break;
884     #endif
885    
886     case REQ_DB_SYNC:
887     req->result = req->db->sync (req->db, req->uint1);
888     break;
889    
890     case REQ_DB_UPGRADE:
891     req->result = req->db->upgrade (req->db, req->buf1, req->uint1);
892     break;
893    
894     case REQ_DB_PUT:
895     req->result = req->db->put (req->db, req->txn, &req->dbt1, &req->dbt2, req->uint1);
896     break;
897    
898     #if DB_VERSION_MINOR >= 6
899     case REQ_DB_EXISTS:
900     req->result = req->db->exists (req->db, req->txn, &req->dbt1, req->uint1);
901     break;
902     #endif
903     case REQ_DB_GET:
904     req->result = req->db->get (req->db, req->txn, &req->dbt1, &req->dbt3, req->uint1);
905     break;
906    
907     case REQ_DB_PGET:
908     req->result = req->db->pget (req->db, req->txn, &req->dbt1, &req->dbt2, &req->dbt3, req->uint1);
909     break;
910    
911     case REQ_DB_DEL:
912     req->result = req->db->del (req->db, req->txn, &req->dbt1, req->uint1);
913     break;
914    
915     case REQ_DB_KEY_RANGE:
916     req->result = req->db->key_range (req->db, req->txn, &req->dbt1, &req->key_range, req->uint1);
917     break;
918    
919     case REQ_TXN_COMMIT:
920     req->result = req->txn->commit (req->txn, req->uint1);
921     break;
922    
923     case REQ_TXN_ABORT:
924     req->result = req->txn->abort (req->txn);
925     break;
926    
927     case REQ_TXN_FINISH:
928     if (req->txn->flags & TXN_DEADLOCK)
929     {
930     req->result = req->txn->abort (req->txn);
931     if (!req->result)
932     req->result = DB_LOCK_DEADLOCK;
933     }
934     else
935     req->result = req->txn->commit (req->txn, req->uint1);
936     break;
937    
938     case REQ_C_CLOSE:
939     req->result = req->dbc->c_close (req->dbc);
940     break;
941    
942     case REQ_C_COUNT:
943     {
944     db_recno_t recno;
945     req->result = req->dbc->c_count (req->dbc, &recno, req->uint1);
946     req->uv1 = recno;
947     }
948     break;
949    
950     case REQ_C_PUT:
951     req->result = req->dbc->c_put (req->dbc, &req->dbt1, &req->dbt2, req->uint1);
952     break;
953    
954     case REQ_C_GET:
955     req->result = req->dbc->c_get (req->dbc, &req->dbt1, &req->dbt3, req->uint1);
956     break;
957    
958     case REQ_C_PGET:
959     req->result = req->dbc->c_pget (req->dbc, &req->dbt1, &req->dbt2, &req->dbt3, req->uint1);
960     break;
961    
962     case REQ_C_DEL:
963     req->result = req->dbc->c_del (req->dbc, req->uint1);
964     break;
965    
966     #if DB_VERSION_MINOR >= 3
967     case REQ_SEQ_OPEN:
968     req->result = req->seq->open (req->seq, req->txn, &req->dbt1, req->uint1);
969     break;
970    
971     case REQ_SEQ_CLOSE:
972     req->result = req->seq->close (req->seq, req->uint1);
973     break;
974    
975     case REQ_SEQ_GET:
976     req->result = req->seq->get (req->seq, req->txn, req->int1, &req->seq_t, req->uint1);
977     break;
978    
979     case REQ_SEQ_REMOVE:
980     req->result = req->seq->remove (req->seq, req->txn, req->uint1);
981     break;
982     #endif
983    
984 root 1.63 case REQ_ENV_LOG_ARCHIVE:
985     {
986     char **listp = 0; /* DB_ARCH_REMOVE does not touch listp, contrary to docs */
987     req->result = req->env->log_archive (req->env, &listp, req->uint1);
988     req->buf1 = (char *)listp;
989     }
990     break;
991    
992 root 1.51 default:
993     req->result = ENOSYS;
994     break;
995     }
996    
997     if (req->txn && (req->result > 0 || req->result == DB_LOCK_NOTGRANTED))
998     req->txn->flags |= TXN_DEADLOCK;
999     }
1000    
1001 root 1.13 X_THREAD_PROC (bdb_proc)
1002 root 1.1 {
1003 root 1.28 bdb_req req;
1004 root 1.1 struct timespec ts;
1005     worker *self = (worker *)thr_arg;
1006    
1007     /* try to distribute timeouts somewhat evenly */
1008 root 1.13 ts.tv_nsec = ((unsigned long)self & 1023UL) * (1000000000UL / 1024UL);
1009 root 1.1
1010     for (;;)
1011     {
1012     ts.tv_sec = time (0) + IDLE_TIMEOUT;
1013    
1014 root 1.12 X_LOCK (reqlock);
1015 root 1.1
1016     for (;;)
1017     {
1018     self->req = req = reqq_shift (&req_queue);
1019    
1020     if (req)
1021     break;
1022    
1023     ++idle;
1024    
1025 root 1.12 if (X_COND_TIMEDWAIT (reqwait, reqlock, ts)
1026 root 1.1 == ETIMEDOUT)
1027     {
1028     if (idle > max_idle)
1029     {
1030     --idle;
1031 root 1.12 X_UNLOCK (reqlock);
1032     X_LOCK (wrklock);
1033 root 1.1 --started;
1034 root 1.12 X_UNLOCK (wrklock);
1035 root 1.1 goto quit;
1036     }
1037    
1038     /* we are allowed to idle, so do so without any timeout */
1039 root 1.12 X_COND_WAIT (reqwait, reqlock);
1040 root 1.1 ts.tv_sec = time (0) + IDLE_TIMEOUT;
1041     }
1042    
1043     --idle;
1044     }
1045    
1046     --nready;
1047    
1048 root 1.12 X_UNLOCK (reqlock);
1049 root 1.49
1050 root 1.51 if (req->type == REQ_QUIT)
1051 root 1.52 {
1052     X_LOCK (reslock);
1053     free (req);
1054     self->req = 0;
1055     X_UNLOCK (reslock);
1056    
1057     goto quit;
1058     }
1059 root 1.1
1060 root 1.51 bdb_request (req);
1061 root 1.17
1062 root 1.12 X_LOCK (reslock);
1063 root 1.1
1064     ++npending;
1065    
1066     if (!reqq_push (&res_queue, req))
1067     /* write a dummy byte to the pipe so fh becomes ready */
1068 root 1.13 respipe_write (respipe_osf [1], (const void *)&respipe_osf, 1);
1069 root 1.1
1070     self->req = 0;
1071     worker_clear (self);
1072    
1073 root 1.12 X_UNLOCK (reslock);
1074 root 1.1 }
1075    
1076     quit:
1077 root 1.12 X_LOCK (wrklock);
1078 root 1.1 worker_free (self);
1079 root 1.12 X_UNLOCK (wrklock);
1080 root 1.1
1081     return 0;
1082     }
1083    
1084     /*****************************************************************************/
1085    
1086     static void atfork_prepare (void)
1087     {
1088 root 1.12 X_LOCK (wrklock);
1089     X_LOCK (reqlock);
1090     X_LOCK (reslock);
1091 root 1.1 }
1092    
1093     static void atfork_parent (void)
1094     {
1095 root 1.12 X_UNLOCK (reslock);
1096     X_UNLOCK (reqlock);
1097     X_UNLOCK (wrklock);
1098 root 1.1 }
1099    
1100     static void atfork_child (void)
1101     {
1102 root 1.28 bdb_req prv;
1103 root 1.1
1104     while (prv = reqq_shift (&req_queue))
1105     req_free (prv);
1106    
1107     while (prv = reqq_shift (&res_queue))
1108     req_free (prv);
1109    
1110     while (wrk_first.next != &wrk_first)
1111     {
1112     worker *wrk = wrk_first.next;
1113    
1114     if (wrk->req)
1115     req_free (wrk->req);
1116    
1117     worker_clear (wrk);
1118     worker_free (wrk);
1119     }
1120    
1121     started = 0;
1122     idle = 0;
1123     nreqs = 0;
1124     nready = 0;
1125     npending = 0;
1126    
1127 root 1.19 create_respipe ();
1128 root 1.1
1129     atfork_parent ();
1130     }
1131    
1132 root 1.50 #define dREQ(reqtype,rsvcnt) \
1133 root 1.28 bdb_req req; \
1134 root 1.1 int req_pri = next_pri; \
1135     next_pri = DEFAULT_PRI + PRI_BIAS; \
1136     \
1137 root 1.41 if (callback && SvOK (callback)) \
1138     croak ("callback has illegal type or extra arguments"); \
1139 root 1.1 \
1140 root 1.28 Newz (0, req, 1, bdb_cb); \
1141 root 1.1 if (!req) \
1142 root 1.28 croak ("out of memory during bdb_req allocation"); \
1143 root 1.1 \
1144 root 1.50 req->callback = SvREFCNT_inc (cb); \
1145 root 1.2 req->type = (reqtype); \
1146 root 1.50 req->pri = req_pri; \
1147     if (rsvcnt >= 1) req->rsv1 = SvREFCNT_inc (ST (0)); \
1148     if (rsvcnt >= 2) req->rsv2 = SvREFCNT_inc (ST (1)); \
1149     (void)0;
1150 root 1.1
1151     #define REQ_SEND \
1152 root 1.2 req_send (req)
1153    
1154 root 1.30 #define SvPTR(var, arg, type, class, nullok) \
1155 root 1.5 if (!SvOK (arg)) \
1156     { \
1157 root 1.30 if (nullok != 1) \
1158 root 1.7 croak (# var " must be a " # class " object, not undef"); \
1159 root 1.5 \
1160     (var) = 0; \
1161     } \
1162     else if (sv_derived_from ((arg), # class)) \
1163     { \
1164     IV tmp = SvIV ((SV*) SvRV (arg)); \
1165     (var) = INT2PTR (type, tmp); \
1166 root 1.54 if (!var && nullok != 2) \
1167 root 1.7 croak (# var " is not a valid " # class " object anymore"); \
1168 root 1.5 } \
1169     else \
1170 root 1.42 croak (# var " is not of type " # class);
1171 root 1.3
1172 root 1.54 #define ARG_MUTABLE(name) \
1173     if (SvREADONLY (name)) \
1174     croak ("argument " #name " is read-only/constant, but the request requires it to be mutable");
1175    
1176 root 1.5 static void
1177     ptr_nuke (SV *sv)
1178 root 1.3 {
1179 root 1.5 assert (SvROK (sv));
1180     sv_setiv (SvRV (sv), 0);
1181     }
1182 root 1.3
1183 root 1.31 static int
1184     errno_get (pTHX_ SV *sv, MAGIC *mg)
1185     {
1186     if (*mg->mg_ptr == '!') // should always be the case
1187     if (-30999 <= errno && errno <= -30800)
1188     {
1189 root 1.32 sv_setnv (sv, (NV)errno);
1190 root 1.31 sv_setpv (sv, db_strerror (errno));
1191 root 1.32 SvNOK_on (sv); /* what a wonderful hack! */
1192     // ^^^ copied from perl sources
1193 root 1.31 return 0;
1194     }
1195    
1196     return PL_vtbl_sv.svt_get (aTHX_ sv, mg);
1197     }
1198    
1199     static MGVTBL vtbl_errno;
1200    
1201     // this wonderful hack :( patches perl's $! variable to support our errno values
1202     static void
1203     patch_errno (void)
1204     {
1205     SV *sv;
1206     MAGIC *mg;
1207    
1208     if (!(sv = get_sv ("!", 1)))
1209     return;
1210    
1211     if (!(mg = mg_find (sv, PERL_MAGIC_sv)))
1212     return;
1213    
1214     if (mg->mg_virtual != &PL_vtbl_sv)
1215     return;
1216    
1217     vtbl_errno = PL_vtbl_sv;
1218     vtbl_errno.svt_get = errno_get;
1219     mg->mg_virtual = &vtbl_errno;
1220     }
1221    
1222 root 1.42 #if __GNUC__ >= 4
1223     # define noinline __attribute__ ((noinline))
1224     #else
1225     # define noinline
1226     #endif
1227    
1228     static noinline SV *
1229 root 1.41 pop_callback (I32 *ritems, SV *sv)
1230     {
1231     if (SvROK (sv))
1232     {
1233     HV *st;
1234     GV *gvp;
1235 root 1.42 CV *cv;
1236     const char *name;
1237    
1238     /* forgive me */
1239     if (SvTYPE (SvRV (sv)) == SVt_PVMG
1240     && (st = SvSTASH (SvRV (sv)))
1241     && (name = HvNAME_get (st))
1242     && (name [0] == 'B' && name [1] == 'D' && name [2] == 'B' && name [3] == ':'))
1243     return 0;
1244 root 1.41
1245 root 1.42 if ((cv = sv_2cv (sv, &st, &gvp, 0)))
1246 root 1.41 {
1247     --*ritems;
1248     return (SV *)cv;
1249     }
1250     }
1251    
1252     return 0;
1253     }
1254    
1255 root 1.64 /*****************************************************************************/
1256    
1257     #if 0
1258     static int
1259     bt_pfxc_compare (DB *db, const DBT *dbt1, const DBT *dbt2)
1260     {
1261     ssize_t size1 = dbt1->size;
1262     ssize_t size2 = dbt2->size;
1263     int res = memcmp ((void *)dbt1->data, (void *)dbt2->data,
1264     size1 <= size2 ? size1 : size2);
1265    
1266     if (res)
1267     return res;
1268     else if (size1 - size2)
1269     return size1 - size2;
1270     else
1271     return 0;
1272     }
1273    
1274     static size_t
1275     bt_pfxc_prefix_x (DB *db, const DBT *dbt1, const DBT *dbt2)
1276     {
1277     ssize_t size1 = dbt1->size;
1278     ssize_t size2 = dbt2->size;
1279     u_int8_t *p1 = (u_int8_t *)dbt1->data;
1280     u_int8_t *p2 = (u_int8_t *)dbt2->data;
1281     u_int8_t *pe = p1 + (size1 <= size2 ? size1 : size2);
1282    
1283     while (p1 < pe)
1284     if (*p1++ != *p2++)
1285     return p1 - (u_int8_t *)dbt1->data - 1;
1286    
1287     if (size1 < size2) return size1 + 1;
1288     if (size1 > size2) return size2 + 1;
1289    
1290     return size1;
1291     }
1292     #endif
1293    
1294     /*****************************************************************************/
1295    
1296 root 1.58 /* stupid windows defines CALLBACK as well */
1297 root 1.47 #undef CALLBACK
1298 root 1.41 #define CALLBACK SV *cb = pop_callback (&items, ST (items - 1));
1299    
1300 root 1.2 MODULE = BDB PACKAGE = BDB
1301 root 1.1
1302     PROTOTYPES: ENABLE
1303    
1304     BOOT:
1305     {
1306 root 1.2 HV *stash = gv_stashpv ("BDB", 1);
1307    
1308     static const struct {
1309     const char *name;
1310     IV iv;
1311     } *civ, const_iv[] = {
1312     #define const_iv(name) { # name, (IV)DB_ ## name },
1313     const_iv (RPCCLIENT)
1314     const_iv (INIT_CDB)
1315     const_iv (INIT_LOCK)
1316     const_iv (INIT_LOG)
1317     const_iv (INIT_MPOOL)
1318     const_iv (INIT_REP)
1319     const_iv (INIT_TXN)
1320     const_iv (RECOVER)
1321     const_iv (INIT_TXN)
1322     const_iv (RECOVER_FATAL)
1323     const_iv (CREATE)
1324 root 1.20 const_iv (RDONLY)
1325 root 1.2 const_iv (USE_ENVIRON)
1326     const_iv (USE_ENVIRON_ROOT)
1327     const_iv (LOCKDOWN)
1328     const_iv (PRIVATE)
1329     const_iv (SYSTEM_MEM)
1330     const_iv (AUTO_COMMIT)
1331     const_iv (CDB_ALLDB)
1332     const_iv (DIRECT_DB)
1333     const_iv (NOLOCKING)
1334     const_iv (NOMMAP)
1335     const_iv (NOPANIC)
1336     const_iv (OVERWRITE)
1337     const_iv (PANIC_ENVIRONMENT)
1338     const_iv (REGION_INIT)
1339     const_iv (TIME_NOTGRANTED)
1340     const_iv (TXN_NOSYNC)
1341 root 1.20 const_iv (TXN_NOT_DURABLE)
1342 root 1.2 const_iv (TXN_WRITE_NOSYNC)
1343 root 1.5 const_iv (WRITECURSOR)
1344 root 1.2 const_iv (YIELDCPU)
1345     const_iv (ENCRYPT_AES)
1346     const_iv (XA_CREATE)
1347     const_iv (BTREE)
1348     const_iv (HASH)
1349     const_iv (QUEUE)
1350     const_iv (RECNO)
1351     const_iv (UNKNOWN)
1352     const_iv (EXCL)
1353     const_iv (TRUNCATE)
1354     const_iv (NOSYNC)
1355     const_iv (CHKSUM)
1356     const_iv (ENCRYPT)
1357     const_iv (DUP)
1358     const_iv (DUPSORT)
1359 root 1.61 //const_iv (RECNUM)
1360 root 1.2 const_iv (RENUMBER)
1361     const_iv (REVSPLITOFF)
1362     const_iv (CONSUME)
1363     const_iv (CONSUME_WAIT)
1364 root 1.5 const_iv (GET_BOTH)
1365 root 1.6 const_iv (GET_BOTH_RANGE)
1366 root 1.5 //const_iv (SET_RECNO)
1367     //const_iv (MULTIPLE)
1368 root 1.2 const_iv (SNAPSHOT)
1369     const_iv (JOIN_ITEM)
1370 root 1.27 const_iv (JOIN_NOSORT)
1371 root 1.2 const_iv (RMW)
1372    
1373     const_iv (NOTFOUND)
1374     const_iv (KEYEMPTY)
1375     const_iv (LOCK_DEADLOCK)
1376     const_iv (LOCK_NOTGRANTED)
1377     const_iv (RUNRECOVERY)
1378 root 1.3 const_iv (OLD_VERSION)
1379     const_iv (REP_HANDLE_DEAD)
1380 root 1.6 const_iv (SECONDARY_BAD)
1381 root 1.3
1382     const_iv (APPEND)
1383     const_iv (NODUPDATA)
1384     const_iv (NOOVERWRITE)
1385    
1386 root 1.4 const_iv (TXN_NOWAIT)
1387     const_iv (TXN_SYNC)
1388    
1389 root 1.3 const_iv (SET_LOCK_TIMEOUT)
1390     const_iv (SET_TXN_TIMEOUT)
1391 root 1.6
1392     const_iv (FIRST)
1393     const_iv (NEXT)
1394     const_iv (NEXT_DUP)
1395     const_iv (NEXT_NODUP)
1396     const_iv (PREV)
1397     const_iv (PREV_NODUP)
1398     const_iv (SET)
1399     const_iv (SET_RANGE)
1400     const_iv (LAST)
1401     const_iv (BEFORE)
1402     const_iv (AFTER)
1403     const_iv (CURRENT)
1404     const_iv (KEYFIRST)
1405     const_iv (KEYLAST)
1406     const_iv (NODUPDATA)
1407 root 1.8
1408     const_iv (FORCE)
1409    
1410     const_iv (LOCK_DEFAULT)
1411     const_iv (LOCK_EXPIRE)
1412     const_iv (LOCK_MAXLOCKS)
1413     const_iv (LOCK_MINLOCKS)
1414     const_iv (LOCK_MINWRITE)
1415     const_iv (LOCK_OLDEST)
1416     const_iv (LOCK_RANDOM)
1417     const_iv (LOCK_YOUNGEST)
1418    
1419 root 1.14 const_iv (DONOTINDEX)
1420     const_iv (KEYEMPTY )
1421     const_iv (KEYEXIST )
1422     const_iv (LOCK_DEADLOCK)
1423     const_iv (LOCK_NOTGRANTED)
1424     const_iv (NOSERVER)
1425     const_iv (NOSERVER_HOME)
1426     const_iv (NOSERVER_ID)
1427     const_iv (NOTFOUND)
1428     const_iv (PAGE_NOTFOUND)
1429     const_iv (REP_DUPMASTER)
1430     const_iv (REP_HANDLE_DEAD)
1431     const_iv (REP_HOLDELECTION)
1432     const_iv (REP_ISPERM)
1433     const_iv (REP_NEWMASTER)
1434     const_iv (REP_NEWSITE)
1435     const_iv (REP_NOTPERM)
1436     const_iv (REP_UNAVAIL)
1437     const_iv (RUNRECOVERY)
1438     const_iv (SECONDARY_BAD)
1439     const_iv (VERIFY_BAD)
1440    
1441 root 1.63 const_iv (ARCH_ABS)
1442     const_iv (ARCH_DATA)
1443     const_iv (ARCH_LOG)
1444     const_iv (ARCH_REMOVE)
1445    
1446 root 1.14 const_iv (VERB_DEADLOCK)
1447     const_iv (VERB_RECOVERY)
1448     const_iv (VERB_REPLICATION)
1449     const_iv (VERB_WAITSFOR)
1450    
1451     const_iv (VERSION_MAJOR)
1452     const_iv (VERSION_MINOR)
1453     const_iv (VERSION_PATCH)
1454 root 1.47 #if DB_VERSION_MINOR >= 3
1455     const_iv (INORDER)
1456     const_iv (LOCK_MAXWRITE)
1457     const_iv (SEQ_DEC)
1458     const_iv (SEQ_INC)
1459     const_iv (SEQ_WRAP)
1460     const_iv (BUFFER_SMALL)
1461     const_iv (LOG_BUFFER_FULL)
1462     const_iv (VERSION_MISMATCH)
1463     #endif
1464     #if DB_VERSION_MINOR >= 4
1465     const_iv (REGISTER)
1466     const_iv (DSYNC_DB)
1467     const_iv (READ_COMMITTED)
1468     const_iv (READ_UNCOMMITTED)
1469     const_iv (REP_IGNORE)
1470     const_iv (REP_LOCKOUT)
1471     const_iv (REP_JOIN_FAILURE)
1472     const_iv (FREE_SPACE)
1473     const_iv (FREELIST_ONLY)
1474     const_iv (VERB_REGISTER)
1475     #endif
1476 root 1.13 #if DB_VERSION_MINOR >= 5
1477     const_iv (MULTIVERSION)
1478     const_iv (TXN_SNAPSHOT)
1479     #endif
1480 root 1.15 #if DB_VERSION_MINOR >= 6
1481 root 1.16 const_iv (PREV_DUP)
1482     const_iv (PRIORITY_UNCHANGED)
1483     const_iv (PRIORITY_VERY_LOW)
1484     const_iv (PRIORITY_LOW)
1485     const_iv (PRIORITY_DEFAULT)
1486     const_iv (PRIORITY_HIGH)
1487     const_iv (PRIORITY_VERY_HIGH)
1488 root 1.63 const_iv (IGNORE_LEASE)
1489 root 1.15 #endif
1490 root 1.39 #if DB_VERSION_MINOR >= 7
1491 root 1.61 //const_iv (MULTIPLE_KEY)
1492 root 1.39 const_iv (LOG_DIRECT)
1493     const_iv (LOG_DSYNC)
1494     const_iv (LOG_AUTO_REMOVE)
1495     const_iv (LOG_IN_MEMORY)
1496     const_iv (LOG_ZERO)
1497     #else
1498     const_iv (DIRECT_LOG)
1499 root 1.47 const_iv (LOG_AUTOREMOVE)
1500     # if DB_VERSION_MINOR >= 3
1501 root 1.39 const_iv (DSYNC_LOG)
1502     const_iv (LOG_INMEMORY)
1503 root 1.47 # endif
1504 root 1.39 #endif
1505 root 1.2 };
1506    
1507     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1508     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
1509 root 1.1
1510 root 1.53 prepare_cb = &PL_sv_undef;
1511    
1512 root 1.40 {
1513     /* we currently only allow version, minor-version and patchlevel to go up to 255 */
1514     char vstring[3] = { DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH };
1515    
1516     newCONSTSUB (stash, "VERSION_v", newSVpvn (vstring, 3));
1517     }
1518    
1519 root 1.24 newCONSTSUB (stash, "VERSION_STRING", newSVpv (DB_VERSION_STRING, 0));
1520 root 1.14
1521 root 1.19 create_respipe ();
1522 root 1.12
1523     X_THREAD_ATFORK (atfork_prepare, atfork_parent, atfork_child);
1524 root 1.31 patch_errno ();
1525 root 1.1 }
1526    
1527     void
1528     max_poll_reqs (int nreqs)
1529     PROTOTYPE: $
1530     CODE:
1531     max_poll_reqs = nreqs;
1532    
1533     void
1534     max_poll_time (double nseconds)
1535     PROTOTYPE: $
1536     CODE:
1537     max_poll_time = nseconds * AIO_TICKS;
1538    
1539     void
1540     min_parallel (int nthreads)
1541     PROTOTYPE: $
1542    
1543     void
1544     max_parallel (int nthreads)
1545     PROTOTYPE: $
1546    
1547     void
1548     max_idle (int nthreads)
1549     PROTOTYPE: $
1550     CODE:
1551     set_max_idle (nthreads);
1552    
1553     int
1554     max_outstanding (int maxreqs)
1555     PROTOTYPE: $
1556     CODE:
1557     RETVAL = max_outstanding;
1558     max_outstanding = maxreqs;
1559     OUTPUT:
1560     RETVAL
1561    
1562     int
1563 root 1.3 dbreq_pri (int pri = 0)
1564 root 1.1 PROTOTYPE: ;$
1565     CODE:
1566     RETVAL = next_pri - PRI_BIAS;
1567     if (items > 0)
1568     {
1569     if (pri < PRI_MIN) pri = PRI_MIN;
1570     if (pri > PRI_MAX) pri = PRI_MAX;
1571     next_pri = pri + PRI_BIAS;
1572     }
1573     OUTPUT:
1574     RETVAL
1575    
1576     void
1577 root 1.3 dbreq_nice (int nice = 0)
1578 root 1.1 CODE:
1579     nice = next_pri - nice;
1580     if (nice < PRI_MIN) nice = PRI_MIN;
1581     if (nice > PRI_MAX) nice = PRI_MAX;
1582     next_pri = nice + PRI_BIAS;
1583    
1584     void
1585     flush ()
1586     PROTOTYPE:
1587     CODE:
1588     while (nreqs)
1589     {
1590     poll_wait ();
1591     poll_cb ();
1592     }
1593    
1594     int
1595 root 1.3 poll ()
1596 root 1.1 PROTOTYPE:
1597     CODE:
1598     poll_wait ();
1599     RETVAL = poll_cb ();
1600     OUTPUT:
1601     RETVAL
1602    
1603     int
1604 root 1.3 poll_fileno ()
1605 root 1.1 PROTOTYPE:
1606     CODE:
1607     RETVAL = respipe [0];
1608     OUTPUT:
1609     RETVAL
1610    
1611     int
1612 root 1.3 poll_cb (...)
1613 root 1.1 PROTOTYPE:
1614     CODE:
1615     RETVAL = poll_cb ();
1616     OUTPUT:
1617     RETVAL
1618    
1619     void
1620 root 1.3 poll_wait ()
1621 root 1.1 PROTOTYPE:
1622     CODE:
1623     poll_wait ();
1624    
1625     int
1626 root 1.3 nreqs ()
1627 root 1.1 PROTOTYPE:
1628     CODE:
1629     RETVAL = nreqs;
1630     OUTPUT:
1631     RETVAL
1632    
1633     int
1634 root 1.3 nready ()
1635 root 1.1 PROTOTYPE:
1636     CODE:
1637     RETVAL = get_nready ();
1638     OUTPUT:
1639     RETVAL
1640    
1641     int
1642 root 1.3 npending ()
1643 root 1.1 PROTOTYPE:
1644     CODE:
1645     RETVAL = get_npending ();
1646     OUTPUT:
1647     RETVAL
1648    
1649     int
1650 root 1.3 nthreads ()
1651 root 1.1 PROTOTYPE:
1652     CODE:
1653 root 1.12 if (WORDACCESS_UNSAFE) X_LOCK (wrklock);
1654 root 1.1 RETVAL = started;
1655 root 1.12 if (WORDACCESS_UNSAFE) X_UNLOCK (wrklock);
1656 root 1.1 OUTPUT:
1657     RETVAL
1658    
1659 root 1.53 SV *
1660 root 1.3 set_sync_prepare (SV *cb)
1661     PROTOTYPE: &
1662     CODE:
1663 root 1.53 RETVAL = prepare_cb;
1664 root 1.3 prepare_cb = newSVsv (cb);
1665 root 1.53 OUTPUT:
1666     RETVAL
1667 root 1.3
1668 root 1.14 char *
1669     strerror (int errorno = errno)
1670     PROTOTYPE: ;$
1671     CODE:
1672     RETVAL = db_strerror (errorno);
1673     OUTPUT:
1674     RETVAL
1675 root 1.8
1676 root 1.37 void _on_next_submit (SV *cb)
1677     CODE:
1678     SvREFCNT_dec (on_next_submit);
1679     on_next_submit = SvOK (cb) ? newSVsv (cb) : 0;
1680    
1681 root 1.2 DB_ENV *
1682 root 1.3 db_env_create (U32 env_flags = 0)
1683 root 1.2 CODE:
1684     {
1685 root 1.3 errno = db_env_create (&RETVAL, env_flags);
1686     if (errno)
1687     croak ("db_env_create: %s", db_strerror (errno));
1688 root 1.14
1689     if (0)
1690     {
1691     RETVAL->set_errcall (RETVAL, debug_errcall);
1692     RETVAL->set_msgcall (RETVAL, debug_msgcall);
1693     }
1694 root 1.2 }
1695 root 1.3 OUTPUT:
1696     RETVAL
1697 root 1.2
1698     void
1699 root 1.41 db_env_open (DB_ENV *env, bdb_filename db_home, U32 open_flags, int mode, SV *callback = 0)
1700     PREINIT:
1701     CALLBACK
1702 root 1.2 CODE:
1703     {
1704 root 1.50 dREQ (REQ_ENV_OPEN, 1);
1705 root 1.2 req->env = env;
1706 root 1.3 req->uint1 = open_flags | DB_THREAD;
1707 root 1.2 req->int1 = mode;
1708 root 1.3 req->buf1 = strdup_ornull (db_home);
1709 root 1.2 REQ_SEND;
1710     }
1711    
1712     void
1713 root 1.41 db_env_close (DB_ENV *env, U32 flags = 0, SV *callback = 0)
1714     PREINIT:
1715     CALLBACK
1716 root 1.2 CODE:
1717     {
1718 root 1.56 dREQ (REQ_ENV_CLOSE, 0);
1719 root 1.54 ptr_nuke (ST (0));
1720 root 1.2 req->env = env;
1721     req->uint1 = flags;
1722     REQ_SEND;
1723     }
1724    
1725 root 1.8 void
1726 root 1.41 db_env_txn_checkpoint (DB_ENV *env, U32 kbyte = 0, U32 min = 0, U32 flags = 0, SV *callback = 0)
1727     PREINIT:
1728     CALLBACK
1729 root 1.8 CODE:
1730     {
1731 root 1.50 dREQ (REQ_ENV_TXN_CHECKPOINT, 1);
1732 root 1.8 req->env = env;
1733     req->uint1 = kbyte;
1734     req->int1 = min;
1735     req->uint2 = flags;
1736     REQ_SEND;
1737     }
1738    
1739     void
1740 root 1.41 db_env_lock_detect (DB_ENV *env, U32 flags = 0, U32 atype = DB_LOCK_DEFAULT, SV *dummy = 0, SV *callback = 0)
1741     PREINIT:
1742     CALLBACK
1743 root 1.8 CODE:
1744     {
1745 root 1.50 dREQ (REQ_ENV_LOCK_DETECT, 1);
1746 root 1.8 req->env = env;
1747     req->uint1 = flags;
1748     req->uint2 = atype;
1749 root 1.41 /* req->int2 = 0; dummy */
1750 root 1.8 REQ_SEND;
1751     }
1752    
1753     void
1754 root 1.41 db_env_memp_sync (DB_ENV *env, SV *dummy = 0, SV *callback = 0)
1755     PREINIT:
1756     CALLBACK
1757 root 1.8 CODE:
1758     {
1759 root 1.50 dREQ (REQ_ENV_MEMP_SYNC, 1);
1760 root 1.8 req->env = env;
1761     REQ_SEND;
1762     }
1763    
1764     void
1765 root 1.41 db_env_memp_trickle (DB_ENV *env, int percent, SV *dummy = 0, SV *callback = 0)
1766     PREINIT:
1767     CALLBACK
1768 root 1.8 CODE:
1769     {
1770 root 1.50 dREQ (REQ_ENV_MEMP_TRICKLE, 1);
1771 root 1.8 req->env = env;
1772     req->int1 = percent;
1773     REQ_SEND;
1774     }
1775    
1776 root 1.39 void
1777 root 1.41 db_env_dbremove (DB_ENV *env, DB_TXN_ornull *txnid, bdb_filename file, bdb_filename database, U32 flags = 0, SV *callback = 0)
1778     PREINIT:
1779     CALLBACK
1780 root 1.39 CODE:
1781     {
1782 root 1.50 dREQ (REQ_ENV_DBREMOVE, 2);
1783 root 1.39 req->env = env;
1784     req->buf1 = strdup_ornull (file);
1785     req->buf2 = strdup_ornull (database);
1786     req->uint1 = flags;
1787     REQ_SEND;
1788     }
1789    
1790     void
1791 root 1.41 db_env_dbrename (DB_ENV *env, DB_TXN_ornull *txnid, bdb_filename file, bdb_filename database, bdb_filename newname, U32 flags = 0, SV *callback = 0)
1792     PREINIT:
1793     CALLBACK
1794 root 1.39 CODE:
1795     {
1796 root 1.50 dREQ (REQ_ENV_DBRENAME, 2);
1797 root 1.39 req->env = env;
1798     req->buf1 = strdup_ornull (file);
1799     req->buf2 = strdup_ornull (database);
1800     req->buf3 = strdup_ornull (newname);
1801     req->uint1 = flags;
1802     REQ_SEND;
1803     }
1804 root 1.8
1805 root 1.63 void
1806     db_env_log_archive (DB_ENV *env, SV_mutable *listp, U32 flags = 0, SV *callback = 0)
1807     PREINIT:
1808     CALLBACK
1809     CODE:
1810     {
1811     dREQ (REQ_ENV_LOG_ARCHIVE, 1);
1812     req->sv1 = SvREFCNT_inc (listp);
1813     req->env = env;
1814     req->uint1 = flags;
1815     REQ_SEND;
1816     }
1817    
1818 root 1.2 DB *
1819 root 1.3 db_create (DB_ENV *env = 0, U32 flags = 0)
1820 root 1.2 CODE:
1821     {
1822 root 1.3 errno = db_create (&RETVAL, env, flags);
1823     if (errno)
1824 root 1.6 croak ("db_create: %s", db_strerror (errno));
1825 root 1.5
1826     if (RETVAL)
1827     RETVAL->app_private = (void *)newSVsv (ST (0));
1828 root 1.2 }
1829 root 1.3 OUTPUT:
1830     RETVAL
1831 root 1.2
1832     void
1833 root 1.41 db_open (DB *db, DB_TXN_ornull *txnid, bdb_filename file, bdb_filename database, int type, U32 flags, int mode, SV *callback = 0)
1834     PREINIT:
1835     CALLBACK
1836 root 1.2 CODE:
1837     {
1838 root 1.50 dREQ (REQ_DB_OPEN, 2);
1839 root 1.2 req->db = db;
1840     req->txn = txnid;
1841 root 1.3 req->buf1 = strdup_ornull (file);
1842     req->buf2 = strdup_ornull (database);
1843 root 1.2 req->int1 = type;
1844 root 1.3 req->uint1 = flags | DB_THREAD;
1845 root 1.2 req->int2 = mode;
1846     REQ_SEND;
1847     }
1848    
1849     void
1850 root 1.41 db_close (DB *db, U32 flags = 0, SV *callback = 0)
1851     PREINIT:
1852     CALLBACK
1853 root 1.2 CODE:
1854     {
1855 root 1.56 dREQ (REQ_DB_CLOSE, 0);
1856 root 1.54 ptr_nuke (ST (0));
1857 root 1.2 req->db = db;
1858     req->uint1 = flags;
1859 root 1.5 req->sv1 = (SV *)db->app_private;
1860 root 1.2 REQ_SEND;
1861     }
1862    
1863 root 1.47 #if DB_VERSION_MINOR >= 4
1864    
1865 root 1.3 void
1866 root 1.41 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 = 0)
1867     PREINIT:
1868     CALLBACK
1869 root 1.3 CODE:
1870     {
1871 root 1.50 dREQ (REQ_DB_COMPACT, 2);
1872 root 1.3 req->db = db;
1873     req->txn = txn;
1874 root 1.62 if (start) sv_to_dbt (&req->dbt1, start);
1875     if (stop ) sv_to_dbt (&req->dbt2, stop );
1876 root 1.3 req->uint1 = flags;
1877     REQ_SEND;
1878     }
1879    
1880 root 1.47 #endif
1881    
1882 root 1.3 void
1883 root 1.41 db_sync (DB *db, U32 flags = 0, SV *callback = 0)
1884     PREINIT:
1885     CALLBACK
1886 root 1.3 CODE:
1887     {
1888 root 1.50 dREQ (REQ_DB_SYNC, 1);
1889 root 1.3 req->db = db;
1890     req->uint1 = flags;
1891     REQ_SEND;
1892     }
1893    
1894     void
1895 root 1.41 db_upgrade (DB *db, bdb_filename file, U32 flags = 0, SV *callback = 0)
1896     PREINIT:
1897     CALLBACK
1898 root 1.26 CODE:
1899     {
1900 root 1.50 dREQ (REQ_DB_SYNC, 1);
1901 root 1.26 req->db = db;
1902     req->buf1 = strdup (file);
1903     req->uint1 = flags;
1904     REQ_SEND;
1905     }
1906    
1907     void
1908 root 1.54 db_key_range (DB *db, DB_TXN_ornull *txn, SV *key, SV_mutable *key_range, U32 flags = 0, SV *callback = 0)
1909 root 1.41 PREINIT:
1910     CALLBACK
1911 root 1.8 CODE:
1912     {
1913 root 1.50 dREQ (REQ_DB_KEY_RANGE, 2);
1914 root 1.8 req->db = db;
1915     req->txn = txn;
1916     sv_to_dbt (&req->dbt1, key);
1917     req->uint1 = flags;
1918     req->sv1 = SvREFCNT_inc (key_range); SvREADONLY_on (key_range);
1919     REQ_SEND;
1920     }
1921    
1922     void
1923 root 1.41 db_put (DB *db, DB_TXN_ornull *txn, SV *key, SV *data, U32 flags = 0, SV *callback = 0)
1924     PREINIT:
1925     CALLBACK
1926 root 1.3 CODE:
1927     {
1928 root 1.50 dREQ (REQ_DB_PUT, 2);
1929 root 1.3 req->db = db;
1930 root 1.5 req->txn = txn;
1931     sv_to_dbt (&req->dbt1, key);
1932     sv_to_dbt (&req->dbt2, data);
1933 root 1.3 req->uint1 = flags;
1934     REQ_SEND;
1935     }
1936    
1937 root 1.46 #if DB_VERSION_MINOR >= 6
1938    
1939 root 1.5 void
1940 root 1.45 db_exists (DB *db, DB_TXN_ornull *txn, SV *key, U32 flags = 0, SV *callback = 0)
1941     PREINIT:
1942     CALLBACK
1943     CODE:
1944     {
1945 root 1.50 dREQ (REQ_DB_EXISTS, 2);
1946 root 1.45 req->db = db;
1947     req->txn = txn;
1948     req->uint1 = flags;
1949     sv_to_dbt (&req->dbt1, key);
1950     REQ_SEND;
1951     }
1952    
1953 root 1.46 #endif
1954    
1955 root 1.45 void
1956 root 1.54 db_get (DB *db, DB_TXN_ornull *txn, SV *key, SV_mutable *data, U32 flags = 0, SV *callback = 0)
1957 root 1.41 PREINIT:
1958     CALLBACK
1959 root 1.5 CODE:
1960 root 1.28 {
1961 root 1.54 //TODO: key is somtimesmutable
1962 root 1.50 dREQ (REQ_DB_GET, 2);
1963 root 1.5 req->db = db;
1964     req->txn = txn;
1965 root 1.6 req->uint1 = flags;
1966 root 1.5 sv_to_dbt (&req->dbt1, key);
1967     req->dbt3.flags = DB_DBT_MALLOC;
1968 root 1.6 req->sv3 = SvREFCNT_inc (data); SvREADONLY_on (data);
1969 root 1.5 REQ_SEND;
1970     }
1971    
1972     void
1973 root 1.54 db_pget (DB *db, DB_TXN_ornull *txn, SV *key, SV_mutable *pkey, SV_mutable *data, U32 flags = 0, SV *callback = 0)
1974 root 1.41 PREINIT:
1975     CALLBACK
1976 root 1.5 CODE:
1977 root 1.28 {
1978 root 1.54 //TODO: key is somtimesmutable
1979 root 1.50 dREQ (REQ_DB_PGET, 2);
1980 root 1.5 req->db = db;
1981     req->txn = txn;
1982 root 1.6 req->uint1 = flags;
1983 root 1.54
1984 root 1.5 sv_to_dbt (&req->dbt1, key);
1985 root 1.54
1986     req->dbt2.flags = DB_DBT_MALLOC;
1987     req->sv2 = SvREFCNT_inc (pkey); SvREADONLY_on (pkey);
1988    
1989 root 1.5 req->dbt3.flags = DB_DBT_MALLOC;
1990 root 1.6 req->sv3 = SvREFCNT_inc (data); SvREADONLY_on (data);
1991     REQ_SEND;
1992     }
1993    
1994     void
1995 root 1.41 db_del (DB *db, DB_TXN_ornull *txn, SV *key, U32 flags = 0, SV *callback = 0)
1996     PREINIT:
1997     CALLBACK
1998 root 1.6 CODE:
1999     {
2000 root 1.50 dREQ (REQ_DB_DEL, 2);
2001 root 1.6 req->db = db;
2002     req->txn = txn;
2003 root 1.5 req->uint1 = flags;
2004 root 1.6 sv_to_dbt (&req->dbt1, key);
2005 root 1.5 REQ_SEND;
2006     }
2007    
2008     void
2009 root 1.41 db_txn_commit (DB_TXN *txn, U32 flags = 0, SV *callback = 0)
2010     PREINIT:
2011     CALLBACK
2012 root 1.5 CODE:
2013     {
2014 root 1.56 dREQ (REQ_TXN_COMMIT, 0);
2015 root 1.54 ptr_nuke (ST (0));
2016 root 1.5 req->txn = txn;
2017     req->uint1 = flags;
2018     REQ_SEND;
2019     }
2020    
2021     void
2022 root 1.41 db_txn_abort (DB_TXN *txn, SV *callback = 0)
2023     PREINIT:
2024     CALLBACK
2025 root 1.5 CODE:
2026     {
2027 root 1.56 dREQ (REQ_TXN_ABORT, 0);
2028 root 1.54 ptr_nuke (ST (0));
2029 root 1.5 req->txn = txn;
2030     REQ_SEND;
2031     }
2032    
2033 root 1.6 void
2034 root 1.41 db_txn_finish (DB_TXN *txn, U32 flags = 0, SV *callback = 0)
2035     PREINIT:
2036     CALLBACK
2037 root 1.17 CODE:
2038     {
2039 root 1.56 dREQ (REQ_TXN_FINISH, 0);
2040 root 1.54 ptr_nuke (ST (0));
2041 root 1.17 req->txn = txn;
2042     req->uint1 = flags;
2043     REQ_SEND;
2044     }
2045    
2046     void
2047 root 1.41 db_c_close (DBC *dbc, SV *callback = 0)
2048     PREINIT:
2049     CALLBACK
2050 root 1.6 CODE:
2051     {
2052 root 1.56 dREQ (REQ_C_CLOSE, 0);
2053 root 1.54 ptr_nuke (ST (0));
2054 root 1.6 req->dbc = dbc;
2055     REQ_SEND;
2056     }
2057    
2058     void
2059 root 1.41 db_c_count (DBC *dbc, SV *count, U32 flags = 0, SV *callback = 0)
2060     PREINIT:
2061     CALLBACK
2062 root 1.6 CODE:
2063     {
2064 root 1.50 dREQ (REQ_C_COUNT, 1);
2065 root 1.6 req->dbc = dbc;
2066     req->sv1 = SvREFCNT_inc (count);
2067     REQ_SEND;
2068     }
2069    
2070     void
2071 root 1.41 db_c_put (DBC *dbc, SV *key, SV *data, U32 flags = 0, SV *callback = 0)
2072     PREINIT:
2073     CALLBACK
2074 root 1.6 CODE:
2075     {
2076 root 1.50 dREQ (REQ_C_PUT, 1);
2077 root 1.6 req->dbc = dbc;
2078     sv_to_dbt (&req->dbt1, key);
2079     sv_to_dbt (&req->dbt2, data);
2080     req->uint1 = flags;
2081     REQ_SEND;
2082     }
2083    
2084     void
2085 root 1.54 db_c_get (DBC *dbc, SV *key, SV_mutable *data, U32 flags = 0, SV *callback = 0)
2086 root 1.41 PREINIT:
2087     CALLBACK
2088 root 1.6 CODE:
2089     {
2090 root 1.61 if ((flags & DB_OPFLAGS_MASK) != DB_SET && SvREADONLY (key))
2091 root 1.54 croak ("db_c_get was passed a read-only/constant 'key' argument but operation is not DB_SET");
2092 root 1.59 if (SvPOKp (key) && !sv_utf8_downgrade (key, 1))
2093     croak ("argument \"%s\" must be byte/octet-encoded in %s",
2094     "key",
2095     "BDB::db_c_get");
2096 root 1.54
2097 root 1.57 {
2098     dREQ (REQ_C_GET, 1);
2099     req->dbc = dbc;
2100     req->uint1 = flags;
2101 root 1.61 if ((flags & DB_OPFLAGS_MASK) == DB_SET)
2102 root 1.57 sv_to_dbt (&req->dbt1, key);
2103     else
2104     {
2105 root 1.61 if ((flags & DB_OPFLAGS_MASK) == DB_SET_RANGE)
2106 root 1.57 sv_to_dbt (&req->dbt1, key);
2107     else
2108     req->dbt1.flags = DB_DBT_MALLOC;
2109    
2110     req->sv1 = SvREFCNT_inc (key); SvREADONLY_on (key);
2111     }
2112    
2113 root 1.61 if ((flags & DB_OPFLAGS_MASK) == DB_GET_BOTH
2114     || (flags & DB_OPFLAGS_MASK) == DB_GET_BOTH_RANGE)
2115 root 1.57 sv_to_dbt (&req->dbt3, data);
2116     else
2117     req->dbt3.flags = DB_DBT_MALLOC;
2118    
2119     req->sv3 = SvREFCNT_inc (data); SvREADONLY_on (data);
2120     REQ_SEND;
2121     }
2122 root 1.6 }
2123    
2124     void
2125 root 1.54 db_c_pget (DBC *dbc, SV *key, SV_mutable *pkey, SV_mutable *data, U32 flags = 0, SV *callback = 0)
2126 root 1.41 PREINIT:
2127     CALLBACK
2128 root 1.6 CODE:
2129     {
2130 root 1.61 if ((flags & DB_OPFLAGS_MASK) != DB_SET && SvREADONLY (key))
2131 root 1.54 croak ("db_c_pget was passed a read-only/constant 'key' argument but operation is not DB_SET");
2132 root 1.59 if (SvPOKp (key) && !sv_utf8_downgrade (key, 1))
2133     croak ("argument \"%s\" must be byte/octet-encoded in %s",
2134     "key",
2135     "BDB::db_c_pget");
2136 root 1.54
2137 root 1.57 {
2138     dREQ (REQ_C_PGET, 1);
2139     req->dbc = dbc;
2140     req->uint1 = flags;
2141 root 1.61 if ((flags & DB_OPFLAGS_MASK) == DB_SET)
2142 root 1.57 sv_to_dbt (&req->dbt1, key);
2143     else
2144     {
2145 root 1.61 if ((flags & DB_OPFLAGS_MASK) == DB_SET_RANGE)
2146 root 1.57 sv_to_dbt (&req->dbt1, key);
2147     else
2148     req->dbt1.flags = DB_DBT_MALLOC;
2149    
2150     req->sv1 = SvREFCNT_inc (key); SvREADONLY_on (key);
2151     }
2152    
2153     req->dbt2.flags = DB_DBT_MALLOC;
2154     req->sv2 = SvREFCNT_inc (pkey); SvREADONLY_on (pkey);
2155    
2156 root 1.61 if ((flags & DB_OPFLAGS_MASK) == DB_GET_BOTH
2157     || (flags & DB_OPFLAGS_MASK) == DB_GET_BOTH_RANGE)
2158 root 1.57 sv_to_dbt (&req->dbt3, data);
2159     else
2160     req->dbt3.flags = DB_DBT_MALLOC;
2161    
2162     req->sv3 = SvREFCNT_inc (data); SvREADONLY_on (data);
2163     REQ_SEND;
2164     }
2165 root 1.6 }
2166    
2167     void
2168 root 1.41 db_c_del (DBC *dbc, U32 flags = 0, SV *callback = 0)
2169     PREINIT:
2170     CALLBACK
2171 root 1.6 CODE:
2172     {
2173 root 1.50 dREQ (REQ_C_DEL, 1);
2174 root 1.6 req->dbc = dbc;
2175     req->uint1 = flags;
2176     REQ_SEND;
2177     }
2178    
2179 root 1.2
2180 root 1.47 #if DB_VERSION_MINOR >= 3
2181    
2182 root 1.8 void
2183 root 1.41 db_sequence_open (DB_SEQUENCE *seq, DB_TXN_ornull *txnid, SV *key, U32 flags = 0, SV *callback = 0)
2184     PREINIT:
2185     CALLBACK
2186 root 1.8 CODE:
2187     {
2188 root 1.50 dREQ (REQ_SEQ_OPEN, 2);
2189 root 1.8 req->seq = seq;
2190     req->txn = txnid;
2191     req->uint1 = flags | DB_THREAD;
2192     sv_to_dbt (&req->dbt1, key);
2193     REQ_SEND;
2194     }
2195    
2196     void
2197 root 1.41 db_sequence_close (DB_SEQUENCE *seq, U32 flags = 0, SV *callback = 0)
2198     PREINIT:
2199     CALLBACK
2200 root 1.8 CODE:
2201     {
2202 root 1.56 dREQ (REQ_SEQ_CLOSE, 0);
2203 root 1.54 ptr_nuke (ST (0));
2204 root 1.8 req->seq = seq;
2205     req->uint1 = flags;
2206     REQ_SEND;
2207     }
2208    
2209     void
2210 root 1.54 db_sequence_get (DB_SEQUENCE *seq, DB_TXN_ornull *txnid, int delta, SV_mutable *seq_value, U32 flags = DB_TXN_NOSYNC, SV *callback = 0)
2211 root 1.41 PREINIT:
2212     CALLBACK
2213 root 1.8 CODE:
2214     {
2215 root 1.50 dREQ (REQ_SEQ_GET, 2);
2216 root 1.8 req->seq = seq;
2217     req->txn = txnid;
2218     req->int1 = delta;
2219     req->uint1 = flags;
2220     req->sv1 = SvREFCNT_inc (seq_value); SvREADONLY_on (seq_value);
2221     REQ_SEND;
2222     }
2223    
2224     void
2225 root 1.41 db_sequence_remove (DB_SEQUENCE *seq, DB_TXN_ornull *txnid = 0, U32 flags = 0, SV *callback = 0)
2226     PREINIT:
2227     CALLBACK
2228 root 1.8 CODE:
2229     {
2230 root 1.50 dREQ (REQ_SEQ_REMOVE, 2);
2231 root 1.8 req->seq = seq;
2232     req->txn = txnid;
2233     req->uint1 = flags;
2234     REQ_SEND;
2235     }
2236    
2237 root 1.47 #endif
2238    
2239 root 1.8
2240 root 1.2 MODULE = BDB PACKAGE = BDB::Env
2241    
2242 root 1.5 void
2243 root 1.30 DESTROY (DB_ENV_ornuked *env)
2244 root 1.5 CODE:
2245     if (env)
2246     env->close (env, 0);
2247    
2248 root 1.8 int set_data_dir (DB_ENV *env, const char *dir)
2249     CODE:
2250     RETVAL = env->set_data_dir (env, dir);
2251     OUTPUT:
2252     RETVAL
2253    
2254     int set_tmp_dir (DB_ENV *env, const char *dir)
2255     CODE:
2256     RETVAL = env->set_tmp_dir (env, dir);
2257     OUTPUT:
2258     RETVAL
2259    
2260     int set_lg_dir (DB_ENV *env, const char *dir)
2261     CODE:
2262     RETVAL = env->set_lg_dir (env, dir);
2263     OUTPUT:
2264     RETVAL
2265    
2266     int set_shm_key (DB_ENV *env, long shm_key)
2267     CODE:
2268     RETVAL = env->set_shm_key (env, shm_key);
2269     OUTPUT:
2270     RETVAL
2271    
2272 root 1.2 int set_cachesize (DB_ENV *env, U32 gbytes, U32 bytes, int ncache = 0)
2273 root 1.3 CODE:
2274     RETVAL = env->set_cachesize (env, gbytes, bytes, ncache);
2275     OUTPUT:
2276     RETVAL
2277 root 1.2
2278 root 1.25 int set_flags (DB_ENV *env, U32 flags, int onoff = 1)
2279 root 1.3 CODE:
2280     RETVAL = env->set_flags (env, flags, onoff);
2281     OUTPUT:
2282     RETVAL
2283    
2284 root 1.39 #if DB_VERSION_MINOR >= 7
2285    
2286     int set_intermediate_dir_mode (DB_ENV *env, const char *mode)
2287     CODE:
2288     RETVAL = env->set_intermediate_dir_mode (env, mode);
2289     OUTPUT:
2290     RETVAL
2291    
2292     int log_set_config (DB_ENV *env, U32 flags, int onoff = 1)
2293     CODE:
2294     RETVAL = env->log_set_config (env, flags, onoff);
2295     OUTPUT:
2296     RETVAL
2297    
2298     #endif
2299    
2300    
2301 root 1.16 void set_errfile (DB_ENV *env, FILE *errfile = 0)
2302 root 1.14 CODE:
2303     env->set_errfile (env, errfile);
2304    
2305 root 1.16 void set_msgfile (DB_ENV *env, FILE *msgfile = 0)
2306 root 1.14 CODE:
2307     env->set_msgfile (env, msgfile);
2308    
2309 root 1.25 int set_verbose (DB_ENV *env, U32 which = -1, int onoff = 1)
2310 root 1.14 CODE:
2311     RETVAL = env->set_verbose (env, which, onoff);
2312     OUTPUT:
2313     RETVAL
2314    
2315 root 1.3 int set_encrypt (DB_ENV *env, const char *password, U32 flags = 0)
2316     CODE:
2317     RETVAL = env->set_encrypt (env, password, flags);
2318     OUTPUT:
2319     RETVAL
2320    
2321 root 1.17 int set_timeout (DB_ENV *env, NV timeout, U32 flags = DB_SET_TXN_TIMEOUT)
2322 root 1.3 CODE:
2323     RETVAL = env->set_timeout (env, timeout * 1000000, flags);
2324     OUTPUT:
2325     RETVAL
2326 root 1.2
2327 root 1.8 int set_mp_max_openfd (DB_ENV *env, int maxopenfd);
2328     CODE:
2329     RETVAL = env->set_mp_max_openfd (env, maxopenfd);
2330     OUTPUT:
2331     RETVAL
2332    
2333     int set_mp_max_write (DB_ENV *env, int maxwrite, int maxwrite_sleep);
2334     CODE:
2335     RETVAL = env->set_mp_max_write (env, maxwrite, maxwrite_sleep);
2336     OUTPUT:
2337     RETVAL
2338    
2339     int set_mp_mmapsize (DB_ENV *env, int mmapsize_mb)
2340     CODE:
2341     RETVAL = env->set_mp_mmapsize (env, ((size_t)mmapsize_mb) << 20);
2342     OUTPUT:
2343     RETVAL
2344    
2345 root 1.9 int set_lk_detect (DB_ENV *env, U32 detect = DB_LOCK_DEFAULT)
2346 root 1.8 CODE:
2347     RETVAL = env->set_lk_detect (env, detect);
2348     OUTPUT:
2349     RETVAL
2350    
2351     int set_lk_max_lockers (DB_ENV *env, U32 max)
2352     CODE:
2353     RETVAL = env->set_lk_max_lockers (env, max);
2354     OUTPUT:
2355     RETVAL
2356    
2357     int set_lk_max_locks (DB_ENV *env, U32 max)
2358     CODE:
2359     RETVAL = env->set_lk_max_locks (env, max);
2360     OUTPUT:
2361     RETVAL
2362    
2363     int set_lk_max_objects (DB_ENV *env, U32 max)
2364     CODE:
2365     RETVAL = env->set_lk_max_objects (env, max);
2366     OUTPUT:
2367     RETVAL
2368    
2369     int set_lg_bsize (DB_ENV *env, U32 max)
2370     CODE:
2371     RETVAL = env->set_lg_bsize (env, max);
2372     OUTPUT:
2373     RETVAL
2374    
2375     int set_lg_max (DB_ENV *env, U32 max)
2376     CODE:
2377     RETVAL = env->set_lg_max (env, max);
2378     OUTPUT:
2379     RETVAL
2380    
2381 root 1.47 #if DB_VERSION_MINOR >= 4
2382    
2383 root 1.22 int mutex_set_max (DB_ENV *env, U32 max)
2384     CODE:
2385     RETVAL = env->mutex_set_max (env, max);
2386     OUTPUT:
2387     RETVAL
2388    
2389     int mutex_set_increment (DB_ENV *env, U32 increment)
2390     CODE:
2391     RETVAL = env->mutex_set_increment (env, increment);
2392     OUTPUT:
2393     RETVAL
2394    
2395     int mutex_set_tas_spins (DB_ENV *env, U32 tas_spins)
2396     CODE:
2397     RETVAL = env->mutex_set_tas_spins (env, tas_spins);
2398     OUTPUT:
2399     RETVAL
2400    
2401     int mutex_set_align (DB_ENV *env, U32 align)
2402     CODE:
2403     RETVAL = env->mutex_set_align (env, align);
2404     OUTPUT:
2405     RETVAL
2406    
2407 root 1.47 #endif
2408    
2409 root 1.5 DB_TXN *
2410     txn_begin (DB_ENV *env, DB_TXN_ornull *parent = 0, U32 flags = 0)
2411     CODE:
2412     errno = env->txn_begin (env, parent, &RETVAL, flags);
2413     if (errno)
2414 root 1.6 croak ("DB_ENV->txn_begin: %s", db_strerror (errno));
2415 root 1.5 OUTPUT:
2416     RETVAL
2417 root 1.2
2418 root 1.46 #if DB_VERSION_MINOR >= 5
2419    
2420 root 1.44 DB_TXN *
2421     cdsgroup_begin (DB_ENV *env)
2422     CODE:
2423     errno = env->cdsgroup_begin (env, &RETVAL);
2424     if (errno)
2425     croak ("DB_ENV->cdsgroup_begin: %s", db_strerror (errno));
2426     OUTPUT:
2427     RETVAL
2428    
2429 root 1.46 #endif
2430    
2431 root 1.2 MODULE = BDB PACKAGE = BDB::Db
2432    
2433 root 1.5 void
2434 root 1.30 DESTROY (DB_ornuked *db)
2435 root 1.5 CODE:
2436     if (db)
2437     {
2438     SV *env = (SV *)db->app_private;
2439     db->close (db, 0);
2440     SvREFCNT_dec (env);
2441     }
2442    
2443 root 1.2 int set_cachesize (DB *db, U32 gbytes, U32 bytes, int ncache = 0)
2444 root 1.3 CODE:
2445     RETVAL = db->set_cachesize (db, gbytes, bytes, ncache);
2446     OUTPUT:
2447     RETVAL
2448 root 1.2
2449 root 1.60 int set_pagesize (DB *db, U32 pagesize)
2450     CODE:
2451     RETVAL = db->set_pagesize (db, pagesize);
2452     OUTPUT:
2453     RETVAL
2454    
2455 root 1.16 int set_flags (DB *db, U32 flags)
2456 root 1.3 CODE:
2457     RETVAL = db->set_flags (db, flags);
2458     OUTPUT:
2459     RETVAL
2460 root 1.2
2461     int set_encrypt (DB *db, const char *password, U32 flags)
2462 root 1.3 CODE:
2463     RETVAL = db->set_encrypt (db, password, flags);
2464     OUTPUT:
2465     RETVAL
2466 root 1.2
2467     int set_lorder (DB *db, int lorder)
2468 root 1.3 CODE:
2469     RETVAL = db->set_lorder (db, lorder);
2470     OUTPUT:
2471     RETVAL
2472 root 1.2
2473     int set_bt_minkey (DB *db, U32 minkey)
2474 root 1.3 CODE:
2475     RETVAL = db->set_bt_minkey (db, minkey);
2476     OUTPUT:
2477     RETVAL
2478 root 1.2
2479 root 1.16 int set_re_delim (DB *db, int delim)
2480 root 1.3 CODE:
2481     RETVAL = db->set_re_delim (db, delim);
2482     OUTPUT:
2483     RETVAL
2484 root 1.2
2485     int set_re_pad (DB *db, int re_pad)
2486 root 1.3 CODE:
2487     RETVAL = db->set_re_pad (db, re_pad);
2488     OUTPUT:
2489     RETVAL
2490 root 1.2
2491     int set_re_source (DB *db, char *source)
2492 root 1.3 CODE:
2493     RETVAL = db->set_re_source (db, source);
2494     OUTPUT:
2495     RETVAL
2496 root 1.2
2497     int set_re_len (DB *db, U32 re_len)
2498 root 1.3 CODE:
2499     RETVAL = db->set_re_len (db, re_len);
2500     OUTPUT:
2501     RETVAL
2502 root 1.2
2503     int set_h_ffactor (DB *db, U32 h_ffactor)
2504 root 1.3 CODE:
2505     RETVAL = db->set_h_ffactor (db, h_ffactor);
2506     OUTPUT:
2507     RETVAL
2508 root 1.2
2509     int set_h_nelem (DB *db, U32 h_nelem)
2510 root 1.3 CODE:
2511     RETVAL = db->set_h_nelem (db, h_nelem);
2512     OUTPUT:
2513     RETVAL
2514 root 1.2
2515     int set_q_extentsize (DB *db, U32 extentsize)
2516 root 1.3 CODE:
2517     RETVAL = db->set_q_extentsize (db, extentsize);
2518     OUTPUT:
2519     RETVAL
2520 root 1.2
2521 root 1.6 DBC *
2522     cursor (DB *db, DB_TXN_ornull *txn = 0, U32 flags = 0)
2523     CODE:
2524     errno = db->cursor (db, txn, &RETVAL, flags);
2525     if (errno)
2526     croak ("DB->cursor: %s", db_strerror (errno));
2527     OUTPUT:
2528     RETVAL
2529    
2530 root 1.47 #if DB_VERSION_MINOR >= 3
2531    
2532 root 1.8 DB_SEQUENCE *
2533     sequence (DB *db, U32 flags = 0)
2534     CODE:
2535     {
2536     errno = db_sequence_create (&RETVAL, db, flags);
2537     if (errno)
2538     croak ("db_sequence_create: %s", db_strerror (errno));
2539     }
2540     OUTPUT:
2541     RETVAL
2542    
2543 root 1.47 #endif
2544    
2545 root 1.6
2546 root 1.5 MODULE = BDB PACKAGE = BDB::Txn
2547    
2548     void
2549 root 1.30 DESTROY (DB_TXN_ornuked *txn)
2550 root 1.5 CODE:
2551     if (txn)
2552     txn->abort (txn);
2553    
2554 root 1.17 int set_timeout (DB_TXN *txn, NV timeout, U32 flags = DB_SET_TXN_TIMEOUT)
2555 root 1.5 CODE:
2556     RETVAL = txn->set_timeout (txn, timeout * 1000000, flags);
2557     OUTPUT:
2558     RETVAL
2559    
2560 root 1.17 int failed (DB_TXN *txn)
2561     CODE:
2562     RETVAL = !!(txn->flags & TXN_DEADLOCK);
2563     OUTPUT:
2564     RETVAL
2565    
2566 root 1.1
2567 root 1.6 MODULE = BDB PACKAGE = BDB::Cursor
2568    
2569     void
2570 root 1.30 DESTROY (DBC_ornuked *dbc)
2571 root 1.6 CODE:
2572     if (dbc)
2573     dbc->c_close (dbc);
2574    
2575 root 1.27 #if DB_VERSION_MINOR >= 6
2576    
2577     int set_priority (DBC *dbc, int priority)
2578     CODE:
2579     dbc->set_priority (dbc, priority);
2580    
2581     #endif
2582    
2583 root 1.47 #if DB_VERSION_MINOR >= 3
2584    
2585 root 1.8 MODULE = BDB PACKAGE = BDB::Sequence
2586    
2587     void
2588 root 1.30 DESTROY (DB_SEQUENCE_ornuked *seq)
2589 root 1.8 CODE:
2590     if (seq)
2591     seq->close (seq, 0);
2592    
2593     int initial_value (DB_SEQUENCE *seq, db_seq_t value)
2594     CODE:
2595     RETVAL = seq->initial_value (seq, value);
2596     OUTPUT:
2597     RETVAL
2598    
2599     int set_cachesize (DB_SEQUENCE *seq, U32 size)
2600     CODE:
2601     RETVAL = seq->set_cachesize (seq, size);
2602     OUTPUT:
2603     RETVAL
2604    
2605     int set_flags (DB_SEQUENCE *seq, U32 flags)
2606     CODE:
2607     RETVAL = seq->set_flags (seq, flags);
2608     OUTPUT:
2609     RETVAL
2610    
2611     int set_range (DB_SEQUENCE *seq, db_seq_t min, db_seq_t max)
2612     CODE:
2613     RETVAL = seq->set_range (seq, min, max);
2614     OUTPUT:
2615     RETVAL
2616    
2617 root 1.47 #endif
2618    
2619 root 1.31