… | |
… | |
18 | |
18 | |
19 | #include <stddef.h> |
19 | #include <stddef.h> |
20 | #include <stdlib.h> |
20 | #include <stdlib.h> |
21 | #include <errno.h> |
21 | #include <errno.h> |
22 | #include <sys/time.h> |
22 | #include <sys/time.h> |
23 | #include <sys/select.h> |
|
|
24 | #include <sys/types.h> |
23 | #include <sys/types.h> |
25 | #include <sys/stat.h> |
|
|
26 | #include <limits.h> |
24 | #include <limits.h> |
27 | #include <unistd.h> |
25 | #include <unistd.h> |
28 | #include <fcntl.h> |
26 | #include <fcntl.h> |
29 | #include <signal.h> |
27 | |
30 | #include <sched.h> |
28 | #include <db.h> |
31 | |
29 | |
32 | /* number of seconds after which idle threads exit */ |
30 | /* number of seconds after which idle threads exit */ |
33 | #define IDLE_TIMEOUT 10 |
31 | #define IDLE_TIMEOUT 10 |
34 | |
32 | |
35 | /* wether word reads are potentially non-atomic. |
33 | /* wether word reads are potentially non-atomic. |
… | |
… | |
44 | # endif |
42 | # endif |
45 | #endif |
43 | #endif |
46 | |
44 | |
47 | typedef SV SV8; /* byte-sv, used for argument-checking */ |
45 | typedef SV SV8; /* byte-sv, used for argument-checking */ |
48 | |
46 | |
49 | enum { |
47 | enum |
|
|
48 | { |
50 | REQ_QUIT, |
49 | REQ_QUIT, |
|
|
50 | REQ_ENV_OPEN, REQ_ENV_CLOSE, |
|
|
51 | REQ_DB_OPEN, REQ_DB_CLOSE, |
51 | }; |
52 | }; |
52 | |
53 | |
53 | #define AIO_CB \ |
|
|
54 | struct aio_cb *volatile next; \ |
|
|
55 | SV *callback; \ |
|
|
56 | int type, pri |
|
|
57 | |
|
|
58 | typedef struct aio_cb |
54 | typedef struct aio_cb |
59 | { |
55 | { |
60 | AIO_CB; |
56 | struct aio_cb *volatile next; |
|
|
57 | SV *callback; |
|
|
58 | int type, pri, errorno; |
|
|
59 | |
|
|
60 | DB_ENV *env; |
|
|
61 | DB *db; |
|
|
62 | DB_TXN *txn; |
|
|
63 | DBC *cursor; |
|
|
64 | int int1, int2; |
|
|
65 | U32 uint1, uint2; |
|
|
66 | char *buf1, *buf2; |
61 | } aio_cb; |
67 | } aio_cb; |
62 | |
68 | |
63 | typedef aio_cb *aio_req; |
69 | typedef aio_cb *aio_req; |
64 | |
70 | |
65 | enum { |
71 | enum { |
… | |
… | |
230 | |
236 | |
231 | abort (); |
237 | abort (); |
232 | } |
238 | } |
233 | |
239 | |
234 | static int poll_cb (); |
240 | static int poll_cb (); |
235 | static int req_invoke (aio_req req); |
|
|
236 | static void req_free (aio_req req); |
241 | static void req_free (aio_req req); |
237 | static void req_cancel (aio_req req); |
242 | static void req_cancel (aio_req req); |
238 | |
243 | |
239 | static int req_invoke (aio_req req) |
244 | static int req_invoke (aio_req req) |
240 | { |
245 | { |
… | |
… | |
262 | return !SvTRUE (ERRSV); |
267 | return !SvTRUE (ERRSV); |
263 | } |
268 | } |
264 | |
269 | |
265 | static void req_free (aio_req req) |
270 | static void req_free (aio_req req) |
266 | { |
271 | { |
|
|
272 | free (req->buf1); |
|
|
273 | free (req->buf2); |
267 | Safefree (req); |
274 | Safefree (req); |
268 | } |
275 | } |
269 | |
276 | |
270 | static void *aio_proc(void *arg); |
277 | static void *aio_proc(void *arg); |
271 | |
278 | |
… | |
… | |
616 | create_pipe (); |
623 | create_pipe (); |
617 | |
624 | |
618 | atfork_parent (); |
625 | atfork_parent (); |
619 | } |
626 | } |
620 | |
627 | |
621 | #define dREQ \ |
628 | #define dREQ(reqtype) \ |
622 | aio_req req; \ |
629 | aio_req req; \ |
623 | int req_pri = next_pri; \ |
630 | int req_pri = next_pri; \ |
624 | next_pri = DEFAULT_PRI + PRI_BIAS; \ |
631 | next_pri = DEFAULT_PRI + PRI_BIAS; \ |
625 | \ |
632 | \ |
626 | if (SvOK (callback) && !SvROK (callback)) \ |
633 | if (SvOK (callback) && !SvROK (callback)) \ |
627 | croak ("callback must be undef or of reference type"); \ |
634 | croak ("callback must be undef or of reference type"); \ |
628 | \ |
635 | \ |
629 | Newz (0, req, 1, aio_cb); \ |
636 | Newz (0, req, 1, aio_cb); \ |
630 | if (!req) \ |
637 | if (!req) \ |
631 | croak ("out of memory during aio_req allocation"); \ |
638 | croak ("out of memory during aio_req allocation"); \ |
632 | \ |
639 | \ |
633 | req->callback = newSVsv (callback); \ |
640 | req->callback = newSVsv (callback); \ |
|
|
641 | req->type = (reqtype); \ |
634 | req->pri = req_pri |
642 | req->pri = req_pri |
635 | |
643 | |
636 | #define REQ_SEND \ |
644 | #define REQ_SEND \ |
637 | req_send (req); \ |
645 | req_send (req) |
638 | \ |
646 | |
639 | if (GIMME_V != G_VOID) \ |
647 | #define SvPTR(var, arg, type, class) \ |
640 | XPUSHs (req_sv (req, AIO_REQ_KLASS)); |
648 | if (!SvOK (arg)) \ |
|
|
649 | (var) = 0; \ |
|
|
650 | else if (sv_derived_from ((arg), # class)) \ |
|
|
651 | { \ |
|
|
652 | IV tmp = SvIV ((SV*) SvRV (arg)); \ |
|
|
653 | (var) = INT2PTR (type, tmp); \ |
|
|
654 | } \ |
|
|
655 | else \ |
|
|
656 | Perl_croak (# var " is not of type " # type) |
641 | |
657 | |
642 | MODULE = BDB::AIO PACKAGE = BDB::AIO |
658 | MODULE = BDB PACKAGE = BDB |
643 | |
659 | |
644 | PROTOTYPES: ENABLE |
660 | PROTOTYPES: ENABLE |
645 | |
661 | |
646 | BOOT: |
662 | BOOT: |
647 | { |
663 | { |
648 | HV *stash = gv_stashpv ("BDB::AIO", 1); |
664 | HV *stash = gv_stashpv ("BDB", 1); |
|
|
665 | |
|
|
666 | static const struct { |
|
|
667 | const char *name; |
|
|
668 | IV iv; |
|
|
669 | } *civ, const_iv[] = { |
|
|
670 | #define const_iv(name) { # name, (IV)DB_ ## name }, |
|
|
671 | const_iv (RPCCLIENT) |
|
|
672 | const_iv (INIT_CDB) |
|
|
673 | const_iv (INIT_LOCK) |
|
|
674 | const_iv (INIT_LOG) |
|
|
675 | const_iv (INIT_MPOOL) |
|
|
676 | const_iv (INIT_REP) |
|
|
677 | const_iv (INIT_TXN) |
|
|
678 | const_iv (RECOVER) |
|
|
679 | const_iv (INIT_TXN) |
|
|
680 | const_iv (RECOVER_FATAL) |
|
|
681 | const_iv (CREATE) |
|
|
682 | const_iv (USE_ENVIRON) |
|
|
683 | const_iv (USE_ENVIRON_ROOT) |
|
|
684 | const_iv (LOCKDOWN) |
|
|
685 | const_iv (PRIVATE) |
|
|
686 | const_iv (REGISTER) |
|
|
687 | const_iv (SYSTEM_MEM) |
|
|
688 | const_iv (AUTO_COMMIT) |
|
|
689 | const_iv (CDB_ALLDB) |
|
|
690 | const_iv (DIRECT_DB) |
|
|
691 | const_iv (DIRECT_LOG) |
|
|
692 | const_iv (DSYNC_DB) |
|
|
693 | const_iv (DSYNC_LOG) |
|
|
694 | const_iv (LOG_AUTOREMOVE) |
|
|
695 | const_iv (LOG_INMEMORY) |
|
|
696 | const_iv (NOLOCKING) |
|
|
697 | const_iv (MULTIVERSION) |
|
|
698 | const_iv (NOMMAP) |
|
|
699 | const_iv (NOPANIC) |
|
|
700 | const_iv (OVERWRITE) |
|
|
701 | const_iv (PANIC_ENVIRONMENT) |
|
|
702 | const_iv (REGION_INIT) |
|
|
703 | const_iv (TIME_NOTGRANTED) |
|
|
704 | const_iv (TXN_NOSYNC) |
|
|
705 | const_iv (TXN_SNAPSHOT) |
|
|
706 | const_iv (TXN_WRITE_NOSYNC) |
|
|
707 | const_iv (YIELDCPU) |
|
|
708 | const_iv (ENCRYPT_AES) |
|
|
709 | const_iv (XA_CREATE) |
|
|
710 | const_iv (BTREE) |
|
|
711 | const_iv (HASH) |
|
|
712 | const_iv (QUEUE) |
|
|
713 | const_iv (RECNO) |
|
|
714 | const_iv (UNKNOWN) |
|
|
715 | const_iv (EXCL) |
|
|
716 | const_iv (READ_UNCOMMITTED) |
|
|
717 | const_iv (TRUNCATE) |
|
|
718 | const_iv (NOSYNC) |
|
|
719 | const_iv (CHKSUM) |
|
|
720 | const_iv (ENCRYPT) |
|
|
721 | const_iv (TXN_NOT_DURABLE) |
|
|
722 | const_iv (DUP) |
|
|
723 | const_iv (DUPSORT) |
|
|
724 | const_iv (RECNUM) |
|
|
725 | const_iv (RENUMBER) |
|
|
726 | const_iv (REVSPLITOFF) |
|
|
727 | const_iv (INORDER) |
|
|
728 | const_iv (CONSUME) |
|
|
729 | const_iv (CONSUME_WAIT) |
|
|
730 | const_iv (SNAPSHOT) |
|
|
731 | const_iv (JOIN_ITEM) |
|
|
732 | const_iv (RMW) |
|
|
733 | |
|
|
734 | const_iv (NOTFOUND) |
|
|
735 | const_iv (KEYEMPTY) |
|
|
736 | const_iv (LOCK_DEADLOCK) |
|
|
737 | const_iv (LOCK_NOTGRANTED) |
|
|
738 | const_iv (RUNRECOVERY) |
|
|
739 | }; |
|
|
740 | |
|
|
741 | for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; ) |
|
|
742 | newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv)); |
649 | |
743 | |
650 | create_pipe (); |
744 | create_pipe (); |
651 | pthread_atfork (atfork_prepare, atfork_parent, atfork_child); |
745 | pthread_atfork (atfork_prepare, atfork_parent, atfork_child); |
652 | } |
746 | } |
653 | |
747 | |
… | |
… | |
781 | RETVAL = started; |
875 | RETVAL = started; |
782 | if (WORDACCESS_UNSAFE) UNLOCK (wrklock); |
876 | if (WORDACCESS_UNSAFE) UNLOCK (wrklock); |
783 | OUTPUT: |
877 | OUTPUT: |
784 | RETVAL |
878 | RETVAL |
785 | |
879 | |
|
|
880 | DB_ENV * |
|
|
881 | bdb_env_create (U32 env_flags = 0) |
|
|
882 | CODE: |
|
|
883 | { |
|
|
884 | int err = db_env_create (&RETVAL, env_flags); |
|
|
885 | if (err) |
|
|
886 | croak ("db_env_create: %s", db_strerror (err)); |
|
|
887 | } |
786 | |
888 | |
|
|
889 | void |
|
|
890 | bdb_env_open (DB_ENV *env, char *db_home, U32 open_flags, int mode, SV *callback = 0) |
|
|
891 | CODE: |
|
|
892 | { |
|
|
893 | dREQ (REQ_ENV_OPEN); |
|
|
894 | req->env = env; |
|
|
895 | req->uint1 = open_flags; |
|
|
896 | req->int1 = mode; |
|
|
897 | req->buf1 = strdup (db_home); |
|
|
898 | REQ_SEND; |
|
|
899 | } |
|
|
900 | |
|
|
901 | void |
|
|
902 | bdb_env_close (DB_ENV *env, U32 flags = 0, SV *callback = 0) |
|
|
903 | CODE: |
|
|
904 | { |
|
|
905 | dREQ (REQ_ENV_CLOSE); |
|
|
906 | req->env = env; |
|
|
907 | req->uint1 = flags; |
|
|
908 | REQ_SEND; |
|
|
909 | } |
|
|
910 | |
|
|
911 | DB * |
|
|
912 | bdb_db_create (DB_ENV *env = 0, U32 flags = 0) |
|
|
913 | CODE: |
|
|
914 | { |
|
|
915 | int err = db_create (&RETVAL, env, flags); |
|
|
916 | if (err) |
|
|
917 | croak ("db_env_create: %s", db_strerror (err)); |
|
|
918 | } |
|
|
919 | |
|
|
920 | void |
|
|
921 | bdb_db_open (DB *db, DB_TXN *txnid, const char *file, const char *database, int type, U32 flags, int mode, SV *callback = 0) |
|
|
922 | CODE: |
|
|
923 | { |
|
|
924 | dREQ (REQ_DB_OPEN); |
|
|
925 | req->db = db; |
|
|
926 | req->txn = txnid; |
|
|
927 | req->buf1 = strdup (file); |
|
|
928 | req->buf2 = strdup (database); |
|
|
929 | req->int1 = type; |
|
|
930 | req->uint1 = flags; |
|
|
931 | req->int2 = mode; |
|
|
932 | REQ_SEND; |
|
|
933 | } |
|
|
934 | |
|
|
935 | void |
|
|
936 | bdb_db_close (DB *db, U32 flags = 0, SV *callback = 0) |
|
|
937 | CODE: |
|
|
938 | { |
|
|
939 | dREQ (REQ_DB_CLOSE); |
|
|
940 | req->db = db; |
|
|
941 | req->uint1 = flags; |
|
|
942 | REQ_SEND; |
|
|
943 | } |
|
|
944 | |
|
|
945 | |
|
|
946 | MODULE = BDB PACKAGE = BDB::Env |
|
|
947 | |
|
|
948 | int set_cachesize (DB_ENV *env, U32 gbytes, U32 bytes, int ncache = 0) |
|
|
949 | |
|
|
950 | int set_flags (DB_ENV *env, U32 flags, int onoff) |
|
|
951 | |
|
|
952 | int set_encrypt (DB_ENV *env, const char *password, U32 flags) |
|
|
953 | |
|
|
954 | MODULE = BDB PACKAGE = BDB::Db |
|
|
955 | |
|
|
956 | int set_cachesize (DB *db, U32 gbytes, U32 bytes, int ncache = 0) |
|
|
957 | |
|
|
958 | int set_flags (DB *env, U32 flags, int onoff) |
|
|
959 | |
|
|
960 | int set_encrypt (DB *db, const char *password, U32 flags) |
|
|
961 | |
|
|
962 | int set_lorder (DB *db, int lorder) |
|
|
963 | |
|
|
964 | |
|
|
965 | int set_bt_minkey (DB *db, U32 minkey) |
|
|
966 | |
|
|
967 | int set_re_delim(DB *db, int delim); |
|
|
968 | |
|
|
969 | int set_re_pad (DB *db, int re_pad) |
|
|
970 | |
|
|
971 | int set_re_source (DB *db, char *source) |
|
|
972 | |
|
|
973 | int set_re_len (DB *db, U32 re_len) |
|
|
974 | |
|
|
975 | int set_h_ffactor (DB *db, U32 h_ffactor) |
|
|
976 | |
|
|
977 | int set_h_nelem (DB *db, U32 h_nelem) |
|
|
978 | |
|
|
979 | int set_q_extentsize (DB *db, U32 extentsize) |
|
|
980 | |
|
|
981 | |