diff options
53 files changed, 2987 insertions, 2686 deletions
@@ -10,6 +10,7 @@ Alejandra Morales | |||
10 | Andreas Fuchs | 10 | Andreas Fuchs |
11 | Bart Polot <bart@net.in.tum.de> | 11 | Bart Polot <bart@net.in.tum.de> |
12 | Bruno Cabral <bcabral@uw.edu> | 12 | Bruno Cabral <bcabral@uw.edu> |
13 | Carlo von lynX <psyc://loupsycedyglgamf.onion/~lynX> | ||
13 | Christian Fuchs <christian.fuchs@cfuchs.net> | 14 | Christian Fuchs <christian.fuchs@cfuchs.net> |
14 | Christian Grothoff <christian@grothoff.org> | 15 | Christian Grothoff <christian@grothoff.org> |
15 | Claudiu Olteanu | 16 | Claudiu Olteanu |
diff --git a/configure.ac b/configure.ac index 76f627597..8a2ab9262 100644 --- a/configure.ac +++ b/configure.ac | |||
@@ -71,7 +71,7 @@ case "$host_os" in | |||
71 | AC_DEFINE_UNQUOTED(DARWIN,1,[This is an Apple Darwin system]) | 71 | AC_DEFINE_UNQUOTED(DARWIN,1,[This is an Apple Darwin system]) |
72 | CPPFLAGS="-D_APPLE_C_SOURCE $CPPFLAGS" | 72 | CPPFLAGS="-D_APPLE_C_SOURCE $CPPFLAGS" |
73 | CFLAGS="-fno-common $CFLAGS" | 73 | CFLAGS="-fno-common $CFLAGS" |
74 | AC_MSG_WARN([The VPN application cannot be compiled on your OS]) | 74 | AC_MSG_WARN([WARNING: The VPN application cannot be compiled on your OS]) |
75 | build_target="darwin" | 75 | build_target="darwin" |
76 | DEFAULT_INTERFACE="\"en0\"" | 76 | DEFAULT_INTERFACE="\"en0\"" |
77 | LIBPREFIX= | 77 | LIBPREFIX= |
@@ -522,7 +522,7 @@ then | |||
522 | AM_CONDITIONAL(HAVE_LIBCURL, false) | 522 | AM_CONDITIONAL(HAVE_LIBCURL, false) |
523 | if test "$gnurl" = 0 | 523 | if test "$gnurl" = 0 |
524 | then | 524 | then |
525 | AC_MSG_WARN([GNUnet requires libcurl-gnutls or gnurl >= 7.34]) | 525 | AC_MSG_WARN([ERROR: GNUnet requires libcurl-gnutls or gnurl >= 7.34]) |
526 | fi | 526 | fi |
527 | else | 527 | else |
528 | AM_CONDITIONAL(HAVE_LIBCURL, true) | 528 | AM_CONDITIONAL(HAVE_LIBCURL, true) |
@@ -542,19 +542,18 @@ AC_CHECK_MEMBERS(glp_iocp.presolve,,[gplk=false],[[#include <glpk.h>]]) | |||
542 | if test x$gplk = xfalse | 542 | if test x$gplk = xfalse |
543 | then | 543 | then |
544 | AM_CONDITIONAL(HAVE_LIBGLPK, false) | 544 | AM_CONDITIONAL(HAVE_LIBGLPK, false) |
545 | AC_MSG_WARN([GNUnet requires GLPK >= 4.32]) | 545 | AC_MSG_WARN([ERROR: GNUnet requires GLPK >= 4.32]) |
546 | else | 546 | else |
547 | AM_CONDITIONAL(HAVE_LIBGLPK, true) | 547 | AM_CONDITIONAL(HAVE_LIBGLPK, true) |
548 | AC_DEFINE([HAVE_LIBGLPK],[1],[Have GLPK]) | 548 | AC_DEFINE([HAVE_LIBGLPK],[1],[Have GLPK]) |
549 | fi | 549 | fi |
550 | 550 | ||
551 | 551 | ||
552 | |||
553 | AC_CHECK_HEADERS([nss.h],[nss=true],[nss=false]) | 552 | AC_CHECK_HEADERS([nss.h],[nss=true],[nss=false]) |
554 | if test x$nss = xfalse | 553 | if test x$nss = xfalse |
555 | then | 554 | then |
556 | AM_CONDITIONAL(HAVE_GLIBCNSS, false) | 555 | AM_CONDITIONAL(HAVE_GLIBCNSS, false) |
557 | AC_MSG_WARN([No GNU libc nss header, will not build NSS plugin]) | 556 | AC_MSG_WARN([ERROR: No GNU libc nss header, will not build NSS plugin]) |
558 | else | 557 | else |
559 | AM_CONDITIONAL(HAVE_GLIBCNSS, true) | 558 | AM_CONDITIONAL(HAVE_GLIBCNSS, true) |
560 | fi | 559 | fi |
@@ -1138,16 +1137,20 @@ AC_ARG_WITH(nssdir, | |||
1138 | esac | 1137 | esac |
1139 | ], | 1138 | ], |
1140 | [ | 1139 | [ |
1141 | if test "x$SUDO_BINARY" != "x" -o -w / | 1140 | # This test is inappropriate when installation with DESTDIR is |
1142 | then | 1141 | # run much later and uid will be root when needed. Enabling this |
1142 | # code breaks the gnunet.ebuild for gentoo. | ||
1143 | # | ||
1144 | # if test "x$SUDO_BINARY" != "x" -o -w / | ||
1145 | # then | ||
1143 | NSS_DIR="/lib" | 1146 | NSS_DIR="/lib" |
1144 | install_nss=1 | 1147 | install_nss=1 |
1145 | AC_MSG_RESULT([yes, to /lib]) | 1148 | AC_MSG_RESULT([yes, to /lib]) |
1146 | else | 1149 | # else |
1147 | NSS_DIR= | 1150 | # NSS_DIR= |
1148 | install_nss=0 | 1151 | # install_nss=0 |
1149 | AC_MSG_RESULT([no]) | 1152 | # AC_MSG_RESULT([no]) |
1150 | fi | 1153 | # fi |
1151 | ]) | 1154 | ]) |
1152 | AC_SUBST(NSS_DIR) | 1155 | AC_SUBST(NSS_DIR) |
1153 | AM_CONDITIONAL([INSTALL_NSS], [test "x$install_nss" != "x0"]) | 1156 | AM_CONDITIONAL([INSTALL_NSS], [test "x$install_nss" != "x0"]) |
@@ -1612,7 +1615,6 @@ src/peerinfo-tool/Makefile | |||
1612 | src/peerstore/Makefile | 1615 | src/peerstore/Makefile |
1613 | src/peerstore/peerstore.conf | 1616 | src/peerstore/peerstore.conf |
1614 | src/pq/Makefile | 1617 | src/pq/Makefile |
1615 | src/postgres/Makefile | ||
1616 | src/psycutil/Makefile | 1618 | src/psycutil/Makefile |
1617 | src/psyc/Makefile | 1619 | src/psyc/Makefile |
1618 | src/psyc/psyc.conf | 1620 | src/psyc/psyc.conf |
@@ -1683,7 +1685,6 @@ pkgconfig/gnunetnat.pc | |||
1683 | pkgconfig/gnunetnse.pc | 1685 | pkgconfig/gnunetnse.pc |
1684 | pkgconfig/gnunetpeerinfo.pc | 1686 | pkgconfig/gnunetpeerinfo.pc |
1685 | pkgconfig/gnunetpq.pc | 1687 | pkgconfig/gnunetpq.pc |
1686 | pkgconfig/gnunetpostgres.pc | ||
1687 | pkgconfig/gnunetpsyc.pc | 1688 | pkgconfig/gnunetpsyc.pc |
1688 | pkgconfig/gnunetpsycstore.pc | 1689 | pkgconfig/gnunetpsycstore.pc |
1689 | pkgconfig/gnunetregex.pc | 1690 | pkgconfig/gnunetregex.pc |
@@ -1708,7 +1709,7 @@ AC_OUTPUT | |||
1708 | # warn user if mysql found but not used due to version | 1709 | # warn user if mysql found but not used due to version |
1709 | if test "$mysqlfail" = "true" | 1710 | if test "$mysqlfail" = "true" |
1710 | then | 1711 | then |
1711 | AC_MSG_NOTICE([NOTICE: MySQL found, but too old. MySQL support will not be compiled.]) | 1712 | AC_MSG_NOTICE([WARNING: MySQL found, but too old. MySQL support will not be compiled.]) |
1712 | fi | 1713 | fi |
1713 | 1714 | ||
1714 | # sqlite | 1715 | # sqlite |
@@ -1722,7 +1723,7 @@ if test "$gnurl" = "0" | |||
1722 | then | 1723 | then |
1723 | if test "x$curl" = "xfalse" | 1724 | if test "x$curl" = "xfalse" |
1724 | then | 1725 | then |
1725 | AC_MSG_NOTICE([NOTICE: libgnurl not found. http client support will not be compiled.]) | 1726 | AC_MSG_NOTICE([WARNING: libgnurl not found. http client support will not be compiled.]) |
1726 | AC_MSG_WARN([ERROR: libgnurl not found. hostlist daemon will not be compiled, and you probably WANT the hostlist daemon]) | 1727 | AC_MSG_WARN([ERROR: libgnurl not found. hostlist daemon will not be compiled, and you probably WANT the hostlist daemon]) |
1727 | else | 1728 | else |
1728 | AC_MSG_NOTICE([WARNING: libgnurl not found, trying to use libcurl-gnutls instead.]) | 1729 | AC_MSG_NOTICE([WARNING: libgnurl not found, trying to use libcurl-gnutls instead.]) |
@@ -1733,36 +1734,36 @@ fi | |||
1733 | # bluetooth | 1734 | # bluetooth |
1734 | if test "x$bluetooth" = "x0" | 1735 | if test "x$bluetooth" = "x0" |
1735 | then | 1736 | then |
1736 | AC_MSG_NOTICE([NOTICE: bluetooth library not found. bluetooth support will not be compiled.]) | 1737 | AC_MSG_NOTICE([WARNING: bluetooth library not found. bluetooth support will not be compiled.]) |
1737 | fi | 1738 | fi |
1738 | 1739 | ||
1739 | # jansson | 1740 | # jansson |
1740 | if test "x$jansson" = "x0" | 1741 | if test "x$jansson" = "x0" |
1741 | then | 1742 | then |
1742 | AC_MSG_NOTICE([NOTICE: jansson library not found. json support will not be compiled.]) | 1743 | AC_MSG_NOTICE([WARNING: jansson library not found. json support will not be compiled.]) |
1743 | fi | 1744 | fi |
1744 | 1745 | ||
1745 | #gnutls | 1746 | #gnutls |
1746 | if test x$gnutls != xtrue | 1747 | if test x$gnutls != xtrue |
1747 | then | 1748 | then |
1748 | AC_MSG_NOTICE([NOTICE: GnuTLS not found, gnunet-gns-proxy will not be built]) | 1749 | AC_MSG_NOTICE([WARNING: GnuTLS not found, gnunet-gns-proxy will not be built]) |
1749 | else | 1750 | else |
1750 | if test "x$gnutls_dane" != "x1" | 1751 | if test "x$gnutls_dane" != "x1" |
1751 | then | 1752 | then |
1752 | AC_MSG_NOTICE([NOTICE: GnuTLS has no DANE support, DANE validation will not be possible]) | 1753 | AC_MSG_NOTICE([WARNING: GnuTLS has no DANE support, DANE validation will not be possible]) |
1753 | fi | 1754 | fi |
1754 | fi | 1755 | fi |
1755 | 1756 | ||
1756 | # java ports | 1757 | # java ports |
1757 | if test "x$enable_java_ports" = "xyes" | 1758 | if test "x$enable_java_ports" = "xyes" |
1758 | then | 1759 | then |
1759 | AC_MSG_NOTICE([NOTICE: opening ports for gnunet-java bindings by default.]) | 1760 | AC_MSG_NOTICE([NOTICE: Opening ports for gnunet-java bindings by default.]) |
1760 | fi | 1761 | fi |
1761 | 1762 | ||
1762 | # MHD | 1763 | # MHD |
1763 | if test "x$lmhd" != "x1" | 1764 | if test "x$lmhd" != "x1" |
1764 | then | 1765 | then |
1765 | AC_MSG_NOTICE([NOTICE: libmicrohttpd not found, http transport will not be installed.]) | 1766 | AC_MSG_NOTICE([WARNING: libmicrohttpd not found, http transport will not be installed.]) |
1766 | fi | 1767 | fi |
1767 | 1768 | ||
1768 | # conversation | 1769 | # conversation |
@@ -1770,35 +1771,35 @@ if test "x$conversation_backend" = "xnone" | |||
1770 | then | 1771 | then |
1771 | if test "x$pulse" != "x1" | 1772 | if test "x$pulse" != "x1" |
1772 | then | 1773 | then |
1773 | AC_MSG_NOTICE([NOTICE: libpulse(audio) not found, conversation will not be built.]) | 1774 | AC_MSG_NOTICE([WARNING: libpulse(audio) not found, conversation will not be built.]) |
1774 | fi | 1775 | fi |
1775 | if test "x$opus" != "x1" | 1776 | if test "x$opus" != "x1" |
1776 | then | 1777 | then |
1777 | AC_MSG_NOTICE([NOTICE: libopus not found, conversation will not be built.]) | 1778 | AC_MSG_NOTICE([WARNING: libopus not found, conversation will not be built.]) |
1778 | fi | 1779 | fi |
1779 | if test "x$gst" != "x1" | 1780 | if test "x$gst" != "x1" |
1780 | then | 1781 | then |
1781 | AC_MSG_NOTICE([NOTICE: GStreamer not found, conversation will not be built.]) | 1782 | AC_MSG_NOTICE([WARNING: GStreamer not found, conversation will not be built.]) |
1782 | fi | 1783 | fi |
1783 | fi | 1784 | fi |
1784 | 1785 | ||
1785 | if test "$extractor" != 1 | 1786 | if test "$extractor" != 1 |
1786 | then | 1787 | then |
1787 | AC_MSG_WARN([NOTICE: libextractor not found, but various file-sharing functions require it]) | 1788 | AC_MSG_WARN([ERROR: libextractor not found, but various file-sharing functions require it]) |
1788 | fi | 1789 | fi |
1789 | 1790 | ||
1790 | AC_MSG_NOTICE([NOTICE: Database support is set to MySQL: $mysql, SQLite: $sqlite, Postgres: $postgres]) | 1791 | AC_MSG_NOTICE([NOTICE: Database support is set to MySQL: $mysql, SQLite: $sqlite, Postgres: $postgres]) |
1791 | 1792 | ||
1792 | if test "$enable_framework_build" = "yes" | 1793 | if test "$enable_framework_build" = "yes" |
1793 | then | 1794 | then |
1794 | AC_MSG_NOTICE([NOTICE: Mac OS X framework build enabled.]) | 1795 | AC_MSG_NOTICE([Mac OS X framework build enabled.]) |
1795 | fi | 1796 | fi |
1796 | 1797 | ||
1797 | if test "x$install_nss" = "x0" | 1798 | if test "x$install_nss" = "x0" |
1798 | then | 1799 | then |
1799 | AC_MSG_NOTICE([NOTICE: --with-sudo not specified and not running as 'root', will not install GNS NSS library]) | 1800 | AC_MSG_NOTICE([WARNING: Will not install GNS NSS library]) |
1800 | else | 1801 | else |
1801 | AC_MSG_NOTICE([NOTICE: Will to install GNS NSS library to $NSS_DIR]) | 1802 | AC_MSG_NOTICE([NOTICE: Will install GNS NSS library to $NSS_DIR]) |
1802 | fi | 1803 | fi |
1803 | 1804 | ||
1804 | 1805 | ||
diff --git a/contrib/gnunet-gns-import.sh b/contrib/gnunet-gns-import.sh index 635360803..7b46379d6 100755 --- a/contrib/gnunet-gns-import.sh +++ b/contrib/gnunet-gns-import.sh | |||
@@ -48,10 +48,6 @@ gnunet-identity -C sks-zone $options | |||
48 | 48 | ||
49 | #### Integrate those with the respective subsystems #### | 49 | #### Integrate those with the respective subsystems #### |
50 | 50 | ||
51 | # Zone for shortening by gns-proxy, | ||
52 | # (remove this entry to disable shortening) | ||
53 | gnunet-identity -e short-zone -s gns-short $options | ||
54 | |||
55 | # Default zone for 'gnunet-gns' lookups | 51 | # Default zone for 'gnunet-gns' lookups |
56 | gnunet-identity -e master-zone -s gns-master $options | 52 | gnunet-identity -e master-zone -s gns-master $options |
57 | 53 | ||
@@ -76,23 +72,16 @@ gnunet-identity -e sks-zone -s fs-sks $options | |||
76 | 72 | ||
77 | # Get the public keys as strings (so we can create PKEY records) | 73 | # Get the public keys as strings (so we can create PKEY records) |
78 | MASTER=`gnunet-identity -d $options | grep master-zone | awk '{print $3}'` | 74 | MASTER=`gnunet-identity -d $options | grep master-zone | awk '{print $3}'` |
79 | SHORT=`gnunet-identity -d $options | grep short-zone | awk '{print $3}'` | ||
80 | PRIVATE=`gnunet-identity -d $options | grep private-zone | awk '{print $3}'` | 75 | PRIVATE=`gnunet-identity -d $options | grep private-zone | awk '{print $3}'` |
81 | PIN=DWJASSPE33MRN8T6Q0PENRNBTQY0E6ZYGTRCDP5DGPBF2CRJMJEG | 76 | PIN=DWJASSPE33MRN8T6Q0PENRNBTQY0E6ZYGTRCDP5DGPBF2CRJMJEG |
82 | 77 | ||
83 | # Link short and private zones into master zone | 78 | # Link private zone into master zone |
84 | if (gnunet-namestore -z master-zone -D -n private -t PKEY | grep "PKEY: $PRIVATE" 1>/dev/null) | 79 | if (gnunet-namestore -z master-zone -D -n private -t PKEY | grep "PKEY: $PRIVATE" 1>/dev/null) |
85 | then | 80 | then |
86 | echo "Private zone link exists, skipping" | 81 | echo "Private zone link exists, skipping" |
87 | else | 82 | else |
88 | gnunet-namestore -z master-zone -a -e never -n private -p -t PKEY -V $PRIVATE $options | 83 | gnunet-namestore -z master-zone -a -e never -n private -p -t PKEY -V $PRIVATE $options |
89 | fi | 84 | fi |
90 | if (gnunet-namestore -z master-zone -D -n short -t PKEY | grep "PKEY: $SHORT" 1>/dev/null) | ||
91 | then | ||
92 | echo "Shorten zone link exists, skipping" | ||
93 | else | ||
94 | gnunet-namestore -z master-zone -a -e never -n short -p -t PKEY -V $SHORT $options | ||
95 | fi | ||
96 | 85 | ||
97 | # Link GNUnet's FCFS zone into master zone under label "pin" | 86 | # Link GNUnet's FCFS zone into master zone under label "pin" |
98 | if (gnunet-namestore -z master-zone -D -n pin -t PKEY | grep "PKEY: $PIN" 1>/dev/null) | 87 | if (gnunet-namestore -z master-zone -D -n pin -t PKEY | grep "PKEY: $PIN" 1>/dev/null) |
diff --git a/doc/man/gnunet-ecc.1 b/doc/man/gnunet-ecc.1 index 35d877efd..a91a2ac2f 100644 --- a/doc/man/gnunet-ecc.1 +++ b/doc/man/gnunet-ecc.1 | |||
@@ -1,4 +1,4 @@ | |||
1 | .TH GNUNET\-ECC 1 "Mar 15, 2012" "GNUnet" | 1 | .TH GNUNET\-ECC 1 "Jun 5, 2017" "GNUnet" |
2 | 2 | ||
3 | .SH NAME | 3 | .SH NAME |
4 | gnunet\-ecc \- manipulate GNUnet ECC key files | 4 | gnunet\-ecc \- manipulate GNUnet ECC key files |
@@ -19,6 +19,9 @@ Create COUNT public-private key pairs and write them to FILENAME. Used for crea | |||
19 | .IP "\-p, \-\-print-public-key" | 19 | .IP "\-p, \-\-print-public-key" |
20 | Print the corresponding public key to stdout. This is the value used for PKEY records in GNS. | 20 | Print the corresponding public key to stdout. This is the value used for PKEY records in GNS. |
21 | .B | 21 | .B |
22 | .IP "\-p, \-\-print-hex" | ||
23 | Print the corresponding public key to stdout in HEX format. Useful for comparing to Ed25519 keys in X.509 tools. | ||
24 | .B | ||
22 | .IP "\-P, \-\-print-peer-identity" | 25 | .IP "\-P, \-\-print-peer-identity" |
23 | Print the corresponding peer identity (hash of the public key) to stdout. This hash is used for the name of peers. | 26 | Print the corresponding peer identity (hash of the public key) to stdout. This hash is used for the name of peers. |
24 | .B | 27 | .B |
@@ -37,4 +40,3 @@ Print GNUnet version number. | |||
37 | 40 | ||
38 | .SH BUGS | 41 | .SH BUGS |
39 | Report bugs by using Mantis <https://gnunet.org/bugs/> or by sending electronic mail to <gnunet\-developers@gnu.org> | 42 | Report bugs by using Mantis <https://gnunet.org/bugs/> or by sending electronic mail to <gnunet\-developers@gnu.org> |
40 | |||
diff --git a/guix-env.scm b/guix-env.scm index fc3d5a231..ec3a8e1f8 100644 --- a/guix-env.scm +++ b/guix-env.scm | |||
@@ -35,7 +35,8 @@ | |||
35 | ;; guix build -f guix-env.scm | 35 | ;; guix build -f guix-env.scm |
36 | ;; | 36 | ;; |
37 | ;; We'd like to provide advanced functions such as guix environment specific | 37 | ;; We'd like to provide advanced functions such as guix environment specific |
38 | ;; gnunet-svn package, but this is subject to tests right now. | 38 | ;; gnunet-git package and usage of gnunet-gtk-git, but this is subject |
39 | ;; to tests right now. | ||
39 | ;; | 40 | ;; |
40 | ;; Further versions of GNUnet for Guix can currently be found in | 41 | ;; Further versions of GNUnet for Guix can currently be found in |
41 | ;; https://git.pragmatique.xyz/ng0-packages/log.html, mirrored at | 42 | ;; https://git.pragmatique.xyz/ng0-packages/log.html, mirrored at |
@@ -49,6 +50,7 @@ | |||
49 | (guix build-system gnu) | 50 | (guix build-system gnu) |
50 | (guix gexp) | 51 | (guix gexp) |
51 | ((guix build utils) #:select (with-directory-excursion)) | 52 | ((guix build utils) #:select (with-directory-excursion)) |
53 | (guix git-download) | ||
52 | (gnu packages) | 54 | (gnu packages) |
53 | (gnu packages aidc) | 55 | (gnu packages aidc) |
54 | (gnu packages autotools) | 56 | (gnu packages autotools) |
@@ -94,7 +96,8 @@ | |||
94 | (version (string-append "0.10.1-" "dev")) | 96 | (version (string-append "0.10.1-" "dev")) |
95 | (source | 97 | (source |
96 | (local-file %source-dir | 98 | (local-file %source-dir |
97 | #:recursive? #t)) | 99 | #:recursive? #t |
100 | #:select? (git-predicate %source-dir))) | ||
98 | (build-system gnu-build-system) | 101 | (build-system gnu-build-system) |
99 | (inputs | 102 | (inputs |
100 | `(("glpk" ,glpk) | 103 | `(("glpk" ,glpk) |
@@ -138,7 +141,6 @@ | |||
138 | (arguments | 141 | (arguments |
139 | `(#:configure-flags | 142 | `(#:configure-flags |
140 | (list (string-append "--with-nssdir=" %output "/lib") | 143 | (list (string-append "--with-nssdir=" %output "/lib") |
141 | ;; These appear to be "broken" on Guix, needs debugging. | ||
142 | "--enable-gcc-hardening" | 144 | "--enable-gcc-hardening" |
143 | "--enable-linker-hardening" | 145 | "--enable-linker-hardening" |
144 | 146 | ||
diff --git a/pkgconfig/Makefile.am b/pkgconfig/Makefile.am index f6cd58494..9c9eb5c6b 100644 --- a/pkgconfig/Makefile.am +++ b/pkgconfig/Makefile.am | |||
@@ -27,7 +27,6 @@ pcfiles = \ | |||
27 | gnunetnat.pc \ | 27 | gnunetnat.pc \ |
28 | gnunetnse.pc \ | 28 | gnunetnse.pc \ |
29 | gnunetpeerinfo.pc \ | 29 | gnunetpeerinfo.pc \ |
30 | gnunetpostgres.pc \ | ||
31 | gnunetpsyc.pc \ | 30 | gnunetpsyc.pc \ |
32 | gnunetpsycstore.pc \ | 31 | gnunetpsycstore.pc \ |
33 | gnunetregex.pc \ | 32 | gnunetregex.pc \ |
diff --git a/po/POTFILES.in b/po/POTFILES.in index 82208bb67..50c182833 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in | |||
@@ -269,8 +269,11 @@ src/peerstore/peerstore_api.c | |||
269 | src/peerstore/peerstore_common.c | 269 | src/peerstore/peerstore_common.c |
270 | src/peerstore/plugin_peerstore_flat.c | 270 | src/peerstore/plugin_peerstore_flat.c |
271 | src/peerstore/plugin_peerstore_sqlite.c | 271 | src/peerstore/plugin_peerstore_sqlite.c |
272 | src/postgres/postgres.c | ||
273 | src/pq/pq.c | 272 | src/pq/pq.c |
273 | src/pq/pq_connect.c | ||
274 | src/pq/pq_eval.c | ||
275 | src/pq/pq_exec.c | ||
276 | src/pq/pq_prepare.c | ||
274 | src/pq/pq_query_helper.c | 277 | src/pq/pq_query_helper.c |
275 | src/pq/pq_result_helper.c | 278 | src/pq/pq_result_helper.c |
276 | src/psyc/gnunet-service-psyc.c | 279 | src/psyc/gnunet-service-psyc.c |
@@ -497,7 +500,6 @@ src/zonemaster/gnunet-service-zonemaster.c | |||
497 | src/fs/fs_api.h | 500 | src/fs/fs_api.h |
498 | src/include/gnunet_common.h | 501 | src/include/gnunet_common.h |
499 | src/include/gnunet_mq_lib.h | 502 | src/include/gnunet_mq_lib.h |
500 | src/include/gnunet_postgres_lib.h | ||
501 | src/include/gnunet_time_lib.h | 503 | src/include/gnunet_time_lib.h |
502 | src/rps/rps-test_util.h | 504 | src/rps/rps-test_util.h |
503 | src/scalarproduct/scalarproduct.h | 505 | src/scalarproduct/scalarproduct.h |
diff --git a/src/Makefile.am b/src/Makefile.am index 4a1d909ed..e4d7d8924 100644 --- a/src/Makefile.am +++ b/src/Makefile.am | |||
@@ -11,9 +11,9 @@ endif | |||
11 | 11 | ||
12 | if HAVE_EXPERIMENTAL | 12 | if HAVE_EXPERIMENTAL |
13 | EXP_DIR = \ | 13 | EXP_DIR = \ |
14 | dv \ | ||
15 | rps | 14 | rps |
16 | endif | 15 | endif |
16 | # dv (FTBFS) | ||
17 | 17 | ||
18 | if HAVE_JSON | 18 | if HAVE_JSON |
19 | if HAVE_MHD | 19 | if HAVE_MHD |
@@ -49,7 +49,7 @@ if HAVE_MYSQL | |||
49 | endif | 49 | endif |
50 | 50 | ||
51 | if HAVE_POSTGRESQL | 51 | if HAVE_POSTGRESQL |
52 | POSTGRES_DIR = pq postgres | 52 | POSTGRES_DIR = pq |
53 | endif | 53 | endif |
54 | 54 | ||
55 | if HAVE_MHD | 55 | if HAVE_MHD |
diff --git a/src/consensus/gnunet-service-consensus.c b/src/consensus/gnunet-service-consensus.c index 4af7199aa..84b1cbe55 100644 --- a/src/consensus/gnunet-service-consensus.c +++ b/src/consensus/gnunet-service-consensus.c | |||
@@ -693,7 +693,7 @@ send_to_client_iter (void *cls, | |||
693 | GNUNET_assert (GNUNET_BLOCK_TYPE_CONSENSUS_ELEMENT == element->element_type); | 693 | GNUNET_assert (GNUNET_BLOCK_TYPE_CONSENSUS_ELEMENT == element->element_type); |
694 | ce = element->data; | 694 | ce = element->data; |
695 | 695 | ||
696 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "marker is %u\n", (unsigned) ce->marker); | 696 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "marker is %u\n", (unsigned) ce->marker); |
697 | 697 | ||
698 | if (0 != ce->marker) | 698 | if (0 != ce->marker) |
699 | return GNUNET_YES; | 699 | return GNUNET_YES; |
@@ -988,7 +988,7 @@ set_result_cb (void *cls, | |||
988 | 988 | ||
989 | if ( (NULL != consensus_element) && (0 != consensus_element->marker) ) | 989 | if ( (NULL != consensus_element) && (0 != consensus_element->marker) ) |
990 | { | 990 | { |
991 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 991 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
992 | "P%u: got some marker\n", | 992 | "P%u: got some marker\n", |
993 | session->local_peer_idx); | 993 | session->local_peer_idx); |
994 | if ( (GNUNET_YES == setop->transceive_contested) && | 994 | if ( (GNUNET_YES == setop->transceive_contested) && |
@@ -1002,7 +1002,7 @@ set_result_cb (void *cls, | |||
1002 | if (CONSENSUS_MARKER_SIZE == consensus_element->marker) | 1002 | if (CONSENSUS_MARKER_SIZE == consensus_element->marker) |
1003 | { | 1003 | { |
1004 | 1004 | ||
1005 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 1005 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1006 | "P%u: got size marker\n", | 1006 | "P%u: got size marker\n", |
1007 | session->local_peer_idx); | 1007 | session->local_peer_idx); |
1008 | 1008 | ||
@@ -1018,7 +1018,7 @@ set_result_cb (void *cls, | |||
1018 | uint64_t *copy = GNUNET_memdup (session->first_sizes_received, sizeof (uint64_t) * session->num_peers); | 1018 | uint64_t *copy = GNUNET_memdup (session->first_sizes_received, sizeof (uint64_t) * session->num_peers); |
1019 | qsort (copy, session->num_peers, sizeof (uint64_t), cmp_uint64_t); | 1019 | qsort (copy, session->num_peers, sizeof (uint64_t), cmp_uint64_t); |
1020 | session->lower_bound = copy[session->num_peers / 3 + 1]; | 1020 | session->lower_bound = copy[session->num_peers / 3 + 1]; |
1021 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 1021 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1022 | "P%u: lower bound %llu\n", | 1022 | "P%u: lower bound %llu\n", |
1023 | session->local_peer_idx, | 1023 | session->local_peer_idx, |
1024 | (long long) session->lower_bound); | 1024 | (long long) session->lower_bound); |
@@ -1045,7 +1045,7 @@ set_result_cb (void *cls, | |||
1045 | NULL, | 1045 | NULL, |
1046 | NULL); | 1046 | NULL); |
1047 | #ifdef GNUNET_EXTRA_LOGGING | 1047 | #ifdef GNUNET_EXTRA_LOGGING |
1048 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 1048 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1049 | "P%u: adding element %s into set {%s} of task {%s}\n", | 1049 | "P%u: adding element %s into set {%s} of task {%s}\n", |
1050 | session->local_peer_idx, | 1050 | session->local_peer_idx, |
1051 | debug_str_element (element), | 1051 | debug_str_element (element), |
@@ -1057,7 +1057,7 @@ set_result_cb (void *cls, | |||
1057 | { | 1057 | { |
1058 | diff_insert (output_diff, 1, element); | 1058 | diff_insert (output_diff, 1, element); |
1059 | #ifdef GNUNET_EXTRA_LOGGING | 1059 | #ifdef GNUNET_EXTRA_LOGGING |
1060 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 1060 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1061 | "P%u: adding element %s into diff {%s} of task {%s}\n", | 1061 | "P%u: adding element %s into diff {%s} of task {%s}\n", |
1062 | session->local_peer_idx, | 1062 | session->local_peer_idx, |
1063 | debug_str_element (element), | 1063 | debug_str_element (element), |
@@ -1069,7 +1069,7 @@ set_result_cb (void *cls, | |||
1069 | { | 1069 | { |
1070 | rfn_vote (output_rfn, task_other_peer (task), VOTE_ADD, element); | 1070 | rfn_vote (output_rfn, task_other_peer (task), VOTE_ADD, element); |
1071 | #ifdef GNUNET_EXTRA_LOGGING | 1071 | #ifdef GNUNET_EXTRA_LOGGING |
1072 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 1072 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1073 | "P%u: adding element %s into rfn {%s} of task {%s}\n", | 1073 | "P%u: adding element %s into rfn {%s} of task {%s}\n", |
1074 | session->local_peer_idx, | 1074 | session->local_peer_idx, |
1075 | debug_str_element (element), | 1075 | debug_str_element (element), |
@@ -1096,7 +1096,7 @@ set_result_cb (void *cls, | |||
1096 | NULL, | 1096 | NULL, |
1097 | NULL); | 1097 | NULL); |
1098 | #ifdef GNUNET_EXTRA_LOGGING | 1098 | #ifdef GNUNET_EXTRA_LOGGING |
1099 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 1099 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1100 | "P%u: removing element %s from set {%s} of task {%s}\n", | 1100 | "P%u: removing element %s from set {%s} of task {%s}\n", |
1101 | session->local_peer_idx, | 1101 | session->local_peer_idx, |
1102 | debug_str_element (element), | 1102 | debug_str_element (element), |
@@ -1108,7 +1108,7 @@ set_result_cb (void *cls, | |||
1108 | { | 1108 | { |
1109 | diff_insert (output_diff, -1, element); | 1109 | diff_insert (output_diff, -1, element); |
1110 | #ifdef GNUNET_EXTRA_LOGGING | 1110 | #ifdef GNUNET_EXTRA_LOGGING |
1111 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 1111 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1112 | "P%u: removing element %s from diff {%s} of task {%s}\n", | 1112 | "P%u: removing element %s from diff {%s} of task {%s}\n", |
1113 | session->local_peer_idx, | 1113 | session->local_peer_idx, |
1114 | debug_str_element (element), | 1114 | debug_str_element (element), |
@@ -1120,7 +1120,7 @@ set_result_cb (void *cls, | |||
1120 | { | 1120 | { |
1121 | rfn_vote (output_rfn, task_other_peer (task), VOTE_REMOVE, element); | 1121 | rfn_vote (output_rfn, task_other_peer (task), VOTE_REMOVE, element); |
1122 | #ifdef GNUNET_EXTRA_LOGGING | 1122 | #ifdef GNUNET_EXTRA_LOGGING |
1123 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 1123 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1124 | "P%u: removing element %s from rfn {%s} of task {%s}\n", | 1124 | "P%u: removing element %s from rfn {%s} of task {%s}\n", |
1125 | session->local_peer_idx, | 1125 | session->local_peer_idx, |
1126 | debug_str_element (element), | 1126 | debug_str_element (element), |
@@ -1133,8 +1133,11 @@ set_result_cb (void *cls, | |||
1133 | // XXX: check first if any changes to the underlying | 1133 | // XXX: check first if any changes to the underlying |
1134 | // set are still pending | 1134 | // set are still pending |
1135 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1135 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1136 | "Finishing setop in Task {%s}\n", | 1136 | "P%u: Finishing setop in Task {%s} (%u/%u)\n", |
1137 | debug_str_task_key (&task->key)); | 1137 | session->local_peer_idx, |
1138 | debug_str_task_key (&task->key), | ||
1139 | (unsigned int) task->step->finished_tasks, | ||
1140 | (unsigned int) task->step->tasks_len); | ||
1138 | if (NULL != output_rfn) | 1141 | if (NULL != output_rfn) |
1139 | { | 1142 | { |
1140 | rfn_commit (output_rfn, task_other_peer (task)); | 1143 | rfn_commit (output_rfn, task_other_peer (task)); |
@@ -1345,7 +1348,7 @@ commit_set (struct ConsensusSession *session, | |||
1345 | .size = 0, | 1348 | .size = 0, |
1346 | .sender_index = 0 | 1349 | .sender_index = 0 |
1347 | }; | 1350 | }; |
1348 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "inserting size marker\n"); | 1351 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "inserting size marker\n"); |
1349 | cse.ce.marker = CONSENSUS_MARKER_SIZE; | 1352 | cse.ce.marker = CONSENSUS_MARKER_SIZE; |
1350 | cse.size = GNUNET_htonll (session->first_size); | 1353 | cse.size = GNUNET_htonll (session->first_size); |
1351 | cse.sender_index = session->local_peer_idx; | 1354 | cse.sender_index = session->local_peer_idx; |
@@ -1421,7 +1424,7 @@ commit_set (struct ConsensusSession *session, | |||
1421 | } | 1424 | } |
1422 | GNUNET_SET_add_element (set->h, &element, NULL, NULL); | 1425 | GNUNET_SET_add_element (set->h, &element, NULL, NULL); |
1423 | #ifdef GNUNET_EXTRA_LOGGING | 1426 | #ifdef GNUNET_EXTRA_LOGGING |
1424 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 1427 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1425 | "P%u: evil peer: cramming element %s into set {%s} of task {%s}\n", | 1428 | "P%u: evil peer: cramming element %s into set {%s} of task {%s}\n", |
1426 | session->local_peer_idx, | 1429 | session->local_peer_idx, |
1427 | debug_str_element (&element), | 1430 | debug_str_element (&element), |
@@ -1436,7 +1439,7 @@ commit_set (struct ConsensusSession *session, | |||
1436 | GNUNET_SET_commit (setop->op, set->h); | 1439 | GNUNET_SET_commit (setop->op, set->h); |
1437 | break; | 1440 | break; |
1438 | case EVILNESS_SLACK: | 1441 | case EVILNESS_SLACK: |
1439 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 1442 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1440 | "P%u: evil peer: slacking\n", | 1443 | "P%u: evil peer: slacking\n", |
1441 | (unsigned int) session->local_peer_idx); | 1444 | (unsigned int) session->local_peer_idx); |
1442 | /* Do nothing. */ | 1445 | /* Do nothing. */ |
@@ -1470,6 +1473,7 @@ commit_set (struct ConsensusSession *session, | |||
1470 | peers to wait. */ | 1473 | peers to wait. */ |
1471 | GNUNET_SET_operation_cancel (setop->op); | 1474 | GNUNET_SET_operation_cancel (setop->op); |
1472 | setop->op = NULL; | 1475 | setop->op = NULL; |
1476 | finish_task (task); | ||
1473 | } | 1477 | } |
1474 | #endif | 1478 | #endif |
1475 | } | 1479 | } |
@@ -1891,7 +1895,7 @@ task_start_apply_round (struct TaskEntry *task) | |||
1891 | ri->element, | 1895 | ri->element, |
1892 | &set_mutation_done, | 1896 | &set_mutation_done, |
1893 | progress_cls)); | 1897 | progress_cls)); |
1894 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 1898 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1895 | "P%u: apply round: adding element %s with %u-majority.\n", | 1899 | "P%u: apply round: adding element %s with %u-majority.\n", |
1896 | session->local_peer_idx, | 1900 | session->local_peer_idx, |
1897 | debug_str_element (ri->element), majority_num); | 1901 | debug_str_element (ri->element), majority_num); |
@@ -1903,13 +1907,13 @@ task_start_apply_round (struct TaskEntry *task) | |||
1903 | ri->element, | 1907 | ri->element, |
1904 | &set_mutation_done, | 1908 | &set_mutation_done, |
1905 | progress_cls)); | 1909 | progress_cls)); |
1906 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 1910 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1907 | "P%u: apply round: deleting element %s with %u-majority.\n", | 1911 | "P%u: apply round: deleting element %s with %u-majority.\n", |
1908 | session->local_peer_idx, | 1912 | session->local_peer_idx, |
1909 | debug_str_element (ri->element), majority_num); | 1913 | debug_str_element (ri->element), majority_num); |
1910 | break; | 1914 | break; |
1911 | case VOTE_STAY: | 1915 | case VOTE_STAY: |
1912 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 1916 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1913 | "P%u: apply round: keeping element %s with %u-majority.\n", | 1917 | "P%u: apply round: keeping element %s with %u-majority.\n", |
1914 | session->local_peer_idx, | 1918 | session->local_peer_idx, |
1915 | debug_str_element (ri->element), majority_num); | 1919 | debug_str_element (ri->element), majority_num); |
@@ -2378,6 +2382,13 @@ finish_task (struct TaskEntry *task) | |||
2378 | 2382 | ||
2379 | task->step->finished_tasks++; | 2383 | task->step->finished_tasks++; |
2380 | 2384 | ||
2385 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
2386 | "P%u: Finishing Task {%s} (now %u/%u tasks finished in step)\n", | ||
2387 | task->step->session->local_peer_idx, | ||
2388 | debug_str_task_key (&task->key), | ||
2389 | (unsigned int) task->step->finished_tasks, | ||
2390 | (unsigned int) task->step->tasks_len); | ||
2391 | |||
2381 | if (task->step->finished_tasks == task->step->tasks_len) | 2392 | if (task->step->finished_tasks == task->step->tasks_len) |
2382 | finish_step (task->step); | 2393 | finish_step (task->step); |
2383 | } | 2394 | } |
diff --git a/src/consensus/test_consensus.conf b/src/consensus/test_consensus.conf index 881251a66..f78b77d09 100644 --- a/src/consensus/test_consensus.conf +++ b/src/consensus/test_consensus.conf | |||
@@ -5,7 +5,7 @@ GNUNET_TEST_HOME = /tmp/test-consensus/ | |||
5 | #OPTIONS = -L INFO | 5 | #OPTIONS = -L INFO |
6 | BINARY = gnunet-service-evil-consensus | 6 | BINARY = gnunet-service-evil-consensus |
7 | 7 | ||
8 | PREFIX = valgrind | 8 | #PREFIX = valgrind |
9 | 9 | ||
10 | #EVIL_SPEC = 0;cram-all;noreplace;5 | 10 | #EVIL_SPEC = 0;cram-all;noreplace;5 |
11 | #EVIL_SPEC = 0;cram;5/1;cram;5 | 11 | #EVIL_SPEC = 0;cram;5/1;cram;5 |
diff --git a/src/conversation/test_conversation.conf b/src/conversation/test_conversation.conf index e0fd8200c..87c4b8f07 100644 --- a/src/conversation/test_conversation.conf +++ b/src/conversation/test_conversation.conf | |||
@@ -2,7 +2,7 @@ | |||
2 | 2 | ||
3 | [conversation] | 3 | [conversation] |
4 | LINE=1 | 4 | LINE=1 |
5 | PREFIX = valgrind | 5 | #PREFIX = valgrind |
6 | 6 | ||
7 | [nse] | 7 | [nse] |
8 | WORKBITS = 0 | 8 | WORKBITS = 0 |
diff --git a/src/datacache/Makefile.am b/src/datacache/Makefile.am index 670a64926..898b51563 100644 --- a/src/datacache/Makefile.am +++ b/src/datacache/Makefile.am | |||
@@ -71,7 +71,7 @@ libgnunet_plugin_datacache_heap_la_LDFLAGS = \ | |||
71 | libgnunet_plugin_datacache_postgres_la_SOURCES = \ | 71 | libgnunet_plugin_datacache_postgres_la_SOURCES = \ |
72 | plugin_datacache_postgres.c | 72 | plugin_datacache_postgres.c |
73 | libgnunet_plugin_datacache_postgres_la_LIBADD = \ | 73 | libgnunet_plugin_datacache_postgres_la_LIBADD = \ |
74 | $(top_builddir)/src/postgres/libgnunetpostgres.la \ | 74 | $(top_builddir)/src/pq/libgnunetpq.la \ |
75 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | 75 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ |
76 | $(top_builddir)/src/util/libgnunetutil.la \ | 76 | $(top_builddir)/src/util/libgnunetutil.la \ |
77 | $(GN_PLUGIN_LDFLAGS) -lpq | 77 | $(GN_PLUGIN_LDFLAGS) -lpq |
diff --git a/src/datacache/plugin_datacache_postgres.c b/src/datacache/plugin_datacache_postgres.c index 13c2c26a2..5c497cdf8 100644 --- a/src/datacache/plugin_datacache_postgres.c +++ b/src/datacache/plugin_datacache_postgres.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet | 2 | This file is part of GNUnet |
3 | Copyright (C) 2006, 2009, 2010, 2012, 2015 GNUnet e.V. | 3 | Copyright (C) 2006, 2009, 2010, 2012, 2015, 2017 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
@@ -25,7 +25,7 @@ | |||
25 | */ | 25 | */ |
26 | #include "platform.h" | 26 | #include "platform.h" |
27 | #include "gnunet_util_lib.h" | 27 | #include "gnunet_util_lib.h" |
28 | #include "gnunet_postgres_lib.h" | 28 | #include "gnunet_pq_lib.h" |
29 | #include "gnunet_datacache_plugin.h" | 29 | #include "gnunet_datacache_plugin.h" |
30 | 30 | ||
31 | #define LOG(kind,...) GNUNET_log_from (kind, "datacache-postgres", __VA_ARGS__) | 31 | #define LOG(kind,...) GNUNET_log_from (kind, "datacache-postgres", __VA_ARGS__) |
@@ -66,115 +66,67 @@ struct Plugin | |||
66 | static int | 66 | static int |
67 | init_connection (struct Plugin *plugin) | 67 | init_connection (struct Plugin *plugin) |
68 | { | 68 | { |
69 | PGresult *ret; | 69 | struct GNUNET_PQ_ExecuteStatement es[] = { |
70 | GNUNET_PQ_make_execute ("CREATE TEMPORARY TABLE IF NOT EXISTS gn090dc (" | ||
71 | " type INTEGER NOT NULL DEFAULT 0," | ||
72 | " discard_time BIGINT NOT NULL DEFAULT 0," | ||
73 | " key BYTEA NOT NULL DEFAULT ''," | ||
74 | " value BYTEA NOT NULL DEFAULT ''," | ||
75 | " path BYTEA DEFAULT '')" | ||
76 | "WITH OIDS"), | ||
77 | GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS idx_key ON gn090dc (key)"), | ||
78 | GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS idx_dt ON gn090dc (discard_time)"), | ||
79 | GNUNET_PQ_make_execute ("ALTER TABLE gn090dc ALTER value SET STORAGE EXTERNAL"), | ||
80 | GNUNET_PQ_make_execute ("ALTER TABLE gn090dc ALTER key SET STORAGE PLAIN"), | ||
81 | GNUNET_PQ_EXECUTE_STATEMENT_END | ||
82 | }; | ||
83 | struct GNUNET_PQ_PreparedStatement ps[] = { | ||
84 | GNUNET_PQ_make_prepare ("getkt", | ||
85 | "SELECT discard_time,type,value,path FROM gn090dc " | ||
86 | "WHERE key=$1 AND type=$2", | ||
87 | 2), | ||
88 | GNUNET_PQ_make_prepare ("getk", | ||
89 | "SELECT discard_time,type,value,path FROM gn090dc " | ||
90 | "WHERE key=$1", | ||
91 | 1), | ||
92 | GNUNET_PQ_make_prepare ("getm", | ||
93 | "SELECT length(value) AS len,oid,key FROM gn090dc " | ||
94 | "ORDER BY discard_time ASC LIMIT 1", | ||
95 | 0), | ||
96 | GNUNET_PQ_make_prepare ("get_random", | ||
97 | "SELECT discard_time,type,value,path,key FROM gn090dc " | ||
98 | "ORDER BY key ASC LIMIT 1 OFFSET $1", | ||
99 | 1), | ||
100 | GNUNET_PQ_make_prepare ("get_closest", | ||
101 | "SELECT discard_time,type,value,path,key FROM gn090dc " | ||
102 | "WHERE key>=$1 ORDER BY key ASC LIMIT $2", | ||
103 | 1), | ||
104 | GNUNET_PQ_make_prepare ("delrow", | ||
105 | "DELETE FROM gn090dc WHERE oid=$1", | ||
106 | 1), | ||
107 | GNUNET_PQ_make_prepare ("put", | ||
108 | "INSERT INTO gn090dc (type, discard_time, key, value, path) " | ||
109 | "VALUES ($1, $2, $3, $4, $5)", | ||
110 | 5), | ||
111 | GNUNET_PQ_PREPARED_STATEMENT_END | ||
112 | }; | ||
70 | 113 | ||
71 | plugin->dbh = GNUNET_POSTGRES_connect (plugin->env->cfg, | 114 | plugin->dbh = GNUNET_PQ_connect_with_cfg (plugin->env->cfg, |
72 | "datacache-postgres"); | 115 | "datacache-postgres"); |
73 | if (NULL == plugin->dbh) | 116 | if (NULL == plugin->dbh) |
74 | return GNUNET_SYSERR; | 117 | return GNUNET_SYSERR; |
75 | ret = | ||
76 | PQexec (plugin->dbh, | ||
77 | "CREATE TEMPORARY TABLE IF NOT EXISTS gn090dc (" | ||
78 | " type INTEGER NOT NULL DEFAULT 0," | ||
79 | " discard_time BIGINT NOT NULL DEFAULT 0," | ||
80 | " key BYTEA NOT NULL DEFAULT ''," | ||
81 | " value BYTEA NOT NULL DEFAULT ''," | ||
82 | " path BYTEA DEFAULT '')" | ||
83 | "WITH OIDS"); | ||
84 | if ( (ret == NULL) || | ||
85 | ((PQresultStatus (ret) != PGRES_COMMAND_OK) && | ||
86 | (0 != strcmp ("42P07", /* duplicate table */ | ||
87 | PQresultErrorField | ||
88 | (ret, | ||
89 | PG_DIAG_SQLSTATE))))) | ||
90 | { | ||
91 | (void) GNUNET_POSTGRES_check_result (plugin->dbh, ret, | ||
92 | PGRES_COMMAND_OK, | ||
93 | "CREATE TABLE", | ||
94 | "gn090dc"); | ||
95 | PQfinish (plugin->dbh); | ||
96 | plugin->dbh = NULL; | ||
97 | return GNUNET_SYSERR; | ||
98 | } | ||
99 | if (PQresultStatus (ret) == PGRES_COMMAND_OK) | ||
100 | { | ||
101 | if ((GNUNET_OK != | ||
102 | GNUNET_POSTGRES_exec (plugin->dbh, | ||
103 | "CREATE INDEX IF NOT EXISTS idx_key ON gn090dc (key)")) || | ||
104 | (GNUNET_OK != | ||
105 | GNUNET_POSTGRES_exec (plugin->dbh, | ||
106 | "CREATE INDEX IF NOT EXISTS idx_dt ON gn090dc (discard_time)"))) | ||
107 | { | ||
108 | PQclear (ret); | ||
109 | PQfinish (plugin->dbh); | ||
110 | plugin->dbh = NULL; | ||
111 | return GNUNET_SYSERR; | ||
112 | } | ||
113 | } | ||
114 | PQclear (ret); | ||
115 | ret = | ||
116 | PQexec (plugin->dbh, | ||
117 | "ALTER TABLE gn090dc ALTER value SET STORAGE EXTERNAL"); | ||
118 | if (GNUNET_OK != | 118 | if (GNUNET_OK != |
119 | GNUNET_POSTGRES_check_result (plugin->dbh, | 119 | GNUNET_PQ_exec_statements (plugin->dbh, |
120 | ret, | 120 | es)) |
121 | PGRES_COMMAND_OK, | ||
122 | "ALTER TABLE", | ||
123 | "gn090dc")) | ||
124 | { | 121 | { |
125 | PQfinish (plugin->dbh); | 122 | PQfinish (plugin->dbh); |
126 | plugin->dbh = NULL; | 123 | plugin->dbh = NULL; |
127 | return GNUNET_SYSERR; | 124 | return GNUNET_SYSERR; |
128 | } | 125 | } |
129 | PQclear (ret); | 126 | |
130 | ret = PQexec (plugin->dbh, | ||
131 | "ALTER TABLE gn090dc ALTER key SET STORAGE PLAIN"); | ||
132 | if (GNUNET_OK != | 127 | if (GNUNET_OK != |
133 | GNUNET_POSTGRES_check_result (plugin->dbh, | 128 | GNUNET_PQ_prepare_statements (plugin->dbh, |
134 | ret, | 129 | ps)) |
135 | PGRES_COMMAND_OK, | ||
136 | "ALTER TABLE", | ||
137 | "gn090dc")) | ||
138 | { | ||
139 | PQfinish (plugin->dbh); | ||
140 | plugin->dbh = NULL; | ||
141 | return GNUNET_SYSERR; | ||
142 | } | ||
143 | PQclear (ret); | ||
144 | if ((GNUNET_OK != | ||
145 | GNUNET_POSTGRES_prepare (plugin->dbh, | ||
146 | "getkt", | ||
147 | "SELECT discard_time,type,value,path FROM gn090dc " | ||
148 | "WHERE key=$1 AND type=$2 ", 2)) || | ||
149 | (GNUNET_OK != | ||
150 | GNUNET_POSTGRES_prepare (plugin->dbh, | ||
151 | "getk", | ||
152 | "SELECT discard_time,type,value,path FROM gn090dc " | ||
153 | "WHERE key=$1", 1)) || | ||
154 | (GNUNET_OK != | ||
155 | GNUNET_POSTGRES_prepare (plugin->dbh, | ||
156 | "getm", | ||
157 | "SELECT length(value),oid,key FROM gn090dc " | ||
158 | "ORDER BY discard_time ASC LIMIT 1", 0)) || | ||
159 | (GNUNET_OK != | ||
160 | GNUNET_POSTGRES_prepare (plugin->dbh, | ||
161 | "get_random", | ||
162 | "SELECT discard_time,type,value,path,key FROM gn090dc " | ||
163 | "ORDER BY key ASC LIMIT 1 OFFSET $1", 1)) || | ||
164 | (GNUNET_OK != | ||
165 | GNUNET_POSTGRES_prepare (plugin->dbh, | ||
166 | "get_closest", | ||
167 | "SELECT discard_time,type,value,path,key FROM gn090dc " | ||
168 | "WHERE key>=$1 ORDER BY key ASC LIMIT $2", 1)) || | ||
169 | (GNUNET_OK != | ||
170 | GNUNET_POSTGRES_prepare (plugin->dbh, | ||
171 | "delrow", | ||
172 | "DELETE FROM gn090dc WHERE oid=$1", 1)) || | ||
173 | (GNUNET_OK != | ||
174 | GNUNET_POSTGRES_prepare (plugin->dbh, | ||
175 | "put", | ||
176 | "INSERT INTO gn090dc (type, discard_time, key, value, path) " | ||
177 | "VALUES ($1, $2, $3, $4, $5)", 5))) | ||
178 | { | 130 | { |
179 | PQfinish (plugin->dbh); | 131 | PQfinish (plugin->dbh); |
180 | plugin->dbh = NULL; | 132 | plugin->dbh = NULL; |
@@ -189,7 +141,7 @@ init_connection (struct Plugin *plugin) | |||
189 | * | 141 | * |
190 | * @param cls closure (our `struct Plugin`) | 142 | * @param cls closure (our `struct Plugin`) |
191 | * @param key key to store @a data under | 143 | * @param key key to store @a data under |
192 | * @param size number of bytes in @a data | 144 | * @param data_size number of bytes in @a data |
193 | * @param data data to store | 145 | * @param data data to store |
194 | * @param type type of the value | 146 | * @param type type of the value |
195 | * @param discard_time when to discard the value in any case | 147 | * @param discard_time when to discard the value in any case |
@@ -200,7 +152,7 @@ init_connection (struct Plugin *plugin) | |||
200 | static ssize_t | 152 | static ssize_t |
201 | postgres_plugin_put (void *cls, | 153 | postgres_plugin_put (void *cls, |
202 | const struct GNUNET_HashCode *key, | 154 | const struct GNUNET_HashCode *key, |
203 | size_t size, | 155 | size_t data_size, |
204 | const char *data, | 156 | const char *data, |
205 | enum GNUNET_BLOCK_Type type, | 157 | enum GNUNET_BLOCK_Type type, |
206 | struct GNUNET_TIME_Absolute discard_time, | 158 | struct GNUNET_TIME_Absolute discard_time, |
@@ -208,36 +160,125 @@ postgres_plugin_put (void *cls, | |||
208 | const struct GNUNET_PeerIdentity *path_info) | 160 | const struct GNUNET_PeerIdentity *path_info) |
209 | { | 161 | { |
210 | struct Plugin *plugin = cls; | 162 | struct Plugin *plugin = cls; |
211 | PGresult *ret; | 163 | uint32_t type32 = (uint32_t) type; |
212 | uint32_t btype = htonl (type); | 164 | struct GNUNET_PQ_QueryParam params[] = { |
213 | uint64_t bexpi = GNUNET_TIME_absolute_hton (discard_time).abs_value_us__; | 165 | GNUNET_PQ_query_param_uint32 (&type32), |
214 | 166 | GNUNET_PQ_query_param_absolute_time (&discard_time), | |
215 | const char *paramValues[] = { | 167 | GNUNET_PQ_query_param_auto_from_type (key), |
216 | (const char *) &btype, | 168 | GNUNET_PQ_query_param_fixed_size (data, data_size), |
217 | (const char *) &bexpi, | 169 | GNUNET_PQ_query_param_fixed_size (path_info, |
218 | (const char *) key, | 170 | path_info_len * sizeof (struct GNUNET_PeerIdentity)), |
219 | (const char *) data, | 171 | GNUNET_PQ_query_param_end |
220 | (const char *) path_info | ||
221 | }; | ||
222 | int paramLengths[] = { | ||
223 | sizeof (btype), | ||
224 | sizeof (bexpi), | ||
225 | sizeof (struct GNUNET_HashCode), | ||
226 | size, | ||
227 | path_info_len * sizeof (struct GNUNET_PeerIdentity) | ||
228 | }; | 172 | }; |
229 | const int paramFormats[] = { 1, 1, 1, 1, 1 }; | 173 | enum GNUNET_DB_QueryStatus ret; |
230 | 174 | ||
231 | ret = | 175 | ret = GNUNET_PQ_eval_prepared_non_select (plugin->dbh, |
232 | PQexecPrepared (plugin->dbh, "put", 5, paramValues, paramLengths, | 176 | "put", |
233 | paramFormats, 1); | 177 | params); |
234 | if (GNUNET_OK != | 178 | if (0 > ret) |
235 | GNUNET_POSTGRES_check_result (plugin->dbh, ret, | ||
236 | PGRES_COMMAND_OK, "PQexecPrepared", "put")) | ||
237 | return -1; | 179 | return -1; |
238 | plugin->num_items++; | 180 | plugin->num_items++; |
239 | PQclear (ret); | 181 | return data_size + OVERHEAD; |
240 | return size + OVERHEAD; | 182 | } |
183 | |||
184 | |||
185 | /** | ||
186 | * Closure for #handle_results. | ||
187 | */ | ||
188 | struct HandleResultContext | ||
189 | { | ||
190 | |||
191 | /** | ||
192 | * Function to call on each result, may be NULL. | ||
193 | */ | ||
194 | GNUNET_DATACACHE_Iterator iter; | ||
195 | |||
196 | /** | ||
197 | * Closure for @e iter. | ||
198 | */ | ||
199 | void *iter_cls; | ||
200 | |||
201 | /** | ||
202 | * Key used. | ||
203 | */ | ||
204 | const struct GNUNET_HashCode *key; | ||
205 | }; | ||
206 | |||
207 | |||
208 | /** | ||
209 | * Function to be called with the results of a SELECT statement | ||
210 | * that has returned @a num_results results. Parse the result | ||
211 | * and call the callback given in @a cls | ||
212 | * | ||
213 | * @param cls closure of type `struct HandleResultContext` | ||
214 | * @param result the postgres result | ||
215 | * @param num_result the number of results in @a result | ||
216 | */ | ||
217 | static void | ||
218 | handle_results (void *cls, | ||
219 | PGresult *result, | ||
220 | unsigned int num_results) | ||
221 | { | ||
222 | struct HandleResultContext *hrc = cls; | ||
223 | |||
224 | for (unsigned int i=0;i<num_results;i++) | ||
225 | { | ||
226 | struct GNUNET_TIME_Absolute expiration_time; | ||
227 | uint32_t type; | ||
228 | void *data; | ||
229 | size_t data_size; | ||
230 | struct GNUNET_PeerIdentity *path; | ||
231 | size_t path_len; | ||
232 | struct GNUNET_PQ_ResultSpec rs[] = { | ||
233 | GNUNET_PQ_result_spec_absolute_time ("discard_time", | ||
234 | &expiration_time), | ||
235 | GNUNET_PQ_result_spec_uint32 ("type", | ||
236 | &type), | ||
237 | GNUNET_PQ_result_spec_variable_size ("value", | ||
238 | &data, | ||
239 | &data_size), | ||
240 | GNUNET_PQ_result_spec_variable_size ("path", | ||
241 | (void **) &path, | ||
242 | &path_len), | ||
243 | GNUNET_PQ_result_spec_end | ||
244 | }; | ||
245 | |||
246 | if (GNUNET_YES != | ||
247 | GNUNET_PQ_extract_result (result, | ||
248 | rs, | ||
249 | i)) | ||
250 | { | ||
251 | GNUNET_break (0); | ||
252 | return; | ||
253 | } | ||
254 | if (0 != (path_len % sizeof (struct GNUNET_PeerIdentity))) | ||
255 | { | ||
256 | GNUNET_break (0); | ||
257 | path_len = 0; | ||
258 | } | ||
259 | path_len %= sizeof (struct GNUNET_PeerIdentity); | ||
260 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
261 | "Found result of size %u bytes and type %u in database\n", | ||
262 | (unsigned int) data_size, | ||
263 | (unsigned int) type); | ||
264 | if ( (NULL != hrc->iter) && | ||
265 | (GNUNET_SYSERR == | ||
266 | hrc->iter (hrc->iter_cls, | ||
267 | hrc->key, | ||
268 | data_size, | ||
269 | data, | ||
270 | (enum GNUNET_BLOCK_Type) type, | ||
271 | expiration_time, | ||
272 | path_len, | ||
273 | path)) ) | ||
274 | { | ||
275 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
276 | "Ending iteration (client error)\n"); | ||
277 | GNUNET_PQ_cleanup_result (rs); | ||
278 | return; | ||
279 | } | ||
280 | GNUNET_PQ_cleanup_result (rs); | ||
281 | } | ||
241 | } | 282 | } |
242 | 283 | ||
243 | 284 | ||
@@ -260,94 +301,30 @@ postgres_plugin_get (void *cls, | |||
260 | void *iter_cls) | 301 | void *iter_cls) |
261 | { | 302 | { |
262 | struct Plugin *plugin = cls; | 303 | struct Plugin *plugin = cls; |
263 | uint32_t btype = htonl (type); | 304 | uint32_t type32 = (uint32_t) type; |
264 | 305 | struct GNUNET_PQ_QueryParam paramk[] = { | |
265 | const char *paramValues[] = { | 306 | GNUNET_PQ_query_param_auto_from_type (key), |
266 | (const char *) key, | 307 | GNUNET_PQ_query_param_end |
267 | (const char *) &btype | ||
268 | }; | 308 | }; |
269 | int paramLengths[] = { | 309 | struct GNUNET_PQ_QueryParam paramkt[] = { |
270 | sizeof (struct GNUNET_HashCode), | 310 | GNUNET_PQ_query_param_auto_from_type (key), |
271 | sizeof (btype) | 311 | GNUNET_PQ_query_param_uint32 (&type32), |
312 | GNUNET_PQ_query_param_end | ||
272 | }; | 313 | }; |
273 | const int paramFormats[] = { 1, 1 }; | 314 | enum GNUNET_DB_QueryStatus res; |
274 | struct GNUNET_TIME_Absolute expiration_time; | 315 | struct HandleResultContext hr_ctx; |
275 | uint32_t size; | 316 | |
276 | unsigned int cnt; | 317 | hr_ctx.iter = iter; |
277 | unsigned int i; | 318 | hr_ctx.iter_cls = iter_cls; |
278 | unsigned int path_len; | 319 | hr_ctx.key = key; |
279 | const struct GNUNET_PeerIdentity *path; | 320 | res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh, |
280 | PGresult *res; | 321 | (0 == type) ? "getk" : "getkt", |
281 | 322 | (0 == type) ? paramk : paramkt, | |
282 | res = | 323 | &handle_results, |
283 | PQexecPrepared (plugin->dbh, (type == 0) ? "getk" : "getkt", | 324 | &hr_ctx); |
284 | (type == 0) ? 1 : 2, paramValues, paramLengths, | 325 | if (res < 0) |
285 | paramFormats, 1); | ||
286 | if (GNUNET_OK != | ||
287 | GNUNET_POSTGRES_check_result (plugin->dbh, | ||
288 | res, | ||
289 | PGRES_TUPLES_OK, | ||
290 | "PQexecPrepared", | ||
291 | (type == 0) ? "getk" : "getkt")) | ||
292 | { | ||
293 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
294 | "Ending iteration (postgres error)\n"); | ||
295 | return 0; | 326 | return 0; |
296 | } | 327 | return res; |
297 | |||
298 | if (0 == (cnt = PQntuples (res))) | ||
299 | { | ||
300 | /* no result */ | ||
301 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
302 | "Ending iteration (no more results)\n"); | ||
303 | PQclear (res); | ||
304 | return 0; | ||
305 | } | ||
306 | if (iter == NULL) | ||
307 | { | ||
308 | PQclear (res); | ||
309 | return cnt; | ||
310 | } | ||
311 | if ( (4 != PQnfields (res)) || | ||
312 | (sizeof (uint64_t) != PQfsize (res, 0)) || | ||
313 | (sizeof (uint32_t) != PQfsize (res, 1))) | ||
314 | { | ||
315 | GNUNET_break (0); | ||
316 | PQclear (res); | ||
317 | return 0; | ||
318 | } | ||
319 | for (i = 0; i < cnt; i++) | ||
320 | { | ||
321 | expiration_time.abs_value_us = | ||
322 | GNUNET_ntohll (*(uint64_t *) PQgetvalue (res, i, 0)); | ||
323 | type = ntohl (*(uint32_t *) PQgetvalue (res, i, 1)); | ||
324 | size = PQgetlength (res, i, 2); | ||
325 | path_len = PQgetlength (res, i, 3); | ||
326 | if (0 != (path_len % sizeof (struct GNUNET_PeerIdentity))) | ||
327 | { | ||
328 | GNUNET_break (0); | ||
329 | path_len = 0; | ||
330 | } | ||
331 | path_len %= sizeof (struct GNUNET_PeerIdentity); | ||
332 | path = (const struct GNUNET_PeerIdentity *) PQgetvalue (res, i, 3); | ||
333 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
334 | "Found result of size %u bytes and type %u in database\n", | ||
335 | (unsigned int) size, (unsigned int) type); | ||
336 | if (GNUNET_SYSERR == | ||
337 | iter (iter_cls, key, size, PQgetvalue (res, i, 2), | ||
338 | (enum GNUNET_BLOCK_Type) type, | ||
339 | expiration_time, | ||
340 | path_len, | ||
341 | path)) | ||
342 | { | ||
343 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
344 | "Ending iteration (client error)\n"); | ||
345 | PQclear (res); | ||
346 | return cnt; | ||
347 | } | ||
348 | } | ||
349 | PQclear (res); | ||
350 | return cnt; | ||
351 | } | 328 | } |
352 | 329 | ||
353 | 330 | ||
@@ -362,54 +339,53 @@ static int | |||
362 | postgres_plugin_del (void *cls) | 339 | postgres_plugin_del (void *cls) |
363 | { | 340 | { |
364 | struct Plugin *plugin = cls; | 341 | struct Plugin *plugin = cls; |
342 | struct GNUNET_PQ_QueryParam pempty[] = { | ||
343 | GNUNET_PQ_query_param_end | ||
344 | }; | ||
365 | uint32_t size; | 345 | uint32_t size; |
366 | uint32_t oid; | 346 | uint32_t oid; |
367 | struct GNUNET_HashCode key; | 347 | struct GNUNET_HashCode key; |
368 | PGresult *res; | 348 | struct GNUNET_PQ_ResultSpec rs[] = { |
349 | GNUNET_PQ_result_spec_uint32 ("len", | ||
350 | &size), | ||
351 | GNUNET_PQ_result_spec_uint32 ("oid", | ||
352 | &oid), | ||
353 | GNUNET_PQ_result_spec_auto_from_type ("key", | ||
354 | &key), | ||
355 | GNUNET_PQ_result_spec_end | ||
356 | }; | ||
357 | enum GNUNET_DB_QueryStatus res; | ||
358 | struct GNUNET_PQ_QueryParam dparam[] = { | ||
359 | GNUNET_PQ_query_param_uint32 (&oid), | ||
360 | GNUNET_PQ_query_param_end | ||
361 | }; | ||
369 | 362 | ||
370 | res = PQexecPrepared (plugin->dbh, | 363 | res = GNUNET_PQ_eval_prepared_singleton_select (plugin->dbh, |
371 | "getm", | 364 | "getm", |
372 | 0, NULL, NULL, NULL, 1); | 365 | pempty, |
373 | if (GNUNET_OK != | 366 | rs); |
374 | GNUNET_POSTGRES_check_result (plugin->dbh, | 367 | if (0 > res) |
375 | res, | 368 | return GNUNET_SYSERR; |
376 | PGRES_TUPLES_OK, | 369 | if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == res) |
377 | "PQexecPrepared", | ||
378 | "getm")) | ||
379 | { | ||
380 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
381 | "Ending iteration (postgres error)\n"); | ||
382 | return 0; | ||
383 | } | ||
384 | if (0 == PQntuples (res)) | ||
385 | { | 370 | { |
386 | /* no result */ | 371 | /* no result */ |
387 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 372 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
388 | "Ending iteration (no more results)\n"); | 373 | "Ending iteration (no more results)\n"); |
389 | PQclear (res); | ||
390 | return GNUNET_SYSERR; | ||
391 | } | ||
392 | if ((3 != PQnfields (res)) || (sizeof (size) != PQfsize (res, 0)) || | ||
393 | (sizeof (oid) != PQfsize (res, 1)) || | ||
394 | (sizeof (struct GNUNET_HashCode) != PQgetlength (res, 0, 2))) | ||
395 | { | ||
396 | GNUNET_break (0); | ||
397 | PQclear (res); | ||
398 | return 0; | 374 | return 0; |
399 | } | 375 | } |
400 | size = ntohl (*(uint32_t *) PQgetvalue (res, 0, 0)); | 376 | res = GNUNET_PQ_eval_prepared_non_select (plugin->dbh, |
401 | oid = ntohl (*(uint32_t *) PQgetvalue (res, 0, 1)); | 377 | "delrow", |
402 | GNUNET_memcpy (&key, PQgetvalue (res, 0, 2), sizeof (struct GNUNET_HashCode)); | 378 | dparam); |
403 | PQclear (res); | 379 | if (0 > res) |
404 | if (GNUNET_OK != | 380 | { |
405 | GNUNET_POSTGRES_delete_by_rowid (plugin->dbh, | 381 | GNUNET_PQ_cleanup_result (rs); |
406 | "delrow", | ||
407 | oid)) | ||
408 | return GNUNET_SYSERR; | 382 | return GNUNET_SYSERR; |
383 | } | ||
409 | plugin->num_items--; | 384 | plugin->num_items--; |
410 | plugin->env->delete_notify (plugin->env->cls, | 385 | plugin->env->delete_notify (plugin->env->cls, |
411 | &key, | 386 | &key, |
412 | size + OVERHEAD); | 387 | size + OVERHEAD); |
388 | GNUNET_PQ_cleanup_result (rs); | ||
413 | return GNUNET_OK; | 389 | return GNUNET_OK; |
414 | } | 390 | } |
415 | 391 | ||
@@ -428,22 +404,34 @@ postgres_plugin_get_random (void *cls, | |||
428 | void *iter_cls) | 404 | void *iter_cls) |
429 | { | 405 | { |
430 | struct Plugin *plugin = cls; | 406 | struct Plugin *plugin = cls; |
431 | unsigned int off; | 407 | uint32_t off; |
432 | uint32_t off_be; | ||
433 | struct GNUNET_TIME_Absolute expiration_time; | 408 | struct GNUNET_TIME_Absolute expiration_time; |
434 | uint32_t size; | 409 | size_t data_size; |
435 | unsigned int path_len; | 410 | void *data; |
436 | const struct GNUNET_PeerIdentity *path; | 411 | size_t path_len; |
437 | const struct GNUNET_HashCode *key; | 412 | struct GNUNET_PeerIdentity *path; |
438 | unsigned int type; | 413 | struct GNUNET_HashCode key; |
439 | PGresult *res; | 414 | uint32_t type; |
440 | const char *paramValues[] = { | 415 | enum GNUNET_DB_QueryStatus res; |
441 | (const char *) &off_be | 416 | struct GNUNET_PQ_QueryParam params[] = { |
417 | GNUNET_PQ_query_param_uint32 (&off), | ||
418 | GNUNET_PQ_query_param_end | ||
442 | }; | 419 | }; |
443 | int paramLengths[] = { | 420 | struct GNUNET_PQ_ResultSpec rs[] = { |
444 | sizeof (off_be) | 421 | GNUNET_PQ_result_spec_absolute_time ("discard_time", |
422 | &expiration_time), | ||
423 | GNUNET_PQ_result_spec_uint32 ("type", | ||
424 | &type), | ||
425 | GNUNET_PQ_result_spec_variable_size ("value", | ||
426 | &data, | ||
427 | &data_size), | ||
428 | GNUNET_PQ_result_spec_variable_size ("path", | ||
429 | (void **) &path, | ||
430 | &path_len), | ||
431 | GNUNET_PQ_result_spec_auto_from_type ("key", | ||
432 | &key), | ||
433 | GNUNET_PQ_result_spec_end | ||
445 | }; | 434 | }; |
446 | const int paramFormats[] = { 1 }; | ||
447 | 435 | ||
448 | if (0 == plugin->num_items) | 436 | if (0 == plugin->num_items) |
449 | return 0; | 437 | return 0; |
@@ -451,67 +439,136 @@ postgres_plugin_get_random (void *cls, | |||
451 | return 1; | 439 | return 1; |
452 | off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, | 440 | off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, |
453 | plugin->num_items); | 441 | plugin->num_items); |
454 | off_be = htonl (off); | 442 | res = GNUNET_PQ_eval_prepared_singleton_select (plugin->dbh, |
455 | res = | 443 | "get_random", |
456 | PQexecPrepared (plugin->dbh, "get_random", | 444 | params, |
457 | 1, paramValues, paramLengths, paramFormats, | 445 | rs); |
458 | 1); | 446 | if (0 > res) |
459 | if (GNUNET_OK != | ||
460 | GNUNET_POSTGRES_check_result (plugin->dbh, | ||
461 | res, | ||
462 | PGRES_TUPLES_OK, | ||
463 | "PQexecPrepared", | ||
464 | "get_random")) | ||
465 | { | 447 | { |
466 | GNUNET_break (0); | 448 | GNUNET_break (0); |
467 | return 0; | 449 | return 0; |
468 | } | 450 | } |
469 | if (0 == PQntuples (res)) | 451 | if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == res) |
470 | { | 452 | { |
471 | GNUNET_break (0); | 453 | GNUNET_break (0); |
472 | return 0; | 454 | return 0; |
473 | } | 455 | } |
474 | if ( (5 != PQnfields (res)) || | ||
475 | (sizeof (uint64_t) != PQfsize (res, 0)) || | ||
476 | (sizeof (uint32_t) != PQfsize (res, 1)) || | ||
477 | (sizeof (struct GNUNET_HashCode) != PQfsize (res, 4)) ) | ||
478 | { | ||
479 | GNUNET_break (0); | ||
480 | PQclear (res); | ||
481 | return 0; | ||
482 | } | ||
483 | expiration_time.abs_value_us = | ||
484 | GNUNET_ntohll (*(uint64_t *) PQgetvalue (res, 0, 0)); | ||
485 | type = ntohl (*(uint32_t *) PQgetvalue (res, 0, 1)); | ||
486 | size = PQgetlength (res, 0, 2); | ||
487 | path_len = PQgetlength (res, 0, 3); | ||
488 | if (0 != (path_len % sizeof (struct GNUNET_PeerIdentity))) | 456 | if (0 != (path_len % sizeof (struct GNUNET_PeerIdentity))) |
489 | { | 457 | { |
490 | GNUNET_break (0); | 458 | GNUNET_break (0); |
491 | path_len = 0; | 459 | path_len = 0; |
492 | } | 460 | } |
493 | path_len %= sizeof (struct GNUNET_PeerIdentity); | 461 | path_len %= sizeof (struct GNUNET_PeerIdentity); |
494 | path = (const struct GNUNET_PeerIdentity *) PQgetvalue (res, 0, 3); | ||
495 | key = (const struct GNUNET_HashCode *) PQgetvalue (res, 0, 4); | ||
496 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 462 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
497 | "Found random value with key %s of size %u bytes and type %u in database\n", | 463 | "Found random value with key %s of size %u bytes and type %u in database\n", |
498 | GNUNET_h2s (key), | 464 | GNUNET_h2s (&key), |
499 | (unsigned int) size, | 465 | (unsigned int) data_size, |
500 | (unsigned int) type); | 466 | (unsigned int) type); |
501 | (void) iter (iter_cls, | 467 | (void) iter (iter_cls, |
502 | key, | 468 | &key, |
503 | size, | 469 | data_size, |
504 | PQgetvalue (res, 0, 2), | 470 | data, |
505 | (enum GNUNET_BLOCK_Type) type, | 471 | (enum GNUNET_BLOCK_Type) type, |
506 | expiration_time, | 472 | expiration_time, |
507 | path_len, | 473 | path_len, |
508 | path); | 474 | path); |
509 | PQclear (res); | 475 | GNUNET_PQ_cleanup_result (rs); |
510 | return 1; | 476 | return 1; |
511 | } | 477 | } |
512 | 478 | ||
513 | 479 | ||
514 | /** | 480 | /** |
481 | * Closure for #extract_result_cb. | ||
482 | */ | ||
483 | struct ExtractResultContext | ||
484 | { | ||
485 | /** | ||
486 | * Function to call for each result found. | ||
487 | */ | ||
488 | GNUNET_DATACACHE_Iterator iter; | ||
489 | |||
490 | /** | ||
491 | * Closure for @e iter. | ||
492 | */ | ||
493 | void *iter_cls; | ||
494 | |||
495 | }; | ||
496 | |||
497 | |||
498 | /** | ||
499 | * Function to be called with the results of a SELECT statement | ||
500 | * that has returned @a num_results results. Calls the `iter` | ||
501 | * from @a cls for each result. | ||
502 | * | ||
503 | * @param cls closure with the `struct ExtractResultContext` | ||
504 | * @param result the postgres result | ||
505 | * @param num_result the number of results in @a result | ||
506 | */ | ||
507 | static void | ||
508 | extract_result_cb (void *cls, | ||
509 | PGresult *result, | ||
510 | unsigned int num_results) | ||
511 | { | ||
512 | struct ExtractResultContext *erc = cls; | ||
513 | |||
514 | if (NULL == erc->iter) | ||
515 | return; | ||
516 | for (unsigned int i=0;i<num_results;i++) | ||
517 | { | ||
518 | struct GNUNET_TIME_Absolute expiration_time; | ||
519 | uint32_t type; | ||
520 | void *data; | ||
521 | size_t data_size; | ||
522 | struct GNUNET_PeerIdentity *path; | ||
523 | size_t path_len; | ||
524 | struct GNUNET_HashCode key; | ||
525 | struct GNUNET_PQ_ResultSpec rs[] = { | ||
526 | GNUNET_PQ_result_spec_absolute_time ("", | ||
527 | &expiration_time), | ||
528 | GNUNET_PQ_result_spec_uint32 ("type", | ||
529 | &type), | ||
530 | GNUNET_PQ_result_spec_variable_size ("value", | ||
531 | &data, | ||
532 | &data_size), | ||
533 | GNUNET_PQ_result_spec_variable_size ("path", | ||
534 | (void **) &path, | ||
535 | &path_len), | ||
536 | GNUNET_PQ_result_spec_auto_from_type ("key", | ||
537 | &key), | ||
538 | GNUNET_PQ_result_spec_end | ||
539 | }; | ||
540 | |||
541 | if (0 != (path_len % sizeof (struct GNUNET_PeerIdentity))) | ||
542 | { | ||
543 | GNUNET_break (0); | ||
544 | path_len = 0; | ||
545 | } | ||
546 | path_len %= sizeof (struct GNUNET_PeerIdentity); | ||
547 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
548 | "Found result of size %u bytes and type %u in database\n", | ||
549 | (unsigned int) data_size, | ||
550 | (unsigned int) type); | ||
551 | if (GNUNET_SYSERR == | ||
552 | erc->iter (erc->iter_cls, | ||
553 | &key, | ||
554 | data_size, | ||
555 | data, | ||
556 | (enum GNUNET_BLOCK_Type) type, | ||
557 | expiration_time, | ||
558 | path_len, | ||
559 | path)) | ||
560 | { | ||
561 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
562 | "Ending iteration (client error)\n"); | ||
563 | GNUNET_PQ_cleanup_result (rs); | ||
564 | break; | ||
565 | } | ||
566 | GNUNET_PQ_cleanup_result (rs); | ||
567 | } | ||
568 | } | ||
569 | |||
570 | |||
571 | /** | ||
515 | * Iterate over the results that are "close" to a particular key in | 572 | * Iterate over the results that are "close" to a particular key in |
516 | * the datacache. "close" is defined as numerically larger than @a | 573 | * the datacache. "close" is defined as numerically larger than @a |
517 | * key (when interpreted as a circular address space), with small | 574 | * key (when interpreted as a circular address space), with small |
@@ -532,105 +589,36 @@ postgres_plugin_get_closest (void *cls, | |||
532 | void *iter_cls) | 589 | void *iter_cls) |
533 | { | 590 | { |
534 | struct Plugin *plugin = cls; | 591 | struct Plugin *plugin = cls; |
535 | uint32_t nbo_limit = htonl (num_results); | 592 | uint32_t num_results32 = (uint32_t) num_results; |
536 | const char *paramValues[] = { | 593 | struct GNUNET_PQ_QueryParam params[] = { |
537 | (const char *) key, | 594 | GNUNET_PQ_query_param_auto_from_type (key), |
538 | (const char *) &nbo_limit, | 595 | GNUNET_PQ_query_param_uint32 (&num_results32), |
596 | GNUNET_PQ_query_param_end | ||
539 | }; | 597 | }; |
540 | int paramLengths[] = { | 598 | enum GNUNET_DB_QueryStatus res; |
541 | sizeof (struct GNUNET_HashCode), | 599 | struct ExtractResultContext erc; |
542 | sizeof (nbo_limit) | 600 | |
543 | 601 | erc.iter = iter; | |
544 | }; | 602 | erc.iter_cls = iter_cls; |
545 | const int paramFormats[] = { 1, 1 }; | 603 | res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh, |
546 | struct GNUNET_TIME_Absolute expiration_time; | 604 | "get_closest", |
547 | uint32_t size; | 605 | params, |
548 | unsigned int type; | 606 | &extract_result_cb, |
549 | unsigned int cnt; | 607 | &erc); |
550 | unsigned int i; | 608 | if (0 > res) |
551 | unsigned int path_len; | ||
552 | const struct GNUNET_PeerIdentity *path; | ||
553 | PGresult *res; | ||
554 | |||
555 | res = | ||
556 | PQexecPrepared (plugin->dbh, | ||
557 | "get_closest", | ||
558 | 2, | ||
559 | paramValues, | ||
560 | paramLengths, | ||
561 | paramFormats, | ||
562 | 1); | ||
563 | if (GNUNET_OK != | ||
564 | GNUNET_POSTGRES_check_result (plugin->dbh, | ||
565 | res, | ||
566 | PGRES_TUPLES_OK, | ||
567 | "PQexecPrepared", | ||
568 | "get_closest")) | ||
569 | { | 609 | { |
570 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 610 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
571 | "Ending iteration (postgres error)\n"); | 611 | "Ending iteration (postgres error)\n"); |
572 | return 0; | 612 | return 0; |
573 | } | 613 | } |
574 | 614 | if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == res) | |
575 | if (0 == (cnt = PQntuples (res))) | ||
576 | { | 615 | { |
577 | /* no result */ | 616 | /* no result */ |
578 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 617 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
579 | "Ending iteration (no more results)\n"); | 618 | "Ending iteration (no more results)\n"); |
580 | PQclear (res); | ||
581 | return 0; | 619 | return 0; |
582 | } | 620 | } |
583 | if (NULL == iter) | 621 | return res; |
584 | { | ||
585 | PQclear (res); | ||
586 | return cnt; | ||
587 | } | ||
588 | if ( (5 != PQnfields (res)) || | ||
589 | (sizeof (uint64_t) != PQfsize (res, 0)) || | ||
590 | (sizeof (uint32_t) != PQfsize (res, 1)) || | ||
591 | (sizeof (struct GNUNET_HashCode) != PQfsize (res, 4)) ) | ||
592 | { | ||
593 | GNUNET_break (0); | ||
594 | PQclear (res); | ||
595 | return 0; | ||
596 | } | ||
597 | for (i = 0; i < cnt; i++) | ||
598 | { | ||
599 | expiration_time.abs_value_us = | ||
600 | GNUNET_ntohll (*(uint64_t *) PQgetvalue (res, i, 0)); | ||
601 | type = ntohl (*(uint32_t *) PQgetvalue (res, i, 1)); | ||
602 | size = PQgetlength (res, i, 2); | ||
603 | path_len = PQgetlength (res, i, 3); | ||
604 | if (0 != (path_len % sizeof (struct GNUNET_PeerIdentity))) | ||
605 | { | ||
606 | GNUNET_break (0); | ||
607 | path_len = 0; | ||
608 | } | ||
609 | path_len %= sizeof (struct GNUNET_PeerIdentity); | ||
610 | path = (const struct GNUNET_PeerIdentity *) PQgetvalue (res, i, 3); | ||
611 | key = (const struct GNUNET_HashCode *) PQgetvalue (res, i, 4); | ||
612 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
613 | "Found result of size %u bytes and type %u in database\n", | ||
614 | (unsigned int) size, | ||
615 | (unsigned int) type); | ||
616 | if (GNUNET_SYSERR == | ||
617 | iter (iter_cls, | ||
618 | key, | ||
619 | size, | ||
620 | PQgetvalue (res, i, 2), | ||
621 | (enum GNUNET_BLOCK_Type) type, | ||
622 | expiration_time, | ||
623 | path_len, | ||
624 | path)) | ||
625 | { | ||
626 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
627 | "Ending iteration (client error)\n"); | ||
628 | PQclear (res); | ||
629 | return cnt; | ||
630 | } | ||
631 | } | ||
632 | PQclear (res); | ||
633 | return cnt; | ||
634 | } | 622 | } |
635 | 623 | ||
636 | 624 | ||
diff --git a/src/datastore/Makefile.am b/src/datastore/Makefile.am index 9b8cf365f..240abbc67 100644 --- a/src/datastore/Makefile.am +++ b/src/datastore/Makefile.am | |||
@@ -148,7 +148,6 @@ libgnunet_plugin_datastore_postgres_la_SOURCES = \ | |||
148 | plugin_datastore_postgres.c | 148 | plugin_datastore_postgres.c |
149 | libgnunet_plugin_datastore_postgres_la_LIBADD = \ | 149 | libgnunet_plugin_datastore_postgres_la_LIBADD = \ |
150 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | 150 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ |
151 | $(top_builddir)/src/postgres/libgnunetpostgres.la \ | ||
152 | $(top_builddir)/src/pq/libgnunetpq.la \ | 151 | $(top_builddir)/src/pq/libgnunetpq.la \ |
153 | $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lpq | 152 | $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lpq |
154 | libgnunet_plugin_datastore_postgres_la_LDFLAGS = \ | 153 | libgnunet_plugin_datastore_postgres_la_LDFLAGS = \ |
diff --git a/src/datastore/plugin_datastore_postgres.c b/src/datastore/plugin_datastore_postgres.c index b6aeb0be6..fd1a533bb 100644 --- a/src/datastore/plugin_datastore_postgres.c +++ b/src/datastore/plugin_datastore_postgres.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet | 2 | This file is part of GNUnet |
3 | Copyright (C) 2009-2016 GNUnet e.V. | 3 | Copyright (C) 2009-2017 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
@@ -23,10 +23,8 @@ | |||
23 | * @brief postgres-based datastore backend | 23 | * @brief postgres-based datastore backend |
24 | * @author Christian Grothoff | 24 | * @author Christian Grothoff |
25 | */ | 25 | */ |
26 | |||
27 | #include "platform.h" | 26 | #include "platform.h" |
28 | #include "gnunet_datastore_plugin.h" | 27 | #include "gnunet_datastore_plugin.h" |
29 | #include "gnunet_postgres_lib.h" | ||
30 | #include "gnunet_pq_lib.h" | 28 | #include "gnunet_pq_lib.h" |
31 | 29 | ||
32 | 30 | ||
@@ -70,160 +68,106 @@ struct Plugin | |||
70 | static int | 68 | static int |
71 | init_connection (struct Plugin *plugin) | 69 | init_connection (struct Plugin *plugin) |
72 | { | 70 | { |
73 | PGresult *ret; | 71 | struct GNUNET_PQ_ExecuteStatement es[] = { |
72 | /* FIXME: PostgreSQL does not have unsigned integers! This is ok for the type column because | ||
73 | * we only test equality on it and can cast it to/from uint32_t. For repl, prio, and anonLevel | ||
74 | * we do math or inequality tests, so we can't handle the entire range of uint32_t. | ||
75 | * This will also cause problems for expiration times after 294247-01-10-04:00:54 UTC. | ||
76 | * PostgreSQL also recommends against using WITH OIDS. | ||
77 | */ | ||
78 | GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS gn090 (" | ||
79 | " repl INTEGER NOT NULL DEFAULT 0," | ||
80 | " type INTEGER NOT NULL DEFAULT 0," | ||
81 | " prio INTEGER NOT NULL DEFAULT 0," | ||
82 | " anonLevel INTEGER NOT NULL DEFAULT 0," | ||
83 | " expire BIGINT NOT NULL DEFAULT 0," | ||
84 | " rvalue BIGINT NOT NULL DEFAULT 0," | ||
85 | " hash BYTEA NOT NULL DEFAULT ''," | ||
86 | " vhash BYTEA NOT NULL DEFAULT ''," | ||
87 | " value BYTEA NOT NULL DEFAULT '')" | ||
88 | "WITH OIDS"), | ||
89 | GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS idx_hash ON gn090 (hash)"), | ||
90 | GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS idx_prio ON gn090 (prio)"), | ||
91 | GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS idx_expire ON gn090 (expire)"), | ||
92 | GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS idx_prio_anon ON gn090 (prio,anonLevel)"), | ||
93 | GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS idx_prio_hash_anon ON gn090 (prio,hash,anonLevel)"), | ||
94 | GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS idx_repl_rvalue ON gn090 (repl,rvalue)"), | ||
95 | GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS idx_expire_hash ON gn090 (expire,hash)"), | ||
96 | GNUNET_PQ_make_execute ("ALTER TABLE gn090 ALTER value SET STORAGE EXTERNAL"), | ||
97 | GNUNET_PQ_make_execute ("ALTER TABLE gn090 ALTER hash SET STORAGE PLAIN"), | ||
98 | GNUNET_PQ_make_execute ("ALTER TABLE gn090 ALTER vhash SET STORAGE PLAIN"), | ||
99 | GNUNET_PQ_EXECUTE_STATEMENT_END | ||
100 | }; | ||
101 | #define RESULT_COLUMNS "repl, type, prio, anonLevel, expire, hash, value, oid" | ||
102 | struct GNUNET_PQ_PreparedStatement ps[] = { | ||
103 | GNUNET_PQ_make_prepare ("get", | ||
104 | "SELECT " RESULT_COLUMNS " FROM gn090 " | ||
105 | "WHERE oid >= $1::bigint AND " | ||
106 | "(rvalue >= $2 OR 0 = $3::smallint) AND " | ||
107 | "(hash = $4 OR 0 = $5::smallint) AND " | ||
108 | "(type = $6 OR 0 = $7::smallint) " | ||
109 | "ORDER BY oid ASC LIMIT 1", | ||
110 | 7), | ||
111 | GNUNET_PQ_make_prepare ("put", | ||
112 | "INSERT INTO gn090 (repl, type, prio, anonLevel, expire, rvalue, hash, vhash, value) " | ||
113 | "VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", | ||
114 | 9), | ||
115 | GNUNET_PQ_make_prepare ("update", | ||
116 | "UPDATE gn090 " | ||
117 | "SET prio = prio + $1, " | ||
118 | "repl = repl + $2, " | ||
119 | "expire = GREATEST(expire, $3) " | ||
120 | "WHERE hash = $4 AND vhash = $5", | ||
121 | 5), | ||
122 | GNUNET_PQ_make_prepare ("decrepl", | ||
123 | "UPDATE gn090 SET repl = GREATEST (repl - 1, 0) " | ||
124 | "WHERE oid = $1", | ||
125 | 1), | ||
126 | GNUNET_PQ_make_prepare ("select_non_anonymous", | ||
127 | "SELECT " RESULT_COLUMNS " FROM gn090 " | ||
128 | "WHERE anonLevel = 0 AND type = $1 AND oid >= $2::bigint " | ||
129 | "ORDER BY oid ASC LIMIT 1", | ||
130 | 2), | ||
131 | GNUNET_PQ_make_prepare ("select_expiration_order", | ||
132 | "(SELECT " RESULT_COLUMNS " FROM gn090 " | ||
133 | "WHERE expire < $1 ORDER BY prio ASC LIMIT 1) " | ||
134 | "UNION " | ||
135 | "(SELECT " RESULT_COLUMNS " FROM gn090 " | ||
136 | "ORDER BY prio ASC LIMIT 1) " | ||
137 | "ORDER BY expire ASC LIMIT 1", | ||
138 | 1), | ||
139 | GNUNET_PQ_make_prepare ("select_replication_order", | ||
140 | "SELECT " RESULT_COLUMNS " FROM gn090 " | ||
141 | "ORDER BY repl DESC,RANDOM() LIMIT 1", | ||
142 | 0), | ||
143 | GNUNET_PQ_make_prepare ("delrow", | ||
144 | "DELETE FROM gn090 " "WHERE oid=$1", | ||
145 | 1), | ||
146 | GNUNET_PQ_make_prepare ("remove", "DELETE FROM gn090 " | ||
147 | "WHERE hash = $1 AND " | ||
148 | "value = $2", | ||
149 | 2), | ||
150 | GNUNET_PQ_make_prepare ("get_keys", | ||
151 | "SELECT hash FROM gn090", | ||
152 | 0), | ||
153 | GNUNET_PQ_make_prepare ("estimate_size", | ||
154 | "SELECT SUM(LENGTH(value))+256*COUNT(*) AS total FROM gn090", | ||
155 | 0), | ||
156 | GNUNET_PQ_PREPARED_STATEMENT_END | ||
157 | }; | ||
158 | #undef RESULT_COLUMNS | ||
74 | 159 | ||
75 | plugin->dbh = GNUNET_POSTGRES_connect (plugin->env->cfg, "datastore-postgres"); | 160 | plugin->dbh = GNUNET_PQ_connect_with_cfg (plugin->env->cfg, |
161 | "datastore-postgres"); | ||
76 | if (NULL == plugin->dbh) | 162 | if (NULL == plugin->dbh) |
77 | return GNUNET_SYSERR; | 163 | return GNUNET_SYSERR; |
78 | 164 | ||
79 | /* FIXME: PostgreSQL does not have unsigned integers! This is ok for the type column because | 165 | if ( (GNUNET_OK != |
80 | * we only test equality on it and can cast it to/from uint32_t. For repl, prio, and anonLevel | 166 | GNUNET_PQ_exec_statements (plugin->dbh, |
81 | * we do math or inequality tests, so we can't handle the entire range of uint32_t. | 167 | es)) || |
82 | * This will also cause problems for expiration times after 294247-01-10-04:00:54 UTC. | 168 | (GNUNET_OK != |
83 | * PostgreSQL also recommends against using WITH OIDS. | 169 | GNUNET_PQ_prepare_statements (plugin->dbh, |
84 | */ | 170 | ps)) ) |
85 | ret = | ||
86 | PQexec (plugin->dbh, | ||
87 | "CREATE TABLE IF NOT EXISTS gn090 (" | ||
88 | " repl INTEGER NOT NULL DEFAULT 0," | ||
89 | " type INTEGER NOT NULL DEFAULT 0," | ||
90 | " prio INTEGER NOT NULL DEFAULT 0," | ||
91 | " anonLevel INTEGER NOT NULL DEFAULT 0," | ||
92 | " expire BIGINT NOT NULL DEFAULT 0," | ||
93 | " rvalue BIGINT NOT NULL DEFAULT 0," | ||
94 | " hash BYTEA NOT NULL DEFAULT ''," | ||
95 | " vhash BYTEA NOT NULL DEFAULT ''," | ||
96 | " value BYTEA NOT NULL DEFAULT '')" | ||
97 | "WITH OIDS"); | ||
98 | if ( (NULL == ret) || | ||
99 | ((PQresultStatus (ret) != PGRES_COMMAND_OK) && | ||
100 | (0 != strcmp ("42P07", /* duplicate table */ | ||
101 | PQresultErrorField | ||
102 | (ret, | ||
103 | PG_DIAG_SQLSTATE))))) | ||
104 | { | ||
105 | (void) GNUNET_POSTGRES_check_result (plugin->dbh, | ||
106 | ret, | ||
107 | PGRES_COMMAND_OK, | ||
108 | "CREATE TABLE", | ||
109 | "gn090"); | ||
110 | PQfinish (plugin->dbh); | ||
111 | plugin->dbh = NULL; | ||
112 | return GNUNET_SYSERR; | ||
113 | } | ||
114 | |||
115 | if (PQresultStatus (ret) == PGRES_COMMAND_OK) | ||
116 | { | ||
117 | if ((GNUNET_OK != | ||
118 | GNUNET_POSTGRES_exec (plugin->dbh, | ||
119 | "CREATE INDEX IF NOT EXISTS idx_hash ON gn090 (hash)")) || | ||
120 | (GNUNET_OK != | ||
121 | GNUNET_POSTGRES_exec (plugin->dbh, | ||
122 | "CREATE INDEX IF NOT EXISTS idx_prio ON gn090 (prio)")) || | ||
123 | (GNUNET_OK != | ||
124 | GNUNET_POSTGRES_exec (plugin->dbh, | ||
125 | "CREATE INDEX IF NOT EXISTS idx_expire ON gn090 (expire)")) || | ||
126 | (GNUNET_OK != | ||
127 | GNUNET_POSTGRES_exec (plugin->dbh, | ||
128 | "CREATE INDEX IF NOT EXISTS idx_prio_anon ON gn090 (prio,anonLevel)")) || | ||
129 | (GNUNET_OK != | ||
130 | GNUNET_POSTGRES_exec (plugin->dbh, | ||
131 | "CREATE INDEX IF NOT EXISTS idx_prio_hash_anon ON gn090 (prio,hash,anonLevel)")) || | ||
132 | (GNUNET_OK != | ||
133 | GNUNET_POSTGRES_exec (plugin->dbh, | ||
134 | "CREATE INDEX IF NOT EXISTS idx_repl_rvalue ON gn090 (repl,rvalue)")) || | ||
135 | (GNUNET_OK != | ||
136 | GNUNET_POSTGRES_exec (plugin->dbh, | ||
137 | "CREATE INDEX IF NOT EXISTS idx_expire_hash ON gn090 (expire,hash)"))) | ||
138 | { | ||
139 | PQclear (ret); | ||
140 | PQfinish (plugin->dbh); | ||
141 | plugin->dbh = NULL; | ||
142 | return GNUNET_SYSERR; | ||
143 | } | ||
144 | } | ||
145 | PQclear (ret); | ||
146 | |||
147 | ret = | ||
148 | PQexec (plugin->dbh, | ||
149 | "ALTER TABLE gn090 ALTER value SET STORAGE EXTERNAL"); | ||
150 | if (GNUNET_OK != | ||
151 | GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_COMMAND_OK, "ALTER TABLE", "gn090")) | ||
152 | { | ||
153 | PQfinish (plugin->dbh); | ||
154 | plugin->dbh = NULL; | ||
155 | return GNUNET_SYSERR; | ||
156 | } | ||
157 | PQclear (ret); | ||
158 | ret = PQexec (plugin->dbh, "ALTER TABLE gn090 ALTER hash SET STORAGE PLAIN"); | ||
159 | if (GNUNET_OK != | ||
160 | GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_COMMAND_OK, "ALTER TABLE", "gn090")) | ||
161 | { | ||
162 | PQfinish (plugin->dbh); | ||
163 | plugin->dbh = NULL; | ||
164 | return GNUNET_SYSERR; | ||
165 | } | ||
166 | PQclear (ret); | ||
167 | ret = PQexec (plugin->dbh, "ALTER TABLE gn090 ALTER vhash SET STORAGE PLAIN"); | ||
168 | if (GNUNET_OK != | ||
169 | GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_COMMAND_OK, "ALTER TABLE", "gn090")) | ||
170 | { | ||
171 | PQfinish (plugin->dbh); | ||
172 | plugin->dbh = NULL; | ||
173 | return GNUNET_SYSERR; | ||
174 | } | ||
175 | PQclear (ret); | ||
176 | #define RESULT_COLUMNS "repl, type, prio, anonLevel, expire, hash, value, oid" | ||
177 | if ((GNUNET_OK != | ||
178 | GNUNET_POSTGRES_prepare (plugin->dbh, "get", | ||
179 | "SELECT " RESULT_COLUMNS " FROM gn090 " | ||
180 | "WHERE oid >= $1::bigint AND " | ||
181 | "(rvalue >= $2 OR 0 = $3::smallint) AND " | ||
182 | "(hash = $4 OR 0 = $5::smallint) AND " | ||
183 | "(type = $6 OR 0 = $7::smallint) " | ||
184 | "ORDER BY oid ASC LIMIT 1", 7)) || | ||
185 | (GNUNET_OK != | ||
186 | GNUNET_POSTGRES_prepare (plugin->dbh, "put", | ||
187 | "INSERT INTO gn090 (repl, type, prio, anonLevel, expire, rvalue, hash, vhash, value) " | ||
188 | "VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", 9)) || | ||
189 | (GNUNET_OK != | ||
190 | GNUNET_POSTGRES_prepare (plugin->dbh, "update", | ||
191 | "UPDATE gn090 " | ||
192 | "SET prio = prio + $1, " | ||
193 | "repl = repl + $2, " | ||
194 | "expire = GREATEST(expire, $3) " | ||
195 | "WHERE hash = $4 AND vhash = $5", 5)) || | ||
196 | (GNUNET_OK != | ||
197 | GNUNET_POSTGRES_prepare (plugin->dbh, "decrepl", | ||
198 | "UPDATE gn090 SET repl = GREATEST (repl - 1, 0) " | ||
199 | "WHERE oid = $1", 1)) || | ||
200 | (GNUNET_OK != | ||
201 | GNUNET_POSTGRES_prepare (plugin->dbh, "select_non_anonymous", | ||
202 | "SELECT " RESULT_COLUMNS " FROM gn090 " | ||
203 | "WHERE anonLevel = 0 AND type = $1 AND oid >= $2::bigint " | ||
204 | "ORDER BY oid ASC LIMIT 1", | ||
205 | 2)) || | ||
206 | (GNUNET_OK != | ||
207 | GNUNET_POSTGRES_prepare (plugin->dbh, "select_expiration_order", | ||
208 | "(SELECT " RESULT_COLUMNS " FROM gn090 " | ||
209 | "WHERE expire < $1 ORDER BY prio ASC LIMIT 1) " | ||
210 | "UNION " | ||
211 | "(SELECT " RESULT_COLUMNS " FROM gn090 " | ||
212 | "ORDER BY prio ASC LIMIT 1) " | ||
213 | "ORDER BY expire ASC LIMIT 1", | ||
214 | 1)) || | ||
215 | (GNUNET_OK != | ||
216 | GNUNET_POSTGRES_prepare (plugin->dbh, "select_replication_order", | ||
217 | "SELECT " RESULT_COLUMNS " FROM gn090 " | ||
218 | "ORDER BY repl DESC,RANDOM() LIMIT 1", 0)) || | ||
219 | (GNUNET_OK != | ||
220 | GNUNET_POSTGRES_prepare (plugin->dbh, "delrow", "DELETE FROM gn090 " "WHERE oid=$1", 1)) || | ||
221 | (GNUNET_OK != | ||
222 | GNUNET_POSTGRES_prepare (plugin->dbh, "remove", "DELETE FROM gn090 " | ||
223 | "WHERE hash = $1 AND " | ||
224 | "value = $2", 2)) || | ||
225 | (GNUNET_OK != | ||
226 | GNUNET_POSTGRES_prepare (plugin->dbh, "get_keys", "SELECT hash FROM gn090", 0))) | ||
227 | { | 171 | { |
228 | PQfinish (plugin->dbh); | 172 | PQfinish (plugin->dbh); |
229 | plugin->dbh = NULL; | 173 | plugin->dbh = NULL; |
@@ -241,44 +185,32 @@ init_connection (struct Plugin *plugin) | |||
241 | * @return number of bytes used on disk | 185 | * @return number of bytes used on disk |
242 | */ | 186 | */ |
243 | static void | 187 | static void |
244 | postgres_plugin_estimate_size (void *cls, unsigned long long *estimate) | 188 | postgres_plugin_estimate_size (void *cls, |
189 | unsigned long long *estimate) | ||
245 | { | 190 | { |
246 | struct Plugin *plugin = cls; | 191 | struct Plugin *plugin = cls; |
247 | unsigned long long total; | 192 | uint64_t total; |
248 | PGresult *ret; | 193 | struct GNUNET_PQ_QueryParam params[] = { |
194 | GNUNET_PQ_query_param_end | ||
195 | }; | ||
196 | struct GNUNET_PQ_ResultSpec rs[] = { | ||
197 | GNUNET_PQ_result_spec_uint64 ("total", | ||
198 | &total), | ||
199 | GNUNET_PQ_result_spec_end | ||
200 | }; | ||
201 | enum GNUNET_DB_QueryStatus ret; | ||
249 | 202 | ||
250 | if (NULL == estimate) | 203 | if (NULL == estimate) |
251 | return; | 204 | return; |
252 | ret = | 205 | ret = GNUNET_PQ_eval_prepared_singleton_select (plugin->dbh, |
253 | PQexecParams (plugin->dbh, | 206 | "estimate_size", |
254 | "SELECT SUM(LENGTH(value))+256*COUNT(*) FROM gn090", 0, | 207 | params, |
255 | NULL, NULL, NULL, NULL, 1); | 208 | rs); |
256 | if (GNUNET_OK != | 209 | if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != ret) |
257 | GNUNET_POSTGRES_check_result (plugin->dbh, | ||
258 | ret, | ||
259 | PGRES_TUPLES_OK, | ||
260 | "PQexecParams", | ||
261 | "get_size")) | ||
262 | { | ||
263 | *estimate = 0; | ||
264 | return; | ||
265 | } | ||
266 | if ((PQntuples (ret) != 1) || (PQnfields (ret) != 1) ) | ||
267 | { | ||
268 | GNUNET_break (0); | ||
269 | PQclear (ret); | ||
270 | *estimate = 0; | ||
271 | return; | ||
272 | } | ||
273 | if (PQgetlength (ret, 0, 0) != sizeof (unsigned long long)) | ||
274 | { | 210 | { |
275 | GNUNET_break (0 == PQgetlength (ret, 0, 0)); | 211 | *estimate = 0LL; |
276 | PQclear (ret); | ||
277 | *estimate = 0; | ||
278 | return; | 212 | return; |
279 | } | 213 | } |
280 | total = GNUNET_ntohll (*(const unsigned long long *) PQgetvalue (ret, 0, 0)); | ||
281 | PQclear (ret); | ||
282 | *estimate = total; | 214 | *estimate = total; |
283 | } | 215 | } |
284 | 216 | ||
@@ -315,13 +247,12 @@ postgres_plugin_put (void *cls, | |||
315 | { | 247 | { |
316 | struct Plugin *plugin = cls; | 248 | struct Plugin *plugin = cls; |
317 | struct GNUNET_HashCode vhash; | 249 | struct GNUNET_HashCode vhash; |
318 | PGresult *ret; | 250 | enum GNUNET_DB_QueryStatus ret; |
319 | 251 | ||
320 | GNUNET_CRYPTO_hash (data, | 252 | GNUNET_CRYPTO_hash (data, |
321 | size, | 253 | size, |
322 | &vhash); | 254 | &vhash); |
323 | 255 | if (! absent) | |
324 | if (!absent) | ||
325 | { | 256 | { |
326 | struct GNUNET_PQ_QueryParam params[] = { | 257 | struct GNUNET_PQ_QueryParam params[] = { |
327 | GNUNET_PQ_query_param_uint32 (&priority), | 258 | GNUNET_PQ_query_param_uint32 (&priority), |
@@ -331,15 +262,10 @@ postgres_plugin_put (void *cls, | |||
331 | GNUNET_PQ_query_param_auto_from_type (&vhash), | 262 | GNUNET_PQ_query_param_auto_from_type (&vhash), |
332 | GNUNET_PQ_query_param_end | 263 | GNUNET_PQ_query_param_end |
333 | }; | 264 | }; |
334 | ret = GNUNET_PQ_exec_prepared (plugin->dbh, | 265 | ret = GNUNET_PQ_eval_prepared_non_select (plugin->dbh, |
335 | "update", | 266 | "update", |
336 | params); | 267 | params); |
337 | if (GNUNET_OK != | 268 | if (0 > ret) |
338 | GNUNET_POSTGRES_check_result (plugin->dbh, | ||
339 | ret, | ||
340 | PGRES_COMMAND_OK, | ||
341 | "PQexecPrepared", | ||
342 | "update")) | ||
343 | { | 269 | { |
344 | cont (cont_cls, | 270 | cont (cont_cls, |
345 | key, | 271 | key, |
@@ -348,9 +274,7 @@ postgres_plugin_put (void *cls, | |||
348 | _("Postgress exec failure")); | 274 | _("Postgress exec failure")); |
349 | return; | 275 | return; |
350 | } | 276 | } |
351 | /* What an awful API, this function really does return a string */ | 277 | bool affected = (0 != ret); |
352 | bool affected = 0 != strcmp ("0", PQcmdTuples (ret)); | ||
353 | PQclear (ret); | ||
354 | if (affected) | 278 | if (affected) |
355 | { | 279 | { |
356 | cont (cont_cls, | 280 | cont (cont_cls, |
@@ -362,177 +286,195 @@ postgres_plugin_put (void *cls, | |||
362 | } | 286 | } |
363 | } | 287 | } |
364 | 288 | ||
365 | uint32_t utype = type; | ||
366 | uint64_t rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
367 | UINT64_MAX); | ||
368 | struct GNUNET_PQ_QueryParam params[] = { | ||
369 | GNUNET_PQ_query_param_uint32 (&replication), | ||
370 | GNUNET_PQ_query_param_uint32 (&utype), | ||
371 | GNUNET_PQ_query_param_uint32 (&priority), | ||
372 | GNUNET_PQ_query_param_uint32 (&anonymity), | ||
373 | GNUNET_PQ_query_param_absolute_time (&expiration), | ||
374 | GNUNET_PQ_query_param_uint64 (&rvalue), | ||
375 | GNUNET_PQ_query_param_auto_from_type (key), | ||
376 | GNUNET_PQ_query_param_auto_from_type (&vhash), | ||
377 | GNUNET_PQ_query_param_fixed_size (data, size), | ||
378 | GNUNET_PQ_query_param_end | ||
379 | }; | ||
380 | |||
381 | ret = GNUNET_PQ_exec_prepared (plugin->dbh, | ||
382 | "put", | ||
383 | params); | ||
384 | if (GNUNET_OK != | ||
385 | GNUNET_POSTGRES_check_result (plugin->dbh, | ||
386 | ret, | ||
387 | PGRES_COMMAND_OK, | ||
388 | "PQexecPrepared", "put")) | ||
389 | { | 289 | { |
390 | cont (cont_cls, key, size, | 290 | uint32_t utype = (uint32_t) type; |
391 | GNUNET_SYSERR, | 291 | uint64_t rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, |
392 | _("Postgress exec failure")); | 292 | UINT64_MAX); |
393 | return; | 293 | struct GNUNET_PQ_QueryParam params[] = { |
294 | GNUNET_PQ_query_param_uint32 (&replication), | ||
295 | GNUNET_PQ_query_param_uint32 (&utype), | ||
296 | GNUNET_PQ_query_param_uint32 (&priority), | ||
297 | GNUNET_PQ_query_param_uint32 (&anonymity), | ||
298 | GNUNET_PQ_query_param_absolute_time (&expiration), | ||
299 | GNUNET_PQ_query_param_uint64 (&rvalue), | ||
300 | GNUNET_PQ_query_param_auto_from_type (key), | ||
301 | GNUNET_PQ_query_param_auto_from_type (&vhash), | ||
302 | GNUNET_PQ_query_param_fixed_size (data, size), | ||
303 | GNUNET_PQ_query_param_end | ||
304 | }; | ||
305 | |||
306 | ret = GNUNET_PQ_eval_prepared_non_select (plugin->dbh, | ||
307 | "put", | ||
308 | params); | ||
309 | if (0 > ret) | ||
310 | { | ||
311 | cont (cont_cls, | ||
312 | key, | ||
313 | size, | ||
314 | GNUNET_SYSERR, | ||
315 | "Postgress exec failure"); | ||
316 | return; | ||
317 | } | ||
394 | } | 318 | } |
395 | PQclear (ret); | ||
396 | plugin->env->duc (plugin->env->cls, | 319 | plugin->env->duc (plugin->env->cls, |
397 | size + GNUNET_DATASTORE_ENTRY_OVERHEAD); | 320 | size + GNUNET_DATASTORE_ENTRY_OVERHEAD); |
398 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | 321 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, |
399 | "datastore-postgres", | 322 | "datastore-postgres", |
400 | "Stored %u bytes in database\n", | 323 | "Stored %u bytes in database\n", |
401 | (unsigned int) size); | 324 | (unsigned int) size); |
402 | cont (cont_cls, key, size, GNUNET_OK, NULL); | 325 | cont (cont_cls, |
326 | key, | ||
327 | size, | ||
328 | GNUNET_OK, | ||
329 | NULL); | ||
403 | } | 330 | } |
404 | 331 | ||
405 | 332 | ||
406 | /** | 333 | /** |
407 | * Function invoked to process the result and call the processor. | 334 | * Closure for #process_result. |
335 | */ | ||
336 | struct ProcessResultContext | ||
337 | { | ||
338 | |||
339 | /** | ||
340 | * The plugin handle. | ||
341 | */ | ||
342 | struct Plugin *plugin; | ||
343 | |||
344 | /** | ||
345 | * Function to call on each result. | ||
346 | */ | ||
347 | PluginDatumProcessor proc; | ||
348 | |||
349 | /** | ||
350 | * Closure for @e proc. | ||
351 | */ | ||
352 | void *proc_cls; | ||
353 | |||
354 | }; | ||
355 | |||
356 | |||
357 | /** | ||
358 | * Function invoked to process the result and call the processor of @a | ||
359 | * cls. | ||
408 | * | 360 | * |
409 | * @param plugin global plugin data | 361 | * @param cls our `struct ProcessResultContext` |
410 | * @param proc function to call the value (once only). | ||
411 | * @param proc_cls closure for proc | ||
412 | * @param res result from exec | 362 | * @param res result from exec |
413 | * @param filename filename for error messages | 363 | * @param num_results number of results in @a res |
414 | * @param line line number for error messages | ||
415 | */ | 364 | */ |
416 | static void | 365 | static void |
417 | process_result (struct Plugin *plugin, | 366 | process_result (void *cls, |
418 | PluginDatumProcessor proc, | 367 | PGresult *res, |
419 | void *proc_cls, | 368 | unsigned int num_results) |
420 | PGresult * res, | ||
421 | const char *filename, int line) | ||
422 | { | 369 | { |
423 | int iret; | 370 | struct ProcessResultContext *prc = cls; |
424 | uint32_t rowid; | 371 | struct Plugin *plugin = prc->plugin; |
425 | uint32_t utype; | ||
426 | uint32_t anonymity; | ||
427 | uint32_t replication; | ||
428 | uint32_t priority; | ||
429 | size_t size; | ||
430 | void *data; | ||
431 | struct GNUNET_TIME_Absolute expiration_time; | ||
432 | struct GNUNET_HashCode key; | ||
433 | struct GNUNET_PQ_ResultSpec rs[] = { | ||
434 | GNUNET_PQ_result_spec_uint32 ("repl", &replication), | ||
435 | GNUNET_PQ_result_spec_uint32 ("type", &utype), | ||
436 | GNUNET_PQ_result_spec_uint32 ("prio", &priority), | ||
437 | GNUNET_PQ_result_spec_uint32 ("anonLevel", &anonymity), | ||
438 | GNUNET_PQ_result_spec_absolute_time ("expire", &expiration_time), | ||
439 | GNUNET_PQ_result_spec_auto_from_type ("hash", &key), | ||
440 | GNUNET_PQ_result_spec_variable_size ("value", &data, &size), | ||
441 | GNUNET_PQ_result_spec_uint32 ("oid", &rowid), | ||
442 | GNUNET_PQ_result_spec_end | ||
443 | }; | ||
444 | 372 | ||
445 | if (GNUNET_OK != | 373 | if (0 == num_results) |
446 | GNUNET_POSTGRES_check_result_ (plugin->dbh, | ||
447 | res, | ||
448 | PGRES_TUPLES_OK, | ||
449 | "PQexecPrepared", | ||
450 | "select", | ||
451 | filename, line)) | ||
452 | { | ||
453 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
454 | "datastore-postgres", | ||
455 | "Ending iteration (postgres error)\n"); | ||
456 | proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); | ||
457 | return; | ||
458 | } | ||
459 | |||
460 | if (0 == PQntuples (res)) | ||
461 | { | 374 | { |
462 | /* no result */ | 375 | /* no result */ |
463 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | 376 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, |
464 | "datastore-postgres", | 377 | "datastore-postgres", |
465 | "Ending iteration (no more results)\n"); | 378 | "Ending iteration (no more results)\n"); |
466 | proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); | 379 | prc->proc (prc->proc_cls, NULL, 0, NULL, 0, 0, 0, 0, |
467 | PQclear (res); | 380 | GNUNET_TIME_UNIT_ZERO_ABS, 0); |
468 | return; | 381 | return; |
469 | } | 382 | } |
470 | if (1 != PQntuples (res)) | 383 | if (1 != num_results) |
471 | { | 384 | { |
472 | GNUNET_break (0); | 385 | GNUNET_break (0); |
473 | proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); | 386 | prc->proc (prc->proc_cls, NULL, 0, NULL, 0, 0, 0, 0, |
474 | PQclear (res); | 387 | GNUNET_TIME_UNIT_ZERO_ABS, 0); |
475 | return; | 388 | return; |
476 | } | 389 | } |
477 | if (GNUNET_OK != | 390 | /* Technically we don't need the loop here, but nicer in case |
478 | GNUNET_PQ_extract_result (res, | 391 | we ever relax the condition above. */ |
479 | rs, | 392 | for (unsigned int i=0;i<num_results;i++) |
480 | 0)) | ||
481 | { | 393 | { |
482 | GNUNET_break (0); | 394 | int iret; |
483 | PQclear (res); | 395 | uint32_t rowid; |
484 | GNUNET_POSTGRES_delete_by_rowid (plugin->dbh, | 396 | uint32_t utype; |
485 | "delrow", | 397 | uint32_t anonymity; |
486 | rowid); | 398 | uint32_t replication; |
487 | proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); | 399 | uint32_t priority; |
488 | return; | 400 | size_t size; |
489 | } | 401 | void *data; |
402 | struct GNUNET_TIME_Absolute expiration_time; | ||
403 | struct GNUNET_HashCode key; | ||
404 | struct GNUNET_PQ_ResultSpec rs[] = { | ||
405 | GNUNET_PQ_result_spec_uint32 ("repl", &replication), | ||
406 | GNUNET_PQ_result_spec_uint32 ("type", &utype), | ||
407 | GNUNET_PQ_result_spec_uint32 ("prio", &priority), | ||
408 | GNUNET_PQ_result_spec_uint32 ("anonLevel", &anonymity), | ||
409 | GNUNET_PQ_result_spec_absolute_time ("expire", &expiration_time), | ||
410 | GNUNET_PQ_result_spec_auto_from_type ("hash", &key), | ||
411 | GNUNET_PQ_result_spec_variable_size ("value", &data, &size), | ||
412 | GNUNET_PQ_result_spec_uint32 ("oid", &rowid), | ||
413 | GNUNET_PQ_result_spec_end | ||
414 | }; | ||
490 | 415 | ||
491 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | 416 | if (GNUNET_OK != |
492 | "datastore-postgres", | 417 | GNUNET_PQ_extract_result (res, |
493 | "Found result of size %u bytes and type %u in database\n", | 418 | rs, |
494 | (unsigned int) size, | 419 | i)) |
495 | (unsigned int) utype); | ||
496 | iret = proc (proc_cls, | ||
497 | &key, | ||
498 | size, | ||
499 | data, | ||
500 | (enum GNUNET_BLOCK_Type) utype, | ||
501 | priority, | ||
502 | anonymity, | ||
503 | replication, | ||
504 | expiration_time, | ||
505 | rowid); | ||
506 | PQclear (res); | ||
507 | if (iret == GNUNET_NO) | ||
508 | { | ||
509 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
510 | "Processor asked for item %u to be removed.\n", | ||
511 | (unsigned int) rowid); | ||
512 | if (GNUNET_OK == | ||
513 | GNUNET_POSTGRES_delete_by_rowid (plugin->dbh, | ||
514 | "delrow", | ||
515 | rowid)) | ||
516 | { | 420 | { |
517 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | 421 | GNUNET_break (0); |
518 | "datastore-postgres", | 422 | prc->proc (prc->proc_cls, NULL, 0, NULL, 0, 0, 0, 0, |
519 | "Deleting %u bytes from database\n", | 423 | GNUNET_TIME_UNIT_ZERO_ABS, 0); |
520 | (unsigned int) size); | 424 | return; |
521 | plugin->env->duc (plugin->env->cls, | ||
522 | - (size + GNUNET_DATASTORE_ENTRY_OVERHEAD)); | ||
523 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
524 | "datastore-postgres", | ||
525 | "Deleted %u bytes from database\n", | ||
526 | (unsigned int) size); | ||
527 | } | 425 | } |
528 | } | 426 | |
427 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
428 | "datastore-postgres", | ||
429 | "Found result of size %u bytes and type %u in database\n", | ||
430 | (unsigned int) size, | ||
431 | (unsigned int) utype); | ||
432 | iret = prc->proc (prc->proc_cls, | ||
433 | &key, | ||
434 | size, | ||
435 | data, | ||
436 | (enum GNUNET_BLOCK_Type) utype, | ||
437 | priority, | ||
438 | anonymity, | ||
439 | replication, | ||
440 | expiration_time, | ||
441 | rowid); | ||
442 | if (iret == GNUNET_NO) | ||
443 | { | ||
444 | struct GNUNET_PQ_QueryParam param[] = { | ||
445 | GNUNET_PQ_query_param_uint32 (&rowid), | ||
446 | GNUNET_PQ_query_param_end | ||
447 | }; | ||
448 | |||
449 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
450 | "Processor asked for item %u to be removed.\n", | ||
451 | (unsigned int) rowid); | ||
452 | if (0 < | ||
453 | GNUNET_PQ_eval_prepared_non_select (plugin->dbh, | ||
454 | "delrow", | ||
455 | param)) | ||
456 | { | ||
457 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
458 | "datastore-postgres", | ||
459 | "Deleting %u bytes from database\n", | ||
460 | (unsigned int) size); | ||
461 | plugin->env->duc (plugin->env->cls, | ||
462 | - (size + GNUNET_DATASTORE_ENTRY_OVERHEAD)); | ||
463 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
464 | "datastore-postgres", | ||
465 | "Deleted %u bytes from database\n", | ||
466 | (unsigned int) size); | ||
467 | } | ||
468 | } | ||
469 | GNUNET_PQ_cleanup_result (rs); | ||
470 | } /* for (i) */ | ||
529 | } | 471 | } |
530 | 472 | ||
531 | 473 | ||
532 | /** | 474 | /** |
533 | * Get one of the results for a particular key in the datastore. | 475 | * Get one of the results for a particular key in the datastore. |
534 | * | 476 | * |
535 | * @param cls closure with the 'struct Plugin' | 477 | * @param cls closure with the `struct Plugin` |
536 | * @param next_uid return the result with lowest uid >= next_uid | 478 | * @param next_uid return the result with lowest uid >= next_uid |
537 | * @param random if true, return a random result instead of using next_uid | 479 | * @param random if true, return a random result instead of using next_uid |
538 | * @param key maybe NULL (to match all entries) | 480 | * @param key maybe NULL (to match all entries) |
@@ -567,7 +509,8 @@ postgres_plugin_get_key (void *cls, | |||
567 | GNUNET_PQ_query_param_uint16 (&use_type), | 509 | GNUNET_PQ_query_param_uint16 (&use_type), |
568 | GNUNET_PQ_query_param_end | 510 | GNUNET_PQ_query_param_end |
569 | }; | 511 | }; |
570 | PGresult *ret; | 512 | struct ProcessResultContext prc; |
513 | enum GNUNET_DB_QueryStatus res; | ||
571 | 514 | ||
572 | if (random) | 515 | if (random) |
573 | { | 516 | { |
@@ -576,16 +519,21 @@ postgres_plugin_get_key (void *cls, | |||
576 | next_uid = 0; | 519 | next_uid = 0; |
577 | } | 520 | } |
578 | else | 521 | else |
522 | { | ||
579 | rvalue = 0; | 523 | rvalue = 0; |
580 | 524 | } | |
581 | ret = GNUNET_PQ_exec_prepared (plugin->dbh, | 525 | prc.plugin = plugin; |
582 | "get", | 526 | prc.proc = proc; |
583 | params); | 527 | prc.proc_cls = proc_cls; |
584 | process_result (plugin, | 528 | |
585 | proc, | 529 | res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh, |
586 | proc_cls, | 530 | "get", |
587 | ret, | 531 | params, |
588 | __FILE__, __LINE__); | 532 | &process_result, |
533 | &prc); | ||
534 | if (0 > res) | ||
535 | proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, | ||
536 | GNUNET_TIME_UNIT_ZERO_ABS, 0); | ||
589 | } | 537 | } |
590 | 538 | ||
591 | 539 | ||
@@ -615,16 +563,20 @@ postgres_plugin_get_zero_anonymity (void *cls, | |||
615 | GNUNET_PQ_query_param_uint64 (&next_uid), | 563 | GNUNET_PQ_query_param_uint64 (&next_uid), |
616 | GNUNET_PQ_query_param_end | 564 | GNUNET_PQ_query_param_end |
617 | }; | 565 | }; |
618 | PGresult *ret; | 566 | struct ProcessResultContext prc; |
619 | 567 | enum GNUNET_DB_QueryStatus res; | |
620 | ret = GNUNET_PQ_exec_prepared (plugin->dbh, | 568 | |
621 | "select_non_anonymous", | 569 | prc.plugin = plugin; |
622 | params); | 570 | prc.proc = proc; |
623 | 571 | prc.proc_cls = proc_cls; | |
624 | process_result (plugin, | 572 | res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh, |
625 | proc, proc_cls, | 573 | "select_non_anonymous", |
626 | ret, | 574 | params, |
627 | __FILE__, __LINE__); | 575 | &process_result, |
576 | &prc); | ||
577 | if (0 > res) | ||
578 | proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, | ||
579 | GNUNET_TIME_UNIT_ZERO_ABS, 0); | ||
628 | } | 580 | } |
629 | 581 | ||
630 | 582 | ||
@@ -692,7 +644,7 @@ repl_proc (void *cls, | |||
692 | GNUNET_PQ_query_param_uint32 (&oid), | 644 | GNUNET_PQ_query_param_uint32 (&oid), |
693 | GNUNET_PQ_query_param_end | 645 | GNUNET_PQ_query_param_end |
694 | }; | 646 | }; |
695 | PGresult *qret; | 647 | enum GNUNET_DB_QueryStatus qret; |
696 | 648 | ||
697 | ret = rc->proc (rc->proc_cls, | 649 | ret = rc->proc (rc->proc_cls, |
698 | key, | 650 | key, |
@@ -706,17 +658,11 @@ repl_proc (void *cls, | |||
706 | uid); | 658 | uid); |
707 | if (NULL == key) | 659 | if (NULL == key) |
708 | return ret; | 660 | return ret; |
709 | qret = GNUNET_PQ_exec_prepared (plugin->dbh, | 661 | qret = GNUNET_PQ_eval_prepared_non_select (plugin->dbh, |
710 | "decrepl", | 662 | "decrepl", |
711 | params); | 663 | params); |
712 | if (GNUNET_OK != | 664 | if (0 > qret) |
713 | GNUNET_POSTGRES_check_result (plugin->dbh, | ||
714 | qret, | ||
715 | PGRES_COMMAND_OK, | ||
716 | "PQexecPrepared", | ||
717 | "decrepl")) | ||
718 | return GNUNET_SYSERR; | 665 | return GNUNET_SYSERR; |
719 | PQclear (qret); | ||
720 | return ret; | 666 | return ret; |
721 | } | 667 | } |
722 | 668 | ||
@@ -738,20 +684,27 @@ postgres_plugin_get_replication (void *cls, | |||
738 | void *proc_cls) | 684 | void *proc_cls) |
739 | { | 685 | { |
740 | struct Plugin *plugin = cls; | 686 | struct Plugin *plugin = cls; |
687 | struct GNUNET_PQ_QueryParam params[] = { | ||
688 | GNUNET_PQ_query_param_end | ||
689 | }; | ||
741 | struct ReplCtx rc; | 690 | struct ReplCtx rc; |
742 | PGresult *ret; | 691 | struct ProcessResultContext prc; |
692 | enum GNUNET_DB_QueryStatus res; | ||
743 | 693 | ||
744 | rc.plugin = plugin; | 694 | rc.plugin = plugin; |
745 | rc.proc = proc; | 695 | rc.proc = proc; |
746 | rc.proc_cls = proc_cls; | 696 | rc.proc_cls = proc_cls; |
747 | ret = PQexecPrepared (plugin->dbh, | 697 | prc.plugin = plugin; |
748 | "select_replication_order", 0, NULL, NULL, | 698 | prc.proc = &repl_proc; |
749 | NULL, 1); | 699 | prc.proc_cls = &rc; |
750 | process_result (plugin, | 700 | res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh, |
751 | &repl_proc, | 701 | "select_replication_order", |
752 | &rc, | 702 | params, |
753 | ret, | 703 | &process_result, |
754 | __FILE__, __LINE__); | 704 | &prc); |
705 | if (0 > res) | ||
706 | proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, | ||
707 | GNUNET_TIME_UNIT_ZERO_ABS, 0); | ||
755 | } | 708 | } |
756 | 709 | ||
757 | 710 | ||
@@ -774,16 +727,75 @@ postgres_plugin_get_expiration (void *cls, | |||
774 | GNUNET_PQ_query_param_absolute_time (&now), | 727 | GNUNET_PQ_query_param_absolute_time (&now), |
775 | GNUNET_PQ_query_param_end | 728 | GNUNET_PQ_query_param_end |
776 | }; | 729 | }; |
777 | PGresult *ret; | 730 | struct ProcessResultContext prc; |
778 | 731 | ||
779 | now = GNUNET_TIME_absolute_get (); | 732 | now = GNUNET_TIME_absolute_get (); |
780 | ret = GNUNET_PQ_exec_prepared (plugin->dbh, | 733 | prc.plugin = plugin; |
781 | "select_expiration_order", | 734 | prc.proc = proc; |
782 | params); | 735 | prc.proc_cls = proc_cls; |
783 | process_result (plugin, | 736 | (void) GNUNET_PQ_eval_prepared_multi_select (plugin->dbh, |
784 | proc, proc_cls, | 737 | "select_expiration_order", |
785 | ret, | 738 | params, |
786 | __FILE__, __LINE__); | 739 | &process_result, |
740 | &prc); | ||
741 | } | ||
742 | |||
743 | |||
744 | /** | ||
745 | * Closure for #process_keys. | ||
746 | */ | ||
747 | struct ProcessKeysContext | ||
748 | { | ||
749 | |||
750 | /** | ||
751 | * Function to call for each key. | ||
752 | */ | ||
753 | PluginKeyProcessor proc; | ||
754 | |||
755 | /** | ||
756 | * Closure for @e proc. | ||
757 | */ | ||
758 | void *proc_cls; | ||
759 | }; | ||
760 | |||
761 | |||
762 | /** | ||
763 | * Function to be called with the results of a SELECT statement | ||
764 | * that has returned @a num_results results. | ||
765 | * | ||
766 | * @param cls closure with a `struct ProcessKeysContext` | ||
767 | * @param result the postgres result | ||
768 | * @param num_result the number of results in @a result | ||
769 | */ | ||
770 | static void | ||
771 | process_keys (void *cls, | ||
772 | PGresult *result, | ||
773 | unsigned int num_results) | ||
774 | { | ||
775 | struct ProcessKeysContext *pkc = cls; | ||
776 | |||
777 | for (unsigned i=0;i<num_results;i++) | ||
778 | { | ||
779 | struct GNUNET_HashCode key; | ||
780 | struct GNUNET_PQ_ResultSpec rs[] = { | ||
781 | GNUNET_PQ_result_spec_auto_from_type ("hash", | ||
782 | &key), | ||
783 | GNUNET_PQ_result_spec_end | ||
784 | }; | ||
785 | |||
786 | if (GNUNET_OK != | ||
787 | GNUNET_PQ_extract_result (result, | ||
788 | rs, | ||
789 | i)) | ||
790 | { | ||
791 | GNUNET_break (0); | ||
792 | continue; | ||
793 | } | ||
794 | pkc->proc (pkc->proc_cls, | ||
795 | &key, | ||
796 | 1); | ||
797 | GNUNET_PQ_cleanup_result (rs); | ||
798 | } | ||
787 | } | 799 | } |
788 | 800 | ||
789 | 801 | ||
@@ -800,28 +812,21 @@ postgres_plugin_get_keys (void *cls, | |||
800 | void *proc_cls) | 812 | void *proc_cls) |
801 | { | 813 | { |
802 | struct Plugin *plugin = cls; | 814 | struct Plugin *plugin = cls; |
803 | int ret; | 815 | struct GNUNET_PQ_QueryParam params[] = { |
804 | int i; | 816 | GNUNET_PQ_query_param_end |
805 | struct GNUNET_HashCode key; | 817 | }; |
806 | PGresult * res; | 818 | struct ProcessKeysContext pkc; |
807 | 819 | ||
808 | res = PQexecPrepared (plugin->dbh, | 820 | pkc.proc = proc; |
809 | "get_keys", | 821 | pkc.proc_cls = proc_cls; |
810 | 0, NULL, NULL, NULL, 1); | 822 | (void) GNUNET_PQ_eval_prepared_multi_select (plugin->dbh, |
811 | ret = PQntuples (res); | 823 | "get_keys", |
812 | for (i=0;i<ret;i++) | 824 | params, |
813 | { | 825 | &process_keys, |
814 | if (sizeof (struct GNUNET_HashCode) != | 826 | &pkc); |
815 | PQgetlength (res, i, 0)) | 827 | proc (proc_cls, |
816 | { | 828 | NULL, |
817 | GNUNET_memcpy (&key, | 829 | 0); |
818 | PQgetvalue (res, i, 0), | ||
819 | sizeof (struct GNUNET_HashCode)); | ||
820 | proc (proc_cls, &key, 1); | ||
821 | } | ||
822 | } | ||
823 | PQclear (res); | ||
824 | proc (proc_cls, NULL, 0); | ||
825 | } | 830 | } |
826 | 831 | ||
827 | 832 | ||
@@ -834,10 +839,14 @@ static void | |||
834 | postgres_plugin_drop (void *cls) | 839 | postgres_plugin_drop (void *cls) |
835 | { | 840 | { |
836 | struct Plugin *plugin = cls; | 841 | struct Plugin *plugin = cls; |
842 | struct GNUNET_PQ_ExecuteStatement es[] = { | ||
843 | GNUNET_PQ_make_execute ("DROP TABLE gn090"), | ||
844 | GNUNET_PQ_EXECUTE_STATEMENT_END | ||
845 | }; | ||
837 | 846 | ||
838 | if (GNUNET_OK != | 847 | if (GNUNET_OK != |
839 | GNUNET_POSTGRES_exec (plugin->dbh, | 848 | GNUNET_PQ_exec_statements (plugin->dbh, |
840 | "DROP TABLE gn090")) | 849 | es)) |
841 | GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, | 850 | GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, |
842 | "postgres", | 851 | "postgres", |
843 | _("Failed to drop table from database.\n")); | 852 | _("Failed to drop table from database.\n")); |
@@ -863,21 +872,17 @@ postgres_plugin_remove_key (void *cls, | |||
863 | void *cont_cls) | 872 | void *cont_cls) |
864 | { | 873 | { |
865 | struct Plugin *plugin = cls; | 874 | struct Plugin *plugin = cls; |
866 | PGresult *ret; | 875 | enum GNUNET_DB_QueryStatus ret; |
867 | struct GNUNET_PQ_QueryParam params[] = { | 876 | struct GNUNET_PQ_QueryParam params[] = { |
868 | GNUNET_PQ_query_param_auto_from_type (key), | 877 | GNUNET_PQ_query_param_auto_from_type (key), |
869 | GNUNET_PQ_query_param_fixed_size (data, size), | 878 | GNUNET_PQ_query_param_fixed_size (data, size), |
870 | GNUNET_PQ_query_param_end | 879 | GNUNET_PQ_query_param_end |
871 | }; | 880 | }; |
872 | ret = GNUNET_PQ_exec_prepared (plugin->dbh, | 881 | |
873 | "remove", | 882 | ret = GNUNET_PQ_eval_prepared_non_select (plugin->dbh, |
874 | params); | 883 | "remove", |
875 | if (GNUNET_OK != | 884 | params); |
876 | GNUNET_POSTGRES_check_result (plugin->dbh, | 885 | if (0 > ret) |
877 | ret, | ||
878 | PGRES_COMMAND_OK, | ||
879 | "PQexecPrepared", | ||
880 | "remove")) | ||
881 | { | 886 | { |
882 | cont (cont_cls, | 887 | cont (cont_cls, |
883 | key, | 888 | key, |
@@ -886,10 +891,7 @@ postgres_plugin_remove_key (void *cls, | |||
886 | _("Postgress exec failure")); | 891 | _("Postgress exec failure")); |
887 | return; | 892 | return; |
888 | } | 893 | } |
889 | /* What an awful API, this function really does return a string */ | 894 | if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == ret) |
890 | bool affected = 0 != strcmp ("0", PQcmdTuples (ret)); | ||
891 | PQclear (ret); | ||
892 | if (!affected) | ||
893 | { | 895 | { |
894 | cont (cont_cls, | 896 | cont (cont_cls, |
895 | key, | 897 | key, |
diff --git a/src/datastore/plugin_datastore_sqlite.c b/src/datastore/plugin_datastore_sqlite.c index 323c03856..77b8409cd 100644 --- a/src/datastore/plugin_datastore_sqlite.c +++ b/src/datastore/plugin_datastore_sqlite.c | |||
@@ -186,31 +186,19 @@ create_indices (sqlite3 * dbh) | |||
186 | { | 186 | { |
187 | /* create indices */ | 187 | /* create indices */ |
188 | if ((SQLITE_OK != | 188 | if ((SQLITE_OK != |
189 | sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS idx_hash ON gn090 (hash)", | 189 | sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS idx_hash ON gn091 (hash)", |
190 | NULL, NULL, NULL)) || | 190 | NULL, NULL, NULL)) || |
191 | (SQLITE_OK != | 191 | (SQLITE_OK != |
192 | sqlite3_exec (dbh, | 192 | sqlite3_exec (dbh, |
193 | "CREATE INDEX IF NOT EXISTS idx_expire_repl ON gn090 (expire ASC,repl DESC)", | 193 | "CREATE INDEX IF NOT EXISTS idx_anon_type ON gn091 (anonLevel ASC,type)", |
194 | NULL, NULL, NULL)) || | 194 | NULL, NULL, NULL)) || |
195 | (SQLITE_OK != | 195 | (SQLITE_OK != |
196 | sqlite3_exec (dbh, | 196 | sqlite3_exec (dbh, |
197 | "CREATE INDEX IF NOT EXISTS idx_comb ON gn090 (anonLevel ASC,expire ASC,prio,type,hash)", | 197 | "CREATE INDEX IF NOT EXISTS idx_expire ON gn091 (expire ASC)", |
198 | NULL, NULL, NULL)) || | 198 | NULL, NULL, NULL)) || |
199 | (SQLITE_OK != | 199 | (SQLITE_OK != |
200 | sqlite3_exec (dbh, | 200 | sqlite3_exec (dbh, |
201 | "CREATE INDEX IF NOT EXISTS idx_anon_type_hash ON gn090 (anonLevel ASC,type,hash)", | 201 | "CREATE INDEX IF NOT EXISTS idx_repl_rvalue ON gn091 (repl,rvalue)", |
202 | NULL, NULL, NULL)) || | ||
203 | (SQLITE_OK != | ||
204 | sqlite3_exec (dbh, | ||
205 | "CREATE INDEX IF NOT EXISTS idx_expire ON gn090 (expire ASC)", | ||
206 | NULL, NULL, NULL)) || | ||
207 | (SQLITE_OK != | ||
208 | sqlite3_exec (dbh, | ||
209 | "CREATE INDEX IF NOT EXISTS idx_repl_rvalue ON gn090 (repl,rvalue)", | ||
210 | NULL, NULL, NULL)) || | ||
211 | (SQLITE_OK != | ||
212 | sqlite3_exec (dbh, | ||
213 | "CREATE INDEX IF NOT EXISTS idx_repl ON gn090 (repl DESC)", | ||
214 | NULL, NULL, NULL))) | 202 | NULL, NULL, NULL))) |
215 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "sqlite", | 203 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "sqlite", |
216 | "Failed to create indices: %s\n", sqlite3_errmsg (dbh)); | 204 | "Failed to create indices: %s\n", sqlite3_errmsg (dbh)); |
@@ -305,7 +293,7 @@ database_setup (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
305 | ENULL)); | 293 | ENULL)); |
306 | CHECK (SQLITE_OK == | 294 | CHECK (SQLITE_OK == |
307 | sqlite3_exec (plugin->dbh, | 295 | sqlite3_exec (plugin->dbh, |
308 | "PRAGMA page_size=4092", NULL, NULL, | 296 | "PRAGMA page_size=4096", NULL, NULL, |
309 | ENULL)); | 297 | ENULL)); |
310 | 298 | ||
311 | CHECK (SQLITE_OK == | 299 | CHECK (SQLITE_OK == |
@@ -315,7 +303,7 @@ database_setup (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
315 | /* We have to do it here, because otherwise precompiling SQL might fail */ | 303 | /* We have to do it here, because otherwise precompiling SQL might fail */ |
316 | CHECK (SQLITE_OK == | 304 | CHECK (SQLITE_OK == |
317 | sq_prepare (plugin->dbh, | 305 | sq_prepare (plugin->dbh, |
318 | "SELECT 1 FROM sqlite_master WHERE tbl_name = 'gn090'", | 306 | "SELECT 1 FROM sqlite_master WHERE tbl_name = 'gn091'", |
319 | &stmt)); | 307 | &stmt)); |
320 | 308 | ||
321 | /* FIXME: SQLite does not have unsigned integers! This is ok for the type column because | 309 | /* FIXME: SQLite does not have unsigned integers! This is ok for the type column because |
@@ -327,7 +315,7 @@ database_setup (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
327 | sqlite3_step (stmt)) && | 315 | sqlite3_step (stmt)) && |
328 | (SQLITE_OK != | 316 | (SQLITE_OK != |
329 | sqlite3_exec (plugin->dbh, | 317 | sqlite3_exec (plugin->dbh, |
330 | "CREATE TABLE gn090 (" | 318 | "CREATE TABLE gn091 (" |
331 | " repl INT4 NOT NULL DEFAULT 0," | 319 | " repl INT4 NOT NULL DEFAULT 0," |
332 | " type INT4 NOT NULL DEFAULT 0," | 320 | " type INT4 NOT NULL DEFAULT 0," |
333 | " prio INT4 NOT NULL DEFAULT 0," | 321 | " prio INT4 NOT NULL DEFAULT 0," |
@@ -353,7 +341,7 @@ database_setup (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
353 | #define RESULT_COLUMNS "repl, type, prio, anonLevel, expire, hash, value, _ROWID_" | 341 | #define RESULT_COLUMNS "repl, type, prio, anonLevel, expire, hash, value, _ROWID_" |
354 | if ( (SQLITE_OK != | 342 | if ( (SQLITE_OK != |
355 | sq_prepare (plugin->dbh, | 343 | sq_prepare (plugin->dbh, |
356 | "UPDATE gn090 " | 344 | "UPDATE gn091 " |
357 | "SET prio = prio + ?, " | 345 | "SET prio = prio + ?, " |
358 | "repl = repl + ?, " | 346 | "repl = repl + ?, " |
359 | "expire = MAX(expire, ?) " | 347 | "expire = MAX(expire, ?) " |
@@ -361,16 +349,16 @@ database_setup (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
361 | &plugin->update)) || | 349 | &plugin->update)) || |
362 | (SQLITE_OK != | 350 | (SQLITE_OK != |
363 | sq_prepare (plugin->dbh, | 351 | sq_prepare (plugin->dbh, |
364 | "UPDATE gn090 " "SET repl = MAX (0, repl - 1) WHERE _ROWID_ = ?", | 352 | "UPDATE gn091 " "SET repl = MAX (0, repl - 1) WHERE _ROWID_ = ?", |
365 | &plugin->updRepl)) || | 353 | &plugin->updRepl)) || |
366 | (SQLITE_OK != | 354 | (SQLITE_OK != |
367 | sq_prepare (plugin->dbh, | 355 | sq_prepare (plugin->dbh, |
368 | "SELECT " RESULT_COLUMNS " FROM gn090 " | 356 | "SELECT " RESULT_COLUMNS " FROM gn091 " |
369 | #if SQLITE_VERSION_NUMBER >= 3007000 | 357 | #if SQLITE_VERSION_NUMBER >= 3007000 |
370 | "INDEXED BY idx_repl_rvalue " | 358 | "INDEXED BY idx_repl_rvalue " |
371 | #endif | 359 | #endif |
372 | "WHERE repl=?2 AND " " (rvalue>=?1 OR " | 360 | "WHERE repl=?2 AND " " (rvalue>=?1 OR " |
373 | " NOT EXISTS (SELECT 1 FROM gn090 " | 361 | " NOT EXISTS (SELECT 1 FROM gn091 " |
374 | #if SQLITE_VERSION_NUMBER >= 3007000 | 362 | #if SQLITE_VERSION_NUMBER >= 3007000 |
375 | "INDEXED BY idx_repl_rvalue " | 363 | "INDEXED BY idx_repl_rvalue " |
376 | #endif | 364 | #endif |
@@ -379,7 +367,7 @@ database_setup (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
379 | &plugin->selRepl)) || | 367 | &plugin->selRepl)) || |
380 | (SQLITE_OK != | 368 | (SQLITE_OK != |
381 | sq_prepare (plugin->dbh, | 369 | sq_prepare (plugin->dbh, |
382 | "SELECT MAX(repl) FROM gn090" | 370 | "SELECT MAX(repl) FROM gn091" |
383 | #if SQLITE_VERSION_NUMBER >= 3007000 | 371 | #if SQLITE_VERSION_NUMBER >= 3007000 |
384 | " INDEXED BY idx_repl_rvalue" | 372 | " INDEXED BY idx_repl_rvalue" |
385 | #endif | 373 | #endif |
@@ -387,18 +375,18 @@ database_setup (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
387 | &plugin->maxRepl)) || | 375 | &plugin->maxRepl)) || |
388 | (SQLITE_OK != | 376 | (SQLITE_OK != |
389 | sq_prepare (plugin->dbh, | 377 | sq_prepare (plugin->dbh, |
390 | "SELECT " RESULT_COLUMNS " FROM gn090 " | 378 | "SELECT " RESULT_COLUMNS " FROM gn091 " |
391 | #if SQLITE_VERSION_NUMBER >= 3007000 | 379 | #if SQLITE_VERSION_NUMBER >= 3007000 |
392 | "INDEXED BY idx_expire " | 380 | "INDEXED BY idx_expire " |
393 | #endif | 381 | #endif |
394 | "WHERE NOT EXISTS (SELECT 1 FROM gn090 WHERE expire < ?1 LIMIT 1) OR (expire < ?1) " | 382 | "WHERE NOT EXISTS (SELECT 1 FROM gn091 WHERE expire < ?1 LIMIT 1) OR (expire < ?1) " |
395 | "ORDER BY expire ASC LIMIT 1", | 383 | "ORDER BY expire ASC LIMIT 1", |
396 | &plugin->selExpi)) || | 384 | &plugin->selExpi)) || |
397 | (SQLITE_OK != | 385 | (SQLITE_OK != |
398 | sq_prepare (plugin->dbh, | 386 | sq_prepare (plugin->dbh, |
399 | "SELECT " RESULT_COLUMNS " FROM gn090 " | 387 | "SELECT " RESULT_COLUMNS " FROM gn091 " |
400 | #if SQLITE_VERSION_NUMBER >= 3007000 | 388 | #if SQLITE_VERSION_NUMBER >= 3007000 |
401 | "INDEXED BY idx_anon_type_hash " | 389 | "INDEXED BY idx_anon_type " |
402 | #endif | 390 | #endif |
403 | "WHERE _ROWID_ >= ? AND " | 391 | "WHERE _ROWID_ >= ? AND " |
404 | "anonLevel = 0 AND " | 392 | "anonLevel = 0 AND " |
@@ -407,12 +395,12 @@ database_setup (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
407 | &plugin->selZeroAnon)) || | 395 | &plugin->selZeroAnon)) || |
408 | (SQLITE_OK != | 396 | (SQLITE_OK != |
409 | sq_prepare (plugin->dbh, | 397 | sq_prepare (plugin->dbh, |
410 | "INSERT INTO gn090 (repl, type, prio, anonLevel, expire, rvalue, hash, vhash, value) " | 398 | "INSERT INTO gn091 (repl, type, prio, anonLevel, expire, rvalue, hash, vhash, value) " |
411 | "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", | 399 | "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", |
412 | &plugin->insertContent)) || | 400 | &plugin->insertContent)) || |
413 | (SQLITE_OK != | 401 | (SQLITE_OK != |
414 | sq_prepare (plugin->dbh, | 402 | sq_prepare (plugin->dbh, |
415 | "SELECT " RESULT_COLUMNS " FROM gn090 " | 403 | "SELECT " RESULT_COLUMNS " FROM gn091 " |
416 | "WHERE _ROWID_ >= ? AND " | 404 | "WHERE _ROWID_ >= ? AND " |
417 | "(rvalue >= ? OR 0 = ?) AND " | 405 | "(rvalue >= ? OR 0 = ?) AND " |
418 | "(hash = ? OR 0 = ?) AND " | 406 | "(hash = ? OR 0 = ?) AND " |
@@ -421,11 +409,11 @@ database_setup (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
421 | &plugin->get)) || | 409 | &plugin->get)) || |
422 | (SQLITE_OK != | 410 | (SQLITE_OK != |
423 | sq_prepare (plugin->dbh, | 411 | sq_prepare (plugin->dbh, |
424 | "DELETE FROM gn090 WHERE _ROWID_ = ?", | 412 | "DELETE FROM gn091 WHERE _ROWID_ = ?", |
425 | &plugin->delRow)) || | 413 | &plugin->delRow)) || |
426 | (SQLITE_OK != | 414 | (SQLITE_OK != |
427 | sq_prepare (plugin->dbh, | 415 | sq_prepare (plugin->dbh, |
428 | "DELETE FROM gn090 " | 416 | "DELETE FROM gn091 " |
429 | "WHERE hash = ? AND " | 417 | "WHERE hash = ? AND " |
430 | "value = ? ", | 418 | "value = ? ", |
431 | &plugin->remove)) || | 419 | &plugin->remove)) || |
@@ -1137,7 +1125,7 @@ sqlite_plugin_get_keys (void *cls, | |||
1137 | GNUNET_assert (NULL != proc); | 1125 | GNUNET_assert (NULL != proc); |
1138 | if (SQLITE_OK != | 1126 | if (SQLITE_OK != |
1139 | sq_prepare (plugin->dbh, | 1127 | sq_prepare (plugin->dbh, |
1140 | "SELECT hash FROM gn090", | 1128 | "SELECT hash FROM gn091", |
1141 | &stmt)) | 1129 | &stmt)) |
1142 | { | 1130 | { |
1143 | LOG_SQLITE (plugin, | 1131 | LOG_SQLITE (plugin, |
diff --git a/src/gns/gnunet-gns-import.c b/src/gns/gnunet-gns-import.c index 49f6e495f..3b9b0a081 100644 --- a/src/gns/gnunet-gns-import.c +++ b/src/gns/gnunet-gns-import.c | |||
@@ -60,11 +60,6 @@ static char *master_zone_pkey; | |||
60 | static struct GNUNET_CRYPTO_EcdsaPrivateKey master_pk; | 60 | static struct GNUNET_CRYPTO_EcdsaPrivateKey master_pk; |
61 | 61 | ||
62 | /** | 62 | /** |
63 | * String version of PKEY for short-zone. | ||
64 | */ | ||
65 | static char *short_zone_pkey; | ||
66 | |||
67 | /** | ||
68 | * String version of PKEY for private-zone. | 63 | * String version of PKEY for private-zone. |
69 | */ | 64 | */ |
70 | static char *private_zone_pkey; | 65 | static char *private_zone_pkey; |
@@ -80,11 +75,6 @@ static char *pin_zone_pkey = "72QC35CO20UJN1E91KPJFNT9TG4CLKAPB4VK9S3Q758S9MLBRK | |||
80 | static int found_private_rec = GNUNET_NO; | 75 | static int found_private_rec = GNUNET_NO; |
81 | 76 | ||
82 | /** | 77 | /** |
83 | * Set to GNUNET_YES if short record was found; | ||
84 | */ | ||
85 | static int found_short_rec = GNUNET_NO; | ||
86 | |||
87 | /** | ||
88 | * Set to GNUNET_YES if pin record was found; | 78 | * Set to GNUNET_YES if pin record was found; |
89 | */ | 79 | */ |
90 | static int found_pin_rec = GNUNET_NO; | 80 | static int found_pin_rec = GNUNET_NO; |
@@ -219,8 +209,6 @@ zone_iterator (void *cls, | |||
219 | { | 209 | { |
220 | if (0 == strcmp (rname, "private")) | 210 | if (0 == strcmp (rname, "private")) |
221 | check_pkey (rd_len, rd, private_zone_pkey, &found_private_rec); | 211 | check_pkey (rd_len, rd, private_zone_pkey, &found_private_rec); |
222 | else if (0 == strcmp (rname, "short")) | ||
223 | check_pkey (rd_len, rd, short_zone_pkey, &found_short_rec); | ||
224 | else if (0 == strcmp (rname, "pin")) | 212 | else if (0 == strcmp (rname, "pin")) |
225 | check_pkey (rd_len, rd, pin_zone_pkey, &found_pin_rec); | 213 | check_pkey (rd_len, rd, pin_zone_pkey, &found_pin_rec); |
226 | } | 214 | } |
@@ -242,16 +230,6 @@ zone_iteration_error (void *cls) | |||
242 | return; | 230 | return; |
243 | } | 231 | } |
244 | } | 232 | } |
245 | if (!found_short_rec) | ||
246 | { | ||
247 | if (0 != run_process_and_wait (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, &st, &code, | ||
248 | "gnunet-namestore", | ||
249 | "gnunet-namestore", "-z", "master-zone", "-a", "-e", "never", "-n", "short", "-p", "-t", "PKEY", "-V", short_zone_pkey, NULL)) | ||
250 | { | ||
251 | ret = 9; | ||
252 | return; | ||
253 | } | ||
254 | } | ||
255 | if (!found_pin_rec) | 233 | if (!found_pin_rec) |
256 | { | 234 | { |
257 | if (0 != run_process_and_wait (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, &st, &code, | 235 | if (0 != run_process_and_wait (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, &st, &code, |
@@ -274,7 +252,7 @@ zone_iteration_finished (void *cls) | |||
274 | 252 | ||
275 | 253 | ||
276 | /** | 254 | /** |
277 | * Get master-zone, short-zone and private-zone keys. | 255 | * Get master-zone and private-zone keys. |
278 | * | 256 | * |
279 | * This function is initially called for all egos and then again | 257 | * This function is initially called for all egos and then again |
280 | * whenever a ego's identifier changes or if it is deleted. At the | 258 | * whenever a ego's identifier changes or if it is deleted. At the |
@@ -316,7 +294,6 @@ get_ego (void *cls, | |||
316 | if (NULL == ego) | 294 | if (NULL == ego) |
317 | { | 295 | { |
318 | if (NULL == master_zone_pkey || | 296 | if (NULL == master_zone_pkey || |
319 | NULL == short_zone_pkey || | ||
320 | NULL == private_zone_pkey) | 297 | NULL == private_zone_pkey) |
321 | { | 298 | { |
322 | ret = 11; | 299 | ret = 11; |
@@ -340,8 +317,6 @@ get_ego (void *cls, | |||
340 | master_zone_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); | 317 | master_zone_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); |
341 | master_pk = *GNUNET_IDENTITY_ego_get_private_key (ego); | 318 | master_pk = *GNUNET_IDENTITY_ego_get_private_key (ego); |
342 | } | 319 | } |
343 | else if (NULL == short_zone_pkey && 0 == strcmp ("short-zone", identifier)) | ||
344 | short_zone_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); | ||
345 | else if (NULL == private_zone_pkey && 0 == strcmp ("private-zone", identifier)) | 320 | else if (NULL == private_zone_pkey && 0 == strcmp ("private-zone", identifier)) |
346 | private_zone_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); | 321 | private_zone_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); |
347 | } | 322 | } |
@@ -357,8 +332,6 @@ shutdown_task (void *cls) | |||
357 | { | 332 | { |
358 | GNUNET_free_non_null (master_zone_pkey); | 333 | GNUNET_free_non_null (master_zone_pkey); |
359 | master_zone_pkey = NULL; | 334 | master_zone_pkey = NULL; |
360 | GNUNET_free_non_null (short_zone_pkey); | ||
361 | short_zone_pkey = NULL; | ||
362 | GNUNET_free_non_null (private_zone_pkey); | 335 | GNUNET_free_non_null (private_zone_pkey); |
363 | private_zone_pkey = NULL; | 336 | private_zone_pkey = NULL; |
364 | if (NULL != list_it) | 337 | if (NULL != list_it) |
@@ -411,11 +384,6 @@ run (void *cls, char *const *args, const char *cfgfile, | |||
411 | 384 | ||
412 | if (0 != run_process_and_wait (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, &st, &code, | 385 | if (0 != run_process_and_wait (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, &st, &code, |
413 | "gnunet-identity", | 386 | "gnunet-identity", |
414 | "gnunet-identity", "-C", "short-zone", NULL)) | ||
415 | return; | ||
416 | |||
417 | if (0 != run_process_and_wait (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, &st, &code, | ||
418 | "gnunet-identity", | ||
419 | "gnunet-identity", "-C", "private-zone", NULL)) | 387 | "gnunet-identity", "-C", "private-zone", NULL)) |
420 | return; | 388 | return; |
421 | 389 | ||
@@ -426,11 +394,6 @@ run (void *cls, char *const *args, const char *cfgfile, | |||
426 | 394 | ||
427 | if (0 != run_process_and_wait (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, &st, &code, | 395 | if (0 != run_process_and_wait (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, &st, &code, |
428 | "gnunet-identity", | 396 | "gnunet-identity", |
429 | "gnunet-identity", "-e", "short-zone", "-s", "gns-short", NULL)) | ||
430 | return; | ||
431 | |||
432 | if (0 != run_process_and_wait (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, &st, &code, | ||
433 | "gnunet-identity", | ||
434 | "gnunet-identity", "-e", "master-zone", "-s", "gns-master", NULL)) | 397 | "gnunet-identity", "-e", "master-zone", "-s", "gns-master", NULL)) |
435 | return; | 398 | return; |
436 | 399 | ||
diff --git a/src/include/Makefile.am b/src/include/Makefile.am index b745da125..e5abec416 100644 --- a/src/include/Makefile.am +++ b/src/include/Makefile.am | |||
@@ -48,6 +48,7 @@ gnunetinclude_HEADERS = \ | |||
48 | gnunet_datacache_plugin.h \ | 48 | gnunet_datacache_plugin.h \ |
49 | gnunet_datastore_service.h \ | 49 | gnunet_datastore_service.h \ |
50 | gnunet_datastore_plugin.h \ | 50 | gnunet_datastore_plugin.h \ |
51 | gnunet_db_lib.h \ | ||
51 | gnunet_dht_service.h \ | 52 | gnunet_dht_service.h \ |
52 | gnunet_disk_lib.h \ | 53 | gnunet_disk_lib.h \ |
53 | gnunet_dnsparser_lib.h \ | 54 | gnunet_dnsparser_lib.h \ |
@@ -90,7 +91,6 @@ gnunetinclude_HEADERS = \ | |||
90 | gnunet_peerstore_service.h \ | 91 | gnunet_peerstore_service.h \ |
91 | gnunet_plugin_lib.h \ | 92 | gnunet_plugin_lib.h \ |
92 | gnunet_pq_lib.h \ | 93 | gnunet_pq_lib.h \ |
93 | gnunet_postgres_lib.h \ | ||
94 | gnunet_psycstore_plugin.h \ | 94 | gnunet_psycstore_plugin.h \ |
95 | gnunet_psycstore_service.h \ | 95 | gnunet_psycstore_service.h \ |
96 | gnunet_psyc_service.h \ | 96 | gnunet_psyc_service.h \ |
diff --git a/src/include/gnunet_db_lib.h b/src/include/gnunet_db_lib.h new file mode 100644 index 000000000..9356f66cb --- /dev/null +++ b/src/include/gnunet_db_lib.h | |||
@@ -0,0 +1,61 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify it under the | ||
6 | terms of the GNU General Public License as published by the Free Software | ||
7 | Foundation; either version 3, or (at your option) any later version. | ||
8 | |||
9 | GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY | ||
10 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
11 | A PARTICULAR PURPOSE. See the GNU General Public License for more details. | ||
12 | |||
13 | You should have received a copy of the GNU General Public License along with | ||
14 | GNUnet; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/> | ||
15 | */ | ||
16 | /** | ||
17 | * @file include/gnunet_db_lib.h | ||
18 | * @brief shared defintions for transactional databases | ||
19 | * @author Christian Grothoff | ||
20 | */ | ||
21 | #ifndef GNUNET_DB_LIB_H | ||
22 | #define GNUNET_DB_LIB_H | ||
23 | |||
24 | |||
25 | /** | ||
26 | * Status code returned from functions running database commands. | ||
27 | * Can be combined with a function that returns the number | ||
28 | * of results, so all non-negative values indicate success. | ||
29 | */ | ||
30 | enum GNUNET_DB_QueryStatus | ||
31 | { | ||
32 | /** | ||
33 | * A hard error occurred, retrying will not help. | ||
34 | */ | ||
35 | GNUNET_DB_STATUS_HARD_ERROR = -2, | ||
36 | |||
37 | /** | ||
38 | * A soft error occurred, retrying the transaction may succeed. | ||
39 | * Includes DEADLOCKS and SERIALIZATION errors. | ||
40 | */ | ||
41 | GNUNET_DB_STATUS_SOFT_ERROR = -1, | ||
42 | |||
43 | /** | ||
44 | * The transaction succeeded, but yielded zero results. | ||
45 | * May include the case where an INSERT failed with UNIQUE | ||
46 | * violation (i.e. row already exists) or where DELETE | ||
47 | * failed to remove anything (i.e. nothing matched). | ||
48 | */ | ||
49 | GNUNET_DB_STATUS_SUCCESS_NO_RESULTS = 0, | ||
50 | |||
51 | /** | ||
52 | * The transaction succeeded, and yielded one result. | ||
53 | */ | ||
54 | GNUNET_DB_STATUS_SUCCESS_ONE_RESULT = 1 | ||
55 | |||
56 | /* Larger values may be returned for SELECT statements | ||
57 | that returned more than one result. */ | ||
58 | |||
59 | }; | ||
60 | |||
61 | #endif | ||
diff --git a/src/include/gnunet_postgres_lib.h b/src/include/gnunet_postgres_lib.h deleted file mode 100644 index 66fc2a5df..000000000 --- a/src/include/gnunet_postgres_lib.h +++ /dev/null | |||
@@ -1,178 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2012 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @author Christian Grothoff | ||
22 | * | ||
23 | * @file | ||
24 | * Helper library to access a PostgreSQL database | ||
25 | * | ||
26 | * @defgroup postgres PostgreSQL library | ||
27 | * Helper library to access a PostgreSQL database. | ||
28 | * @{ | ||
29 | */ | ||
30 | #ifndef GNUNET_POSTGRES_LIB_H | ||
31 | #define GNUNET_POSTGRES_LIB_H | ||
32 | |||
33 | #include "gnunet_util_lib.h" | ||
34 | #include <libpq-fe.h> | ||
35 | |||
36 | #ifdef __cplusplus | ||
37 | extern "C" | ||
38 | { | ||
39 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
40 | } | ||
41 | #endif | ||
42 | #endif | ||
43 | |||
44 | |||
45 | /** | ||
46 | * Check if the result obtained from Postgres has | ||
47 | * the desired status code. If not, log an error, clear the | ||
48 | * result and return #GNUNET_SYSERR. | ||
49 | * | ||
50 | * @param dbh database handle | ||
51 | * @param ret return value from database operation to check | ||
52 | * @param expected_status desired status | ||
53 | * @param command description of the command that was run | ||
54 | * @param args arguments given to the command | ||
55 | * @param filename name of the source file where the command was run | ||
56 | * @param line line number in the source file | ||
57 | * @return #GNUNET_OK if the result is acceptable | ||
58 | */ | ||
59 | int | ||
60 | GNUNET_POSTGRES_check_result_ (PGconn *dbh, | ||
61 | PGresult *ret, | ||
62 | int expected_status, | ||
63 | const char *command, | ||
64 | const char *args, | ||
65 | const char *filename, | ||
66 | int line); | ||
67 | |||
68 | |||
69 | /** | ||
70 | * Check if the result obtained from Postgres has | ||
71 | * the desired status code. If not, log an error, clear the | ||
72 | * result and return #GNUNET_SYSERR. | ||
73 | * | ||
74 | * @param dbh database handle | ||
75 | * @param ret return value from database operation to check | ||
76 | * @param expected_status desired status | ||
77 | * @param command description of the command that was run | ||
78 | * @param args arguments given to the command | ||
79 | * @return #GNUNET_OK if the result is acceptable | ||
80 | */ | ||
81 | #define GNUNET_POSTGRES_check_result(dbh,ret,expected_status,command,args) GNUNET_POSTGRES_check_result_(dbh,ret,expected_status,command,args,__FILE__,__LINE__) | ||
82 | |||
83 | |||
84 | /** | ||
85 | * Run simple SQL statement (without results). | ||
86 | * | ||
87 | * @param dbh database handle | ||
88 | * @param sql statement to run | ||
89 | * @param filename filename for error reporting | ||
90 | * @param line code line for error reporting | ||
91 | * @return #GNUNET_OK on success | ||
92 | */ | ||
93 | int | ||
94 | GNUNET_POSTGRES_exec_ (PGconn *dbh, | ||
95 | const char *sql, | ||
96 | const char *filename, | ||
97 | int line); | ||
98 | |||
99 | |||
100 | /** | ||
101 | * Run simple SQL statement (without results). | ||
102 | * | ||
103 | * @param dbh database handle | ||
104 | * @param sql statement to run | ||
105 | * @return #GNUNET_OK on success | ||
106 | */ | ||
107 | #define GNUNET_POSTGRES_exec(dbh,sql) GNUNET_POSTGRES_exec_(dbh,sql,__FILE__,__LINE__) | ||
108 | |||
109 | |||
110 | /** | ||
111 | * Prepare SQL statement. | ||
112 | * | ||
113 | * @param dbh database handle | ||
114 | * @param name name for the prepared SQL statement | ||
115 | * @param sql SQL code to prepare | ||
116 | * @param nparams number of parameters in sql | ||
117 | * @param filename filename for error reporting | ||
118 | * @param line code line for error reporting | ||
119 | * @return #GNUNET_OK on success | ||
120 | */ | ||
121 | int | ||
122 | GNUNET_POSTGRES_prepare_ (PGconn *dbh, | ||
123 | const char *name, | ||
124 | const char *sql, | ||
125 | int nparams, | ||
126 | const char *filename, | ||
127 | int line); | ||
128 | |||
129 | |||
130 | /** | ||
131 | * Prepare SQL statement. | ||
132 | * | ||
133 | * @param dbh database handle | ||
134 | * @param name name for the prepared SQL statement | ||
135 | * @param sql SQL code to prepare | ||
136 | * @param nparams number of parameters in sql | ||
137 | * @return #GNUNET_OK on success | ||
138 | */ | ||
139 | #define GNUNET_POSTGRES_prepare(dbh,name,sql,nparams) GNUNET_POSTGRES_prepare_(dbh,name,sql,nparams,__FILE__,__LINE__) | ||
140 | |||
141 | |||
142 | /** | ||
143 | * Connect to a postgres database | ||
144 | * | ||
145 | * @param cfg configuration | ||
146 | * @param section configuration section to use to get Postgres configuration options | ||
147 | * @return the postgres handle | ||
148 | */ | ||
149 | PGconn * | ||
150 | GNUNET_POSTGRES_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
151 | const char *section); | ||
152 | |||
153 | |||
154 | /** | ||
155 | * Delete the row identified by the given rowid (qid | ||
156 | * in postgres). | ||
157 | * | ||
158 | * @param dbh database handle | ||
159 | * @param stmt name of the prepared statement | ||
160 | * @param rowid which row to delete | ||
161 | * @return #GNUNET_OK on success | ||
162 | */ | ||
163 | int | ||
164 | GNUNET_POSTGRES_delete_by_rowid (PGconn *dbh, | ||
165 | const char *stmt, | ||
166 | uint32_t rowid); | ||
167 | |||
168 | |||
169 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
170 | { | ||
171 | #endif | ||
172 | #ifdef __cplusplus | ||
173 | } | ||
174 | #endif | ||
175 | |||
176 | #endif | ||
177 | |||
178 | /** @} */ /* end of group */ | ||
diff --git a/src/include/gnunet_pq_lib.h b/src/include/gnunet_pq_lib.h index 756370b74..ed295b500 100644 --- a/src/include/gnunet_pq_lib.h +++ b/src/include/gnunet_pq_lib.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet | 2 | This file is part of GNUnet |
3 | Copyright (C) 2016 GNUnet e.V. | 3 | Copyright (C) 2016, 2017 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify it under the | 5 | GNUnet is free software; you can redistribute it and/or modify it under the |
6 | terms of the GNU General Public License as published by the Free Software | 6 | terms of the GNU General Public License as published by the Free Software |
@@ -23,6 +23,9 @@ | |||
23 | 23 | ||
24 | #include <libpq-fe.h> | 24 | #include <libpq-fe.h> |
25 | #include "gnunet_util_lib.h" | 25 | #include "gnunet_util_lib.h" |
26 | #include "gnunet_db_lib.h" | ||
27 | |||
28 | /* ************************* pq_query_helper.c functions ************************ */ | ||
26 | 29 | ||
27 | 30 | ||
28 | /** | 31 | /** |
@@ -188,6 +191,9 @@ struct GNUNET_PQ_QueryParam | |||
188 | GNUNET_PQ_query_param_uint64 (const uint64_t *x); | 191 | GNUNET_PQ_query_param_uint64 (const uint64_t *x); |
189 | 192 | ||
190 | 193 | ||
194 | /* ************************* pq_result_helper.c functions ************************ */ | ||
195 | |||
196 | |||
191 | /** | 197 | /** |
192 | * Extract data from a Postgres database @a result at row @a row. | 198 | * Extract data from a Postgres database @a result at row @a row. |
193 | * | 199 | * |
@@ -412,6 +418,8 @@ GNUNET_PQ_result_spec_uint64 (const char *name, | |||
412 | uint64_t *u64); | 418 | uint64_t *u64); |
413 | 419 | ||
414 | 420 | ||
421 | /* ************************* pq.c functions ************************ */ | ||
422 | |||
415 | /** | 423 | /** |
416 | * Execute a prepared statement. | 424 | * Execute a prepared statement. |
417 | * | 425 | * |
@@ -419,6 +427,7 @@ GNUNET_PQ_result_spec_uint64 (const char *name, | |||
419 | * @param name name of the prepared statement | 427 | * @param name name of the prepared statement |
420 | * @param params parameters to the statement | 428 | * @param params parameters to the statement |
421 | * @return postgres result | 429 | * @return postgres result |
430 | * @deprecated (should become an internal API) | ||
422 | */ | 431 | */ |
423 | PGresult * | 432 | PGresult * |
424 | GNUNET_PQ_exec_prepared (PGconn *db_conn, | 433 | GNUNET_PQ_exec_prepared (PGconn *db_conn, |
@@ -435,6 +444,7 @@ GNUNET_PQ_exec_prepared (PGconn *db_conn, | |||
435 | * @return | 444 | * @return |
436 | * #GNUNET_YES if all results could be extracted | 445 | * #GNUNET_YES if all results could be extracted |
437 | * #GNUNET_SYSERR if a result was invalid (non-existing field) | 446 | * #GNUNET_SYSERR if a result was invalid (non-existing field) |
447 | * @deprecated (should become an internal API) | ||
438 | */ | 448 | */ |
439 | int | 449 | int |
440 | GNUNET_PQ_extract_result (PGresult *result, | 450 | GNUNET_PQ_extract_result (PGresult *result, |
@@ -452,6 +462,262 @@ void | |||
452 | GNUNET_PQ_cleanup_result (struct GNUNET_PQ_ResultSpec *rs); | 462 | GNUNET_PQ_cleanup_result (struct GNUNET_PQ_ResultSpec *rs); |
453 | 463 | ||
454 | 464 | ||
465 | /* ******************** pq_eval.c functions ************** */ | ||
466 | |||
467 | |||
468 | /** | ||
469 | * Check the @a result's error code to see what happened. | ||
470 | * Also logs errors. | ||
471 | * | ||
472 | * @param connection connection to execute the statement in | ||
473 | * @param statement_name name of the statement that created @a result | ||
474 | * @param result result to check | ||
475 | * @return status code from the result, mapping PQ status | ||
476 | * codes to `enum GNUNET_DB_QueryStatus`. Never | ||
477 | * returns positive values as this function does | ||
478 | * not look at the result set. | ||
479 | * @deprecated (low level, let's see if we can do with just the high-level functions) | ||
480 | */ | ||
481 | enum GNUNET_DB_QueryStatus | ||
482 | GNUNET_PQ_eval_result (PGconn *connection, | ||
483 | const char *statement_name, | ||
484 | PGresult *result); | ||
485 | |||
486 | |||
487 | /** | ||
488 | * Execute a named prepared @a statement that is NOT a SELECT | ||
489 | * statement in @a connnection using the given @a params. Returns the | ||
490 | * resulting session state. | ||
491 | * | ||
492 | * @param connection connection to execute the statement in | ||
493 | * @param statement_name name of the statement | ||
494 | * @param params parameters to give to the statement (#GNUNET_PQ_query_param_end-terminated) | ||
495 | * @return status code from the result, mapping PQ status | ||
496 | * codes to `enum GNUNET_DB_QueryStatus`. If the | ||
497 | * statement was a DELETE or UPDATE statement, the | ||
498 | * number of affected rows is returned; if the | ||
499 | * statment was an INSERT statement, and no row | ||
500 | * was added due to a UNIQUE violation, we return | ||
501 | * zero; if INSERT was successful, we return one. | ||
502 | */ | ||
503 | enum GNUNET_DB_QueryStatus | ||
504 | GNUNET_PQ_eval_prepared_non_select (PGconn *connection, | ||
505 | const char *statement_name, | ||
506 | const struct GNUNET_PQ_QueryParam *params); | ||
507 | |||
508 | |||
509 | /** | ||
510 | * Function to be called with the results of a SELECT statement | ||
511 | * that has returned @a num_results results. | ||
512 | * | ||
513 | * @param cls closure | ||
514 | * @param result the postgres result | ||
515 | * @param num_result the number of results in @a result | ||
516 | */ | ||
517 | typedef void | ||
518 | (*GNUNET_PQ_PostgresResultHandler)(void *cls, | ||
519 | PGresult *result, | ||
520 | unsigned int num_results); | ||
521 | |||
522 | |||
523 | /** | ||
524 | * Execute a named prepared @a statement that is a SELECT statement | ||
525 | * which may return multiple results in @a connection using the given | ||
526 | * @a params. Call @a rh with the results. Returns the query | ||
527 | * status including the number of results given to @a rh (possibly zero). | ||
528 | * @a rh will not have been called if the return value is negative. | ||
529 | * | ||
530 | * @param connection connection to execute the statement in | ||
531 | * @param statement_name name of the statement | ||
532 | * @param params parameters to give to the statement (#GNUNET_PQ_query_param_end-terminated) | ||
533 | * @param rh function to call with the result set, NULL to ignore | ||
534 | * @param rh_cls closure to pass to @a rh | ||
535 | * @return status code from the result, mapping PQ status | ||
536 | * codes to `enum GNUNET_DB_QueryStatus`. | ||
537 | */ | ||
538 | enum GNUNET_DB_QueryStatus | ||
539 | GNUNET_PQ_eval_prepared_multi_select (PGconn *connection, | ||
540 | const char *statement_name, | ||
541 | const struct GNUNET_PQ_QueryParam *params, | ||
542 | GNUNET_PQ_PostgresResultHandler rh, | ||
543 | void *rh_cls); | ||
544 | |||
545 | |||
546 | /** | ||
547 | * Execute a named prepared @a statement that is a SELECT statement | ||
548 | * which must return a single result in @a connection using the given | ||
549 | * @a params. Stores the result (if any) in @a rs, which the caller | ||
550 | * must then clean up using #GNUNET_PQ_cleanup_result() if the return | ||
551 | * value was #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT. Returns the | ||
552 | * resulting session status. | ||
553 | * | ||
554 | * @param connection connection to execute the statement in | ||
555 | * @param statement_name name of the statement | ||
556 | * @param params parameters to give to the statement (#GNUNET_PQ_query_param_end-terminated) | ||
557 | * @param[in,out] rs result specification to use for storing the result of the query | ||
558 | * @return status code from the result, mapping PQ status | ||
559 | * codes to `enum GNUNET_DB_QueryStatus`. | ||
560 | */ | ||
561 | enum GNUNET_DB_QueryStatus | ||
562 | GNUNET_PQ_eval_prepared_singleton_select (PGconn *connection, | ||
563 | const char *statement_name, | ||
564 | const struct GNUNET_PQ_QueryParam *params, | ||
565 | struct GNUNET_PQ_ResultSpec *rs); | ||
566 | |||
567 | |||
568 | /* ******************** pq_prepare.c functions ************** */ | ||
569 | |||
570 | |||
571 | /** | ||
572 | * Information needed to prepare a list of SQL statements using | ||
573 | * #GNUNET_PQ_prepare_statements(). | ||
574 | */ | ||
575 | struct GNUNET_PQ_PreparedStatement { | ||
576 | |||
577 | /** | ||
578 | * Name of the statement. | ||
579 | */ | ||
580 | const char *name; | ||
581 | |||
582 | /** | ||
583 | * Actual SQL statement. | ||
584 | */ | ||
585 | const char *sql; | ||
586 | |||
587 | /** | ||
588 | * Number of arguments included in @e sql. | ||
589 | */ | ||
590 | unsigned int num_arguments; | ||
591 | |||
592 | }; | ||
593 | |||
594 | |||
595 | /** | ||
596 | * Terminator for prepared statement list. | ||
597 | */ | ||
598 | #define GNUNET_PQ_PREPARED_STATEMENT_END { NULL, NULL, 0 } | ||
599 | |||
600 | |||
601 | /** | ||
602 | * Create a `struct GNUNET_PQ_PreparedStatement`. | ||
603 | * | ||
604 | * @param name name of the statement | ||
605 | * @param sql actual SQL statement | ||
606 | * @param num_args number of arguments in the statement | ||
607 | * @return initialized struct | ||
608 | */ | ||
609 | struct GNUNET_PQ_PreparedStatement | ||
610 | GNUNET_PQ_make_prepare (const char *name, | ||
611 | const char *sql, | ||
612 | unsigned int num_args); | ||
613 | |||
614 | |||
615 | /** | ||
616 | * Request creation of prepared statements @a ps from Postgres. | ||
617 | * | ||
618 | * @param connection connection to prepare the statements for | ||
619 | * @param ps #GNUNET_PQ_PREPARED_STATEMENT_END-terminated array of prepared | ||
620 | * statements. | ||
621 | * @return #GNUNET_OK on success, | ||
622 | * #GNUNET_SYSERR on error | ||
623 | */ | ||
624 | int | ||
625 | GNUNET_PQ_prepare_statements (PGconn *connection, | ||
626 | const struct GNUNET_PQ_PreparedStatement *ps); | ||
627 | |||
628 | |||
629 | /* ******************** pq_exec.c functions ************** */ | ||
630 | |||
631 | |||
632 | /** | ||
633 | * Information needed to run a list of SQL statements using | ||
634 | * #GNUNET_PQ_exec_statements(). | ||
635 | */ | ||
636 | struct GNUNET_PQ_ExecuteStatement { | ||
637 | |||
638 | /** | ||
639 | * Actual SQL statement. | ||
640 | */ | ||
641 | const char *sql; | ||
642 | |||
643 | /** | ||
644 | * Should we ignore errors? | ||
645 | */ | ||
646 | int ignore_errors; | ||
647 | |||
648 | }; | ||
649 | |||
650 | |||
651 | /** | ||
652 | * Terminator for executable statement list. | ||
653 | */ | ||
654 | #define GNUNET_PQ_EXECUTE_STATEMENT_END { NULL, GNUNET_SYSERR } | ||
655 | |||
656 | |||
657 | /** | ||
658 | * Create a `struct GNUNET_PQ_ExecuteStatement` where errors are fatal. | ||
659 | * | ||
660 | * @param sql actual SQL statement | ||
661 | * @return initialized struct | ||
662 | */ | ||
663 | struct GNUNET_PQ_ExecuteStatement | ||
664 | GNUNET_PQ_make_execute (const char *sql); | ||
665 | |||
666 | |||
667 | /** | ||
668 | * Create a `struct GNUNET_PQ_ExecuteStatement` where errors should | ||
669 | * be tolerated. | ||
670 | * | ||
671 | * @param sql actual SQL statement | ||
672 | * @return initialized struct | ||
673 | */ | ||
674 | struct GNUNET_PQ_ExecuteStatement | ||
675 | GNUNET_PQ_make_try_execute (const char *sql); | ||
676 | |||
677 | |||
678 | /** | ||
679 | * Request execution of an array of statements @a es from Postgres. | ||
680 | * | ||
681 | * @param connection connection to execute the statements over | ||
682 | * @param es #GNUNET_PQ_PREPARED_STATEMENT_END-terminated array of prepared | ||
683 | * statements. | ||
684 | * @return #GNUNET_OK on success (modulo statements where errors can be ignored) | ||
685 | * #GNUNET_SYSERR on error | ||
686 | */ | ||
687 | int | ||
688 | GNUNET_PQ_exec_statements (PGconn *connection, | ||
689 | const struct GNUNET_PQ_ExecuteStatement *es); | ||
690 | |||
691 | |||
692 | /* ******************** pq_connect.c functions ************** */ | ||
693 | |||
694 | |||
695 | /** | ||
696 | * Create a connection to the Postgres database using @a config_str | ||
697 | * for the configuration. Initialize logging via GNUnet's log | ||
698 | * routines and disable Postgres's logger. | ||
699 | * | ||
700 | * @param config_str configuration to use | ||
701 | * @return NULL on error | ||
702 | */ | ||
703 | PGconn * | ||
704 | GNUNET_PQ_connect (const char *config_str); | ||
705 | |||
706 | |||
707 | /** | ||
708 | * Connect to a postgres database using the configuration | ||
709 | * option "CONFIG" in @a section. | ||
710 | * | ||
711 | * @param cfg configuration | ||
712 | * @param section configuration section to use to get Postgres configuration options | ||
713 | * @return the postgres handle, NULL on error | ||
714 | */ | ||
715 | PGconn * | ||
716 | GNUNET_PQ_connect_with_cfg (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
717 | const char *section); | ||
718 | |||
719 | |||
720 | |||
455 | #endif /* GNUNET_PQ_LIB_H_ */ | 721 | #endif /* GNUNET_PQ_LIB_H_ */ |
456 | 722 | ||
457 | /* end of include/gnunet_pq_lib.h */ | 723 | /* end of include/gnunet_pq_lib.h */ |
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h index 1d8049593..455a8292b 100644 --- a/src/include/gnunet_protocols.h +++ b/src/include/gnunet_protocols.h | |||
@@ -1814,6 +1814,13 @@ extern "C" | |||
1814 | */ | 1814 | */ |
1815 | #define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_ELEMENT 598 | 1815 | #define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_ELEMENT 598 |
1816 | 1816 | ||
1817 | /** | ||
1818 | * Request all missing elements from the other peer, | ||
1819 | * based on their sets and the elements we previously sent | ||
1820 | * with #GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENTS. | ||
1821 | */ | ||
1822 | #define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_OVER 599 | ||
1823 | |||
1817 | 1824 | ||
1818 | /******************************************************************************* | 1825 | /******************************************************************************* |
1819 | * TESTBED LOGGER message types | 1826 | * TESTBED LOGGER message types |
diff --git a/src/include/gnunet_strings_lib.h b/src/include/gnunet_strings_lib.h index 144780c82..897f9f161 100644 --- a/src/include/gnunet_strings_lib.h +++ b/src/include/gnunet_strings_lib.h | |||
@@ -281,7 +281,7 @@ GNUNET_STRINGS_get_short_name (const char *filename); | |||
281 | 281 | ||
282 | 282 | ||
283 | /** | 283 | /** |
284 | * Convert binary data to ASCII encoding using Base32Hex (RFC 4648). | 284 | * Convert binary data to ASCII encoding using CrockfordBase32. |
285 | * Does not append 0-terminator, but returns a pointer to the place where | 285 | * Does not append 0-terminator, but returns a pointer to the place where |
286 | * it should be placed, if needed. | 286 | * it should be placed, if needed. |
287 | * | 287 | * |
@@ -315,7 +315,7 @@ GNUNET_STRINGS_data_to_string_alloc (const void *buf, | |||
315 | 315 | ||
316 | 316 | ||
317 | /** | 317 | /** |
318 | * Convert Base32hex encoding back to data. | 318 | * Convert CrockfordBase32 encoding back to data. |
319 | * @a out_size must match exactly the size of the data before it was encoded. | 319 | * @a out_size must match exactly the size of the data before it was encoded. |
320 | * | 320 | * |
321 | * @param enc the encoding | 321 | * @param enc the encoding |
diff --git a/src/multicast/Makefile.am b/src/multicast/Makefile.am index 8a754d3db..a4054f5f6 100644 --- a/src/multicast/Makefile.am +++ b/src/multicast/Makefile.am | |||
@@ -51,7 +51,7 @@ gnunet_service_multicast_LDADD = \ | |||
51 | $(GN_LIBINTL) | 51 | $(GN_LIBINTL) |
52 | 52 | ||
53 | check_PROGRAMS = \ | 53 | check_PROGRAMS = \ |
54 | test_multicast_multipeer | 54 | test_multicast_multipeer |
55 | # test_multicast | 55 | # test_multicast |
56 | # test_multicast_2peers | 56 | # test_multicast_2peers |
57 | 57 | ||
diff --git a/src/multicast/gnunet-service-multicast.c b/src/multicast/gnunet-service-multicast.c index 9683efcff..39623e7b1 100644 --- a/src/multicast/gnunet-service-multicast.c +++ b/src/multicast/gnunet-service-multicast.c | |||
@@ -1504,13 +1504,12 @@ handle_client_member_join (void *cls, | |||
1504 | cl->client = client; | 1504 | cl->client = client; |
1505 | GNUNET_CONTAINER_DLL_insert (grp->clients_head, grp->clients_tail, cl); | 1505 | GNUNET_CONTAINER_DLL_insert (grp->clients_head, grp->clients_tail, cl); |
1506 | 1506 | ||
1507 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1508 | "%p Client connected to group %s..\n", | ||
1509 | mem, GNUNET_h2s (&grp->pub_key_hash)); | ||
1510 | char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&mem->pub_key); | 1507 | char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&mem->pub_key); |
1511 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1508 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1512 | "%p ..as member %s (%s).\n", | 1509 | "Client connected to group %s as member %s (%s).\n", |
1513 | mem, GNUNET_h2s (&mem->pub_key_hash), str); | 1510 | GNUNET_h2s (&grp->pub_key_hash), |
1511 | GNUNET_h2s (&mem->pub_key_hash), | ||
1512 | str); | ||
1514 | GNUNET_free (str); | 1513 | GNUNET_free (str); |
1515 | 1514 | ||
1516 | if (NULL != mem->join_dcsn) | 1515 | if (NULL != mem->join_dcsn) |
diff --git a/src/multicast/test_multicast.conf b/src/multicast/test_multicast.conf index 3081aeecc..3dc96adbb 100644 --- a/src/multicast/test_multicast.conf +++ b/src/multicast/test_multicast.conf | |||
@@ -1,12 +1,55 @@ | |||
1 | [testbed] | 1 | [testbed] |
2 | HOSTNAME = localhost | 2 | HOSTNAME = localhost |
3 | #OVERLAY_TOPOLOGY = LINE | ||
3 | 4 | ||
4 | [arm] | 5 | [arm] |
5 | GLOBAL_POSTFIX=-L ERROR | 6 | GLOBAL_POSTFIX=-L ERROR |
6 | 7 | ||
8 | [hostlist] | ||
9 | SERVERS = http://localhost:8080/ | ||
10 | |||
7 | [multicast] | 11 | [multicast] |
8 | #PREFIX = xterm -T peer -e gdb --args | 12 | #PREFIX = tmux split-window -v gdb -x ./cmd.gdb --args |
9 | UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-multicast.sock | 13 | UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-multicast.sock |
10 | 14 | ||
11 | [vpn] | 15 | [vpn] |
12 | AUTOSTART = NO | 16 | AUTOSTART = NO |
17 | |||
18 | [peerinfo] | ||
19 | # Do not use shipped gnunet HELLOs | ||
20 | USE_INCLUDED_HELLOS = NO | ||
21 | |||
22 | # Option to disable all disk IO; only useful for testbed runs | ||
23 | # (large-scale experiments); disables persistence of HELLOs! | ||
24 | NO_IO = YES | ||
25 | |||
26 | [nat] | ||
27 | ENABLE_UPNP = NO | ||
28 | |||
29 | [fs] | ||
30 | FORCESTART = NO | ||
31 | AUTOSTART = NO | ||
32 | |||
33 | [vpn] | ||
34 | FORCESTART = NO | ||
35 | AUTOSTART = NO | ||
36 | |||
37 | [revocation] | ||
38 | FORCESTART = NO | ||
39 | AUTOSTART = NO | ||
40 | |||
41 | [gns] | ||
42 | FORCESTART = NO | ||
43 | AUTOSTART = NO | ||
44 | |||
45 | [namestore] | ||
46 | FORCESTART = NO | ||
47 | AUTOSTART = NO | ||
48 | |||
49 | [namecache] | ||
50 | FORCESTART = NO | ||
51 | AUTOSTART = NO | ||
52 | |||
53 | [topology] | ||
54 | FORCESTART = NO | ||
55 | AUTOSTART = NO | ||
diff --git a/src/multicast/test_multicast_multipeer.c b/src/multicast/test_multicast_multipeer.c index c2078abf9..5c3664f35 100644 --- a/src/multicast/test_multicast_multipeer.c +++ b/src/multicast/test_multicast_multipeer.c | |||
@@ -33,14 +33,15 @@ | |||
33 | #include "gnunet_testbed_service.h" | 33 | #include "gnunet_testbed_service.h" |
34 | #include "gnunet_multicast_service.h" | 34 | #include "gnunet_multicast_service.h" |
35 | 35 | ||
36 | #define NUM_PEERS 3 | 36 | #define NUM_PEERS 2 |
37 | 37 | ||
38 | struct multicast_peer | 38 | struct multicast_peer |
39 | { | 39 | { |
40 | int peer; /* peer number */ | 40 | int peer; /* peer number */ |
41 | const struct GNUNET_PeerIdentity *id; | ||
41 | struct GNUNET_TESTBED_Operation *op; /* not yet in use */ | 42 | struct GNUNET_TESTBED_Operation *op; /* not yet in use */ |
42 | struct GNUNET_TESTBED_Operation *pi_op; /* not yet in use */ | 43 | struct GNUNET_TESTBED_Operation *pi_op; /* not yet in use */ |
43 | uint8_t test_ok; | 44 | int test_ok; |
44 | }; | 45 | }; |
45 | 46 | ||
46 | static void service_connect (void *cls, | 47 | static void service_connect (void *cls, |
@@ -54,7 +55,6 @@ static struct GNUNET_TESTBED_Peer **peers; | |||
54 | // FIXME: refactor | 55 | // FIXME: refactor |
55 | static struct GNUNET_TESTBED_Operation *op[NUM_PEERS]; | 56 | static struct GNUNET_TESTBED_Operation *op[NUM_PEERS]; |
56 | static struct GNUNET_TESTBED_Operation *pi_op[NUM_PEERS]; | 57 | static struct GNUNET_TESTBED_Operation *pi_op[NUM_PEERS]; |
57 | static const struct GNUNET_PeerIdentity *peer_id[NUM_PEERS]; | ||
58 | 58 | ||
59 | static struct GNUNET_MULTICAST_Origin *origin; | 59 | static struct GNUNET_MULTICAST_Origin *origin; |
60 | static struct GNUNET_MULTICAST_Member *member[NUM_PEERS]; /* first element always empty */ | 60 | static struct GNUNET_MULTICAST_Member *member[NUM_PEERS]; /* first element always empty */ |
@@ -80,16 +80,6 @@ static int result; | |||
80 | static void | 80 | static void |
81 | shutdown_task (void *cls) | 81 | shutdown_task (void *cls) |
82 | { | 82 | { |
83 | if (NULL != mc_peers) | ||
84 | { | ||
85 | for (int i=0; i < NUM_PEERS; i++) | ||
86 | { | ||
87 | GNUNET_free (mc_peers[i]); | ||
88 | mc_peers[i] = NULL; | ||
89 | } | ||
90 | GNUNET_free (mc_peers); | ||
91 | } | ||
92 | |||
93 | for (int i=0;i<NUM_PEERS;i++) | 83 | for (int i=0;i<NUM_PEERS;i++) |
94 | { | 84 | { |
95 | if (NULL != op[i]) | 85 | if (NULL != op[i]) |
@@ -104,6 +94,16 @@ shutdown_task (void *cls) | |||
104 | } | 94 | } |
105 | } | 95 | } |
106 | 96 | ||
97 | if (NULL != mc_peers) | ||
98 | { | ||
99 | for (int i=0; i < NUM_PEERS; i++) | ||
100 | { | ||
101 | GNUNET_free (mc_peers[i]); | ||
102 | mc_peers[i] = NULL; | ||
103 | } | ||
104 | GNUNET_free (mc_peers); | ||
105 | } | ||
106 | |||
107 | if (NULL != timeout_tid) | 107 | if (NULL != timeout_tid) |
108 | { | 108 | { |
109 | GNUNET_SCHEDULER_cancel (timeout_tid); | 109 | GNUNET_SCHEDULER_cancel (timeout_tid); |
@@ -130,8 +130,9 @@ member_join_request (void *cls, | |||
130 | { | 130 | { |
131 | struct multicast_peer *mc_peer = (struct multicast_peer*)cls; | 131 | struct multicast_peer *mc_peer = (struct multicast_peer*)cls; |
132 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 132 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
133 | "Peer #%u sent a join request.\n", mc_peer->peer); | 133 | "Peer #%u (%s) sent a join request.\n", |
134 | 134 | mc_peer->peer, | |
135 | GNUNET_i2s (mc_peers[mc_peer->peer]->id)); | ||
135 | } | 136 | } |
136 | 137 | ||
137 | 138 | ||
@@ -165,7 +166,10 @@ member_join_decision (void *cls, | |||
165 | struct GNUNET_MULTICAST_MemberTransmitHandle *req; | 166 | struct GNUNET_MULTICAST_MemberTransmitHandle *req; |
166 | 167 | ||
167 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 168 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
168 | "Peer #%u received a decision from origin: %s\n", mc_peer->peer, (GNUNET_YES == is_admitted)?"accepted":"rejected"); | 169 | "Peer #%u (%s) received a decision from origin: %s\n", |
170 | mc_peer->peer, | ||
171 | GNUNET_i2s (mc_peers[mc_peer->peer]->id), | ||
172 | (GNUNET_YES == is_admitted)?"accepted":"rejected"); | ||
169 | 173 | ||
170 | if (GNUNET_YES == is_admitted) | 174 | if (GNUNET_YES == is_admitted) |
171 | { | 175 | { |
@@ -203,29 +207,30 @@ member_message (void *cls, | |||
203 | if (0 != strncmp ("pong", (char *)&msg[1], 4)) | 207 | if (0 != strncmp ("pong", (char *)&msg[1], 4)) |
204 | { | 208 | { |
205 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 209 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
206 | "peer #%i did not receive pong\n", | 210 | "peer #%i (%s) did not receive pong\n", |
207 | mc_peer->peer); | 211 | mc_peer->peer, |
212 | GNUNET_i2s (mc_peers[mc_peer->peer]->id)); | ||
208 | 213 | ||
209 | result = GNUNET_SYSERR; | 214 | result = GNUNET_SYSERR; |
210 | GNUNET_SCHEDULER_shutdown (); | 215 | GNUNET_SCHEDULER_shutdown (); |
211 | } | 216 | } |
212 | 217 | ||
213 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 218 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
214 | "peer #%i receives: %s\n", | 219 | "peer #%i (%s) receives: %s\n", |
215 | mc_peer->peer, | 220 | mc_peer->peer, |
221 | GNUNET_i2s (mc_peers[mc_peer->peer]->id), | ||
216 | (char *)&msg[1]); | 222 | (char *)&msg[1]); |
217 | 223 | ||
218 | mc_peer->test_ok = GNUNET_OK; | 224 | mc_peer->test_ok = GNUNET_OK; |
219 | 225 | ||
220 | // FIXME: ugly test function | 226 | // FIXME: ugly test function |
221 | /* | 227 | // (we start with 1 because 0 is origin) |
222 | for (int i=1; i<NUM_PEERS; i++) | 228 | for (int i=1; i<NUM_PEERS; i++) |
223 | if (!mc_peers[i]->test_ok) | 229 | if (GNUNET_NO == mc_peers[i]->test_ok) |
224 | return; | 230 | return; |
225 | 231 | ||
226 | result = GNUNET_YES; | 232 | result = GNUNET_YES; |
227 | GNUNET_SCHEDULER_shutdown(); | 233 | GNUNET_SCHEDULER_shutdown(); |
228 | */ | ||
229 | } | 234 | } |
230 | 235 | ||
231 | 236 | ||
@@ -345,7 +350,9 @@ multicast_da (void *cls, | |||
345 | else | 350 | else |
346 | { | 351 | { |
347 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 352 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
348 | "peer #%u parting from multicast group\n", mc_peer->peer); | 353 | "peer #%u (%s) parting from multicast group\n", |
354 | mc_peer->peer, | ||
355 | GNUNET_i2s (mc_peers[mc_peer->peer]->id)); | ||
349 | 356 | ||
350 | GNUNET_MULTICAST_member_part (member[mc_peer->peer], NULL, cls); | 357 | GNUNET_MULTICAST_member_part (member[mc_peer->peer], NULL, cls); |
351 | } | 358 | } |
@@ -381,9 +388,12 @@ multicast_ca (void *cls, | |||
381 | // Get members keys | 388 | // Get members keys |
382 | member_pub_key[mc_peer->peer] = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey); | 389 | member_pub_key[mc_peer->peer] = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey); |
383 | member_key[mc_peer->peer] = GNUNET_CRYPTO_ecdsa_key_create (); | 390 | member_key[mc_peer->peer] = GNUNET_CRYPTO_ecdsa_key_create (); |
384 | GNUNET_CRYPTO_ecdsa_key_get_public (member_key[mc_peer->peer], member_pub_key[mc_peer->peer]); | 391 | GNUNET_CRYPTO_ecdsa_key_get_public (member_key[mc_peer->peer], |
392 | member_pub_key[mc_peer->peer]); | ||
385 | 393 | ||
386 | sprintf(data, "Hi, I am peer #%u. Can I enter?", mc_peer->peer); | 394 | sprintf(data, "Hi, I am peer #%u (%s). Can I enter?", |
395 | mc_peer->peer, | ||
396 | GNUNET_i2s (mc_peers[mc_peer->peer]->id)); | ||
387 | uint8_t data_size = strlen (data) + 1; | 397 | uint8_t data_size = strlen (data) + 1; |
388 | join_msg = GNUNET_malloc (sizeof (join_msg) + data_size); | 398 | join_msg = GNUNET_malloc (sizeof (join_msg) + data_size); |
389 | join_msg->size = htons (sizeof (join_msg) + data_size); | 399 | join_msg->size = htons (sizeof (join_msg) + data_size); |
@@ -391,12 +401,14 @@ multicast_ca (void *cls, | |||
391 | GNUNET_memcpy (&join_msg[1], data, data_size); | 401 | GNUNET_memcpy (&join_msg[1], data, data_size); |
392 | 402 | ||
393 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 403 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
394 | "Peer #%u tries to join multicast group\n", mc_peer->peer); | 404 | "Peer #%u (%s) tries to join multicast group\n", |
405 | mc_peer->peer, | ||
406 | GNUNET_i2s (mc_peers[mc_peer->peer]->id)); | ||
395 | 407 | ||
396 | return GNUNET_MULTICAST_member_join (cfg, | 408 | return GNUNET_MULTICAST_member_join (cfg, |
397 | group_pub_key, | 409 | group_pub_key, |
398 | member_key[mc_peer->peer], | 410 | member_key[mc_peer->peer], |
399 | peer_id[0], | 411 | mc_peers[0]->id, |
400 | 0, | 412 | 0, |
401 | NULL, | 413 | NULL, |
402 | join_msg, /* join message */ | 414 | join_msg, /* join message */ |
@@ -424,13 +436,17 @@ peer_information_cb (void *cls, | |||
424 | GNUNET_SCHEDULER_shutdown (); | 436 | GNUNET_SCHEDULER_shutdown (); |
425 | } | 437 | } |
426 | 438 | ||
427 | peer_id[mc_peer->peer] = pinfo->result.id; | 439 | mc_peers[mc_peer->peer]->id = pinfo->result.id; |
428 | 440 | ||
429 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 441 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
430 | "Got peer information of %s (%s)\n", (0==mc_peer->peer)?"origin":"member" ,GNUNET_i2s(pinfo->result.id)); | 442 | "Got peer information of %s (%s)\n", |
443 | (0 == mc_peer->peer)? "origin" : "member", | ||
444 | GNUNET_i2s (pinfo->result.id)); | ||
431 | 445 | ||
432 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 446 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
433 | "Create peer #%u\n", mc_peer->peer); | 447 | "Create peer #%u (%s)\n", |
448 | mc_peer->peer, | ||
449 | GNUNET_i2s (mc_peers[mc_peer->peer]->id)); | ||
434 | 450 | ||
435 | if (0 != mc_peer->peer) | 451 | if (0 != mc_peer->peer) |
436 | { | 452 | { |
@@ -461,13 +477,18 @@ service_connect (void *cls, | |||
461 | if (NULL == ca_result) | 477 | if (NULL == ca_result) |
462 | { | 478 | { |
463 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 479 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
464 | "Connection adapter not created for peer #%u\n", mc_peer->peer); | 480 | "Connection adapter not created for peer #%u (%s)\n", |
481 | mc_peer->peer, | ||
482 | GNUNET_i2s (mc_peers[mc_peer->peer]->id)); | ||
483 | |||
465 | result = GNUNET_SYSERR; | 484 | result = GNUNET_SYSERR; |
466 | GNUNET_SCHEDULER_shutdown(); | 485 | GNUNET_SCHEDULER_shutdown(); |
467 | } | 486 | } |
468 | 487 | ||
469 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 488 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
470 | "Connected to multicast service of peer #%u\n", mc_peer->peer); | 489 | "Connected to multicast service of peer #%u (%s)\n", |
490 | mc_peer->peer, | ||
491 | GNUNET_i2s (mc_peers[mc_peer->peer]->id)); | ||
471 | 492 | ||
472 | if (0 == mc_peer->peer) | 493 | if (0 == mc_peer->peer) |
473 | { | 494 | { |
@@ -525,9 +546,6 @@ testbed_master (void *cls, | |||
525 | 546 | ||
526 | peers = p; | 547 | peers = p; |
527 | 548 | ||
528 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
529 | "Create origin peer\n"); | ||
530 | |||
531 | mc_peers = GNUNET_new_array (NUM_PEERS, struct multicast_peer*); | 549 | mc_peers = GNUNET_new_array (NUM_PEERS, struct multicast_peer*); |
532 | 550 | ||
533 | // Create test contexts for members | 551 | // Create test contexts for members |
@@ -538,6 +556,9 @@ testbed_master (void *cls, | |||
538 | mc_peers[i]->test_ok = GNUNET_NO; | 556 | mc_peers[i]->test_ok = GNUNET_NO; |
539 | } | 557 | } |
540 | 558 | ||
559 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
560 | "Create origin peer\n"); | ||
561 | |||
541 | op[0] = GNUNET_TESTBED_service_connect (NULL, /* Closure for operation */ | 562 | op[0] = GNUNET_TESTBED_service_connect (NULL, /* Closure for operation */ |
542 | peers[0], /* The peer whose service to connect to */ | 563 | peers[0], /* The peer whose service to connect to */ |
543 | "multicast", /* The name of the service */ | 564 | "multicast", /* The name of the service */ |
@@ -553,7 +574,7 @@ testbed_master (void *cls, | |||
553 | GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); /* Schedule a new task on shutdown */ | 574 | GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); /* Schedule a new task on shutdown */ |
554 | 575 | ||
555 | /* Schedule the shutdown task with a delay of a few Seconds */ | 576 | /* Schedule the shutdown task with a delay of a few Seconds */ |
556 | timeout_tid = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 80), | 577 | timeout_tid = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 400), |
557 | &timeout_task, NULL); | 578 | &timeout_task, NULL); |
558 | } | 579 | } |
559 | 580 | ||
diff --git a/src/namecache/Makefile.am b/src/namecache/Makefile.am index d379b2602..c62ca6a2b 100644 --- a/src/namecache/Makefile.am +++ b/src/namecache/Makefile.am | |||
@@ -133,7 +133,6 @@ libgnunet_plugin_namecache_postgres_la_SOURCES = \ | |||
133 | plugin_namecache_postgres.c | 133 | plugin_namecache_postgres.c |
134 | libgnunet_plugin_namecache_postgres_la_LIBADD = \ | 134 | libgnunet_plugin_namecache_postgres_la_LIBADD = \ |
135 | libgnunetnamecache.la \ | 135 | libgnunetnamecache.la \ |
136 | $(top_builddir)/src/postgres/libgnunetpostgres.la \ | ||
137 | $(top_builddir)/src/pq/libgnunetpq.la \ | 136 | $(top_builddir)/src/pq/libgnunetpq.la \ |
138 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | 137 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ |
139 | $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lpq \ | 138 | $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lpq \ |
diff --git a/src/namecache/plugin_namecache_postgres.c b/src/namecache/plugin_namecache_postgres.c index bec8bffd2..d943b0cd8 100644 --- a/src/namecache/plugin_namecache_postgres.c +++ b/src/namecache/plugin_namecache_postgres.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * This file is part of GNUnet | 2 | * This file is part of GNUnet |
3 | * Copyright (C) 2009-2013, 2016 GNUnet e.V. | 3 | * Copyright (C) 2009-2013, 2016, 2017 GNUnet e.V. |
4 | * | 4 | * |
5 | * GNUnet is free software; you can redistribute it and/or modify | 5 | * GNUnet is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published | 6 | * it under the terms of the GNU General Public License as published |
@@ -27,31 +27,10 @@ | |||
27 | #include "gnunet_namecache_plugin.h" | 27 | #include "gnunet_namecache_plugin.h" |
28 | #include "gnunet_namecache_service.h" | 28 | #include "gnunet_namecache_service.h" |
29 | #include "gnunet_gnsrecord_lib.h" | 29 | #include "gnunet_gnsrecord_lib.h" |
30 | #include "gnunet_postgres_lib.h" | ||
31 | #include "gnunet_pq_lib.h" | 30 | #include "gnunet_pq_lib.h" |
32 | #include "namecache.h" | 31 | #include "namecache.h" |
33 | 32 | ||
34 | 33 | ||
35 | /** | ||
36 | * After how many ms "busy" should a DB operation fail for good? | ||
37 | * A low value makes sure that we are more responsive to requests | ||
38 | * (especially PUTs). A high value guarantees a higher success | ||
39 | * rate (SELECTs in iterate can take several seconds despite LIMIT=1). | ||
40 | * | ||
41 | * The default value of 1s should ensure that users do not experience | ||
42 | * huge latencies while at the same time allowing operations to succeed | ||
43 | * with reasonable probability. | ||
44 | */ | ||
45 | #define BUSY_TIMEOUT_MS 1000 | ||
46 | |||
47 | |||
48 | /** | ||
49 | * Log an error message at log-level 'level' that indicates | ||
50 | * a failure of the command 'cmd' on file 'filename' | ||
51 | * with the message given by strerror(errno). | ||
52 | */ | ||
53 | #define LOG_POSTGRES(db, level, cmd) do { GNUNET_log_from (level, "namecache-postgres", _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh)); } while(0) | ||
54 | |||
55 | #define LOG(kind,...) GNUNET_log_from (kind, "namecache-postgres", __VA_ARGS__) | 34 | #define LOG(kind,...) GNUNET_log_from (kind, "namecache-postgres", __VA_ARGS__) |
56 | 35 | ||
57 | 36 | ||
@@ -72,40 +51,34 @@ struct Plugin | |||
72 | 51 | ||
73 | 52 | ||
74 | /** | 53 | /** |
75 | * Create our database indices. | ||
76 | * | ||
77 | * @param dbh handle to the database | ||
78 | */ | ||
79 | static void | ||
80 | create_indices (PGconn * dbh) | ||
81 | { | ||
82 | /* create indices */ | ||
83 | if ( (GNUNET_OK != | ||
84 | GNUNET_POSTGRES_exec (dbh, | ||
85 | "CREATE INDEX ir_query_hash ON ns096blocks (query,expiration_time)")) || | ||
86 | (GNUNET_OK != | ||
87 | GNUNET_POSTGRES_exec (dbh, | ||
88 | "CREATE INDEX ir_block_expiration ON ns096blocks (expiration_time)")) ) | ||
89 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
90 | _("Failed to create indices\n")); | ||
91 | } | ||
92 | |||
93 | |||
94 | /** | ||
95 | * Initialize the database connections and associated | 54 | * Initialize the database connections and associated |
96 | * data structures (create tables and indices | 55 | * data structures (create tables and indices |
97 | * as needed as well). | 56 | * as needed as well). |
98 | * | 57 | * |
99 | * @param plugin the plugin context (state for this module) | 58 | * @param plugin the plugin context (state for this module) |
100 | * @return GNUNET_OK on success | 59 | * @return #GNUNET_OK on success |
101 | */ | 60 | */ |
102 | static int | 61 | static int |
103 | database_setup (struct Plugin *plugin) | 62 | database_setup (struct Plugin *plugin) |
104 | { | 63 | { |
105 | PGresult *res; | 64 | struct GNUNET_PQ_ExecuteStatement es_temporary = |
106 | 65 | GNUNET_PQ_make_execute ("CREATE TEMPORARY TABLE IF NOT EXISTS ns096blocks (" | |
107 | plugin->dbh = GNUNET_POSTGRES_connect (plugin->cfg, | 66 | " query BYTEA NOT NULL DEFAULT ''," |
108 | "namecache-postgres"); | 67 | " block BYTEA NOT NULL DEFAULT ''," |
68 | " expiration_time BIGINT NOT NULL DEFAULT 0" | ||
69 | ")" | ||
70 | "WITH OIDS"); | ||
71 | struct GNUNET_PQ_ExecuteStatement es_default = | ||
72 | GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS ns096blocks (" | ||
73 | " query BYTEA NOT NULL DEFAULT ''," | ||
74 | " block BYTEA NOT NULL DEFAULT ''," | ||
75 | " expiration_time BIGINT NOT NULL DEFAULT 0" | ||
76 | ")" | ||
77 | "WITH OIDS"); | ||
78 | const struct GNUNET_PQ_ExecuteStatement *cr; | ||
79 | |||
80 | plugin->dbh = GNUNET_PQ_connect_with_cfg (plugin->cfg, | ||
81 | "namecache-postgres"); | ||
109 | if (NULL == plugin->dbh) | 82 | if (NULL == plugin->dbh) |
110 | return GNUNET_SYSERR; | 83 | return GNUNET_SYSERR; |
111 | if (GNUNET_YES == | 84 | if (GNUNET_YES == |
@@ -113,65 +86,56 @@ database_setup (struct Plugin *plugin) | |||
113 | "namecache-postgres", | 86 | "namecache-postgres", |
114 | "TEMPORARY_TABLE")) | 87 | "TEMPORARY_TABLE")) |
115 | { | 88 | { |
116 | res = | 89 | cr = &es_temporary; |
117 | PQexec (plugin->dbh, | ||
118 | "CREATE TEMPORARY TABLE ns096blocks (" | ||
119 | " query BYTEA NOT NULL DEFAULT ''," | ||
120 | " block BYTEA NOT NULL DEFAULT ''," | ||
121 | " expiration_time BIGINT NOT NULL DEFAULT 0" | ||
122 | ")" "WITH OIDS"); | ||
123 | } | 90 | } |
124 | else | 91 | else |
125 | { | 92 | { |
126 | res = | 93 | cr = &es_default; |
127 | PQexec (plugin->dbh, | ||
128 | "CREATE TABLE ns096blocks (" | ||
129 | " query BYTEA NOT NULL DEFAULT ''," | ||
130 | " block BYTEA NOT NULL DEFAULT ''," | ||
131 | " expiration_time BIGINT NOT NULL DEFAULT 0" | ||
132 | ")" "WITH OIDS"); | ||
133 | } | 94 | } |
134 | if ( (NULL == res) || | 95 | |
135 | ((PQresultStatus (res) != PGRES_COMMAND_OK) && | ||
136 | (0 != strcmp ("42P07", /* duplicate table */ | ||
137 | PQresultErrorField | ||
138 | (res, | ||
139 | PG_DIAG_SQLSTATE))))) | ||
140 | { | 96 | { |
141 | (void) GNUNET_POSTGRES_check_result (plugin->dbh, res, | 97 | struct GNUNET_PQ_ExecuteStatement es[] = { |
142 | PGRES_COMMAND_OK, "CREATE TABLE", | 98 | *cr, |
143 | "ns096blocks"); | 99 | GNUNET_PQ_make_try_execute ("CREATE INDEX ir_query_hash ON ns096blocks (query,expiration_time)"), |
144 | PQfinish (plugin->dbh); | 100 | GNUNET_PQ_make_try_execute ("CREATE INDEX ir_block_expiration ON ns096blocks (expiration_time)"), |
145 | plugin->dbh = NULL; | 101 | GNUNET_PQ_EXECUTE_STATEMENT_END |
146 | return GNUNET_SYSERR; | 102 | }; |
103 | |||
104 | if (GNUNET_OK != | ||
105 | GNUNET_PQ_exec_statements (plugin->dbh, | ||
106 | es)) | ||
107 | { | ||
108 | PQfinish (plugin->dbh); | ||
109 | plugin->dbh = NULL; | ||
110 | return GNUNET_SYSERR; | ||
111 | } | ||
147 | } | 112 | } |
148 | if (PQresultStatus (res) == PGRES_COMMAND_OK) | 113 | |
149 | create_indices (plugin->dbh); | ||
150 | PQclear (res); | ||
151 | |||
152 | if ((GNUNET_OK != | ||
153 | GNUNET_POSTGRES_prepare (plugin->dbh, | ||
154 | "cache_block", | ||
155 | "INSERT INTO ns096blocks (query, block, expiration_time) VALUES " | ||
156 | "($1, $2, $3)", 3)) || | ||
157 | (GNUNET_OK != | ||
158 | GNUNET_POSTGRES_prepare (plugin->dbh, | ||
159 | "expire_blocks", | ||
160 | "DELETE FROM ns096blocks WHERE expiration_time<$1", 1)) || | ||
161 | (GNUNET_OK != | ||
162 | GNUNET_POSTGRES_prepare (plugin->dbh, | ||
163 | "delete_block", | ||
164 | "DELETE FROM ns096blocks WHERE query=$1 AND expiration_time<=$2", 2)) || | ||
165 | (GNUNET_OK != | ||
166 | GNUNET_POSTGRES_prepare (plugin->dbh, | ||
167 | "lookup_block", | ||
168 | "SELECT block FROM ns096blocks WHERE query=$1" | ||
169 | " ORDER BY expiration_time DESC LIMIT 1", 1))) | ||
170 | { | 114 | { |
171 | PQfinish (plugin->dbh); | 115 | struct GNUNET_PQ_PreparedStatement ps[] = { |
172 | plugin->dbh = NULL; | 116 | GNUNET_PQ_make_prepare ("cache_block", |
173 | return GNUNET_SYSERR; | 117 | "INSERT INTO ns096blocks (query, block, expiration_time) VALUES " |
118 | "($1, $2, $3)", 3), | ||
119 | GNUNET_PQ_make_prepare ("expire_blocks", | ||
120 | "DELETE FROM ns096blocks WHERE expiration_time<$1", 1), | ||
121 | GNUNET_PQ_make_prepare ("delete_block", | ||
122 | "DELETE FROM ns096blocks WHERE query=$1 AND expiration_time<=$2", 2), | ||
123 | GNUNET_PQ_make_prepare ("lookup_block", | ||
124 | "SELECT block FROM ns096blocks WHERE query=$1" | ||
125 | " ORDER BY expiration_time DESC LIMIT 1", 1), | ||
126 | GNUNET_PQ_PREPARED_STATEMENT_END | ||
127 | }; | ||
128 | |||
129 | if (GNUNET_OK != | ||
130 | GNUNET_PQ_prepare_statements (plugin->dbh, | ||
131 | ps)) | ||
132 | { | ||
133 | PQfinish (plugin->dbh); | ||
134 | plugin->dbh = NULL; | ||
135 | return GNUNET_SYSERR; | ||
136 | } | ||
174 | } | 137 | } |
138 | |||
175 | return GNUNET_OK; | 139 | return GNUNET_OK; |
176 | } | 140 | } |
177 | 141 | ||
@@ -185,23 +149,16 @@ static void | |||
185 | namecache_postgres_expire_blocks (struct Plugin *plugin) | 149 | namecache_postgres_expire_blocks (struct Plugin *plugin) |
186 | { | 150 | { |
187 | struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); | 151 | struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); |
188 | struct GNUNET_PQ_QueryParam params[] = { | 152 | struct GNUNET_PQ_QueryParam params[] = { |
189 | GNUNET_PQ_query_param_absolute_time (&now), | 153 | GNUNET_PQ_query_param_absolute_time (&now), |
190 | GNUNET_PQ_query_param_end | 154 | GNUNET_PQ_query_param_end |
191 | }; | 155 | }; |
192 | PGresult *res; | 156 | enum GNUNET_DB_QueryStatus res; |
193 | 157 | ||
194 | res = GNUNET_PQ_exec_prepared (plugin->dbh, | 158 | res = GNUNET_PQ_eval_prepared_non_select (plugin->dbh, |
195 | "expire_blocks", | 159 | "expire_blocks", |
196 | params); | 160 | params); |
197 | if (GNUNET_OK != | 161 | GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != res); |
198 | GNUNET_POSTGRES_check_result (plugin->dbh, | ||
199 | res, | ||
200 | PGRES_COMMAND_OK, | ||
201 | "PQexecPrepared", | ||
202 | "expire_blocks")) | ||
203 | return; | ||
204 | PQclear (res); | ||
205 | } | 162 | } |
206 | 163 | ||
207 | 164 | ||
@@ -217,24 +174,17 @@ delete_old_block (struct Plugin *plugin, | |||
217 | const struct GNUNET_HashCode *query, | 174 | const struct GNUNET_HashCode *query, |
218 | struct GNUNET_TIME_AbsoluteNBO expiration_time) | 175 | struct GNUNET_TIME_AbsoluteNBO expiration_time) |
219 | { | 176 | { |
220 | struct GNUNET_PQ_QueryParam params[] = { | 177 | struct GNUNET_PQ_QueryParam params[] = { |
221 | GNUNET_PQ_query_param_auto_from_type (query), | 178 | GNUNET_PQ_query_param_auto_from_type (query), |
222 | GNUNET_PQ_query_param_absolute_time_nbo (&expiration_time), | 179 | GNUNET_PQ_query_param_absolute_time_nbo (&expiration_time), |
223 | GNUNET_PQ_query_param_end | 180 | GNUNET_PQ_query_param_end |
224 | }; | 181 | }; |
225 | PGresult *res; | 182 | enum GNUNET_DB_QueryStatus res; |
226 | 183 | ||
227 | res = GNUNET_PQ_exec_prepared (plugin->dbh, | 184 | res = GNUNET_PQ_eval_prepared_non_select (plugin->dbh, |
228 | "delete_block", | 185 | "delete_block", |
229 | params); | 186 | params); |
230 | if (GNUNET_OK != | 187 | GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != res); |
231 | GNUNET_POSTGRES_check_result (plugin->dbh, | ||
232 | res, | ||
233 | PGRES_COMMAND_OK, | ||
234 | "PQexecPrepared", | ||
235 | "delete_block")) | ||
236 | return; | ||
237 | PQclear (res); | ||
238 | } | 188 | } |
239 | 189 | ||
240 | 190 | ||
@@ -254,13 +204,13 @@ namecache_postgres_cache_block (void *cls, | |||
254 | size_t block_size = ntohl (block->purpose.size) + | 204 | size_t block_size = ntohl (block->purpose.size) + |
255 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) + | 205 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) + |
256 | sizeof (struct GNUNET_CRYPTO_EcdsaSignature); | 206 | sizeof (struct GNUNET_CRYPTO_EcdsaSignature); |
257 | struct GNUNET_PQ_QueryParam params[] = { | 207 | struct GNUNET_PQ_QueryParam params[] = { |
258 | GNUNET_PQ_query_param_auto_from_type (&query), | 208 | GNUNET_PQ_query_param_auto_from_type (&query), |
259 | GNUNET_PQ_query_param_fixed_size (block, block_size), | 209 | GNUNET_PQ_query_param_fixed_size (block, block_size), |
260 | GNUNET_PQ_query_param_absolute_time_nbo (&block->expiration_time), | 210 | GNUNET_PQ_query_param_absolute_time_nbo (&block->expiration_time), |
261 | GNUNET_PQ_query_param_end | 211 | GNUNET_PQ_query_param_end |
262 | }; | 212 | }; |
263 | PGresult *res; | 213 | enum GNUNET_DB_QueryStatus res; |
264 | 214 | ||
265 | namecache_postgres_expire_blocks (plugin); | 215 | namecache_postgres_expire_blocks (plugin); |
266 | GNUNET_CRYPTO_hash (&block->derived_key, | 216 | GNUNET_CRYPTO_hash (&block->derived_key, |
@@ -271,19 +221,15 @@ namecache_postgres_cache_block (void *cls, | |||
271 | GNUNET_break (0); | 221 | GNUNET_break (0); |
272 | return GNUNET_SYSERR; | 222 | return GNUNET_SYSERR; |
273 | } | 223 | } |
274 | delete_old_block (plugin, &query, block->expiration_time); | 224 | delete_old_block (plugin, |
275 | 225 | &query, | |
276 | res = GNUNET_PQ_exec_prepared (plugin->dbh, | 226 | block->expiration_time); |
277 | "cache_block", | 227 | |
278 | params); | 228 | res = GNUNET_PQ_eval_prepared_non_select (plugin->dbh, |
279 | if (GNUNET_OK != | 229 | "cache_block", |
280 | GNUNET_POSTGRES_check_result (plugin->dbh, | 230 | params); |
281 | res, | 231 | if (0 > res) |
282 | PGRES_COMMAND_OK, | ||
283 | "PQexecPrepared", | ||
284 | "cache_block")) | ||
285 | return GNUNET_SYSERR; | 232 | return GNUNET_SYSERR; |
286 | PQclear (res); | ||
287 | return GNUNET_OK; | 233 | return GNUNET_OK; |
288 | } | 234 | } |
289 | 235 | ||
@@ -301,42 +247,41 @@ namecache_postgres_cache_block (void *cls, | |||
301 | static int | 247 | static int |
302 | namecache_postgres_lookup_block (void *cls, | 248 | namecache_postgres_lookup_block (void *cls, |
303 | const struct GNUNET_HashCode *query, | 249 | const struct GNUNET_HashCode *query, |
304 | GNUNET_NAMECACHE_BlockCallback iter, void *iter_cls) | 250 | GNUNET_NAMECACHE_BlockCallback iter, |
251 | void *iter_cls) | ||
305 | { | 252 | { |
306 | struct Plugin *plugin = cls; | 253 | struct Plugin *plugin = cls; |
307 | struct GNUNET_PQ_QueryParam params[] = { | 254 | size_t bsize; |
255 | struct GNUNET_GNSRECORD_Block *block; | ||
256 | struct GNUNET_PQ_QueryParam params[] = { | ||
308 | GNUNET_PQ_query_param_auto_from_type (query), | 257 | GNUNET_PQ_query_param_auto_from_type (query), |
309 | GNUNET_PQ_query_param_end | 258 | GNUNET_PQ_query_param_end |
310 | }; | 259 | }; |
311 | PGresult *res; | 260 | struct GNUNET_PQ_ResultSpec rs[] = { |
312 | unsigned int cnt; | 261 | GNUNET_PQ_result_spec_variable_size ("block", |
313 | size_t bsize; | 262 | (void **) &block, |
314 | const struct GNUNET_GNSRECORD_Block *block; | 263 | &bsize), |
315 | 264 | GNUNET_PQ_result_spec_end | |
316 | res = GNUNET_PQ_exec_prepared (plugin->dbh, | 265 | }; |
317 | "lookup_block", | 266 | enum GNUNET_DB_QueryStatus res; |
318 | params); | 267 | |
319 | if (GNUNET_OK != | 268 | res = GNUNET_PQ_eval_prepared_singleton_select (plugin->dbh, |
320 | GNUNET_POSTGRES_check_result (plugin->dbh, res, PGRES_TUPLES_OK, | 269 | "lookup_block", |
321 | "PQexecPrepared", | 270 | params, |
322 | "lookup_block")) | 271 | rs); |
272 | if (0 > res) | ||
323 | { | 273 | { |
324 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 274 | LOG (GNUNET_ERROR_TYPE_WARNING, |
325 | "Failing lookup (postgres error)\n"); | 275 | "Failing lookup block in namecache (postgres error)\n"); |
326 | return GNUNET_SYSERR; | 276 | return GNUNET_SYSERR; |
327 | } | 277 | } |
328 | if (0 == (cnt = PQntuples (res))) | 278 | if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == res) |
329 | { | 279 | { |
330 | /* no result */ | 280 | /* no result */ |
331 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 281 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
332 | "Ending iteration (no more results)\n"); | 282 | "Ending iteration (no more results)\n"); |
333 | PQclear (res); | ||
334 | return GNUNET_NO; | 283 | return GNUNET_NO; |
335 | } | 284 | } |
336 | GNUNET_assert (1 == cnt); | ||
337 | GNUNET_assert (1 != PQnfields (res)); | ||
338 | bsize = PQgetlength (res, 0, 0); | ||
339 | block = (const struct GNUNET_GNSRECORD_Block *) PQgetvalue (res, 0, 0); | ||
340 | if ( (bsize < sizeof (*block)) || | 285 | if ( (bsize < sizeof (*block)) || |
341 | (bsize != ntohl (block->purpose.size) + | 286 | (bsize != ntohl (block->purpose.size) + |
342 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) + | 287 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) + |
@@ -345,11 +290,12 @@ namecache_postgres_lookup_block (void *cls, | |||
345 | GNUNET_break (0); | 290 | GNUNET_break (0); |
346 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 291 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
347 | "Failing lookup (corrupt block)\n"); | 292 | "Failing lookup (corrupt block)\n"); |
348 | PQclear (res); | 293 | GNUNET_PQ_cleanup_result (rs); |
349 | return GNUNET_SYSERR; | 294 | return GNUNET_SYSERR; |
350 | } | 295 | } |
351 | iter (iter_cls, block); | 296 | iter (iter_cls, |
352 | PQclear (res); | 297 | block); |
298 | GNUNET_PQ_cleanup_result (rs); | ||
353 | return GNUNET_OK; | 299 | return GNUNET_OK; |
354 | } | 300 | } |
355 | 301 | ||
@@ -395,7 +341,7 @@ libgnunet_plugin_namecache_postgres_init (void *cls) | |||
395 | api->cache_block = &namecache_postgres_cache_block; | 341 | api->cache_block = &namecache_postgres_cache_block; |
396 | api->lookup_block = &namecache_postgres_lookup_block; | 342 | api->lookup_block = &namecache_postgres_lookup_block; |
397 | LOG (GNUNET_ERROR_TYPE_INFO, | 343 | LOG (GNUNET_ERROR_TYPE_INFO, |
398 | _("Postgres database running\n")); | 344 | "Postgres namecache plugin running\n"); |
399 | return api; | 345 | return api; |
400 | } | 346 | } |
401 | 347 | ||
@@ -416,7 +362,7 @@ libgnunet_plugin_namecache_postgres_done (void *cls) | |||
416 | plugin->cfg = NULL; | 362 | plugin->cfg = NULL; |
417 | GNUNET_free (api); | 363 | GNUNET_free (api); |
418 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 364 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
419 | "postgres plugin is finished\n"); | 365 | "Postgres namecache plugin is finished\n"); |
420 | return NULL; | 366 | return NULL; |
421 | } | 367 | } |
422 | 368 | ||
diff --git a/src/namestore/Makefile.am b/src/namestore/Makefile.am index 1b99fcc45..4f710e116 100644 --- a/src/namestore/Makefile.am +++ b/src/namestore/Makefile.am | |||
@@ -199,7 +199,6 @@ libgnunet_plugin_namestore_postgres_la_SOURCES = \ | |||
199 | plugin_namestore_postgres.c | 199 | plugin_namestore_postgres.c |
200 | libgnunet_plugin_namestore_postgres_la_LIBADD = \ | 200 | libgnunet_plugin_namestore_postgres_la_LIBADD = \ |
201 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | 201 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ |
202 | $(top_builddir)/src/postgres/libgnunetpostgres.la \ | ||
203 | $(top_builddir)/src/pq/libgnunetpq.la \ | 202 | $(top_builddir)/src/pq/libgnunetpq.la \ |
204 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | 203 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ |
205 | $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lpq \ | 204 | $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lpq \ |
diff --git a/src/namestore/gnunet-service-namestore.c b/src/namestore/gnunet-service-namestore.c index 6cb4290a0..b27cfb732 100644 --- a/src/namestore/gnunet-service-namestore.c +++ b/src/namestore/gnunet-service-namestore.c | |||
@@ -414,9 +414,12 @@ get_nick_record (const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone) | |||
414 | struct GNUNET_GNSRECORD_Data *nick; | 414 | struct GNUNET_GNSRECORD_Data *nick; |
415 | int res; | 415 | int res; |
416 | 416 | ||
417 | res = GSN_database->lookup_records (GSN_database->cls, zone, | 417 | nick = NULL; |
418 | res = GSN_database->lookup_records (GSN_database->cls, | ||
419 | zone, | ||
418 | GNUNET_GNS_MASTERZONE_STR, | 420 | GNUNET_GNS_MASTERZONE_STR, |
419 | &lookup_nick_it, &nick); | 421 | &lookup_nick_it, |
422 | &nick); | ||
420 | if ( (GNUNET_OK != res) || | 423 | if ( (GNUNET_OK != res) || |
421 | (NULL == nick) ) | 424 | (NULL == nick) ) |
422 | { | 425 | { |
diff --git a/src/namestore/namestore_api.c b/src/namestore/namestore_api.c index 933ba7b95..92068cc01 100644 --- a/src/namestore/namestore_api.c +++ b/src/namestore/namestore_api.c | |||
@@ -1303,11 +1303,14 @@ GNUNET_NAMESTORE_zone_iteration_stop (struct GNUNET_NAMESTORE_ZoneIterator *it) | |||
1303 | 1303 | ||
1304 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1304 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1305 | "Sending ZONE_ITERATION_STOP message\n"); | 1305 | "Sending ZONE_ITERATION_STOP message\n"); |
1306 | env = GNUNET_MQ_msg (msg, | 1306 | if (NULL != h->mq) |
1307 | GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP); | 1307 | { |
1308 | msg->gns_header.r_id = htonl (it->op_id); | 1308 | env = GNUNET_MQ_msg (msg, |
1309 | GNUNET_MQ_send (h->mq, | 1309 | GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP); |
1310 | env); | 1310 | msg->gns_header.r_id = htonl (it->op_id); |
1311 | GNUNET_MQ_send (h->mq, | ||
1312 | env); | ||
1313 | } | ||
1311 | free_ze (it); | 1314 | free_ze (it); |
1312 | } | 1315 | } |
1313 | 1316 | ||
diff --git a/src/namestore/plugin_namestore_postgres.c b/src/namestore/plugin_namestore_postgres.c index 01dbf9e61..491cec1cb 100644 --- a/src/namestore/plugin_namestore_postgres.c +++ b/src/namestore/plugin_namestore_postgres.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * This file is part of GNUnet | 2 | * This file is part of GNUnet |
3 | * Copyright (C) 2009-2013, 2016 GNUnet e.V. | 3 | * Copyright (C) 2009-2013, 2016, 2017 GNUnet e.V. |
4 | * | 4 | * |
5 | * GNUnet is free software; you can redistribute it and/or modify | 5 | * GNUnet is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published | 6 | * it under the terms of the GNU General Public License as published |
@@ -27,31 +27,10 @@ | |||
27 | #include "gnunet_namestore_plugin.h" | 27 | #include "gnunet_namestore_plugin.h" |
28 | #include "gnunet_namestore_service.h" | 28 | #include "gnunet_namestore_service.h" |
29 | #include "gnunet_gnsrecord_lib.h" | 29 | #include "gnunet_gnsrecord_lib.h" |
30 | #include "gnunet_postgres_lib.h" | ||
31 | #include "gnunet_pq_lib.h" | 30 | #include "gnunet_pq_lib.h" |
32 | #include "namestore.h" | 31 | #include "namestore.h" |
33 | 32 | ||
34 | 33 | ||
35 | /** | ||
36 | * After how many ms "busy" should a DB operation fail for good? | ||
37 | * A low value makes sure that we are more responsive to requests | ||
38 | * (especially PUTs). A high value guarantees a higher success | ||
39 | * rate (SELECTs in iterate can take several seconds despite LIMIT=1). | ||
40 | * | ||
41 | * The default value of 1s should ensure that users do not experience | ||
42 | * huge latencies while at the same time allowing operations to succeed | ||
43 | * with reasonable probability. | ||
44 | */ | ||
45 | #define BUSY_TIMEOUT_MS 1000 | ||
46 | |||
47 | |||
48 | /** | ||
49 | * Log an error message at log-level 'level' that indicates | ||
50 | * a failure of the command 'cmd' on file 'filename' | ||
51 | * with the message given by strerror(errno). | ||
52 | */ | ||
53 | #define LOG_POSTGRES(db, level, cmd) do { GNUNET_log_from (level, "namestore-postgres", _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh)); } while(0) | ||
54 | |||
55 | #define LOG(kind,...) GNUNET_log_from (kind, "namestore-postgres", __VA_ARGS__) | 34 | #define LOG(kind,...) GNUNET_log_from (kind, "namestore-postgres", __VA_ARGS__) |
56 | 35 | ||
57 | 36 | ||
@@ -75,30 +54,6 @@ struct Plugin | |||
75 | 54 | ||
76 | 55 | ||
77 | /** | 56 | /** |
78 | * Create our database indices. | ||
79 | * | ||
80 | * @param dbh handle to the database | ||
81 | */ | ||
82 | static void | ||
83 | create_indices (PGconn * dbh) | ||
84 | { | ||
85 | /* create indices */ | ||
86 | if ( (GNUNET_OK != | ||
87 | GNUNET_POSTGRES_exec (dbh, | ||
88 | "CREATE INDEX IF NOT EXISTS ir_pkey_reverse ON ns097records (zone_private_key,pkey)")) || | ||
89 | (GNUNET_OK != | ||
90 | GNUNET_POSTGRES_exec (dbh, | ||
91 | "CREATE INDEX IF NOT EXISTS ir_pkey_iter ON ns097records (zone_private_key,rvalue)")) || | ||
92 | (GNUNET_OK != | ||
93 | GNUNET_POSTGRES_exec (dbh, "CREATE INDEX IF NOT EXISTS it_iter ON ns097records (rvalue)")) || | ||
94 | (GNUNET_OK != | ||
95 | GNUNET_POSTGRES_exec (dbh, "CREATE INDEX IF NOT EXISTS ir_label ON ns097records (label)")) ) | ||
96 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
97 | _("Failed to create indices\n")); | ||
98 | } | ||
99 | |||
100 | |||
101 | /** | ||
102 | * Initialize the database connections and associated | 57 | * Initialize the database connections and associated |
103 | * data structures (create tables and indices | 58 | * data structures (create tables and indices |
104 | * as needed as well). | 59 | * as needed as well). |
@@ -109,10 +64,30 @@ create_indices (PGconn * dbh) | |||
109 | static int | 64 | static int |
110 | database_setup (struct Plugin *plugin) | 65 | database_setup (struct Plugin *plugin) |
111 | { | 66 | { |
112 | PGresult *res; | 67 | struct GNUNET_PQ_ExecuteStatement es_temporary = |
113 | 68 | GNUNET_PQ_make_execute ("CREATE TEMPORARY TABLE IF NOT EXISTS ns097records (" | |
114 | plugin->dbh = GNUNET_POSTGRES_connect (plugin->cfg, | 69 | " zone_private_key BYTEA NOT NULL DEFAULT ''," |
115 | "namestore-postgres"); | 70 | " pkey BYTEA DEFAULT ''," |
71 | " rvalue BYTEA NOT NULL DEFAULT ''," | ||
72 | " record_count INTEGER NOT NULL DEFAULT 0," | ||
73 | " record_data BYTEA NOT NULL DEFAULT ''," | ||
74 | " label TEXT NOT NULL DEFAULT ''" | ||
75 | ")" | ||
76 | "WITH OIDS"); | ||
77 | struct GNUNET_PQ_ExecuteStatement es_default = | ||
78 | GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS ns097records (" | ||
79 | " zone_private_key BYTEA NOT NULL DEFAULT ''," | ||
80 | " pkey BYTEA DEFAULT ''," | ||
81 | " rvalue BYTEA NOT NULL DEFAULT ''," | ||
82 | " record_count INTEGER NOT NULL DEFAULT 0," | ||
83 | " record_data BYTEA NOT NULL DEFAULT ''," | ||
84 | " label TEXT NOT NULL DEFAULT ''" | ||
85 | ")" | ||
86 | "WITH OIDS"); | ||
87 | const struct GNUNET_PQ_ExecuteStatement *cr; | ||
88 | |||
89 | plugin->dbh = GNUNET_PQ_connect_with_cfg (plugin->cfg, | ||
90 | "namestore-postgres"); | ||
116 | if (NULL == plugin->dbh) | 91 | if (NULL == plugin->dbh) |
117 | return GNUNET_SYSERR; | 92 | return GNUNET_SYSERR; |
118 | if (GNUNET_YES == | 93 | if (GNUNET_YES == |
@@ -120,80 +95,70 @@ database_setup (struct Plugin *plugin) | |||
120 | "namestore-postgres", | 95 | "namestore-postgres", |
121 | "TEMPORARY_TABLE")) | 96 | "TEMPORARY_TABLE")) |
122 | { | 97 | { |
123 | res = | 98 | cr = &es_temporary; |
124 | PQexec (plugin->dbh, | ||
125 | "CREATE TEMPORARY TABLE IF NOT EXISTS ns097records (" | ||
126 | " zone_private_key BYTEA NOT NULL DEFAULT ''," | ||
127 | " pkey BYTEA DEFAULT ''," | ||
128 | " rvalue BYTEA NOT NULL DEFAULT ''," | ||
129 | " record_count INTEGER NOT NULL DEFAULT 0," | ||
130 | " record_data BYTEA NOT NULL DEFAULT ''," | ||
131 | " label TEXT NOT NULL DEFAULT ''" | ||
132 | ")" "WITH OIDS"); | ||
133 | } | 99 | } |
134 | else | 100 | else |
135 | { | 101 | { |
136 | res = | 102 | cr = &es_default; |
137 | PQexec (plugin->dbh, | ||
138 | "CREATE TABLE IF NOT EXISTS ns097records (" | ||
139 | " zone_private_key BYTEA NOT NULL DEFAULT ''," | ||
140 | " pkey BYTEA DEFAULT ''," | ||
141 | " rvalue BYTEA NOT NULL DEFAULT ''," | ||
142 | " record_count INTEGER NOT NULL DEFAULT 0," | ||
143 | " record_data BYTEA NOT NULL DEFAULT ''," | ||
144 | " label TEXT NOT NULL DEFAULT ''" | ||
145 | ")" "WITH OIDS"); | ||
146 | } | 103 | } |
147 | if ( (NULL == res) || | 104 | |
148 | ((PQresultStatus (res) != PGRES_COMMAND_OK) && | ||
149 | (0 != strcmp ("42P07", /* duplicate table */ | ||
150 | PQresultErrorField | ||
151 | (res, | ||
152 | PG_DIAG_SQLSTATE))))) | ||
153 | { | 105 | { |
154 | (void) GNUNET_POSTGRES_check_result (plugin->dbh, res, | 106 | struct GNUNET_PQ_ExecuteStatement es[] = { |
155 | PGRES_COMMAND_OK, "CREATE TABLE", | 107 | *cr, |
156 | "ns097records"); | 108 | GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_reverse " |
157 | PQfinish (plugin->dbh); | 109 | "ON ns097records (zone_private_key,pkey)"), |
158 | plugin->dbh = NULL; | 110 | GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_iter " |
159 | return GNUNET_SYSERR; | 111 | "ON ns097records (zone_private_key,rvalue)"), |
112 | GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS it_iter " | ||
113 | "ON ns097records (rvalue)"), | ||
114 | GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_label " | ||
115 | "ON ns097records (label)"), | ||
116 | GNUNET_PQ_EXECUTE_STATEMENT_END | ||
117 | }; | ||
118 | |||
119 | if (GNUNET_OK != | ||
120 | GNUNET_PQ_exec_statements (plugin->dbh, | ||
121 | es)) | ||
122 | { | ||
123 | PQfinish (plugin->dbh); | ||
124 | plugin->dbh = NULL; | ||
125 | return GNUNET_SYSERR; | ||
126 | } | ||
160 | } | 127 | } |
161 | create_indices (plugin->dbh); | 128 | |
162 | |||
163 | if ((GNUNET_OK != | ||
164 | GNUNET_POSTGRES_prepare (plugin->dbh, | ||
165 | "store_records", | ||
166 | "INSERT INTO ns097records (zone_private_key, pkey, rvalue, record_count, record_data, label) VALUES " | ||
167 | "($1, $2, $3, $4, $5, $6)", 6)) || | ||
168 | (GNUNET_OK != | ||
169 | GNUNET_POSTGRES_prepare (plugin->dbh, | ||
170 | "delete_records", | ||
171 | "DELETE FROM ns097records WHERE zone_private_key=$1 AND label=$2", 2)) || | ||
172 | (GNUNET_OK != | ||
173 | GNUNET_POSTGRES_prepare (plugin->dbh, | ||
174 | "zone_to_name", | ||
175 | "SELECT record_count,record_data,label FROM ns097records" | ||
176 | " WHERE zone_private_key=$1 AND pkey=$2", 2)) || | ||
177 | (GNUNET_OK != | ||
178 | GNUNET_POSTGRES_prepare (plugin->dbh, | ||
179 | "iterate_zone", | ||
180 | "SELECT record_count,record_data,label FROM ns097records" | ||
181 | " WHERE zone_private_key=$1 ORDER BY rvalue LIMIT 1 OFFSET $2", 2)) || | ||
182 | (GNUNET_OK != | ||
183 | GNUNET_POSTGRES_prepare (plugin->dbh, | ||
184 | "iterate_all_zones", | ||
185 | "SELECT record_count,record_data,label,zone_private_key" | ||
186 | " FROM ns097records ORDER BY rvalue LIMIT 1 OFFSET $1", 1)) || | ||
187 | (GNUNET_OK != | ||
188 | GNUNET_POSTGRES_prepare (plugin->dbh, | ||
189 | "lookup_label", | ||
190 | "SELECT record_count,record_data,label" | ||
191 | " FROM ns097records WHERE zone_private_key=$1 AND label=$2", 2))) | ||
192 | { | 129 | { |
193 | PQfinish (plugin->dbh); | 130 | struct GNUNET_PQ_PreparedStatement ps[] = { |
194 | plugin->dbh = NULL; | 131 | GNUNET_PQ_make_prepare ("store_records", |
195 | return GNUNET_SYSERR; | 132 | "INSERT INTO ns097records (zone_private_key, pkey, rvalue, record_count, record_data, label) VALUES " |
133 | "($1, $2, $3, $4, $5, $6)", 6), | ||
134 | GNUNET_PQ_make_prepare ("delete_records", | ||
135 | "DELETE FROM ns097records " | ||
136 | "WHERE zone_private_key=$1 AND label=$2", 2), | ||
137 | GNUNET_PQ_make_prepare ("zone_to_name", | ||
138 | "SELECT record_count,record_data,label FROM ns097records" | ||
139 | " WHERE zone_private_key=$1 AND pkey=$2", 2), | ||
140 | GNUNET_PQ_make_prepare ("iterate_zone", | ||
141 | "SELECT record_count,record_data,label FROM ns097records " | ||
142 | "WHERE zone_private_key=$1 ORDER BY rvalue LIMIT 1 OFFSET $2", 2), | ||
143 | GNUNET_PQ_make_prepare ("iterate_all_zones", | ||
144 | "SELECT record_count,record_data,label,zone_private_key" | ||
145 | " FROM ns097records ORDER BY rvalue LIMIT 1 OFFSET $1", 1), | ||
146 | GNUNET_PQ_make_prepare ("lookup_label", | ||
147 | "SELECT record_count,record_data,label " | ||
148 | "FROM ns097records WHERE zone_private_key=$1 AND label=$2", 2), | ||
149 | GNUNET_PQ_PREPARED_STATEMENT_END | ||
150 | }; | ||
151 | |||
152 | if (GNUNET_OK != | ||
153 | GNUNET_PQ_prepare_statements (plugin->dbh, | ||
154 | ps)) | ||
155 | { | ||
156 | PQfinish (plugin->dbh); | ||
157 | plugin->dbh = NULL; | ||
158 | return GNUNET_SYSERR; | ||
159 | } | ||
196 | } | 160 | } |
161 | |||
197 | return GNUNET_OK; | 162 | return GNUNET_OK; |
198 | } | 163 | } |
199 | 164 | ||
@@ -219,21 +184,21 @@ namestore_postgres_store_records (void *cls, | |||
219 | struct Plugin *plugin = cls; | 184 | struct Plugin *plugin = cls; |
220 | struct GNUNET_CRYPTO_EcdsaPublicKey pkey; | 185 | struct GNUNET_CRYPTO_EcdsaPublicKey pkey; |
221 | uint64_t rvalue; | 186 | uint64_t rvalue; |
222 | uint32_t rd_count_nbo = htonl ((uint32_t) rd_count); | 187 | uint32_t rd_count32 = (uint32_t) rd_count; |
223 | size_t data_size; | 188 | size_t data_size; |
224 | unsigned int i; | ||
225 | 189 | ||
226 | memset (&pkey, 0, sizeof (pkey)); | 190 | memset (&pkey, 0, sizeof (pkey)); |
227 | for (i=0;i<rd_count;i++) | 191 | for (unsigned int i=0;i<rd_count;i++) |
228 | if (GNUNET_GNSRECORD_TYPE_PKEY == rd[i].record_type) | 192 | if (GNUNET_GNSRECORD_TYPE_PKEY == rd[i].record_type) |
229 | { | 193 | { |
230 | GNUNET_break (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) == rd[i].data_size); | 194 | GNUNET_break (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) == rd[i].data_size); |
231 | GNUNET_memcpy (&pkey, | 195 | GNUNET_memcpy (&pkey, |
232 | rd[i].data, | 196 | rd[i].data, |
233 | rd[i].data_size); | 197 | rd[i].data_size); |
234 | break; | 198 | break; |
235 | } | 199 | } |
236 | rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX); | 200 | rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, |
201 | UINT64_MAX); | ||
237 | data_size = GNUNET_GNSRECORD_records_get_size (rd_count, rd); | 202 | data_size = GNUNET_GNSRECORD_records_get_size (rd_count, rd); |
238 | if (data_size > 64 * 65536) | 203 | if (data_size > 64 * 65536) |
239 | { | 204 | { |
@@ -242,141 +207,134 @@ namestore_postgres_store_records (void *cls, | |||
242 | } | 207 | } |
243 | { | 208 | { |
244 | char data[data_size]; | 209 | char data[data_size]; |
245 | // FIXME: use libgnunetpq! | 210 | struct GNUNET_PQ_QueryParam params[] = { |
246 | const char *paramValues[] = { | 211 | GNUNET_PQ_query_param_auto_from_type (zone_key), |
247 | (const char *) zone_key, | 212 | GNUNET_PQ_query_param_auto_from_type (&pkey), |
248 | (const char *) &pkey, | 213 | GNUNET_PQ_query_param_uint64 (&rvalue), |
249 | (const char *) &rvalue, | 214 | GNUNET_PQ_query_param_uint32 (&rd_count32), |
250 | (const char *) &rd_count_nbo, | 215 | GNUNET_PQ_query_param_fixed_size (data, data_size), |
251 | (const char *) data, | 216 | GNUNET_PQ_query_param_string (label), |
252 | label | 217 | GNUNET_PQ_query_param_end |
253 | }; | ||
254 | int paramLengths[] = { | ||
255 | sizeof (*zone_key), | ||
256 | sizeof (pkey), | ||
257 | sizeof (rvalue), | ||
258 | sizeof (rd_count_nbo), | ||
259 | data_size, | ||
260 | strlen (label) | ||
261 | }; | 218 | }; |
262 | const int paramFormats[] = { 1, 1, 1, 1, 1, 1 }; | 219 | enum GNUNET_DB_QueryStatus res; |
263 | PGresult *res; | ||
264 | 220 | ||
265 | if (data_size != GNUNET_GNSRECORD_records_serialize (rd_count, rd, | 221 | if (data_size != |
266 | data_size, data)) | 222 | GNUNET_GNSRECORD_records_serialize (rd_count, rd, |
223 | data_size, data)) | ||
267 | { | 224 | { |
268 | GNUNET_break (0); | 225 | GNUNET_break (0); |
269 | return GNUNET_SYSERR; | 226 | return GNUNET_SYSERR; |
270 | } | 227 | } |
271 | 228 | ||
272 | res = | 229 | res = GNUNET_PQ_eval_prepared_non_select (plugin->dbh, |
273 | PQexecPrepared (plugin->dbh, "store_records", 6, | 230 | "store_records", |
274 | paramValues, paramLengths, paramFormats, 1); | 231 | params); |
275 | if (GNUNET_OK != | 232 | if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != res) |
276 | GNUNET_POSTGRES_check_result (plugin->dbh, | ||
277 | res, | ||
278 | PGRES_COMMAND_OK, | ||
279 | "PQexecPrepared", | ||
280 | "store_records")) | ||
281 | return GNUNET_SYSERR; | 233 | return GNUNET_SYSERR; |
282 | PQclear (res); | ||
283 | return GNUNET_OK; | ||
284 | } | 234 | } |
235 | return GNUNET_OK; | ||
285 | } | 236 | } |
286 | 237 | ||
287 | 238 | ||
288 | /** | 239 | /** |
240 | * Closure for #parse_result_call_iterator. | ||
241 | */ | ||
242 | struct ParserContext | ||
243 | { | ||
244 | /** | ||
245 | * Function to call for each result. | ||
246 | */ | ||
247 | GNUNET_NAMESTORE_RecordIterator iter; | ||
248 | |||
249 | /** | ||
250 | * Closure for @e iter. | ||
251 | */ | ||
252 | void *iter_cls; | ||
253 | |||
254 | /** | ||
255 | * Zone key, NULL if part of record. | ||
256 | */ | ||
257 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key; | ||
258 | }; | ||
259 | |||
260 | |||
261 | /** | ||
289 | * A statement has been run. We should evaluate the result, and if possible | 262 | * A statement has been run. We should evaluate the result, and if possible |
290 | * call the given @a iter with the result. | 263 | * call the @a iter in @a cls with the result. |
291 | * | 264 | * |
292 | * @param plugin plugin context | 265 | * @param cls closure of type `struct ParserContext *` |
293 | * @param res result from the statement that was run (to be cleaned up) | 266 | * @param result the postgres result |
294 | * @param zone_key private key of the zone, could be NULL, in which case we should | 267 | * @param num_result the number of results in @a result |
295 | * get the zone from @a res | ||
296 | * @param iter iterator to call with the result | ||
297 | * @param iter_cls closure for @a iter | ||
298 | * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error | ||
299 | */ | 268 | */ |
300 | static int | 269 | static void |
301 | get_record_and_call_iterator (struct Plugin *plugin, | 270 | parse_result_call_iterator (void *cls, |
302 | PGresult *res, | 271 | PGresult *res, |
303 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, | 272 | unsigned int num_results) |
304 | GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls) | ||
305 | { | 273 | { |
306 | const char *data; | 274 | struct ParserContext *pc = cls; |
307 | size_t data_size; | 275 | |
308 | uint32_t record_count; | 276 | for (unsigned int i=0;i<num_results;i++) |
309 | const char *label; | ||
310 | size_t label_len; | ||
311 | unsigned int cnt; | ||
312 | |||
313 | if (GNUNET_OK != | ||
314 | GNUNET_POSTGRES_check_result (plugin->dbh, res, PGRES_TUPLES_OK, | ||
315 | "PQexecPrepared", | ||
316 | "iteration")) | ||
317 | { | ||
318 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
319 | "Failing lookup (postgres error)\n"); | ||
320 | return GNUNET_SYSERR; | ||
321 | } | ||
322 | if (0 == (cnt = PQntuples (res))) | ||
323 | { | ||
324 | /* no result */ | ||
325 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
326 | "Ending iteration (no more results)\n"); | ||
327 | PQclear (res); | ||
328 | return GNUNET_NO; | ||
329 | } | ||
330 | GNUNET_assert (1 == cnt); | ||
331 | GNUNET_assert (3 + ((NULL == zone_key) ? 1 : 0) == PQnfields (res)); | ||
332 | if (NULL == zone_key) | ||
333 | { | 277 | { |
334 | if (sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey) != PQgetlength (res, 0, 3)) | 278 | void *data; |
279 | size_t data_size; | ||
280 | uint32_t record_count; | ||
281 | char *label; | ||
282 | struct GNUNET_CRYPTO_EcdsaPrivateKey zk; | ||
283 | struct GNUNET_PQ_ResultSpec rs_with_zone[] = { | ||
284 | GNUNET_PQ_result_spec_uint32 ("record_count", &record_count), | ||
285 | GNUNET_PQ_result_spec_variable_size ("record_data", &data, &data_size), | ||
286 | GNUNET_PQ_result_spec_string ("label", &label), | ||
287 | GNUNET_PQ_result_spec_auto_from_type ("zone_private_key", &zk), | ||
288 | GNUNET_PQ_result_spec_end | ||
289 | }; | ||
290 | struct GNUNET_PQ_ResultSpec rs_without_zone[] = { | ||
291 | GNUNET_PQ_result_spec_uint32 ("record_count", &record_count), | ||
292 | GNUNET_PQ_result_spec_variable_size ("record_data", &data, &data_size), | ||
293 | GNUNET_PQ_result_spec_string ("label", &label), | ||
294 | GNUNET_PQ_result_spec_end | ||
295 | }; | ||
296 | struct GNUNET_PQ_ResultSpec *rs; | ||
297 | |||
298 | rs = (NULL == pc->zone_key) ? rs_with_zone : rs_without_zone; | ||
299 | if (GNUNET_YES != | ||
300 | GNUNET_PQ_extract_result (res, | ||
301 | rs, | ||
302 | i)) | ||
335 | { | 303 | { |
336 | GNUNET_break (0); | 304 | GNUNET_break (0); |
337 | PQclear (res); | 305 | return; |
338 | return GNUNET_SYSERR; | ||
339 | } | 306 | } |
340 | zone_key = (const struct GNUNET_CRYPTO_EcdsaPrivateKey *) PQgetvalue (res, 0, 3); | ||
341 | } | ||
342 | if (sizeof (uint32_t) != PQfsize (res, 0)) | ||
343 | { | ||
344 | GNUNET_break (0); | ||
345 | PQclear (res); | ||
346 | return GNUNET_SYSERR; | ||
347 | } | ||
348 | 307 | ||
349 | record_count = ntohl (*(uint32_t *) PQgetvalue (res, 0, 0)); | 308 | if (record_count > 64 * 1024) |
350 | data = PQgetvalue (res, 0, 1); | ||
351 | data_size = PQgetlength (res, 0, 1); | ||
352 | label = PQgetvalue (res, 0, 2); | ||
353 | label_len = PQgetlength (res, 0, 1); | ||
354 | if (record_count > 64 * 1024) | ||
355 | { | ||
356 | /* sanity check, don't stack allocate far too much just | ||
357 | because database might contain a large value here */ | ||
358 | GNUNET_break (0); | ||
359 | PQclear (res); | ||
360 | return GNUNET_SYSERR; | ||
361 | } | ||
362 | { | ||
363 | struct GNUNET_GNSRECORD_Data rd[record_count]; | ||
364 | char buf[label_len + 1]; | ||
365 | |||
366 | GNUNET_memcpy (buf, label, label_len); | ||
367 | buf[label_len] = '\0'; | ||
368 | if (GNUNET_OK != | ||
369 | GNUNET_GNSRECORD_records_deserialize (data_size, data, | ||
370 | record_count, rd)) | ||
371 | { | 309 | { |
310 | /* sanity check, don't stack allocate far too much just | ||
311 | because database might contain a large value here */ | ||
372 | GNUNET_break (0); | 312 | GNUNET_break (0); |
373 | PQclear (res); | 313 | GNUNET_PQ_cleanup_result (rs); |
374 | return GNUNET_SYSERR; | 314 | return; |
315 | } | ||
316 | |||
317 | { | ||
318 | struct GNUNET_GNSRECORD_Data rd[record_count]; | ||
319 | |||
320 | if (GNUNET_OK != | ||
321 | GNUNET_GNSRECORD_records_deserialize (data_size, | ||
322 | data, | ||
323 | record_count, | ||
324 | rd)) | ||
325 | { | ||
326 | GNUNET_break (0); | ||
327 | GNUNET_PQ_cleanup_result (rs); | ||
328 | return; | ||
329 | } | ||
330 | pc->iter (pc->iter_cls, | ||
331 | (NULL == pc->zone_key) ? &zk : pc->zone_key, | ||
332 | label, | ||
333 | record_count, | ||
334 | rd); | ||
375 | } | 335 | } |
376 | iter (iter_cls, zone_key, buf, record_count, rd); | 336 | GNUNET_PQ_cleanup_result (rs); |
377 | } | 337 | } |
378 | PQclear (res); | ||
379 | return GNUNET_OK; | ||
380 | } | 338 | } |
381 | 339 | ||
382 | 340 | ||
@@ -398,25 +356,25 @@ namestore_postgres_lookup_records (void *cls, | |||
398 | void *iter_cls) | 356 | void *iter_cls) |
399 | { | 357 | { |
400 | struct Plugin *plugin = cls; | 358 | struct Plugin *plugin = cls; |
401 | const char *paramValues[] = { | 359 | struct GNUNET_PQ_QueryParam params[] = { |
402 | (const char *) zone, | 360 | GNUNET_PQ_query_param_auto_from_type (zone), |
403 | label | 361 | GNUNET_PQ_query_param_string (label), |
362 | GNUNET_PQ_query_param_end | ||
404 | }; | 363 | }; |
405 | int paramLengths[] = { | 364 | struct ParserContext pc; |
406 | sizeof (*zone), | 365 | enum GNUNET_DB_QueryStatus res; |
407 | strlen (label) | 366 | |
408 | }; | 367 | pc.iter = iter; |
409 | const int paramFormats[] = { 1, 1 }; | 368 | pc.iter_cls = iter_cls; |
410 | PGresult *res; | 369 | pc.zone_key = NULL; |
411 | 370 | res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh, | |
412 | res = PQexecPrepared (plugin->dbh, | 371 | "lookup_label", |
413 | "lookup_label", 2, | 372 | params, |
414 | paramValues, paramLengths, paramFormats, | 373 | &parse_result_call_iterator, |
415 | 1); | 374 | &pc); |
416 | return get_record_and_call_iterator (plugin, | 375 | if (res <= 0) |
417 | res, | 376 | return GNUNET_SYSERR; |
418 | zone, | 377 | return GNUNET_OK; |
419 | iter, iter_cls); | ||
420 | } | 378 | } |
421 | 379 | ||
422 | 380 | ||
@@ -435,53 +393,50 @@ static int | |||
435 | namestore_postgres_iterate_records (void *cls, | 393 | namestore_postgres_iterate_records (void *cls, |
436 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, | 394 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, |
437 | uint64_t offset, | 395 | uint64_t offset, |
438 | GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls) | 396 | GNUNET_NAMESTORE_RecordIterator iter, |
397 | void *iter_cls) | ||
439 | { | 398 | { |
440 | struct Plugin *plugin = cls; | 399 | struct Plugin *plugin = cls; |
441 | uint64_t offset_be = GNUNET_htonll (offset); | 400 | enum GNUNET_DB_QueryStatus res; |
401 | struct ParserContext pc; | ||
442 | 402 | ||
403 | pc.iter = iter; | ||
404 | pc.iter_cls = iter_cls; | ||
405 | pc.zone_key = zone; | ||
443 | if (NULL == zone) | 406 | if (NULL == zone) |
444 | { | 407 | { |
445 | const char *paramValues[] = { | 408 | struct GNUNET_PQ_QueryParam params_without_zone[] = { |
446 | (const char *) &offset_be | 409 | GNUNET_PQ_query_param_uint64 (&offset), |
410 | GNUNET_PQ_query_param_end | ||
447 | }; | 411 | }; |
448 | int paramLengths[] = { | 412 | |
449 | sizeof (offset_be) | 413 | res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh, |
450 | }; | 414 | "iterate_all_zones", |
451 | const int paramFormats[] = { 1 }; | 415 | params_without_zone, |
452 | PGresult *res; | 416 | &parse_result_call_iterator, |
453 | 417 | &pc); | |
454 | res = PQexecPrepared (plugin->dbh, | ||
455 | "iterate_all_zones", 1, | ||
456 | paramValues, paramLengths, paramFormats, | ||
457 | 1); | ||
458 | return get_record_and_call_iterator (plugin, | ||
459 | res, | ||
460 | NULL, | ||
461 | iter, iter_cls); | ||
462 | } | 418 | } |
463 | else | 419 | else |
464 | { | 420 | { |
465 | const char *paramValues[] = { | 421 | struct GNUNET_PQ_QueryParam params_with_zone[] = { |
466 | (const char *) zone, | 422 | GNUNET_PQ_query_param_auto_from_type (zone), |
467 | (const char *) &offset_be | 423 | GNUNET_PQ_query_param_uint64 (&offset), |
468 | }; | 424 | GNUNET_PQ_query_param_end |
469 | int paramLengths[] = { | ||
470 | sizeof (*zone), | ||
471 | sizeof (offset_be) | ||
472 | }; | 425 | }; |
473 | const int paramFormats[] = { 1, 1 }; | 426 | |
474 | PGresult *res; | 427 | res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh, |
475 | 428 | "iterate_zone", | |
476 | res = PQexecPrepared (plugin->dbh, | 429 | params_with_zone, |
477 | "iterate_zone", 2, | 430 | &parse_result_call_iterator, |
478 | paramValues, paramLengths, paramFormats, | 431 | &pc); |
479 | 1); | ||
480 | return get_record_and_call_iterator (plugin, | ||
481 | res, | ||
482 | zone, | ||
483 | iter, iter_cls); | ||
484 | } | 432 | } |
433 | if (res < 0) | ||
434 | return GNUNET_SYSERR; | ||
435 | |||
436 | if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == res) | ||
437 | return GNUNET_NO; | ||
438 | |||
439 | return GNUNET_OK; | ||
485 | } | 440 | } |
486 | 441 | ||
487 | 442 | ||
@@ -503,25 +458,26 @@ namestore_postgres_zone_to_name (void *cls, | |||
503 | GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls) | 458 | GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls) |
504 | { | 459 | { |
505 | struct Plugin *plugin = cls; | 460 | struct Plugin *plugin = cls; |
506 | const char *paramValues[] = { | 461 | struct GNUNET_PQ_QueryParam params[] = { |
507 | (const char *) zone, | 462 | GNUNET_PQ_query_param_auto_from_type (zone), |
508 | (const char *) value_zone | 463 | GNUNET_PQ_query_param_auto_from_type (value_zone), |
464 | GNUNET_PQ_query_param_end | ||
509 | }; | 465 | }; |
510 | int paramLengths[] = { | 466 | enum GNUNET_DB_QueryStatus res; |
511 | sizeof (*zone), | 467 | struct ParserContext pc; |
512 | sizeof (*value_zone) | 468 | |
513 | }; | 469 | pc.iter = iter; |
514 | const int paramFormats[] = { 1, 1 }; | 470 | pc.iter_cls = iter_cls; |
515 | PGresult *res; | 471 | pc.zone_key = zone; |
516 | 472 | ||
517 | res = PQexecPrepared (plugin->dbh, | 473 | res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh, |
518 | "zone_to_name", 2, | 474 | "zone_to_name", |
519 | paramValues, paramLengths, paramFormats, | 475 | params, |
520 | 1); | 476 | &parse_result_call_iterator, |
521 | return get_record_and_call_iterator (plugin, | 477 | &pc); |
522 | res, | 478 | if (res < 0) |
523 | zone, | 479 | return GNUNET_SYSERR; |
524 | iter, iter_cls); | 480 | return GNUNET_OK; |
525 | } | 481 | } |
526 | 482 | ||
527 | 483 | ||
@@ -568,7 +524,7 @@ libgnunet_plugin_namestore_postgres_init (void *cls) | |||
568 | api->zone_to_name = &namestore_postgres_zone_to_name; | 524 | api->zone_to_name = &namestore_postgres_zone_to_name; |
569 | api->lookup_records = &namestore_postgres_lookup_records; | 525 | api->lookup_records = &namestore_postgres_lookup_records; |
570 | LOG (GNUNET_ERROR_TYPE_INFO, | 526 | LOG (GNUNET_ERROR_TYPE_INFO, |
571 | _("Postgres database running\n")); | 527 | "Postgres namestore plugin running\n"); |
572 | return api; | 528 | return api; |
573 | } | 529 | } |
574 | 530 | ||
@@ -589,7 +545,7 @@ libgnunet_plugin_namestore_postgres_done (void *cls) | |||
589 | plugin->cfg = NULL; | 545 | plugin->cfg = NULL; |
590 | GNUNET_free (api); | 546 | GNUNET_free (api); |
591 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 547 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
592 | "postgres plugin is finished\n"); | 548 | "Postgres namestore plugin is finished\n"); |
593 | return NULL; | 549 | return NULL; |
594 | } | 550 | } |
595 | 551 | ||
diff --git a/src/postgres/Makefile.am b/src/postgres/Makefile.am deleted file mode 100644 index 6f37e1918..000000000 --- a/src/postgres/Makefile.am +++ /dev/null | |||
@@ -1,24 +0,0 @@ | |||
1 | # This Makefile.am is in the public domain | ||
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include $(POSTGRESQL_CPPFLAGS) | ||
3 | |||
4 | if MINGW | ||
5 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
6 | endif | ||
7 | |||
8 | if USE_COVERAGE | ||
9 | AM_CFLAGS = --coverage | ||
10 | endif | ||
11 | |||
12 | if HAVE_POSTGRESQL | ||
13 | lib_LTLIBRARIES = libgnunetpostgres.la | ||
14 | endif | ||
15 | |||
16 | libgnunetpostgres_la_SOURCES = \ | ||
17 | postgres.c | ||
18 | libgnunetpostgres_la_LIBADD = -lpq \ | ||
19 | $(top_builddir)/src/util/libgnunetutil.la | ||
20 | libgnunetpostgres_la_LDFLAGS = \ | ||
21 | $(POSTGRESQL_LDFLAGS) \ | ||
22 | $(GN_LIB_LDFLAGS) \ | ||
23 | -version-info 0:0:0 | ||
24 | |||
diff --git a/src/postgres/postgres.c b/src/postgres/postgres.c deleted file mode 100644 index 14095c5a4..000000000 --- a/src/postgres/postgres.c +++ /dev/null | |||
@@ -1,247 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2009, 2010, 2012 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file postgres/postgres.c | ||
22 | * @brief library to help with access to a Postgres database | ||
23 | * @author Christian Grothoff | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include "gnunet_postgres_lib.h" | ||
27 | |||
28 | |||
29 | /** | ||
30 | * Check if the result obtained from Postgres has | ||
31 | * the desired status code. If not, log an error, clear the | ||
32 | * result and return GNUNET_SYSERR. | ||
33 | * | ||
34 | * @param dbh database handle | ||
35 | * @param ret return value from database operation to check | ||
36 | * @param expected_status desired status | ||
37 | * @param command description of the command that was run | ||
38 | * @param args arguments given to the command | ||
39 | * @param filename name of the source file where the command was run | ||
40 | * @param line line number in the source file | ||
41 | * @return #GNUNET_OK if the result is acceptable | ||
42 | */ | ||
43 | int | ||
44 | GNUNET_POSTGRES_check_result_ (PGconn *dbh, | ||
45 | PGresult *ret, | ||
46 | int expected_status, | ||
47 | const char *command, | ||
48 | const char *args, | ||
49 | const char *filename, | ||
50 | int line) | ||
51 | { | ||
52 | if (ret == NULL) | ||
53 | { | ||
54 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
55 | "postgres", | ||
56 | "Postgres failed to allocate result for `%s:%s' at %s:%d\n", | ||
57 | command, | ||
58 | args, | ||
59 | filename, | ||
60 | line); | ||
61 | return GNUNET_SYSERR; | ||
62 | } | ||
63 | if (PQresultStatus (ret) != expected_status) | ||
64 | { | ||
65 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
66 | "postgres", | ||
67 | _("`%s:%s' failed at %s:%d with error: %s\n"), | ||
68 | command, | ||
69 | args, | ||
70 | filename, | ||
71 | line, | ||
72 | PQerrorMessage (dbh)); | ||
73 | PQclear (ret); | ||
74 | return GNUNET_SYSERR; | ||
75 | } | ||
76 | return GNUNET_OK; | ||
77 | } | ||
78 | |||
79 | |||
80 | /** | ||
81 | * Run simple SQL statement (without results). | ||
82 | * | ||
83 | * @param dbh database handle | ||
84 | * @param sql statement to run | ||
85 | * @param filename filename for error reporting | ||
86 | * @param line code line for error reporting | ||
87 | * @return #GNUNET_OK on success | ||
88 | */ | ||
89 | int | ||
90 | GNUNET_POSTGRES_exec_ (PGconn * dbh, | ||
91 | const char *sql, | ||
92 | const char *filename, | ||
93 | int line) | ||
94 | { | ||
95 | PGresult *ret; | ||
96 | |||
97 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
98 | "Executing SQL statement `%s' at %s:%d\n", | ||
99 | sql, | ||
100 | filename, | ||
101 | line); | ||
102 | ret = PQexec (dbh, | ||
103 | sql); | ||
104 | if (GNUNET_OK != | ||
105 | GNUNET_POSTGRES_check_result_ (dbh, | ||
106 | ret, | ||
107 | PGRES_COMMAND_OK, | ||
108 | "PQexec", | ||
109 | sql, | ||
110 | filename, | ||
111 | line)) | ||
112 | return GNUNET_SYSERR; | ||
113 | PQclear (ret); | ||
114 | return GNUNET_OK; | ||
115 | } | ||
116 | |||
117 | |||
118 | /** | ||
119 | * Prepare SQL statement. | ||
120 | * | ||
121 | * @param dbh database handle | ||
122 | * @param name name for the prepared SQL statement | ||
123 | * @param sql SQL code to prepare | ||
124 | * @param nparams number of parameters in sql | ||
125 | * @param filename filename for error reporting | ||
126 | * @param line code line for error reporting | ||
127 | * @return #GNUNET_OK on success | ||
128 | */ | ||
129 | int | ||
130 | GNUNET_POSTGRES_prepare_ (PGconn *dbh, | ||
131 | const char *name, | ||
132 | const char *sql, | ||
133 | int nparams, | ||
134 | const char *filename, | ||
135 | int line) | ||
136 | { | ||
137 | PGresult *ret; | ||
138 | |||
139 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
140 | "Preparing SQL statement `%s' as `%s' at %s:%d\n", | ||
141 | sql, | ||
142 | name, | ||
143 | filename, | ||
144 | line); | ||
145 | ret = PQprepare (dbh, | ||
146 | name, | ||
147 | sql, | ||
148 | nparams, NULL); | ||
149 | if (GNUNET_OK != | ||
150 | GNUNET_POSTGRES_check_result_ (dbh, | ||
151 | ret, | ||
152 | PGRES_COMMAND_OK, | ||
153 | "PQprepare", | ||
154 | sql, | ||
155 | filename, | ||
156 | line)) | ||
157 | return GNUNET_SYSERR; | ||
158 | PQclear (ret); | ||
159 | return GNUNET_OK; | ||
160 | } | ||
161 | |||
162 | |||
163 | /** | ||
164 | * Connect to a postgres database | ||
165 | * | ||
166 | * @param cfg configuration | ||
167 | * @param section configuration section to use to get Postgres configuration options | ||
168 | * @return the postgres handle | ||
169 | */ | ||
170 | PGconn * | ||
171 | GNUNET_POSTGRES_connect (const struct GNUNET_CONFIGURATION_Handle * cfg, | ||
172 | const char *section) | ||
173 | { | ||
174 | PGconn *dbh; | ||
175 | char *conninfo; | ||
176 | |||
177 | /* Open database and precompile statements */ | ||
178 | if (GNUNET_OK != | ||
179 | GNUNET_CONFIGURATION_get_value_string (cfg, | ||
180 | section, | ||
181 | "CONFIG", | ||
182 | &conninfo)) | ||
183 | conninfo = NULL; | ||
184 | dbh = PQconnectdb (conninfo == NULL ? "" : conninfo); | ||
185 | |||
186 | if (NULL != dbh) | ||
187 | { | ||
188 | if (PQstatus (dbh) != CONNECTION_OK) | ||
189 | { | ||
190 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, | ||
191 | "postgres", | ||
192 | _("Unable to connect to Postgres database '%s': %s\n"), | ||
193 | conninfo, | ||
194 | PQerrorMessage (dbh)); | ||
195 | PQfinish (dbh); | ||
196 | dbh = NULL; | ||
197 | } | ||
198 | } | ||
199 | // FIXME: warn about out-of-memory when dbh is NULL? | ||
200 | GNUNET_free_non_null (conninfo); | ||
201 | return dbh; | ||
202 | } | ||
203 | |||
204 | |||
205 | /** | ||
206 | * Delete the row identified by the given rowid (qid | ||
207 | * in postgres). | ||
208 | * | ||
209 | * @param dbh database handle | ||
210 | * @param stmt name of the prepared statement | ||
211 | * @param rowid which row to delete | ||
212 | * @return #GNUNET_OK on success | ||
213 | */ | ||
214 | int | ||
215 | GNUNET_POSTGRES_delete_by_rowid (PGconn * dbh, | ||
216 | const char *stmt, | ||
217 | uint32_t rowid) | ||
218 | { | ||
219 | uint32_t brow = htonl (rowid); | ||
220 | const char *paramValues[] = { (const char *) &brow }; | ||
221 | int paramLengths[] = { sizeof (brow) }; | ||
222 | const int paramFormats[] = { 1 }; | ||
223 | PGresult *ret; | ||
224 | |||
225 | ret = PQexecPrepared (dbh, | ||
226 | stmt, | ||
227 | 1, | ||
228 | paramValues, | ||
229 | paramLengths, | ||
230 | paramFormats, | ||
231 | 1); | ||
232 | if (GNUNET_OK != | ||
233 | GNUNET_POSTGRES_check_result_ (dbh, ret, | ||
234 | PGRES_COMMAND_OK, | ||
235 | "PQexecPrepared", | ||
236 | "delrow", | ||
237 | __FILE__, | ||
238 | __LINE__)) | ||
239 | { | ||
240 | return GNUNET_SYSERR; | ||
241 | } | ||
242 | PQclear (ret); | ||
243 | return GNUNET_OK; | ||
244 | } | ||
245 | |||
246 | |||
247 | /* end of postgres.c */ | ||
diff --git a/src/pq/Makefile.am b/src/pq/Makefile.am index 8bb0a0132..d0c71703b 100644 --- a/src/pq/Makefile.am +++ b/src/pq/Makefile.am | |||
@@ -15,6 +15,10 @@ endif | |||
15 | 15 | ||
16 | libgnunetpq_la_SOURCES = \ | 16 | libgnunetpq_la_SOURCES = \ |
17 | pq.c \ | 17 | pq.c \ |
18 | pq_connect.c \ | ||
19 | pq_eval.c \ | ||
20 | pq_exec.c \ | ||
21 | pq_prepare.c \ | ||
18 | pq_query_helper.c \ | 22 | pq_query_helper.c \ |
19 | pq_result_helper.c | 23 | pq_result_helper.c |
20 | libgnunetpq_la_LIBADD = -lpq \ | 24 | libgnunetpq_la_LIBADD = -lpq \ |
diff --git a/src/pq/pq_connect.c b/src/pq/pq_connect.c new file mode 100644 index 000000000..99ad06485 --- /dev/null +++ b/src/pq/pq_connect.c | |||
@@ -0,0 +1,127 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify it under the | ||
6 | terms of the GNU General Public License as published by the Free Software | ||
7 | Foundation; either version 3, or (at your option) any later version. | ||
8 | |||
9 | GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY | ||
10 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
11 | A PARTICULAR PURPOSE. See the GNU General Public License for more details. | ||
12 | |||
13 | You should have received a copy of the GNU General Public License along with | ||
14 | GNUnet; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/> | ||
15 | */ | ||
16 | /** | ||
17 | * @file pq/pq_connect.c | ||
18 | * @brief functions to connect to libpq (PostGres) | ||
19 | * @author Christian Grothoff | ||
20 | */ | ||
21 | #include "platform.h" | ||
22 | #include "gnunet_util_lib.h" | ||
23 | #include "gnunet_pq_lib.h" | ||
24 | |||
25 | |||
26 | /** | ||
27 | * Function called by libpq whenever it wants to log something. | ||
28 | * We already log whenever we care, so this function does nothing | ||
29 | * and merely exists to silence the libpq logging. | ||
30 | * | ||
31 | * @param arg the SQL connection that was used | ||
32 | * @param res information about some libpq event | ||
33 | */ | ||
34 | static void | ||
35 | pq_notice_receiver_cb (void *arg, | ||
36 | const PGresult *res) | ||
37 | { | ||
38 | /* do nothing, intentionally */ | ||
39 | } | ||
40 | |||
41 | |||
42 | /** | ||
43 | * Function called by libpq whenever it wants to log something. | ||
44 | * We log those using the Taler logger. | ||
45 | * | ||
46 | * @param arg the SQL connection that was used | ||
47 | * @param message information about some libpq event | ||
48 | */ | ||
49 | static void | ||
50 | pq_notice_processor_cb (void *arg, | ||
51 | const char *message) | ||
52 | { | ||
53 | GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, | ||
54 | "pq", | ||
55 | "%s", | ||
56 | message); | ||
57 | } | ||
58 | |||
59 | |||
60 | /** | ||
61 | * Create a connection to the Postgres database using @a config_str | ||
62 | * for the configuration. Initialize logging via GNUnet's log | ||
63 | * routines and disable Postgres's logger. | ||
64 | * | ||
65 | * @param config_str configuration to use | ||
66 | * @return NULL on error | ||
67 | */ | ||
68 | PGconn * | ||
69 | GNUNET_PQ_connect (const char *config_str) | ||
70 | { | ||
71 | PGconn *conn; | ||
72 | |||
73 | conn = PQconnectdb (config_str); | ||
74 | if ( (NULL == conn) || | ||
75 | (CONNECTION_OK != | ||
76 | PQstatus (conn)) ) | ||
77 | { | ||
78 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, | ||
79 | "pq", | ||
80 | "Database connection to '%s' failed: %s\n", | ||
81 | config_str, | ||
82 | (NULL != conn) ? | ||
83 | PQerrorMessage (conn) | ||
84 | : "PQconnectdb returned NULL"); | ||
85 | if (NULL != conn) | ||
86 | PQfinish (conn); | ||
87 | return NULL; | ||
88 | } | ||
89 | PQsetNoticeReceiver (conn, | ||
90 | &pq_notice_receiver_cb, | ||
91 | conn); | ||
92 | PQsetNoticeProcessor (conn, | ||
93 | &pq_notice_processor_cb, | ||
94 | conn); | ||
95 | return conn; | ||
96 | } | ||
97 | |||
98 | |||
99 | /** | ||
100 | * Connect to a postgres database using the configuration | ||
101 | * option "CONFIG" in @a section. | ||
102 | * | ||
103 | * @param cfg configuration | ||
104 | * @param section configuration section to use to get Postgres configuration options | ||
105 | * @return the postgres handle, NULL on error | ||
106 | */ | ||
107 | PGconn * | ||
108 | GNUNET_PQ_connect_with_cfg (const struct GNUNET_CONFIGURATION_Handle * cfg, | ||
109 | const char *section) | ||
110 | { | ||
111 | PGconn *dbh; | ||
112 | char *conninfo; | ||
113 | |||
114 | /* Open database and precompile statements */ | ||
115 | if (GNUNET_OK != | ||
116 | GNUNET_CONFIGURATION_get_value_string (cfg, | ||
117 | section, | ||
118 | "CONFIG", | ||
119 | &conninfo)) | ||
120 | conninfo = NULL; | ||
121 | dbh = GNUNET_PQ_connect (conninfo == NULL ? "" : conninfo); | ||
122 | GNUNET_free_non_null (conninfo); | ||
123 | return dbh; | ||
124 | } | ||
125 | |||
126 | |||
127 | /* end of pq/pq_connect.c */ | ||
diff --git a/src/pq/pq_eval.c b/src/pq/pq_eval.c new file mode 100644 index 000000000..0f28aec7e --- /dev/null +++ b/src/pq/pq_eval.c | |||
@@ -0,0 +1,281 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify it under the | ||
6 | terms of the GNU General Public License as published by the Free Software | ||
7 | Foundation; either version 3, or (at your option) any later version. | ||
8 | |||
9 | GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY | ||
10 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
11 | A PARTICULAR PURPOSE. See the GNU General Public License for more details. | ||
12 | |||
13 | You should have received a copy of the GNU General Public License along with | ||
14 | GNUnet; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/> | ||
15 | */ | ||
16 | /** | ||
17 | * @file pq/pq_eval.c | ||
18 | * @brief functions to execute SQL statements with arguments and/or results (PostGres) | ||
19 | * @author Christian Grothoff | ||
20 | */ | ||
21 | #include "platform.h" | ||
22 | #include "gnunet_util_lib.h" | ||
23 | #include "gnunet_pq_lib.h" | ||
24 | |||
25 | |||
26 | /** | ||
27 | * Error code returned by Postgres for deadlock. | ||
28 | */ | ||
29 | #define PQ_DIAG_SQLSTATE_DEADLOCK "40P01" | ||
30 | |||
31 | /** | ||
32 | * Error code returned by Postgres for uniqueness violation. | ||
33 | */ | ||
34 | #define PQ_DIAG_SQLSTATE_UNIQUE_VIOLATION "23505" | ||
35 | |||
36 | /** | ||
37 | * Error code returned by Postgres on serialization failure. | ||
38 | */ | ||
39 | #define PQ_DIAG_SQLSTATE_SERIALIZATION_FAILURE "40001" | ||
40 | |||
41 | |||
42 | /** | ||
43 | * Check the @a result's error code to see what happened. | ||
44 | * Also logs errors. | ||
45 | * | ||
46 | * @param connection connection to execute the statement in | ||
47 | * @param statement_name name of the statement that created @a result | ||
48 | * @param result result to check | ||
49 | * @return status code from the result, mapping PQ status | ||
50 | * codes to `enum GNUNET_DB_QueryStatus`. Never | ||
51 | * returns positive values as this function does | ||
52 | * not look at the result set. | ||
53 | * @deprecated (low level, let's see if we can do with just the high-level functions) | ||
54 | */ | ||
55 | enum GNUNET_DB_QueryStatus | ||
56 | GNUNET_PQ_eval_result (PGconn *connection, | ||
57 | const char *statement_name, | ||
58 | PGresult *result) | ||
59 | { | ||
60 | ExecStatusType est; | ||
61 | |||
62 | est = PQresultStatus (result); | ||
63 | if ( (PGRES_COMMAND_OK != est) && | ||
64 | (PGRES_TUPLES_OK != est) ) | ||
65 | { | ||
66 | const char *sqlstate; | ||
67 | |||
68 | sqlstate = PQresultErrorField (result, | ||
69 | PG_DIAG_SQLSTATE); | ||
70 | if (NULL == sqlstate) | ||
71 | { | ||
72 | /* very unexpected... */ | ||
73 | GNUNET_break (0); | ||
74 | return GNUNET_DB_STATUS_HARD_ERROR; | ||
75 | } | ||
76 | if ( (0 == strcmp (sqlstate, | ||
77 | PQ_DIAG_SQLSTATE_DEADLOCK)) || | ||
78 | (0 == strcmp (sqlstate, | ||
79 | PQ_DIAG_SQLSTATE_SERIALIZATION_FAILURE)) ) | ||
80 | { | ||
81 | /* These two can be retried and have a fair chance of working | ||
82 | the next time */ | ||
83 | GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, | ||
84 | "pq", | ||
85 | "Query `%s' failed with result: %s/%s/%s/%s/%s\n", | ||
86 | statement_name, | ||
87 | PQresultErrorField (result, | ||
88 | PG_DIAG_MESSAGE_PRIMARY), | ||
89 | PQresultErrorField (result, | ||
90 | PG_DIAG_MESSAGE_DETAIL), | ||
91 | PQresultErrorMessage (result), | ||
92 | PQresStatus (PQresultStatus (result)), | ||
93 | PQerrorMessage (connection)); | ||
94 | return GNUNET_DB_STATUS_SOFT_ERROR; | ||
95 | } | ||
96 | if (0 == strcmp (sqlstate, | ||
97 | PQ_DIAG_SQLSTATE_UNIQUE_VIOLATION)) | ||
98 | { | ||
99 | /* Likely no need to retry, INSERT of "same" data. */ | ||
100 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
101 | "pq", | ||
102 | "Query `%s' failed with unique violation: %s/%s/%s/%s/%s\n", | ||
103 | statement_name, | ||
104 | PQresultErrorField (result, | ||
105 | PG_DIAG_MESSAGE_PRIMARY), | ||
106 | PQresultErrorField (result, | ||
107 | PG_DIAG_MESSAGE_DETAIL), | ||
108 | PQresultErrorMessage (result), | ||
109 | PQresStatus (PQresultStatus (result)), | ||
110 | PQerrorMessage (connection)); | ||
111 | return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; | ||
112 | } | ||
113 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, | ||
114 | "pq", | ||
115 | "Query `%s' failed with result: %s/%s/%s/%s/%s\n", | ||
116 | statement_name, | ||
117 | PQresultErrorField (result, | ||
118 | PG_DIAG_MESSAGE_PRIMARY), | ||
119 | PQresultErrorField (result, | ||
120 | PG_DIAG_MESSAGE_DETAIL), | ||
121 | PQresultErrorMessage (result), | ||
122 | PQresStatus (PQresultStatus (result)), | ||
123 | PQerrorMessage (connection)); | ||
124 | return GNUNET_DB_STATUS_HARD_ERROR; | ||
125 | } | ||
126 | return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; | ||
127 | } | ||
128 | |||
129 | |||
130 | /** | ||
131 | * Execute a named prepared @a statement that is NOT a SELECT | ||
132 | * statement in @a connnection using the given @a params. Returns the | ||
133 | * resulting session state. | ||
134 | * | ||
135 | * @param connection connection to execute the statement in | ||
136 | * @param statement_name name of the statement | ||
137 | * @param params parameters to give to the statement (#GNUNET_PQ_query_param_end-terminated) | ||
138 | * @return status code from the result, mapping PQ status | ||
139 | * codes to `enum GNUNET_DB_QueryStatus`. If the | ||
140 | * statement was a DELETE or UPDATE statement, the | ||
141 | * number of affected rows is returned.; if the | ||
142 | * statment was an INSERT statement, and no row | ||
143 | * was added due to a UNIQUE violation, we return | ||
144 | * zero; if INSERT was successful, we return one. | ||
145 | */ | ||
146 | enum GNUNET_DB_QueryStatus | ||
147 | GNUNET_PQ_eval_prepared_non_select (PGconn *connection, | ||
148 | const char *statement_name, | ||
149 | const struct GNUNET_PQ_QueryParam *params) | ||
150 | { | ||
151 | PGresult *result; | ||
152 | enum GNUNET_DB_QueryStatus qs; | ||
153 | |||
154 | result = GNUNET_PQ_exec_prepared (connection, | ||
155 | statement_name, | ||
156 | params); | ||
157 | qs = GNUNET_PQ_eval_result (connection, | ||
158 | statement_name, | ||
159 | result); | ||
160 | if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) | ||
161 | { | ||
162 | const char *tuples; | ||
163 | |||
164 | /* What an awful API, this function really does return a string */ | ||
165 | tuples = PQcmdTuples (result); | ||
166 | if (NULL != tuples) | ||
167 | qs = strtol (tuples, NULL, 10); | ||
168 | } | ||
169 | PQclear (result); | ||
170 | return qs; | ||
171 | } | ||
172 | |||
173 | |||
174 | /** | ||
175 | * Execute a named prepared @a statement that is a SELECT statement | ||
176 | * which may return multiple results in @a connection using the given | ||
177 | * @a params. Call @a rh with the results. Returns the query | ||
178 | * status including the number of results given to @a rh (possibly zero). | ||
179 | * @a rh will not have been called if the return value is negative. | ||
180 | * | ||
181 | * @param connection connection to execute the statement in | ||
182 | * @param statement_name name of the statement | ||
183 | * @param params parameters to give to the statement (#GNUNET_PQ_query_param_end-terminated) | ||
184 | * @param rh function to call with the result set, NULL to ignore | ||
185 | * @param rh_cls closure to pass to @a rh | ||
186 | * @return status code from the result, mapping PQ status | ||
187 | * codes to `enum GNUNET_DB_QueryStatus`. | ||
188 | */ | ||
189 | enum GNUNET_DB_QueryStatus | ||
190 | GNUNET_PQ_eval_prepared_multi_select (PGconn *connection, | ||
191 | const char *statement_name, | ||
192 | const struct GNUNET_PQ_QueryParam *params, | ||
193 | GNUNET_PQ_PostgresResultHandler rh, | ||
194 | void *rh_cls) | ||
195 | { | ||
196 | PGresult *result; | ||
197 | enum GNUNET_DB_QueryStatus qs; | ||
198 | unsigned int ret; | ||
199 | |||
200 | result = GNUNET_PQ_exec_prepared (connection, | ||
201 | statement_name, | ||
202 | params); | ||
203 | qs = GNUNET_PQ_eval_result (connection, | ||
204 | statement_name, | ||
205 | result); | ||
206 | if (qs < 0) | ||
207 | { | ||
208 | PQclear (result); | ||
209 | return qs; | ||
210 | } | ||
211 | ret = PQntuples (result); | ||
212 | if (NULL != rh) | ||
213 | rh (rh_cls, | ||
214 | result, | ||
215 | ret); | ||
216 | PQclear (result); | ||
217 | return ret; | ||
218 | } | ||
219 | |||
220 | |||
221 | /** | ||
222 | * Execute a named prepared @a statement that is a SELECT statement | ||
223 | * which must return a single result in @a connection using the given | ||
224 | * @a params. Stores the result (if any) in @a rs, which the caller | ||
225 | * must then clean up using #GNUNET_PQ_cleanup_result() if the return | ||
226 | * value was #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT. Returns the | ||
227 | * resulting session status. | ||
228 | * | ||
229 | * @param connection connection to execute the statement in | ||
230 | * @param statement_name name of the statement | ||
231 | * @param params parameters to give to the statement (#GNUNET_PQ_query_param_end-terminated) | ||
232 | * @param[in,out] rs result specification to use for storing the result of the query | ||
233 | * @return status code from the result, mapping PQ status | ||
234 | * codes to `enum GNUNET_DB_QueryStatus`. | ||
235 | */ | ||
236 | enum GNUNET_DB_QueryStatus | ||
237 | GNUNET_PQ_eval_prepared_singleton_select (PGconn *connection, | ||
238 | const char *statement_name, | ||
239 | const struct GNUNET_PQ_QueryParam *params, | ||
240 | struct GNUNET_PQ_ResultSpec *rs) | ||
241 | { | ||
242 | PGresult *result; | ||
243 | enum GNUNET_DB_QueryStatus qs; | ||
244 | |||
245 | result = GNUNET_PQ_exec_prepared (connection, | ||
246 | statement_name, | ||
247 | params); | ||
248 | qs = GNUNET_PQ_eval_result (connection, | ||
249 | statement_name, | ||
250 | result); | ||
251 | if (qs < 0) | ||
252 | { | ||
253 | PQclear (result); | ||
254 | return qs; | ||
255 | } | ||
256 | if (0 == PQntuples (result)) | ||
257 | { | ||
258 | PQclear (result); | ||
259 | return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; | ||
260 | } | ||
261 | if (1 != PQntuples (result)) | ||
262 | { | ||
263 | /* more than one result, but there must be at most one */ | ||
264 | GNUNET_break (0); | ||
265 | PQclear (result); | ||
266 | return GNUNET_DB_STATUS_HARD_ERROR; | ||
267 | } | ||
268 | if (GNUNET_OK != | ||
269 | GNUNET_PQ_extract_result (result, | ||
270 | rs, | ||
271 | 0)) | ||
272 | { | ||
273 | PQclear (result); | ||
274 | return GNUNET_DB_STATUS_HARD_ERROR; | ||
275 | } | ||
276 | PQclear (result); | ||
277 | return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; | ||
278 | } | ||
279 | |||
280 | |||
281 | /* end of pq/pq_eval.c */ | ||
diff --git a/src/pq/pq_exec.c b/src/pq/pq_exec.c new file mode 100644 index 000000000..1e5e4eb76 --- /dev/null +++ b/src/pq/pq_exec.c | |||
@@ -0,0 +1,106 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify it under the | ||
6 | terms of the GNU General Public License as published by the Free Software | ||
7 | Foundation; either version 3, or (at your option) any later version. | ||
8 | |||
9 | GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY | ||
10 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
11 | A PARTICULAR PURPOSE. See the GNU General Public License for more details. | ||
12 | |||
13 | You should have received a copy of the GNU General Public License along with | ||
14 | GNUnet; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/> | ||
15 | */ | ||
16 | /** | ||
17 | * @file pq/pq_exec.c | ||
18 | * @brief functions to execute plain SQL statements (PostGres) | ||
19 | * @author Christian Grothoff | ||
20 | */ | ||
21 | #include "platform.h" | ||
22 | #include "gnunet_util_lib.h" | ||
23 | #include "gnunet_pq_lib.h" | ||
24 | |||
25 | |||
26 | /** | ||
27 | * Create a `struct GNUNET_PQ_ExecuteStatement` where errors are fatal. | ||
28 | * | ||
29 | * @param sql actual SQL statement | ||
30 | * @return initialized struct | ||
31 | */ | ||
32 | struct GNUNET_PQ_ExecuteStatement | ||
33 | GNUNET_PQ_make_execute (const char *sql) | ||
34 | { | ||
35 | struct GNUNET_PQ_ExecuteStatement es = { | ||
36 | .sql = sql, | ||
37 | .ignore_errors = GNUNET_NO | ||
38 | }; | ||
39 | |||
40 | return es; | ||
41 | } | ||
42 | |||
43 | |||
44 | /** | ||
45 | * Create a `struct GNUNET_PQ_ExecuteStatement` where errors should | ||
46 | * be tolerated. | ||
47 | * | ||
48 | * @param sql actual SQL statement | ||
49 | * @return initialized struct | ||
50 | */ | ||
51 | struct GNUNET_PQ_ExecuteStatement | ||
52 | GNUNET_PQ_make_try_execute (const char *sql) | ||
53 | { | ||
54 | struct GNUNET_PQ_ExecuteStatement es = { | ||
55 | .sql = sql, | ||
56 | .ignore_errors = GNUNET_YES | ||
57 | }; | ||
58 | |||
59 | return es; | ||
60 | } | ||
61 | |||
62 | |||
63 | /** | ||
64 | * Request execution of an array of statements @a es from Postgres. | ||
65 | * | ||
66 | * @param connection connection to execute the statements over | ||
67 | * @param es #GNUNET_PQ_PREPARED_STATEMENT_END-terminated array of prepared | ||
68 | * statements. | ||
69 | * @return #GNUNET_OK on success (modulo statements where errors can be ignored) | ||
70 | * #GNUNET_SYSERR on error | ||
71 | */ | ||
72 | int | ||
73 | GNUNET_PQ_exec_statements (PGconn *connection, | ||
74 | const struct GNUNET_PQ_ExecuteStatement *es) | ||
75 | { | ||
76 | for (unsigned int i=0; NULL != es[i].sql; i++) | ||
77 | { | ||
78 | PGresult *result; | ||
79 | |||
80 | result = PQexec (connection, | ||
81 | es[i].sql); | ||
82 | |||
83 | if ( (GNUNET_NO == es[i].ignore_errors) && | ||
84 | (PGRES_COMMAND_OK != PQresultStatus (result)) ) | ||
85 | { | ||
86 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, | ||
87 | "pq", | ||
88 | "Failed to execute `%s': %s/%s/%s/%s/%s", | ||
89 | es[i].sql, | ||
90 | PQresultErrorField (result, | ||
91 | PG_DIAG_MESSAGE_PRIMARY), | ||
92 | PQresultErrorField (result, | ||
93 | PG_DIAG_MESSAGE_DETAIL), | ||
94 | PQresultErrorMessage (result), | ||
95 | PQresStatus (PQresultStatus (result)), | ||
96 | PQerrorMessage (connection)); | ||
97 | PQclear (result); | ||
98 | return GNUNET_SYSERR; | ||
99 | } | ||
100 | PQclear (result); | ||
101 | } | ||
102 | return GNUNET_OK; | ||
103 | } | ||
104 | |||
105 | |||
106 | /* end of pq/pq_exec.c */ | ||
diff --git a/src/pq/pq_prepare.c b/src/pq/pq_prepare.c new file mode 100644 index 000000000..612d6df7c --- /dev/null +++ b/src/pq/pq_prepare.c | |||
@@ -0,0 +1,93 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify it under the | ||
6 | terms of the GNU General Public License as published by the Free Software | ||
7 | Foundation; either version 3, or (at your option) any later version. | ||
8 | |||
9 | GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY | ||
10 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
11 | A PARTICULAR PURPOSE. See the GNU General Public License for more details. | ||
12 | |||
13 | You should have received a copy of the GNU General Public License along with | ||
14 | GNUnet; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/> | ||
15 | */ | ||
16 | /** | ||
17 | * @file pq/pq_prepare.c | ||
18 | * @brief functions to connect to libpq (PostGres) | ||
19 | * @author Christian Grothoff | ||
20 | */ | ||
21 | #include "platform.h" | ||
22 | #include "gnunet_util_lib.h" | ||
23 | #include "gnunet_pq_lib.h" | ||
24 | |||
25 | |||
26 | /** | ||
27 | * Create a `struct GNUNET_PQ_PreparedStatement`. | ||
28 | * | ||
29 | * @param name name of the statement | ||
30 | * @param sql actual SQL statement | ||
31 | * @param num_args number of arguments in the statement | ||
32 | * @return initialized struct | ||
33 | */ | ||
34 | struct GNUNET_PQ_PreparedStatement | ||
35 | GNUNET_PQ_make_prepare (const char *name, | ||
36 | const char *sql, | ||
37 | unsigned int num_args) | ||
38 | { | ||
39 | struct GNUNET_PQ_PreparedStatement ps = { | ||
40 | .name = name, | ||
41 | .sql = sql, | ||
42 | .num_arguments = num_args | ||
43 | }; | ||
44 | |||
45 | return ps; | ||
46 | } | ||
47 | |||
48 | |||
49 | /** | ||
50 | * Request creation of prepared statements @a ps from Postgres. | ||
51 | * | ||
52 | * @param connection connection to prepare the statements for | ||
53 | * @param ps #GNUNET_PQ_PREPARED_STATEMENT_END-terminated array of prepared | ||
54 | * statements. | ||
55 | * @return #GNUNET_OK on success, | ||
56 | * #GNUNET_SYSERR on error | ||
57 | */ | ||
58 | int | ||
59 | GNUNET_PQ_prepare_statements (PGconn *connection, | ||
60 | const struct GNUNET_PQ_PreparedStatement *ps) | ||
61 | { | ||
62 | for (unsigned int i=0;NULL != ps[i].name;i++) | ||
63 | { | ||
64 | PGresult *ret; | ||
65 | |||
66 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
67 | "pq", | ||
68 | "Preparing SQL statement `%s' as `%s'\n", | ||
69 | ps[i].sql, | ||
70 | ps[i].name); | ||
71 | ret = PQprepare (connection, | ||
72 | ps[i].name, | ||
73 | ps[i].sql, | ||
74 | ps[i].num_arguments, | ||
75 | NULL); | ||
76 | if (PGRES_COMMAND_OK != PQresultStatus (ret)) | ||
77 | { | ||
78 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
79 | "pq", | ||
80 | _("PQprepare (`%s' as `%s') failed with error: %s\n"), | ||
81 | ps[i].sql, | ||
82 | ps[i].name, | ||
83 | PQerrorMessage (connection)); | ||
84 | PQclear (ret); | ||
85 | return GNUNET_SYSERR; | ||
86 | } | ||
87 | PQclear (ret); | ||
88 | } | ||
89 | return GNUNET_OK; | ||
90 | } | ||
91 | |||
92 | |||
93 | /* end of pq/pq_prepare.c */ | ||
diff --git a/src/psycstore/Makefile.am b/src/psycstore/Makefile.am index a342c06e6..557bb42b5 100644 --- a/src/psycstore/Makefile.am +++ b/src/psycstore/Makefile.am | |||
@@ -88,7 +88,6 @@ libgnunet_plugin_psycstore_postgres_la_SOURCES = \ | |||
88 | plugin_psycstore_postgres.c | 88 | plugin_psycstore_postgres.c |
89 | libgnunet_plugin_psycstore_postgres_la_LIBADD = \ | 89 | libgnunet_plugin_psycstore_postgres_la_LIBADD = \ |
90 | libgnunetpsycstore.la \ | 90 | libgnunetpsycstore.la \ |
91 | $(top_builddir)/src/postgres/libgnunetpostgres.la \ | ||
92 | $(top_builddir)/src/pq/libgnunetpq.la \ | 91 | $(top_builddir)/src/pq/libgnunetpq.la \ |
93 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | 92 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ |
94 | $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lpq \ | 93 | $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lpq \ |
diff --git a/src/psycstore/plugin_psycstore_postgres.c b/src/psycstore/plugin_psycstore_postgres.c index 273ab4e80..b8010af0a 100644 --- a/src/psycstore/plugin_psycstore_postgres.c +++ b/src/psycstore/plugin_psycstore_postgres.c | |||
@@ -25,6 +25,7 @@ | |||
25 | * @author Gabor X Toth | 25 | * @author Gabor X Toth |
26 | * @author Christian Grothoff | 26 | * @author Christian Grothoff |
27 | * @author Christophe Genevey | 27 | * @author Christophe Genevey |
28 | * @author Jeffrey Burdges | ||
28 | */ | 29 | */ |
29 | 30 | ||
30 | #include "platform.h" | 31 | #include "platform.h" |
@@ -34,7 +35,6 @@ | |||
34 | #include "gnunet_crypto_lib.h" | 35 | #include "gnunet_crypto_lib.h" |
35 | #include "gnunet_psyc_util_lib.h" | 36 | #include "gnunet_psyc_util_lib.h" |
36 | #include "psycstore.h" | 37 | #include "psycstore.h" |
37 | #include "gnunet_postgres_lib.h" | ||
38 | #include "gnunet_pq_lib.h" | 38 | #include "gnunet_pq_lib.h" |
39 | 39 | ||
40 | /** | 40 | /** |
@@ -84,342 +84,276 @@ struct Plugin | |||
84 | * as needed as well). | 84 | * as needed as well). |
85 | * | 85 | * |
86 | * @param plugin the plugin context (state for this module) | 86 | * @param plugin the plugin context (state for this module) |
87 | * @return GNUNET_OK on success | 87 | * @return #GNUNET_OK on success |
88 | */ | 88 | */ |
89 | static int | 89 | static int |
90 | database_setup (struct Plugin *plugin) | 90 | database_setup (struct Plugin *plugin) |
91 | { | 91 | { |
92 | struct GNUNET_PQ_ExecuteStatement es[] = { | ||
93 | GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS channels (\n" | ||
94 | " id SERIAL,\n" | ||
95 | " pub_key BYTEA NOT NULL CHECK (LENGTH(pub_key)=32),\n" | ||
96 | " max_state_message_id BIGINT,\n" | ||
97 | " state_hash_message_id BIGINT,\n" | ||
98 | " PRIMARY KEY(id)\n" | ||
99 | ")" | ||
100 | "WITH OIDS"), | ||
101 | GNUNET_PQ_make_execute ("CREATE UNIQUE INDEX IF NOT EXISTS channel_pub_key_idx \n" | ||
102 | " ON channels (pub_key)"), | ||
103 | GNUNET_PQ_make_execute ("CREATE OR REPLACE FUNCTION get_chan_id(BYTEA) RETURNS INTEGER AS \n" | ||
104 | " 'SELECT id FROM channels WHERE pub_key=$1;' LANGUAGE SQL STABLE \n" | ||
105 | "RETURNS NULL ON NULL INPUT"), | ||
106 | GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS slaves (\n" | ||
107 | " id SERIAL,\n" | ||
108 | " pub_key BYTEA NOT NULL CHECK (LENGTH(pub_key)=32),\n" | ||
109 | " PRIMARY KEY(id)\n" | ||
110 | ")" | ||
111 | "WITH OIDS"), | ||
112 | GNUNET_PQ_make_execute ("CREATE UNIQUE INDEX IF NOT EXISTS slaves_pub_key_idx \n" | ||
113 | " ON slaves (pub_key)"), | ||
114 | GNUNET_PQ_make_execute ("CREATE OR REPLACE FUNCTION get_slave_id(BYTEA) RETURNS INTEGER AS \n" | ||
115 | " 'SELECT id FROM slaves WHERE pub_key=$1;' LANGUAGE SQL STABLE \n" | ||
116 | "RETURNS NULL ON NULL INPUT"), | ||
117 | GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS membership (\n" | ||
118 | " channel_id BIGINT NOT NULL REFERENCES channels(id),\n" | ||
119 | " slave_id BIGINT NOT NULL REFERENCES slaves(id),\n" | ||
120 | " did_join INT NOT NULL,\n" | ||
121 | " announced_at BIGINT NOT NULL,\n" | ||
122 | " effective_since BIGINT NOT NULL,\n" | ||
123 | " group_generation BIGINT NOT NULL\n" | ||
124 | ")" | ||
125 | "WITH OIDS"), | ||
126 | GNUNET_PQ_make_execute ("CREATE INDEX IF NOT EXISTS idx_membership_channel_id_slave_id " | ||
127 | "ON membership (channel_id, slave_id)"), | ||
128 | /** @todo messages table: add method_name column */ | ||
129 | GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS messages (\n" | ||
130 | " channel_id BIGINT NOT NULL REFERENCES channels(id),\n" | ||
131 | " hop_counter INT NOT NULL,\n" | ||
132 | " signature BYTEA CHECK (LENGTH(signature)=64),\n" | ||
133 | " purpose BYTEA CHECK (LENGTH(purpose)=8),\n" | ||
134 | " fragment_id BIGINT NOT NULL,\n" | ||
135 | " fragment_offset BIGINT NOT NULL,\n" | ||
136 | " message_id BIGINT NOT NULL,\n" | ||
137 | " group_generation BIGINT NOT NULL,\n" | ||
138 | " multicast_flags INT NOT NULL,\n" | ||
139 | " psycstore_flags INT NOT NULL,\n" | ||
140 | " data BYTEA,\n" | ||
141 | " PRIMARY KEY (channel_id, fragment_id),\n" | ||
142 | " UNIQUE (channel_id, message_id, fragment_offset)\n" | ||
143 | ")" | ||
144 | "WITH OIDS"), | ||
145 | GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS state (\n" | ||
146 | " channel_id BIGINT NOT NULL REFERENCES channels(id),\n" | ||
147 | " name TEXT NOT NULL,\n" | ||
148 | " value_current BYTEA,\n" | ||
149 | " value_signed BYTEA,\n" | ||
150 | " PRIMARY KEY (channel_id, name)\n" | ||
151 | ")" | ||
152 | "WITH OIDS"), | ||
153 | GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS state_sync (\n" | ||
154 | " channel_id BIGINT NOT NULL REFERENCES channels(id),\n" | ||
155 | " name TEXT NOT NULL,\n" | ||
156 | " value BYTEA,\n" | ||
157 | " PRIMARY KEY (channel_id, name)\n" | ||
158 | ")" | ||
159 | "WITH OIDS"), | ||
160 | GNUNET_PQ_EXECUTE_STATEMENT_END | ||
161 | }; | ||
162 | |||
92 | /* Open database and precompile statements */ | 163 | /* Open database and precompile statements */ |
93 | plugin->dbh = GNUNET_POSTGRES_connect (plugin->cfg, | 164 | plugin->dbh = GNUNET_PQ_connect_with_cfg (plugin->cfg, |
94 | "psycstore-postgres"); | 165 | "psycstore-postgres"); |
95 | if (NULL == plugin->dbh) | 166 | if (NULL == plugin->dbh) |
96 | return GNUNET_SYSERR; | 167 | return GNUNET_SYSERR; |
97 | 168 | if (GNUNET_OK != | |
98 | /* Create tables */ | 169 | GNUNET_PQ_exec_statements (plugin->dbh, |
99 | if ((GNUNET_OK != | 170 | es)) |
100 | GNUNET_POSTGRES_exec(plugin->dbh, | ||
101 | "CREATE TABLE IF NOT EXISTS channels (\n" | ||
102 | " id SERIAL,\n" | ||
103 | " pub_key BYTEA NOT NULL CHECK (LENGTH(pub_key)=32),\n" | ||
104 | " max_state_message_id BIGINT,\n" | ||
105 | " state_hash_message_id BIGINT,\n" | ||
106 | " PRIMARY KEY(id)\n" | ||
107 | ")" "WITH OIDS")) || | ||
108 | |||
109 | (GNUNET_OK != | ||
110 | GNUNET_POSTGRES_exec(plugin->dbh, | ||
111 | "CREATE UNIQUE INDEX IF NOT EXISTS channel_pub_key_idx \n" | ||
112 | " ON channels (pub_key)")) || | ||
113 | |||
114 | (GNUNET_OK != | ||
115 | GNUNET_POSTGRES_exec(plugin->dbh, | ||
116 | "CREATE OR REPLACE FUNCTION get_chan_id(BYTEA) RETURNS INTEGER AS \n" | ||
117 | " 'SELECT id FROM channels WHERE pub_key=$1;' LANGUAGE SQL STABLE \n" | ||
118 | "RETURNS NULL ON NULL INPUT")) || | ||
119 | |||
120 | (GNUNET_OK != | ||
121 | GNUNET_POSTGRES_exec(plugin->dbh, | ||
122 | "CREATE TABLE IF NOT EXISTS slaves (\n" | ||
123 | " id SERIAL,\n" | ||
124 | " pub_key BYTEA NOT NULL CHECK (LENGTH(pub_key)=32),\n" | ||
125 | " PRIMARY KEY(id)\n" | ||
126 | ")" "WITH OIDS")) || | ||
127 | |||
128 | (GNUNET_OK != | ||
129 | GNUNET_POSTGRES_exec(plugin->dbh, | ||
130 | "CREATE UNIQUE INDEX IF NOT EXISTS slaves_pub_key_idx \n" | ||
131 | " ON slaves (pub_key)")) || | ||
132 | |||
133 | (GNUNET_OK != | ||
134 | GNUNET_POSTGRES_exec(plugin->dbh, | ||
135 | "CREATE OR REPLACE FUNCTION get_slave_id(BYTEA) RETURNS INTEGER AS \n" | ||
136 | " 'SELECT id FROM slaves WHERE pub_key=$1;' LANGUAGE SQL STABLE \n" | ||
137 | "RETURNS NULL ON NULL INPUT")) || | ||
138 | |||
139 | (GNUNET_OK != | ||
140 | GNUNET_POSTGRES_exec(plugin->dbh, | ||
141 | "CREATE TABLE IF NOT EXISTS membership (\n" | ||
142 | " channel_id BIGINT NOT NULL REFERENCES channels(id),\n" | ||
143 | " slave_id BIGINT NOT NULL REFERENCES slaves(id),\n" | ||
144 | " did_join INT NOT NULL,\n" | ||
145 | " announced_at BIGINT NOT NULL,\n" | ||
146 | " effective_since BIGINT NOT NULL,\n" | ||
147 | " group_generation BIGINT NOT NULL\n" | ||
148 | ")" "WITH OIDS")) || | ||
149 | |||
150 | (GNUNET_OK != | ||
151 | GNUNET_POSTGRES_exec(plugin->dbh, | ||
152 | "CREATE INDEX IF NOT EXISTS idx_membership_channel_id_slave_id " | ||
153 | "ON membership (channel_id, slave_id)")) || | ||
154 | |||
155 | /** @todo messages table: add method_name column */ | ||
156 | (GNUNET_OK != | ||
157 | GNUNET_POSTGRES_exec(plugin->dbh, | ||
158 | "CREATE TABLE IF NOT EXISTS messages (\n" | ||
159 | " channel_id BIGINT NOT NULL REFERENCES channels(id),\n" | ||
160 | " hop_counter INT NOT NULL,\n" | ||
161 | " signature BYTEA CHECK (LENGTH(signature)=64),\n" | ||
162 | " purpose BYTEA CHECK (LENGTH(purpose)=8),\n" | ||
163 | " fragment_id BIGINT NOT NULL,\n" | ||
164 | " fragment_offset BIGINT NOT NULL,\n" | ||
165 | " message_id BIGINT NOT NULL,\n" | ||
166 | " group_generation BIGINT NOT NULL,\n" | ||
167 | " multicast_flags INT NOT NULL,\n" | ||
168 | " psycstore_flags INT NOT NULL,\n" | ||
169 | " data BYTEA,\n" | ||
170 | " PRIMARY KEY (channel_id, fragment_id),\n" | ||
171 | " UNIQUE (channel_id, message_id, fragment_offset)\n" | ||
172 | ")" "WITH OIDS")) || | ||
173 | |||
174 | (GNUNET_OK != | ||
175 | GNUNET_POSTGRES_exec(plugin->dbh, | ||
176 | "CREATE TABLE IF NOT EXISTS state (\n" | ||
177 | " channel_id BIGINT NOT NULL REFERENCES channels(id),\n" | ||
178 | " name TEXT NOT NULL,\n" | ||
179 | " value_current BYTEA,\n" | ||
180 | " value_signed BYTEA,\n" | ||
181 | " PRIMARY KEY (channel_id, name)\n" | ||
182 | ")" "WITH OIDS")) || | ||
183 | (GNUNET_OK != | ||
184 | GNUNET_POSTGRES_exec(plugin->dbh, | ||
185 | "CREATE TABLE IF NOT EXISTS state_sync (\n" | ||
186 | " channel_id BIGINT NOT NULL REFERENCES channels(id),\n" | ||
187 | " name TEXT NOT NULL,\n" | ||
188 | " value BYTEA,\n" | ||
189 | " PRIMARY KEY (channel_id, name)\n" | ||
190 | ")" "WITH OIDS"))) | ||
191 | { | 171 | { |
192 | PQfinish (plugin->dbh); | 172 | PQfinish (plugin->dbh); |
193 | plugin->dbh = NULL; | 173 | plugin->dbh = NULL; |
194 | return GNUNET_SYSERR; | 174 | return GNUNET_SYSERR; |
195 | } | 175 | } |
196 | 176 | ||
197 | |||
198 | /* Prepare statements */ | 177 | /* Prepare statements */ |
199 | if ((GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, | 178 | { |
200 | "transaction_begin", | 179 | struct GNUNET_PQ_PreparedStatement ps[] = { |
201 | "BEGIN", 0)) || | 180 | GNUNET_PQ_make_prepare ("transaction_begin", |
202 | 181 | "BEGIN", 0), | |
203 | (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, | 182 | GNUNET_PQ_make_prepare ("transaction_commit", |
204 | "transaction_commit", | 183 | "COMMIT", 0), |
205 | "COMMIT", 0)) || | 184 | GNUNET_PQ_make_prepare ("transaction_rollback", |
206 | 185 | "ROLLBACK", 0), | |
207 | (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, | 186 | GNUNET_PQ_make_prepare ("insert_channel_key", |
208 | "transaction_rollback", | 187 | "INSERT INTO channels (pub_key) VALUES ($1)" |
209 | "ROLLBACK", 0)) || | 188 | " ON CONFLICT DO NOTHING", 1), |
210 | 189 | GNUNET_PQ_make_prepare ("insert_slave_key", | |
211 | (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, | 190 | "INSERT INTO slaves (pub_key) VALUES ($1)" |
212 | "insert_channel_key", | 191 | " ON CONFLICT DO NOTHING", 1), |
213 | "INSERT INTO channels (pub_key) VALUES ($1)" | 192 | GNUNET_PQ_make_prepare ("insert_membership", |
214 | " ON CONFLICT DO NOTHING", 1)) || | 193 | "INSERT INTO membership\n" |
215 | 194 | " (channel_id, slave_id, did_join, announced_at,\n" | |
216 | (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, | 195 | " effective_since, group_generation)\n" |
217 | "insert_slave_key", | 196 | "VALUES (get_chan_id($1),\n" |
218 | "INSERT INTO slaves (pub_key) VALUES ($1)" | 197 | " get_slave_id($2),\n" |
219 | " ON CONFLICT DO NOTHING", 1)) || | 198 | " $3, $4, $5, $6)", 6), |
220 | 199 | GNUNET_PQ_make_prepare ("select_membership", | |
221 | (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, | 200 | "SELECT did_join FROM membership\n" |
222 | "insert_membership", | 201 | "WHERE channel_id = get_chan_id($1)\n" |
223 | "INSERT INTO membership\n" | 202 | " AND slave_id = get_slave_id($2)\n" |
224 | " (channel_id, slave_id, did_join, announced_at,\n" | 203 | " AND effective_since <= $3 AND did_join = 1\n" |
225 | " effective_since, group_generation)\n" | 204 | "ORDER BY announced_at DESC LIMIT 1", 3), |
226 | "VALUES (get_chan_id($1),\n" | 205 | GNUNET_PQ_make_prepare ("insert_fragment", |
227 | " get_slave_id($2),\n" | 206 | "INSERT INTO messages\n" |
228 | " $3, $4, $5, $6)", 6)) || | 207 | " (channel_id, hop_counter, signature, purpose,\n" |
229 | 208 | " fragment_id, fragment_offset, message_id,\n" | |
230 | (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, | 209 | " group_generation, multicast_flags, psycstore_flags, data)\n" |
231 | "select_membership", | 210 | "VALUES (get_chan_id($1),\n" |
232 | "SELECT did_join FROM membership\n" | 211 | " $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)" |
233 | "WHERE channel_id = get_chan_id($1)\n" | 212 | "ON CONFLICT DO NOTHING", 11), |
234 | " AND slave_id = get_slave_id($2)\n" | 213 | GNUNET_PQ_make_prepare ("update_message_flags", |
235 | " AND effective_since <= $3 AND did_join = 1\n" | 214 | "UPDATE messages\n" |
236 | "ORDER BY announced_at DESC LIMIT 1", 3)) || | 215 | "SET psycstore_flags = psycstore_flags | $1\n" |
237 | 216 | "WHERE channel_id = get_chan_id($2) \n" | |
238 | (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, | 217 | " AND message_id = $3 AND fragment_offset = 0", 3), |
239 | "insert_fragment", | 218 | GNUNET_PQ_make_prepare ("select_fragments", |
240 | "INSERT INTO messages\n" | 219 | "SELECT hop_counter, signature, purpose, fragment_id,\n" |
241 | " (channel_id, hop_counter, signature, purpose,\n" | 220 | " fragment_offset, message_id, group_generation,\n" |
242 | " fragment_id, fragment_offset, message_id,\n" | 221 | " multicast_flags, psycstore_flags, data\n" |
243 | " group_generation, multicast_flags, psycstore_flags, data)\n" | 222 | "FROM messages\n" |
244 | "VALUES (get_chan_id($1),\n" | 223 | "WHERE channel_id = get_chan_id($1) \n" |
245 | " $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)" | 224 | " AND $2 <= fragment_id AND fragment_id <= $3", 3), |
246 | "ON CONFLICT DO NOTHING", 11)) || | ||
247 | |||
248 | (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, | ||
249 | "update_message_flags", | ||
250 | "UPDATE messages\n" | ||
251 | "SET psycstore_flags = psycstore_flags | $1\n" | ||
252 | "WHERE channel_id = get_chan_id($2) \n" | ||
253 | " AND message_id = $3 AND fragment_offset = 0", 3)) || | ||
254 | |||
255 | (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, | ||
256 | "select_fragments", | ||
257 | "SELECT hop_counter, signature, purpose, fragment_id,\n" | ||
258 | " fragment_offset, message_id, group_generation,\n" | ||
259 | " multicast_flags, psycstore_flags, data\n" | ||
260 | "FROM messages\n" | ||
261 | "WHERE channel_id = get_chan_id($1) \n" | ||
262 | " AND $2 <= fragment_id AND fragment_id <= $3", 3)) || | ||
263 | |||
264 | /** @todo select_messages: add method_prefix filter */ | 225 | /** @todo select_messages: add method_prefix filter */ |
265 | (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, | 226 | GNUNET_PQ_make_prepare ("select_messages", |
266 | "select_messages", | 227 | "SELECT hop_counter, signature, purpose, fragment_id,\n" |
267 | "SELECT hop_counter, signature, purpose, fragment_id,\n" | 228 | " fragment_offset, message_id, group_generation,\n" |
268 | " fragment_offset, message_id, group_generation,\n" | 229 | " multicast_flags, psycstore_flags, data\n" |
269 | " multicast_flags, psycstore_flags, data\n" | 230 | "FROM messages\n" |
270 | "FROM messages\n" | 231 | "WHERE channel_id = get_chan_id($1) \n" |
271 | "WHERE channel_id = get_chan_id($1) \n" | 232 | " AND $2 <= message_id AND message_id <= $3\n" |
272 | " AND $2 <= message_id AND message_id <= $3\n" | 233 | "LIMIT $4;", 4), |
273 | "LIMIT $4;", 4)) || | ||
274 | |||
275 | /** @todo select_latest_messages: add method_prefix filter */ | 234 | /** @todo select_latest_messages: add method_prefix filter */ |
276 | (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, | 235 | GNUNET_PQ_make_prepare ("select_latest_fragments", |
277 | "select_latest_fragments", | 236 | "SELECT rev.hop_counter AS hop_counter,\n" |
278 | "SELECT rev.hop_counter AS hop_counter,\n" | 237 | " rev.signature AS signature,\n" |
279 | " rev.signature AS signature,\n" | 238 | " rev.purpose AS purpose,\n" |
280 | " rev.purpose AS purpose,\n" | 239 | " rev.fragment_id AS fragment_id,\n" |
281 | " rev.fragment_id AS fragment_id,\n" | 240 | " rev.fragment_offset AS fragment_offset,\n" |
282 | " rev.fragment_offset AS fragment_offset,\n" | 241 | " rev.message_id AS message_id,\n" |
283 | " rev.message_id AS message_id,\n" | 242 | " rev.group_generation AS group_generation,\n" |
284 | " rev.group_generation AS group_generation,\n" | 243 | " rev.multicast_flags AS multicast_flags,\n" |
285 | " rev.multicast_flags AS multicast_flags,\n" | 244 | " rev.psycstore_flags AS psycstore_flags,\n" |
286 | " rev.psycstore_flags AS psycstore_flags,\n" | 245 | " rev.data AS data\n" |
287 | " rev.data AS data\n" | 246 | " FROM\n" |
288 | " FROM\n" | 247 | " (SELECT hop_counter, signature, purpose, fragment_id,\n" |
289 | " (SELECT hop_counter, signature, purpose, fragment_id,\n" | 248 | " fragment_offset, message_id, group_generation,\n" |
290 | " fragment_offset, message_id, group_generation,\n" | 249 | " multicast_flags, psycstore_flags, data \n" |
291 | " multicast_flags, psycstore_flags, data \n" | 250 | " FROM messages\n" |
292 | " FROM messages\n" | 251 | " WHERE channel_id = get_chan_id($1) \n" |
293 | " WHERE channel_id = get_chan_id($1) \n" | 252 | " ORDER BY fragment_id DESC\n" |
294 | " ORDER BY fragment_id DESC\n" | 253 | " LIMIT $2) AS rev\n" |
295 | " LIMIT $2) AS rev\n" | 254 | " ORDER BY rev.fragment_id;", 2), |
296 | " ORDER BY rev.fragment_id;", 2)) || | 255 | GNUNET_PQ_make_prepare ("select_latest_messages", |
297 | 256 | "SELECT hop_counter, signature, purpose, fragment_id,\n" | |
298 | (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, | 257 | " fragment_offset, message_id, group_generation,\n" |
299 | "select_latest_messages", | 258 | " multicast_flags, psycstore_flags, data\n" |
300 | "SELECT hop_counter, signature, purpose, fragment_id,\n" | 259 | "FROM messages\n" |
301 | " fragment_offset, message_id, group_generation,\n" | 260 | "WHERE channel_id = get_chan_id($1)\n" |
302 | " multicast_flags, psycstore_flags, data\n" | 261 | " AND message_id IN\n" |
303 | "FROM messages\n" | 262 | " (SELECT message_id\n" |
304 | "WHERE channel_id = get_chan_id($1)\n" | 263 | " FROM messages\n" |
305 | " AND message_id IN\n" | 264 | " WHERE channel_id = get_chan_id($2) \n" |
306 | " (SELECT message_id\n" | 265 | " GROUP BY message_id\n" |
307 | " FROM messages\n" | 266 | " ORDER BY message_id\n" |
308 | " WHERE channel_id = get_chan_id($2) \n" | 267 | " DESC LIMIT $3)\n" |
309 | " GROUP BY message_id\n" | 268 | "ORDER BY fragment_id", 3), |
310 | " ORDER BY message_id\n" | 269 | GNUNET_PQ_make_prepare ("select_message_fragment", |
311 | " DESC LIMIT $3)\n" | 270 | "SELECT hop_counter, signature, purpose, fragment_id,\n" |
312 | "ORDER BY fragment_id", 3)) || | 271 | " fragment_offset, message_id, group_generation,\n" |
313 | 272 | " multicast_flags, psycstore_flags, data\n" | |
314 | (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, | 273 | "FROM messages\n" |
315 | "select_message_fragment", | 274 | "WHERE channel_id = get_chan_id($1) \n" |
316 | "SELECT hop_counter, signature, purpose, fragment_id,\n" | 275 | " AND message_id = $2 AND fragment_offset = $3", 3), |
317 | " fragment_offset, message_id, group_generation,\n" | 276 | GNUNET_PQ_make_prepare ("select_counters_message", |
318 | " multicast_flags, psycstore_flags, data\n" | 277 | "SELECT fragment_id, message_id, group_generation\n" |
319 | "FROM messages\n" | 278 | "FROM messages\n" |
320 | "WHERE channel_id = get_chan_id($1) \n" | 279 | "WHERE channel_id = get_chan_id($1)\n" |
321 | " AND message_id = $2 AND fragment_offset = $3", 3)) || | 280 | "ORDER BY fragment_id DESC LIMIT 1", 1), |
322 | 281 | GNUNET_PQ_make_prepare ("select_counters_state", | |
323 | (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, | 282 | "SELECT max_state_message_id\n" |
324 | "select_counters_message", | 283 | "FROM channels\n" |
325 | "SELECT fragment_id, message_id, group_generation\n" | 284 | "WHERE pub_key = $1 AND max_state_message_id IS NOT NULL", 1), |
326 | "FROM messages\n" | 285 | GNUNET_PQ_make_prepare ("update_max_state_message_id", |
327 | "WHERE channel_id = get_chan_id($1)\n" | 286 | "UPDATE channels\n" |
328 | "ORDER BY fragment_id DESC LIMIT 1", 1)) || | 287 | "SET max_state_message_id = $1\n" |
329 | 288 | "WHERE pub_key = $2", 2), | |
330 | (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, | 289 | |
331 | "select_counters_state", | 290 | GNUNET_PQ_make_prepare ("update_state_hash_message_id", |
332 | "SELECT max_state_message_id\n" | 291 | "UPDATE channels\n" |
333 | "FROM channels\n" | 292 | "SET state_hash_message_id = $1\n" |
334 | "WHERE pub_key = $1 AND max_state_message_id IS NOT NULL", 1)) || | 293 | "WHERE pub_key = $2", 2), |
335 | 294 | GNUNET_PQ_make_prepare ("insert_state_current", | |
336 | (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, | 295 | "INSERT INTO state\n" |
337 | "update_max_state_message_id", | 296 | " (channel_id, name, value_current, value_signed)\n" |
338 | "UPDATE channels\n" | 297 | "SELECT new.channel_id, new.name,\n" |
339 | "SET max_state_message_id = $1\n" | 298 | " new.value_current, old.value_signed\n" |
340 | "WHERE pub_key = $2", 2)) || | 299 | "FROM (SELECT get_chan_id($1) AS channel_id,\n" |
341 | 300 | " $2::TEXT AS name, $3::BYTEA AS value_current) AS new\n" | |
342 | (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, | 301 | "LEFT JOIN (SELECT channel_id, name, value_signed\n" |
343 | "update_state_hash_message_id", | 302 | " FROM state) AS old\n" |
344 | "UPDATE channels\n" | 303 | "ON new.channel_id = old.channel_id AND new.name = old.name\n" |
345 | "SET state_hash_message_id = $1\n" | 304 | "ON CONFLICT (channel_id, name)\n" |
346 | "WHERE pub_key = $2", 2)) || | 305 | " DO UPDATE SET value_current = EXCLUDED.value_current,\n" |
347 | 306 | " value_signed = EXCLUDED.value_signed", 3), | |
348 | (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, | 307 | GNUNET_PQ_make_prepare ("delete_state_empty", |
349 | "insert_state_current", | 308 | "DELETE FROM state\n" |
350 | "INSERT INTO state\n" | 309 | "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = $1)\n" |
351 | " (channel_id, name, value_current, value_signed)\n" | 310 | " AND (value_current IS NULL OR length(value_current) = 0)\n" |
352 | "SELECT new.channel_id, new.name,\n" | 311 | " AND (value_signed IS NULL OR length(value_signed) = 0)", 1), |
353 | " new.value_current, old.value_signed\n" | 312 | GNUNET_PQ_make_prepare ("update_state_signed", |
354 | "FROM (SELECT get_chan_id($1) AS channel_id,\n" | 313 | "UPDATE state\n" |
355 | " $2::TEXT AS name, $3::BYTEA AS value_current) AS new\n" | 314 | "SET value_signed = value_current\n" |
356 | "LEFT JOIN (SELECT channel_id, name, value_signed\n" | 315 | "WHERE channel_id = get_chan_id($1) ", 1), |
357 | " FROM state) AS old\n" | 316 | GNUNET_PQ_make_prepare ("delete_state", |
358 | "ON new.channel_id = old.channel_id AND new.name = old.name\n" | 317 | "DELETE FROM state\n" |
359 | "ON CONFLICT (channel_id, name)\n" | 318 | "WHERE channel_id = get_chan_id($1) ", 1), |
360 | " DO UPDATE SET value_current = EXCLUDED.value_current,\n" | 319 | GNUNET_PQ_make_prepare ("insert_state_sync", |
361 | " value_signed = EXCLUDED.value_signed", 3)) || | 320 | "INSERT INTO state_sync (channel_id, name, value)\n" |
362 | 321 | "VALUES (get_chan_id($1), $2, $3)", 3), | |
363 | (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, | 322 | GNUNET_PQ_make_prepare ("insert_state_from_sync", |
364 | "delete_state_empty", | 323 | "INSERT INTO state\n" |
365 | "DELETE FROM state\n" | 324 | " (channel_id, name, value_current, value_signed)\n" |
366 | "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = $1)\n" | 325 | "SELECT channel_id, name, value, value\n" |
367 | " AND (value_current IS NULL OR length(value_current) = 0)\n" | 326 | "FROM state_sync\n" |
368 | " AND (value_signed IS NULL OR length(value_signed) = 0)", 1)) || | 327 | "WHERE channel_id = get_chan_id($1)", 1), |
369 | 328 | GNUNET_PQ_make_prepare ("delete_state_sync", | |
370 | (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, | 329 | "DELETE FROM state_sync\n" |
371 | "update_state_signed", | 330 | "WHERE channel_id = get_chan_id($1)", 1), |
372 | "UPDATE state\n" | 331 | GNUNET_PQ_make_prepare ("select_state_one", |
373 | "SET value_signed = value_current\n" | 332 | "SELECT value_current\n" |
374 | "WHERE channel_id = get_chan_id($1) ", 1)) || | 333 | "FROM state\n" |
375 | 334 | "WHERE channel_id = get_chan_id($1)\n" | |
376 | (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, | 335 | " AND name = $2", 2), |
377 | "delete_state", | 336 | GNUNET_PQ_make_prepare ("select_state_prefix", |
378 | "DELETE FROM state\n" | 337 | "SELECT name, value_current\n" |
379 | "WHERE channel_id = get_chan_id($1) ", 1)) || | 338 | "FROM state\n" |
380 | 339 | "WHERE channel_id = get_chan_id($1)\n" | |
381 | (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, | 340 | " AND (name = $2 OR substr(name, 1, $3) = $4)", 4), |
382 | "insert_state_sync", | 341 | GNUNET_PQ_make_prepare ("select_state_signed", |
383 | "INSERT INTO state_sync (channel_id, name, value)\n" | 342 | "SELECT name, value_signed\n" |
384 | "VALUES (get_chan_id($1), $2, $3)", 3)) || | 343 | "FROM state\n" |
385 | 344 | "WHERE channel_id = get_chan_id($1)\n" | |
386 | (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, | 345 | " AND value_signed IS NOT NULL", 1), |
387 | "insert_state_from_sync", | 346 | GNUNET_PQ_PREPARED_STATEMENT_END |
388 | "INSERT INTO state\n" | 347 | }; |
389 | " (channel_id, name, value_current, value_signed)\n" | 348 | |
390 | "SELECT channel_id, name, value, value\n" | 349 | if (GNUNET_OK != |
391 | "FROM state_sync\n" | 350 | GNUNET_PQ_prepare_statements (plugin->dbh, |
392 | "WHERE channel_id = get_chan_id($1)", 1)) || | 351 | ps)) |
393 | 352 | { | |
394 | (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, | 353 | PQfinish (plugin->dbh); |
395 | "delete_state_sync", | 354 | plugin->dbh = NULL; |
396 | "DELETE FROM state_sync\n" | 355 | return GNUNET_SYSERR; |
397 | "WHERE channel_id = get_chan_id($1)", 1)) || | 356 | } |
398 | |||
399 | (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, | ||
400 | "select_state_one", | ||
401 | "SELECT value_current\n" | ||
402 | "FROM state\n" | ||
403 | "WHERE channel_id = get_chan_id($1)\n" | ||
404 | " AND name = $2", 2)) || | ||
405 | |||
406 | (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, | ||
407 | "select_state_prefix", | ||
408 | "SELECT name, value_current\n" | ||
409 | "FROM state\n" | ||
410 | "WHERE channel_id = get_chan_id($1)\n" | ||
411 | " AND (name = $2 OR substr(name, 1, $3) = $4)", 4)) || | ||
412 | |||
413 | (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, | ||
414 | "select_state_signed", | ||
415 | "SELECT name, value_signed\n" | ||
416 | "FROM state\n" | ||
417 | "WHERE channel_id = get_chan_id($1)\n" | ||
418 | " AND value_signed IS NOT NULL", 1))) | ||
419 | { | ||
420 | PQfinish (plugin->dbh); | ||
421 | plugin->dbh = NULL; | ||
422 | return GNUNET_SYSERR; | ||
423 | } | 357 | } |
424 | 358 | ||
425 | return GNUNET_OK; | 359 | return GNUNET_OK; |
@@ -452,22 +386,15 @@ static int | |||
452 | exec_channel (struct Plugin *plugin, const char *stmt, | 386 | exec_channel (struct Plugin *plugin, const char *stmt, |
453 | const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key) | 387 | const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key) |
454 | { | 388 | { |
455 | PGresult *ret; | ||
456 | struct GNUNET_PQ_QueryParam params[] = { | 389 | struct GNUNET_PQ_QueryParam params[] = { |
457 | GNUNET_PQ_query_param_auto_from_type (channel_key), | 390 | GNUNET_PQ_query_param_auto_from_type (channel_key), |
458 | GNUNET_PQ_query_param_end | 391 | GNUNET_PQ_query_param_end |
459 | }; | 392 | }; |
460 | 393 | ||
461 | ret = GNUNET_PQ_exec_prepared (plugin->dbh, stmt, params); | 394 | if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != |
462 | if (GNUNET_OK != | 395 | GNUNET_PQ_eval_prepared_non_select (plugin->dbh, stmt, params)) |
463 | GNUNET_POSTGRES_check_result (plugin->dbh, | ||
464 | ret, | ||
465 | PGRES_COMMAND_OK, | ||
466 | "PQexecPrepared", stmt)) | ||
467 | return GNUNET_SYSERR; | 396 | return GNUNET_SYSERR; |
468 | 397 | ||
469 | PQclear (ret); | ||
470 | |||
471 | return GNUNET_OK; | 398 | return GNUNET_OK; |
472 | } | 399 | } |
473 | 400 | ||
@@ -478,23 +405,15 @@ exec_channel (struct Plugin *plugin, const char *stmt, | |||
478 | static int | 405 | static int |
479 | transaction_begin (struct Plugin *plugin, enum Transactions transaction) | 406 | transaction_begin (struct Plugin *plugin, enum Transactions transaction) |
480 | { | 407 | { |
481 | PGresult *ret; | ||
482 | struct GNUNET_PQ_QueryParam params[] = { | 408 | struct GNUNET_PQ_QueryParam params[] = { |
483 | GNUNET_PQ_query_param_end | 409 | GNUNET_PQ_query_param_end |
484 | }; | 410 | }; |
485 | 411 | ||
486 | ret = GNUNET_PQ_exec_prepared (plugin->dbh, "transaction_begin", params); | 412 | if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != |
487 | if (GNUNET_OK != | 413 | GNUNET_PQ_eval_prepared_non_select (plugin->dbh, "transaction_begin", params)) |
488 | GNUNET_POSTGRES_check_result (plugin->dbh, | ||
489 | ret, | ||
490 | PGRES_COMMAND_OK, | ||
491 | "PQexecPrepared", "transaction_begin")) | ||
492 | { | ||
493 | return GNUNET_SYSERR; | 414 | return GNUNET_SYSERR; |
494 | } | ||
495 | 415 | ||
496 | plugin->transaction = transaction; | 416 | plugin->transaction = transaction; |
497 | PQclear (ret); | ||
498 | return GNUNET_OK; | 417 | return GNUNET_OK; |
499 | } | 418 | } |
500 | 419 | ||
@@ -505,23 +424,14 @@ transaction_begin (struct Plugin *plugin, enum Transactions transaction) | |||
505 | static int | 424 | static int |
506 | transaction_commit (struct Plugin *plugin) | 425 | transaction_commit (struct Plugin *plugin) |
507 | { | 426 | { |
508 | PGresult *ret; | ||
509 | |||
510 | struct GNUNET_PQ_QueryParam params[] = { | 427 | struct GNUNET_PQ_QueryParam params[] = { |
511 | GNUNET_PQ_query_param_end | 428 | GNUNET_PQ_query_param_end |
512 | }; | 429 | }; |
513 | 430 | ||
514 | ret = GNUNET_PQ_exec_prepared (plugin->dbh, "transaction_commit", params); | 431 | if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != |
515 | if (GNUNET_OK != | 432 | GNUNET_PQ_eval_prepared_non_select (plugin->dbh, "transaction_commit", params)) |
516 | GNUNET_POSTGRES_check_result (plugin->dbh, | ||
517 | ret, | ||
518 | PGRES_COMMAND_OK, | ||
519 | "PQexecPrepared", "transaction_commit")) | ||
520 | { | ||
521 | return GNUNET_SYSERR; | 433 | return GNUNET_SYSERR; |
522 | } | ||
523 | 434 | ||
524 | PQclear (ret); | ||
525 | plugin->transaction = TRANSACTION_NONE; | 435 | plugin->transaction = TRANSACTION_NONE; |
526 | return GNUNET_OK; | 436 | return GNUNET_OK; |
527 | } | 437 | } |
@@ -533,23 +443,14 @@ transaction_commit (struct Plugin *plugin) | |||
533 | static int | 443 | static int |
534 | transaction_rollback (struct Plugin *plugin) | 444 | transaction_rollback (struct Plugin *plugin) |
535 | { | 445 | { |
536 | PGresult *ret; | ||
537 | |||
538 | struct GNUNET_PQ_QueryParam params[] = { | 446 | struct GNUNET_PQ_QueryParam params[] = { |
539 | GNUNET_PQ_query_param_end | 447 | GNUNET_PQ_query_param_end |
540 | }; | 448 | }; |
541 | 449 | ||
542 | ret = GNUNET_PQ_exec_prepared (plugin->dbh, "transaction_rollback", params); | 450 | if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != |
543 | if (GNUNET_OK != | 451 | GNUNET_PQ_eval_prepared_non_select (plugin->dbh, "transaction_rollback", params)) |
544 | GNUNET_POSTGRES_check_result (plugin->dbh, | ||
545 | ret, | ||
546 | PGRES_COMMAND_OK, | ||
547 | "PQexecPrepared", "transaction_rollback")) | ||
548 | { | ||
549 | return GNUNET_SYSERR; | 452 | return GNUNET_SYSERR; |
550 | } | ||
551 | 453 | ||
552 | PQclear (ret); | ||
553 | plugin->transaction = TRANSACTION_NONE; | 454 | plugin->transaction = TRANSACTION_NONE; |
554 | return GNUNET_OK; | 455 | return GNUNET_OK; |
555 | } | 456 | } |
@@ -559,24 +460,15 @@ static int | |||
559 | channel_key_store (struct Plugin *plugin, | 460 | channel_key_store (struct Plugin *plugin, |
560 | const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key) | 461 | const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key) |
561 | { | 462 | { |
562 | PGresult *ret; | ||
563 | |||
564 | struct GNUNET_PQ_QueryParam params[] = { | 463 | struct GNUNET_PQ_QueryParam params[] = { |
565 | GNUNET_PQ_query_param_auto_from_type (channel_key), | 464 | GNUNET_PQ_query_param_auto_from_type (channel_key), |
566 | GNUNET_PQ_query_param_end | 465 | GNUNET_PQ_query_param_end |
567 | }; | 466 | }; |
568 | 467 | ||
569 | ret = GNUNET_PQ_exec_prepared (plugin->dbh, "insert_channel_key", params); | 468 | if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != |
570 | if (GNUNET_OK != | 469 | GNUNET_PQ_eval_prepared_non_select (plugin->dbh, "insert_channel_key", params)) |
571 | GNUNET_POSTGRES_check_result (plugin->dbh, | ||
572 | ret, | ||
573 | PGRES_COMMAND_OK, | ||
574 | "PQexecPrepared", "insert_channel_key")) | ||
575 | { | ||
576 | return GNUNET_SYSERR; | 470 | return GNUNET_SYSERR; |
577 | } | ||
578 | 471 | ||
579 | PQclear (ret); | ||
580 | return GNUNET_OK; | 472 | return GNUNET_OK; |
581 | } | 473 | } |
582 | 474 | ||
@@ -585,24 +477,15 @@ static int | |||
585 | slave_key_store (struct Plugin *plugin, | 477 | slave_key_store (struct Plugin *plugin, |
586 | const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key) | 478 | const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key) |
587 | { | 479 | { |
588 | PGresult *ret; | ||
589 | |||
590 | struct GNUNET_PQ_QueryParam params[] = { | 480 | struct GNUNET_PQ_QueryParam params[] = { |
591 | GNUNET_PQ_query_param_auto_from_type (slave_key), | 481 | GNUNET_PQ_query_param_auto_from_type (slave_key), |
592 | GNUNET_PQ_query_param_end | 482 | GNUNET_PQ_query_param_end |
593 | }; | 483 | }; |
594 | 484 | ||
595 | ret = GNUNET_PQ_exec_prepared (plugin->dbh, "insert_slave_key", params); | 485 | if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != |
596 | if (GNUNET_OK != | 486 | GNUNET_PQ_eval_prepared_non_select (plugin->dbh, "insert_slave_key", params)) |
597 | GNUNET_POSTGRES_check_result (plugin->dbh, | ||
598 | ret, | ||
599 | PGRES_COMMAND_OK, | ||
600 | "PQexecPrepared", "insert_slave_key")) | ||
601 | { | ||
602 | return GNUNET_SYSERR; | 487 | return GNUNET_SYSERR; |
603 | } | ||
604 | 488 | ||
605 | PQclear (ret); | ||
606 | return GNUNET_OK; | 489 | return GNUNET_OK; |
607 | } | 490 | } |
608 | 491 | ||
@@ -624,7 +507,6 @@ postgres_membership_store (void *cls, | |||
624 | uint64_t effective_since, | 507 | uint64_t effective_since, |
625 | uint64_t group_generation) | 508 | uint64_t group_generation) |
626 | { | 509 | { |
627 | PGresult *ret; | ||
628 | struct Plugin *plugin = cls; | 510 | struct Plugin *plugin = cls; |
629 | 511 | ||
630 | uint32_t idid_join = (uint32_t)did_join; | 512 | uint32_t idid_join = (uint32_t)did_join; |
@@ -653,17 +535,10 @@ postgres_membership_store (void *cls, | |||
653 | GNUNET_PQ_query_param_end | 535 | GNUNET_PQ_query_param_end |
654 | }; | 536 | }; |
655 | 537 | ||
656 | ret = GNUNET_PQ_exec_prepared (plugin->dbh, "insert_membership", params); | 538 | if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != |
657 | if (GNUNET_OK != | 539 | GNUNET_PQ_eval_prepared_non_select (plugin->dbh, "insert_membership", params)) |
658 | GNUNET_POSTGRES_check_result (plugin->dbh, | ||
659 | ret, | ||
660 | PGRES_COMMAND_OK, | ||
661 | "PQexecPrepared", "insert_membership")) | ||
662 | { | ||
663 | return GNUNET_SYSERR; | 540 | return GNUNET_SYSERR; |
664 | } | ||
665 | 541 | ||
666 | PQclear (ret); | ||
667 | return GNUNET_OK; | 542 | return GNUNET_OK; |
668 | } | 543 | } |
669 | 544 | ||
@@ -681,13 +556,10 @@ membership_test (void *cls, | |||
681 | const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key, | 556 | const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key, |
682 | uint64_t message_id) | 557 | uint64_t message_id) |
683 | { | 558 | { |
684 | PGresult *res; | ||
685 | struct Plugin *plugin = cls; | 559 | struct Plugin *plugin = cls; |
686 | 560 | ||
687 | uint32_t did_join = 0; | 561 | uint32_t did_join = 0; |
688 | 562 | ||
689 | int ret = GNUNET_SYSERR; | ||
690 | |||
691 | struct GNUNET_PQ_QueryParam params_select[] = { | 563 | struct GNUNET_PQ_QueryParam params_select[] = { |
692 | GNUNET_PQ_query_param_auto_from_type (channel_key), | 564 | GNUNET_PQ_query_param_auto_from_type (channel_key), |
693 | GNUNET_PQ_query_param_auto_from_type (slave_key), | 565 | GNUNET_PQ_query_param_auto_from_type (slave_key), |
@@ -695,35 +567,17 @@ membership_test (void *cls, | |||
695 | GNUNET_PQ_query_param_end | 567 | GNUNET_PQ_query_param_end |
696 | }; | 568 | }; |
697 | 569 | ||
698 | res = GNUNET_PQ_exec_prepared (plugin->dbh, "select_membership", params_select); | ||
699 | if (GNUNET_OK != | ||
700 | GNUNET_POSTGRES_check_result (plugin->dbh, | ||
701 | res, | ||
702 | PGRES_TUPLES_OK, | ||
703 | "PQexecPrepared", "select_membership")) | ||
704 | { | ||
705 | return GNUNET_SYSERR; | ||
706 | } | ||
707 | |||
708 | struct GNUNET_PQ_ResultSpec results_select[] = { | 570 | struct GNUNET_PQ_ResultSpec results_select[] = { |
709 | GNUNET_PQ_result_spec_uint32 ("did_join", &did_join), | 571 | GNUNET_PQ_result_spec_uint32 ("did_join", &did_join), |
710 | GNUNET_PQ_result_spec_end | 572 | GNUNET_PQ_result_spec_end |
711 | }; | 573 | }; |
712 | 574 | ||
713 | switch (GNUNET_PQ_extract_result (res, results_select, 0)) | 575 | if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != |
714 | { | 576 | GNUNET_PQ_eval_prepared_singleton_select (plugin->dbh, "select_membership", |
715 | case GNUNET_OK: | 577 | params_select, results_select)) |
716 | ret = GNUNET_YES; | 578 | return GNUNET_SYSERR; |
717 | break; | ||
718 | |||
719 | default: | ||
720 | ret = GNUNET_NO; | ||
721 | break; | ||
722 | } | ||
723 | 579 | ||
724 | PQclear (res); | 580 | return GNUNET_OK; |
725 | |||
726 | return ret; | ||
727 | } | 581 | } |
728 | 582 | ||
729 | /** | 583 | /** |
@@ -739,7 +593,6 @@ fragment_store (void *cls, | |||
739 | const struct GNUNET_MULTICAST_MessageHeader *msg, | 593 | const struct GNUNET_MULTICAST_MessageHeader *msg, |
740 | uint32_t psycstore_flags) | 594 | uint32_t psycstore_flags) |
741 | { | 595 | { |
742 | PGresult *res; | ||
743 | struct Plugin *plugin = cls; | 596 | struct Plugin *plugin = cls; |
744 | 597 | ||
745 | GNUNET_assert (TRANSACTION_NONE == plugin->transaction); | 598 | GNUNET_assert (TRANSACTION_NONE == plugin->transaction); |
@@ -782,15 +635,10 @@ fragment_store (void *cls, | |||
782 | GNUNET_PQ_query_param_end | 635 | GNUNET_PQ_query_param_end |
783 | }; | 636 | }; |
784 | 637 | ||
785 | res = GNUNET_PQ_exec_prepared (plugin->dbh, "insert_fragment", params_insert); | 638 | if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != |
786 | if (GNUNET_OK != | 639 | GNUNET_PQ_eval_prepared_non_select (plugin->dbh, "insert_fragment", params_insert)) |
787 | GNUNET_POSTGRES_check_result (plugin->dbh, | ||
788 | res, | ||
789 | PGRES_COMMAND_OK, | ||
790 | "PQexecPrepared", "insert_fragment")) | ||
791 | return GNUNET_SYSERR; | 640 | return GNUNET_SYSERR; |
792 | 641 | ||
793 | PQclear (res); | ||
794 | return GNUNET_OK; | 642 | return GNUNET_OK; |
795 | } | 643 | } |
796 | 644 | ||
@@ -807,7 +655,6 @@ message_add_flags (void *cls, | |||
807 | uint64_t message_id, | 655 | uint64_t message_id, |
808 | uint32_t psycstore_flags) | 656 | uint32_t psycstore_flags) |
809 | { | 657 | { |
810 | PGresult *res; | ||
811 | struct Plugin *plugin = cls; | 658 | struct Plugin *plugin = cls; |
812 | 659 | ||
813 | struct GNUNET_PQ_QueryParam params_update[] = { | 660 | struct GNUNET_PQ_QueryParam params_update[] = { |
@@ -817,74 +664,80 @@ message_add_flags (void *cls, | |||
817 | GNUNET_PQ_query_param_end | 664 | GNUNET_PQ_query_param_end |
818 | }; | 665 | }; |
819 | 666 | ||
820 | res = GNUNET_PQ_exec_prepared (plugin->dbh, "update_message_flags", params_update); | 667 | if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != |
821 | if (GNUNET_OK != GNUNET_POSTGRES_check_result (plugin->dbh, | 668 | GNUNET_PQ_eval_prepared_non_select (plugin->dbh, "update_message_flags", params_update)) |
822 | res, | ||
823 | PGRES_COMMAND_OK, | ||
824 | "PQexecPrepared","update_message_flags")) | ||
825 | return GNUNET_SYSERR; | 669 | return GNUNET_SYSERR; |
826 | 670 | ||
827 | PQclear (res); | ||
828 | return GNUNET_OK; | 671 | return GNUNET_OK; |
829 | } | 672 | } |
830 | 673 | ||
831 | 674 | ||
832 | static int | 675 | /** |
833 | fragment_row (struct Plugin *plugin, | 676 | * Closure for #fragment_rows. |
834 | const char *stmt, | 677 | */ |
835 | PGresult *res, | 678 | struct FragmentRowsContext { |
836 | GNUNET_PSYCSTORE_FragmentCallback cb, | 679 | GNUNET_PSYCSTORE_FragmentCallback cb; |
837 | void *cb_cls, | 680 | void *cb_cls; |
838 | uint64_t *returned_fragments) | ||
839 | { | ||
840 | uint32_t hop_counter; | ||
841 | void *signature = NULL; | ||
842 | void *purpose = NULL; | ||
843 | size_t signature_size; | ||
844 | size_t purpose_size; | ||
845 | |||
846 | uint64_t fragment_id; | ||
847 | uint64_t fragment_offset; | ||
848 | uint64_t message_id; | ||
849 | uint64_t group_generation; | ||
850 | uint32_t flags; | ||
851 | void *buf; | ||
852 | size_t buf_size; | ||
853 | int ret = GNUNET_SYSERR; | ||
854 | struct GNUNET_MULTICAST_MessageHeader *mp; | ||
855 | |||
856 | uint32_t msg_flags; | ||
857 | |||
858 | struct GNUNET_PQ_ResultSpec results[] = { | ||
859 | GNUNET_PQ_result_spec_uint32 ("hop_counter", &hop_counter), | ||
860 | GNUNET_PQ_result_spec_variable_size ("signature", &signature, &signature_size), | ||
861 | GNUNET_PQ_result_spec_variable_size ("purpose", &purpose, &purpose_size), | ||
862 | GNUNET_PQ_result_spec_uint64 ("fragment_id", &fragment_id), | ||
863 | GNUNET_PQ_result_spec_uint64 ("fragment_offset", &fragment_offset), | ||
864 | GNUNET_PQ_result_spec_uint64 ("message_id", &message_id), | ||
865 | GNUNET_PQ_result_spec_uint64 ("group_generation", &group_generation), | ||
866 | GNUNET_PQ_result_spec_uint32 ("multicast_flags", &msg_flags), | ||
867 | GNUNET_PQ_result_spec_uint32 ("psycstore_flags", &flags), | ||
868 | GNUNET_PQ_result_spec_variable_size ("data", &buf, &buf_size), | ||
869 | GNUNET_PQ_result_spec_end | ||
870 | }; | ||
871 | 681 | ||
872 | if (GNUNET_OK != | 682 | uint64_t *returned_fragments; |
873 | GNUNET_POSTGRES_check_result (plugin->dbh, res, PGRES_TUPLES_OK, | ||
874 | "PQexecPrepared", | ||
875 | stmt)) | ||
876 | { | ||
877 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
878 | "Failing fragment lookup (postgres error)\n"); | ||
879 | return GNUNET_SYSERR; | ||
880 | } | ||
881 | 683 | ||
882 | int nrows = PQntuples (res); | 684 | /* I preserved this but I do not see the point since |
883 | for (int row = 0; row < nrows; row++) | 685 | * it cannot stop the loop early and gets overwritten ?? */ |
686 | int ret; | ||
687 | }; | ||
688 | |||
689 | |||
690 | /** | ||
691 | * Callback that retrieves the results of a SELECT statement | ||
692 | * reading form the messages table. | ||
693 | * | ||
694 | * Only passed to GNUNET_PQ_eval_prepared_multi_select and | ||
695 | * has type GNUNET_PQ_PostgresResultHandler. | ||
696 | * | ||
697 | * @param cls closure | ||
698 | * @param result the postgres result | ||
699 | * @param num_result the number of results in @a result | ||
700 | */ | ||
701 | void fragment_rows (void *cls, | ||
702 | PGresult *res, | ||
703 | unsigned int num_results) | ||
704 | { | ||
705 | struct FragmentRowsContext *c = cls; | ||
706 | |||
707 | for (unsigned int i=0;i<num_results;i++) | ||
884 | { | 708 | { |
885 | if (GNUNET_OK != GNUNET_PQ_extract_result (res, results, row)) | 709 | uint32_t hop_counter; |
710 | void *signature = NULL; | ||
711 | void *purpose = NULL; | ||
712 | size_t signature_size; | ||
713 | size_t purpose_size; | ||
714 | uint64_t fragment_id; | ||
715 | uint64_t fragment_offset; | ||
716 | uint64_t message_id; | ||
717 | uint64_t group_generation; | ||
718 | uint32_t flags; | ||
719 | void *buf; | ||
720 | size_t buf_size; | ||
721 | uint32_t msg_flags; | ||
722 | struct GNUNET_PQ_ResultSpec results[] = { | ||
723 | GNUNET_PQ_result_spec_uint32 ("hop_counter", &hop_counter), | ||
724 | GNUNET_PQ_result_spec_variable_size ("signature", &signature, &signature_size), | ||
725 | GNUNET_PQ_result_spec_variable_size ("purpose", &purpose, &purpose_size), | ||
726 | GNUNET_PQ_result_spec_uint64 ("fragment_id", &fragment_id), | ||
727 | GNUNET_PQ_result_spec_uint64 ("fragment_offset", &fragment_offset), | ||
728 | GNUNET_PQ_result_spec_uint64 ("message_id", &message_id), | ||
729 | GNUNET_PQ_result_spec_uint64 ("group_generation", &group_generation), | ||
730 | GNUNET_PQ_result_spec_uint32 ("multicast_flags", &msg_flags), | ||
731 | GNUNET_PQ_result_spec_uint32 ("psycstore_flags", &flags), | ||
732 | GNUNET_PQ_result_spec_variable_size ("data", &buf, &buf_size), | ||
733 | GNUNET_PQ_result_spec_end | ||
734 | }; | ||
735 | struct GNUNET_MULTICAST_MessageHeader *mp; | ||
736 | |||
737 | if (GNUNET_YES != GNUNET_PQ_extract_result (res, results, i)) | ||
886 | { | 738 | { |
887 | break; | 739 | GNUNET_PQ_cleanup_result(results); /* missing previously, a memory leak?? */ |
740 | break; /* nothing more?? */ | ||
888 | } | 741 | } |
889 | 742 | ||
890 | mp = GNUNET_malloc (sizeof (*mp) + buf_size); | 743 | mp = GNUNET_malloc (sizeof (*mp) + buf_size); |
@@ -893,11 +746,9 @@ fragment_row (struct Plugin *plugin, | |||
893 | mp->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE); | 746 | mp->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE); |
894 | mp->hop_counter = htonl (hop_counter); | 747 | mp->hop_counter = htonl (hop_counter); |
895 | GNUNET_memcpy (&mp->signature, | 748 | GNUNET_memcpy (&mp->signature, |
896 | signature, | 749 | signature, signature_size); |
897 | signature_size); | ||
898 | GNUNET_memcpy (&mp->purpose, | 750 | GNUNET_memcpy (&mp->purpose, |
899 | purpose, | 751 | purpose, purpose_size); |
900 | purpose_size); | ||
901 | mp->fragment_id = GNUNET_htonll (fragment_id); | 752 | mp->fragment_id = GNUNET_htonll (fragment_id); |
902 | mp->fragment_offset = GNUNET_htonll (fragment_offset); | 753 | mp->fragment_offset = GNUNET_htonll (fragment_offset); |
903 | mp->message_id = GNUNET_htonll (message_id); | 754 | mp->message_id = GNUNET_htonll (message_id); |
@@ -905,15 +756,12 @@ fragment_row (struct Plugin *plugin, | |||
905 | mp->flags = htonl(msg_flags); | 756 | mp->flags = htonl(msg_flags); |
906 | 757 | ||
907 | GNUNET_memcpy (&mp[1], | 758 | GNUNET_memcpy (&mp[1], |
908 | buf, | 759 | buf, buf_size); |
909 | buf_size); | ||
910 | GNUNET_PQ_cleanup_result(results); | 760 | GNUNET_PQ_cleanup_result(results); |
911 | ret = cb (cb_cls, mp, (enum GNUNET_PSYCSTORE_MessageFlags) flags); | 761 | c->ret = c->cb (c->cb_cls, mp, (enum GNUNET_PSYCSTORE_MessageFlags) flags); |
912 | if (NULL != returned_fragments) | 762 | if (NULL != c->returned_fragments) |
913 | (*returned_fragments)++; | 763 | (*c->returned_fragments)++; |
914 | } | 764 | } |
915 | |||
916 | return ret; | ||
917 | } | 765 | } |
918 | 766 | ||
919 | 767 | ||
@@ -925,26 +773,19 @@ fragment_select (struct Plugin *plugin, | |||
925 | GNUNET_PSYCSTORE_FragmentCallback cb, | 773 | GNUNET_PSYCSTORE_FragmentCallback cb, |
926 | void *cb_cls) | 774 | void *cb_cls) |
927 | { | 775 | { |
928 | PGresult *res; | 776 | /* Stack based closure */ |
929 | int ret = GNUNET_SYSERR; | 777 | struct FragmentRowsContext frc = { |
930 | 778 | .cb = cb, | |
931 | res = GNUNET_PQ_exec_prepared (plugin->dbh, stmt, params); | 779 | .cb_cls = cb_cls, |
932 | if (GNUNET_YES == | 780 | .returned_fragments = returned_fragments, |
933 | GNUNET_POSTGRES_check_result (plugin->dbh, | 781 | .ret = GNUNET_SYSERR |
934 | res, | 782 | }; |
935 | PGRES_TUPLES_OK, | ||
936 | "PQexecPrepared", stmt)) | ||
937 | { | ||
938 | if (PQntuples (res) == 0) | ||
939 | ret = GNUNET_NO; | ||
940 | else | ||
941 | { | ||
942 | ret = fragment_row (plugin, stmt, res, cb, cb_cls, returned_fragments); | ||
943 | } | ||
944 | PQclear (res); | ||
945 | } | ||
946 | 783 | ||
947 | return ret; | 784 | if (0 > GNUNET_PQ_eval_prepared_multi_select (plugin->dbh, |
785 | stmt, params, | ||
786 | &fragment_rows, &frc)) | ||
787 | return GNUNET_SYSERR; | ||
788 | return frc.ret; /* GNUNET_OK ?? */ | ||
948 | } | 789 | } |
949 | 790 | ||
950 | /** | 791 | /** |
@@ -964,8 +805,6 @@ fragment_get (void *cls, | |||
964 | void *cb_cls) | 805 | void *cb_cls) |
965 | { | 806 | { |
966 | struct Plugin *plugin = cls; | 807 | struct Plugin *plugin = cls; |
967 | *returned_fragments = 0; | ||
968 | |||
969 | struct GNUNET_PQ_QueryParam params_select[] = { | 808 | struct GNUNET_PQ_QueryParam params_select[] = { |
970 | GNUNET_PQ_query_param_auto_from_type (channel_key), | 809 | GNUNET_PQ_query_param_auto_from_type (channel_key), |
971 | GNUNET_PQ_query_param_uint64 (&first_fragment_id), | 810 | GNUNET_PQ_query_param_uint64 (&first_fragment_id), |
@@ -973,7 +812,12 @@ fragment_get (void *cls, | |||
973 | GNUNET_PQ_query_param_end | 812 | GNUNET_PQ_query_param_end |
974 | }; | 813 | }; |
975 | 814 | ||
976 | return fragment_select (plugin, "select_fragments", params_select, returned_fragments, cb, cb_cls); | 815 | *returned_fragments = 0; |
816 | return fragment_select (plugin, | ||
817 | "select_fragments", | ||
818 | params_select, | ||
819 | returned_fragments, | ||
820 | cb, cb_cls); | ||
977 | } | 821 | } |
978 | 822 | ||
979 | 823 | ||
@@ -1002,7 +846,11 @@ fragment_get_latest (void *cls, | |||
1002 | GNUNET_PQ_query_param_end | 846 | GNUNET_PQ_query_param_end |
1003 | }; | 847 | }; |
1004 | 848 | ||
1005 | return fragment_select (plugin, "select_latest_fragments", params_select, returned_fragments, cb, cb_cls); | 849 | return fragment_select (plugin, |
850 | "select_latest_fragments", | ||
851 | params_select, | ||
852 | returned_fragments, | ||
853 | cb, cb_cls); | ||
1006 | } | 854 | } |
1007 | 855 | ||
1008 | 856 | ||
@@ -1024,11 +872,6 @@ message_get (void *cls, | |||
1024 | void *cb_cls) | 872 | void *cb_cls) |
1025 | { | 873 | { |
1026 | struct Plugin *plugin = cls; | 874 | struct Plugin *plugin = cls; |
1027 | *returned_fragments = 0; | ||
1028 | |||
1029 | if (0 == fragment_limit) | ||
1030 | fragment_limit = INT64_MAX; | ||
1031 | |||
1032 | struct GNUNET_PQ_QueryParam params_select[] = { | 875 | struct GNUNET_PQ_QueryParam params_select[] = { |
1033 | GNUNET_PQ_query_param_auto_from_type (channel_key), | 876 | GNUNET_PQ_query_param_auto_from_type (channel_key), |
1034 | GNUNET_PQ_query_param_uint64 (&first_message_id), | 877 | GNUNET_PQ_query_param_uint64 (&first_message_id), |
@@ -1037,7 +880,14 @@ message_get (void *cls, | |||
1037 | GNUNET_PQ_query_param_end | 880 | GNUNET_PQ_query_param_end |
1038 | }; | 881 | }; |
1039 | 882 | ||
1040 | return fragment_select (plugin, "select_messages", params_select, returned_fragments, cb, cb_cls); | 883 | if (0 == fragment_limit) |
884 | fragment_limit = INT64_MAX; | ||
885 | *returned_fragments = 0; | ||
886 | return fragment_select (plugin, | ||
887 | "select_messages", | ||
888 | params_select, | ||
889 | returned_fragments, | ||
890 | cb, cb_cls); | ||
1041 | } | 891 | } |
1042 | 892 | ||
1043 | 893 | ||
@@ -1057,8 +907,6 @@ message_get_latest (void *cls, | |||
1057 | void *cb_cls) | 907 | void *cb_cls) |
1058 | { | 908 | { |
1059 | struct Plugin *plugin = cls; | 909 | struct Plugin *plugin = cls; |
1060 | *returned_fragments = 0; | ||
1061 | |||
1062 | struct GNUNET_PQ_QueryParam params_select[] = { | 910 | struct GNUNET_PQ_QueryParam params_select[] = { |
1063 | GNUNET_PQ_query_param_auto_from_type (channel_key), | 911 | GNUNET_PQ_query_param_auto_from_type (channel_key), |
1064 | GNUNET_PQ_query_param_auto_from_type (channel_key), | 912 | GNUNET_PQ_query_param_auto_from_type (channel_key), |
@@ -1066,7 +914,12 @@ message_get_latest (void *cls, | |||
1066 | GNUNET_PQ_query_param_end | 914 | GNUNET_PQ_query_param_end |
1067 | }; | 915 | }; |
1068 | 916 | ||
1069 | return fragment_select (plugin, "select_latest_messages", params_select, returned_fragments, cb, cb_cls); | 917 | *returned_fragments = 0; |
918 | return fragment_select (plugin, | ||
919 | "select_latest_messages", | ||
920 | params_select, | ||
921 | returned_fragments, | ||
922 | cb, cb_cls); | ||
1070 | } | 923 | } |
1071 | 924 | ||
1072 | 925 | ||
@@ -1086,9 +939,7 @@ message_get_fragment (void *cls, | |||
1086 | GNUNET_PSYCSTORE_FragmentCallback cb, | 939 | GNUNET_PSYCSTORE_FragmentCallback cb, |
1087 | void *cb_cls) | 940 | void *cb_cls) |
1088 | { | 941 | { |
1089 | PGresult *res; | ||
1090 | struct Plugin *plugin = cls; | 942 | struct Plugin *plugin = cls; |
1091 | int ret = GNUNET_SYSERR; | ||
1092 | const char *stmt = "select_message_fragment"; | 943 | const char *stmt = "select_message_fragment"; |
1093 | 944 | ||
1094 | struct GNUNET_PQ_QueryParam params_select[] = { | 945 | struct GNUNET_PQ_QueryParam params_select[] = { |
@@ -1098,21 +949,19 @@ message_get_fragment (void *cls, | |||
1098 | GNUNET_PQ_query_param_end | 949 | GNUNET_PQ_query_param_end |
1099 | }; | 950 | }; |
1100 | 951 | ||
1101 | res = GNUNET_PQ_exec_prepared (plugin->dbh, stmt, params_select); | 952 | /* Stack based closure */ |
1102 | if (GNUNET_OK == GNUNET_POSTGRES_check_result (plugin->dbh, | 953 | struct FragmentRowsContext frc = { |
1103 | res, | 954 | .cb = cb, |
1104 | PGRES_TUPLES_OK, | 955 | .cb_cls = cb_cls, |
1105 | "PQexecPrepared", stmt)) | 956 | .returned_fragments = NULL, |
1106 | { | 957 | .ret = GNUNET_SYSERR |
1107 | if (PQntuples (res) == 0) | 958 | }; |
1108 | ret = GNUNET_NO; | ||
1109 | else | ||
1110 | ret = fragment_row (plugin, stmt, res, cb, cb_cls, NULL); | ||
1111 | |||
1112 | PQclear (res); | ||
1113 | } | ||
1114 | 959 | ||
1115 | return ret; | 960 | if (0 > GNUNET_PQ_eval_prepared_multi_select (plugin->dbh, |
961 | stmt, params_select, | ||
962 | &fragment_rows, &frc)) | ||
963 | return GNUNET_SYSERR; | ||
964 | return frc.ret; /* GNUNET_OK ?? */ | ||
1116 | } | 965 | } |
1117 | 966 | ||
1118 | /** | 967 | /** |
@@ -1129,7 +978,6 @@ counters_message_get (void *cls, | |||
1129 | uint64_t *max_message_id, | 978 | uint64_t *max_message_id, |
1130 | uint64_t *max_group_generation) | 979 | uint64_t *max_group_generation) |
1131 | { | 980 | { |
1132 | PGresult *res; | ||
1133 | struct Plugin *plugin = cls; | 981 | struct Plugin *plugin = cls; |
1134 | 982 | ||
1135 | const char *stmt = "select_counters_message"; | 983 | const char *stmt = "select_counters_message"; |
@@ -1139,15 +987,6 @@ counters_message_get (void *cls, | |||
1139 | GNUNET_PQ_query_param_end | 987 | GNUNET_PQ_query_param_end |
1140 | }; | 988 | }; |
1141 | 989 | ||
1142 | res = GNUNET_PQ_exec_prepared (plugin->dbh, stmt, params_select); | ||
1143 | if (GNUNET_OK != GNUNET_POSTGRES_check_result (plugin->dbh, | ||
1144 | res, | ||
1145 | PGRES_TUPLES_OK, | ||
1146 | "PQexecPrepared", stmt)) | ||
1147 | { | ||
1148 | return GNUNET_SYSERR; | ||
1149 | } | ||
1150 | |||
1151 | struct GNUNET_PQ_ResultSpec results_select[] = { | 990 | struct GNUNET_PQ_ResultSpec results_select[] = { |
1152 | GNUNET_PQ_result_spec_uint64 ("fragment_id", max_fragment_id), | 991 | GNUNET_PQ_result_spec_uint64 ("fragment_id", max_fragment_id), |
1153 | GNUNET_PQ_result_spec_uint64 ("message_id", max_message_id), | 992 | GNUNET_PQ_result_spec_uint64 ("message_id", max_message_id), |
@@ -1155,14 +994,10 @@ counters_message_get (void *cls, | |||
1155 | GNUNET_PQ_result_spec_end | 994 | GNUNET_PQ_result_spec_end |
1156 | }; | 995 | }; |
1157 | 996 | ||
1158 | if (GNUNET_OK != GNUNET_PQ_extract_result (res, results_select, 0)) | 997 | if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != |
1159 | { | 998 | GNUNET_PQ_eval_prepared_singleton_select (plugin->dbh, stmt, |
1160 | PQclear (res); | 999 | params_select, results_select)) |
1161 | return GNUNET_SYSERR; | 1000 | return GNUNET_SYSERR; |
1162 | } | ||
1163 | |||
1164 | GNUNET_PQ_cleanup_result(results_select); | ||
1165 | PQclear (res); | ||
1166 | 1001 | ||
1167 | return GNUNET_OK; | 1002 | return GNUNET_OK; |
1168 | } | 1003 | } |
@@ -1179,44 +1014,26 @@ counters_state_get (void *cls, | |||
1179 | const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, | 1014 | const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, |
1180 | uint64_t *max_state_message_id) | 1015 | uint64_t *max_state_message_id) |
1181 | { | 1016 | { |
1182 | PGresult *res; | ||
1183 | struct Plugin *plugin = cls; | 1017 | struct Plugin *plugin = cls; |
1184 | 1018 | ||
1185 | const char *stmt = "select_counters_state"; | 1019 | const char *stmt = "select_counters_state"; |
1186 | 1020 | ||
1187 | int ret = GNUNET_SYSERR; | ||
1188 | |||
1189 | struct GNUNET_PQ_QueryParam params_select[] = { | 1021 | struct GNUNET_PQ_QueryParam params_select[] = { |
1190 | GNUNET_PQ_query_param_auto_from_type (channel_key), | 1022 | GNUNET_PQ_query_param_auto_from_type (channel_key), |
1191 | GNUNET_PQ_query_param_end | 1023 | GNUNET_PQ_query_param_end |
1192 | }; | 1024 | }; |
1193 | 1025 | ||
1194 | res = GNUNET_PQ_exec_prepared (plugin->dbh, stmt, params_select); | ||
1195 | if (GNUNET_OK != GNUNET_POSTGRES_check_result (plugin->dbh, | ||
1196 | res, | ||
1197 | PGRES_TUPLES_OK, | ||
1198 | "PQexecPrepared", stmt)) | ||
1199 | { | ||
1200 | return GNUNET_SYSERR; | ||
1201 | } | ||
1202 | |||
1203 | struct GNUNET_PQ_ResultSpec results_select[] = { | 1026 | struct GNUNET_PQ_ResultSpec results_select[] = { |
1204 | GNUNET_PQ_result_spec_uint64 ("max_state_message_id", max_state_message_id), | 1027 | GNUNET_PQ_result_spec_uint64 ("max_state_message_id", max_state_message_id), |
1205 | GNUNET_PQ_result_spec_end | 1028 | GNUNET_PQ_result_spec_end |
1206 | }; | 1029 | }; |
1207 | 1030 | ||
1208 | ret = GNUNET_PQ_extract_result (res, results_select, 0); | 1031 | if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != |
1209 | 1032 | GNUNET_PQ_eval_prepared_singleton_select (plugin->dbh, stmt, | |
1210 | if (GNUNET_OK != ret) | 1033 | params_select, results_select)) |
1211 | { | 1034 | return GNUNET_SYSERR; |
1212 | PQclear (res); | ||
1213 | return GNUNET_SYSERR; | ||
1214 | } | ||
1215 | |||
1216 | GNUNET_PQ_cleanup_result(results_select); | ||
1217 | PQclear (res); | ||
1218 | 1035 | ||
1219 | return ret; | 1036 | return GNUNET_OK; |
1220 | } | 1037 | } |
1221 | 1038 | ||
1222 | 1039 | ||
@@ -1230,8 +1047,6 @@ state_assign (struct Plugin *plugin, const char *stmt, | |||
1230 | const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, | 1047 | const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, |
1231 | const char *name, const void *value, size_t value_size) | 1048 | const char *name, const void *value, size_t value_size) |
1232 | { | 1049 | { |
1233 | PGresult *res; | ||
1234 | |||
1235 | struct GNUNET_PQ_QueryParam params[] = { | 1050 | struct GNUNET_PQ_QueryParam params[] = { |
1236 | GNUNET_PQ_query_param_auto_from_type (channel_key), | 1051 | GNUNET_PQ_query_param_auto_from_type (channel_key), |
1237 | GNUNET_PQ_query_param_string (name), | 1052 | GNUNET_PQ_query_param_string (name), |
@@ -1239,44 +1054,29 @@ state_assign (struct Plugin *plugin, const char *stmt, | |||
1239 | GNUNET_PQ_query_param_end | 1054 | GNUNET_PQ_query_param_end |
1240 | }; | 1055 | }; |
1241 | 1056 | ||
1242 | res = GNUNET_PQ_exec_prepared (plugin->dbh, stmt, params); | 1057 | if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != |
1243 | if (GNUNET_OK != GNUNET_POSTGRES_check_result (plugin->dbh, | 1058 | GNUNET_PQ_eval_prepared_non_select (plugin->dbh, stmt, params)) |
1244 | res, | ||
1245 | PGRES_COMMAND_OK, | ||
1246 | "PQexecPrepared", stmt)) | ||
1247 | { | ||
1248 | return GNUNET_SYSERR; | 1059 | return GNUNET_SYSERR; |
1249 | } | ||
1250 | |||
1251 | PQclear (res); | ||
1252 | 1060 | ||
1253 | return GNUNET_OK; | 1061 | return GNUNET_OK; |
1254 | } | 1062 | } |
1255 | 1063 | ||
1256 | 1064 | ||
1257 | static int | 1065 | static int |
1258 | update_message_id (struct Plugin *plugin, const char *stmt, | 1066 | update_message_id (struct Plugin *plugin, |
1067 | const char *stmt, | ||
1259 | const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, | 1068 | const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, |
1260 | uint64_t message_id) | 1069 | uint64_t message_id) |
1261 | { | 1070 | { |
1262 | PGresult *res; | ||
1263 | |||
1264 | struct GNUNET_PQ_QueryParam params[] = { | 1071 | struct GNUNET_PQ_QueryParam params[] = { |
1265 | GNUNET_PQ_query_param_uint64 (&message_id), | 1072 | GNUNET_PQ_query_param_uint64 (&message_id), |
1266 | GNUNET_PQ_query_param_auto_from_type (channel_key), | 1073 | GNUNET_PQ_query_param_auto_from_type (channel_key), |
1267 | GNUNET_PQ_query_param_end | 1074 | GNUNET_PQ_query_param_end |
1268 | }; | 1075 | }; |
1269 | 1076 | ||
1270 | res = GNUNET_PQ_exec_prepared (plugin->dbh, stmt, params); | 1077 | if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != |
1271 | if (GNUNET_OK != GNUNET_POSTGRES_check_result (plugin->dbh, | 1078 | GNUNET_PQ_eval_prepared_non_select (plugin->dbh, stmt, params)) |
1272 | res, | ||
1273 | PGRES_COMMAND_OK, | ||
1274 | "PQexecPrepared", stmt)) | ||
1275 | { | ||
1276 | return GNUNET_SYSERR; | 1079 | return GNUNET_SYSERR; |
1277 | } | ||
1278 | |||
1279 | PQclear (res); | ||
1280 | 1080 | ||
1281 | return GNUNET_OK; | 1081 | return GNUNET_OK; |
1282 | } | 1082 | } |
@@ -1487,10 +1287,7 @@ static int | |||
1487 | state_get (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, | 1287 | state_get (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, |
1488 | const char *name, GNUNET_PSYCSTORE_StateCallback cb, void *cb_cls) | 1288 | const char *name, GNUNET_PSYCSTORE_StateCallback cb, void *cb_cls) |
1489 | { | 1289 | { |
1490 | PGresult *res; | ||
1491 | |||
1492 | struct Plugin *plugin = cls; | 1290 | struct Plugin *plugin = cls; |
1493 | int ret = GNUNET_SYSERR; | ||
1494 | 1291 | ||
1495 | const char *stmt = "select_state_one"; | 1292 | const char *stmt = "select_state_one"; |
1496 | 1293 | ||
@@ -1503,44 +1300,80 @@ state_get (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, | |||
1503 | void *value_current = NULL; | 1300 | void *value_current = NULL; |
1504 | size_t value_size = 0; | 1301 | size_t value_size = 0; |
1505 | 1302 | ||
1506 | struct GNUNET_PQ_ResultSpec results[] = { | 1303 | struct GNUNET_PQ_ResultSpec results_select[] = { |
1507 | GNUNET_PQ_result_spec_variable_size ("value_current", &value_current, &value_size), | 1304 | GNUNET_PQ_result_spec_variable_size ("value_current", &value_current, &value_size), |
1508 | GNUNET_PQ_result_spec_end | 1305 | GNUNET_PQ_result_spec_end |
1509 | }; | 1306 | }; |
1510 | 1307 | ||
1511 | res = GNUNET_PQ_exec_prepared (plugin->dbh, stmt, params_select); | 1308 | if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != |
1512 | if (GNUNET_OK != GNUNET_POSTGRES_check_result (plugin->dbh, | 1309 | GNUNET_PQ_eval_prepared_singleton_select (plugin->dbh, stmt, |
1513 | res, | 1310 | params_select, results_select)) |
1514 | PGRES_TUPLES_OK, | 1311 | return GNUNET_SYSERR; |
1515 | "PQexecPrepared", stmt)) | ||
1516 | { | ||
1517 | return GNUNET_SYSERR; | ||
1518 | } | ||
1519 | 1312 | ||
1520 | if (PQntuples (res) == 0) | 1313 | return cb (cb_cls, name, value_current, |
1521 | { | 1314 | value_size); |
1522 | PQclear (res); | 1315 | } |
1523 | ret = GNUNET_NO; | ||
1524 | } | ||
1525 | 1316 | ||
1526 | ret = GNUNET_PQ_extract_result (res, results, 0); | ||
1527 | 1317 | ||
1528 | if (GNUNET_OK != ret) | 1318 | |
1319 | /** | ||
1320 | * Closure for #get_state_cb. | ||
1321 | */ | ||
1322 | struct GetStateContext { | ||
1323 | const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key; | ||
1324 | // const char *name, | ||
1325 | GNUNET_PSYCSTORE_StateCallback cb; | ||
1326 | void *cb_cls; | ||
1327 | |||
1328 | const char *value_id; | ||
1329 | |||
1330 | /* I preserved this but I do not see the point since | ||
1331 | * it cannot stop the loop early and gets overwritten ?? */ | ||
1332 | int ret; | ||
1333 | }; | ||
1334 | |||
1335 | |||
1336 | /** | ||
1337 | * Callback that retrieves the results of a SELECT statement | ||
1338 | * reading form the state table. | ||
1339 | * | ||
1340 | * Only passed to GNUNET_PQ_eval_prepared_multi_select and | ||
1341 | * has type GNUNET_PQ_PostgresResultHandler. | ||
1342 | * | ||
1343 | * @param cls closure | ||
1344 | * @param result the postgres result | ||
1345 | * @param num_result the number of results in @a result | ||
1346 | */ | ||
1347 | static void | ||
1348 | get_state_cb (void *cls, | ||
1349 | PGresult *res, | ||
1350 | unsigned int num_results) | ||
1351 | { | ||
1352 | struct GetStateContext *c = cls; | ||
1353 | |||
1354 | for (unsigned int i=0;i<num_results;i++) | ||
1529 | { | 1355 | { |
1530 | PQclear (res); | 1356 | char *name = ""; |
1531 | return GNUNET_SYSERR; | 1357 | void *value = NULL; |
1532 | } | 1358 | size_t value_size = 0; |
1533 | 1359 | ||
1534 | ret = cb (cb_cls, name, value_current, | 1360 | struct GNUNET_PQ_ResultSpec results[] = { |
1535 | value_size); | 1361 | GNUNET_PQ_result_spec_string ("name", &name), |
1362 | GNUNET_PQ_result_spec_variable_size (c->value_id, &value, &value_size), | ||
1363 | GNUNET_PQ_result_spec_end | ||
1364 | }; | ||
1536 | 1365 | ||
1537 | GNUNET_PQ_cleanup_result(results); | 1366 | if (GNUNET_YES != GNUNET_PQ_extract_result (res, results, i)) |
1538 | PQclear (res); | 1367 | { |
1368 | GNUNET_PQ_cleanup_result(results); /* previously invoked via PQclear?? */ | ||
1369 | break; /* nothing more?? */ | ||
1370 | } | ||
1539 | 1371 | ||
1540 | return ret; | 1372 | c->ret = c->cb (c->cb_cls, (const char *) name, value, value_size); |
1373 | GNUNET_PQ_cleanup_result(results); | ||
1374 | } | ||
1541 | } | 1375 | } |
1542 | 1376 | ||
1543 | |||
1544 | /** | 1377 | /** |
1545 | * Retrieve all state variables for a channel with the given prefix. | 1378 | * Retrieve all state variables for a channel with the given prefix. |
1546 | * | 1379 | * |
@@ -1553,9 +1386,7 @@ state_get_prefix (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_ | |||
1553 | const char *name, GNUNET_PSYCSTORE_StateCallback cb, | 1386 | const char *name, GNUNET_PSYCSTORE_StateCallback cb, |
1554 | void *cb_cls) | 1387 | void *cb_cls) |
1555 | { | 1388 | { |
1556 | PGresult *res; | ||
1557 | struct Plugin *plugin = cls; | 1389 | struct Plugin *plugin = cls; |
1558 | int ret = GNUNET_NO; | ||
1559 | 1390 | ||
1560 | const char *stmt = "select_state_prefix"; | 1391 | const char *stmt = "select_state_prefix"; |
1561 | 1392 | ||
@@ -1569,42 +1400,18 @@ state_get_prefix (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_ | |||
1569 | GNUNET_PQ_query_param_end | 1400 | GNUNET_PQ_query_param_end |
1570 | }; | 1401 | }; |
1571 | 1402 | ||
1572 | char *name2 = ""; | 1403 | struct GetStateContext gsc = { |
1573 | void *value_current = NULL; | 1404 | .cb = cb, |
1574 | size_t value_size = 0; | 1405 | .cb_cls = cb_cls, |
1575 | 1406 | .value_id = "value_current", | |
1576 | struct GNUNET_PQ_ResultSpec results[] = { | 1407 | .ret = GNUNET_NO |
1577 | GNUNET_PQ_result_spec_string ("name", &name2), | ||
1578 | GNUNET_PQ_result_spec_variable_size ("value_current", &value_current, &value_size), | ||
1579 | GNUNET_PQ_result_spec_end | ||
1580 | }; | 1408 | }; |
1581 | 1409 | ||
1582 | res = GNUNET_PQ_exec_prepared (plugin->dbh, stmt, params_select); | 1410 | if (0 > GNUNET_PQ_eval_prepared_multi_select (plugin->dbh, |
1583 | if (GNUNET_OK != GNUNET_POSTGRES_check_result (plugin->dbh, | 1411 | stmt, params_select, |
1584 | res, | 1412 | &get_state_cb, &gsc)) |
1585 | PGRES_TUPLES_OK, | ||
1586 | "PQexecPrepared", stmt)) | ||
1587 | { | ||
1588 | return GNUNET_SYSERR; | 1413 | return GNUNET_SYSERR; |
1589 | } | 1414 | return gsc.ret; /* GNUNET_OK ?? */ |
1590 | |||
1591 | int nrows = PQntuples (res); | ||
1592 | for (int row = 0; row < nrows; row++) | ||
1593 | { | ||
1594 | if (GNUNET_OK != GNUNET_PQ_extract_result (res, results, row)) | ||
1595 | { | ||
1596 | break; | ||
1597 | } | ||
1598 | |||
1599 | ret = cb (cb_cls, (const char *) name2, | ||
1600 | value_current, | ||
1601 | value_size); | ||
1602 | GNUNET_PQ_cleanup_result(results); | ||
1603 | } | ||
1604 | |||
1605 | PQclear (res); | ||
1606 | |||
1607 | return ret; | ||
1608 | } | 1415 | } |
1609 | 1416 | ||
1610 | 1417 | ||
@@ -1620,9 +1427,7 @@ state_get_signed (void *cls, | |||
1620 | const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, | 1427 | const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, |
1621 | GNUNET_PSYCSTORE_StateCallback cb, void *cb_cls) | 1428 | GNUNET_PSYCSTORE_StateCallback cb, void *cb_cls) |
1622 | { | 1429 | { |
1623 | PGresult *res; | ||
1624 | struct Plugin *plugin = cls; | 1430 | struct Plugin *plugin = cls; |
1625 | int ret = GNUNET_NO; | ||
1626 | 1431 | ||
1627 | const char *stmt = "select_state_signed"; | 1432 | const char *stmt = "select_state_signed"; |
1628 | 1433 | ||
@@ -1631,43 +1436,18 @@ state_get_signed (void *cls, | |||
1631 | GNUNET_PQ_query_param_end | 1436 | GNUNET_PQ_query_param_end |
1632 | }; | 1437 | }; |
1633 | 1438 | ||
1634 | char *name = ""; | 1439 | struct GetStateContext gsc = { |
1635 | void *value_signed = NULL; | 1440 | .cb = cb, |
1636 | size_t value_size = 0; | 1441 | .cb_cls = cb_cls, |
1637 | 1442 | .value_id = "value_signed", | |
1638 | struct GNUNET_PQ_ResultSpec results[] = { | 1443 | .ret = GNUNET_NO |
1639 | GNUNET_PQ_result_spec_string ("name", &name), | ||
1640 | GNUNET_PQ_result_spec_variable_size ("value_signed", &value_signed, &value_size), | ||
1641 | GNUNET_PQ_result_spec_end | ||
1642 | }; | 1444 | }; |
1643 | 1445 | ||
1644 | res = GNUNET_PQ_exec_prepared (plugin->dbh, stmt, params_select); | 1446 | if (0 > GNUNET_PQ_eval_prepared_multi_select (plugin->dbh, |
1645 | if (GNUNET_OK != GNUNET_POSTGRES_check_result (plugin->dbh, | 1447 | stmt, params_select, |
1646 | res, | 1448 | &get_state_cb, &gsc)) |
1647 | PGRES_TUPLES_OK, | ||
1648 | "PQexecPrepared", stmt)) | ||
1649 | { | ||
1650 | return GNUNET_SYSERR; | 1449 | return GNUNET_SYSERR; |
1651 | } | 1450 | return gsc.ret; /* GNUNET_OK ?? */ |
1652 | |||
1653 | int nrows = PQntuples (res); | ||
1654 | for (int row = 0; row < nrows; row++) | ||
1655 | { | ||
1656 | if (GNUNET_OK != GNUNET_PQ_extract_result (res, results, row)) | ||
1657 | { | ||
1658 | break; | ||
1659 | } | ||
1660 | |||
1661 | ret = cb (cb_cls, (const char *) name, | ||
1662 | value_signed, | ||
1663 | value_size); | ||
1664 | |||
1665 | GNUNET_PQ_cleanup_result (results); | ||
1666 | } | ||
1667 | |||
1668 | PQclear (res); | ||
1669 | |||
1670 | return ret; | ||
1671 | } | 1451 | } |
1672 | 1452 | ||
1673 | 1453 | ||
diff --git a/src/set/gnunet-service-set.c b/src/set/gnunet-service-set.c index 12af653c1..f98d43a7d 100644 --- a/src/set/gnunet-service-set.c +++ b/src/set/gnunet-service-set.c | |||
@@ -1250,6 +1250,10 @@ handle_client_listen (void *cls, | |||
1250 | GNUNET_MESSAGE_TYPE_SET_UNION_P2P_DONE, | 1250 | GNUNET_MESSAGE_TYPE_SET_UNION_P2P_DONE, |
1251 | struct GNUNET_MessageHeader, | 1251 | struct GNUNET_MessageHeader, |
1252 | NULL), | 1252 | NULL), |
1253 | GNUNET_MQ_hd_fixed_size (union_p2p_over, | ||
1254 | GNUNET_MESSAGE_TYPE_SET_UNION_P2P_OVER, | ||
1255 | struct GNUNET_MessageHeader, | ||
1256 | NULL), | ||
1253 | GNUNET_MQ_hd_fixed_size (union_p2p_full_done, | 1257 | GNUNET_MQ_hd_fixed_size (union_p2p_full_done, |
1254 | GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_DONE, | 1258 | GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_DONE, |
1255 | struct GNUNET_MessageHeader, | 1259 | struct GNUNET_MessageHeader, |
@@ -1501,6 +1505,10 @@ handle_client_evaluate (void *cls, | |||
1501 | GNUNET_MESSAGE_TYPE_SET_UNION_P2P_DONE, | 1505 | GNUNET_MESSAGE_TYPE_SET_UNION_P2P_DONE, |
1502 | struct GNUNET_MessageHeader, | 1506 | struct GNUNET_MessageHeader, |
1503 | op), | 1507 | op), |
1508 | GNUNET_MQ_hd_fixed_size (union_p2p_over, | ||
1509 | GNUNET_MESSAGE_TYPE_SET_UNION_P2P_OVER, | ||
1510 | struct GNUNET_MessageHeader, | ||
1511 | op), | ||
1504 | GNUNET_MQ_hd_fixed_size (union_p2p_full_done, | 1512 | GNUNET_MQ_hd_fixed_size (union_p2p_full_done, |
1505 | GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_DONE, | 1513 | GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_DONE, |
1506 | struct GNUNET_MessageHeader, | 1514 | struct GNUNET_MessageHeader, |
diff --git a/src/set/gnunet-service-set_union.c b/src/set/gnunet-service-set_union.c index fc7e578e6..4ca10f0b4 100644 --- a/src/set/gnunet-service-set_union.c +++ b/src/set/gnunet-service-set_union.c | |||
@@ -769,7 +769,7 @@ send_full_element_iterator (void *cls, | |||
769 | struct GNUNET_SET_Element *el = &ee->element; | 769 | struct GNUNET_SET_Element *el = &ee->element; |
770 | struct GNUNET_MQ_Envelope *ev; | 770 | struct GNUNET_MQ_Envelope *ev; |
771 | 771 | ||
772 | LOG (GNUNET_ERROR_TYPE_INFO, | 772 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
773 | "Sending element %s\n", | 773 | "Sending element %s\n", |
774 | GNUNET_h2s (key)); | 774 | GNUNET_h2s (key)); |
775 | ev = GNUNET_MQ_msg_extra (emsg, | 775 | ev = GNUNET_MQ_msg_extra (emsg, |
@@ -796,7 +796,7 @@ send_full_set (struct Operation *op) | |||
796 | struct GNUNET_MQ_Envelope *ev; | 796 | struct GNUNET_MQ_Envelope *ev; |
797 | 797 | ||
798 | op->state->phase = PHASE_FULL_SENDING; | 798 | op->state->phase = PHASE_FULL_SENDING; |
799 | LOG (GNUNET_ERROR_TYPE_INFO, | 799 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
800 | "Dedicing to transmit the full set\n"); | 800 | "Dedicing to transmit the full set\n"); |
801 | /* FIXME: use a more memory-friendly way of doing this with an | 801 | /* FIXME: use a more memory-friendly way of doing this with an |
802 | iterator, just as we do in the non-full case! */ | 802 | iterator, just as we do in the non-full case! */ |
@@ -924,7 +924,7 @@ handle_union_p2p_strata_estimator (void *cls, | |||
924 | (diff > op->state->initial_size / 4) || | 924 | (diff > op->state->initial_size / 4) || |
925 | (0 == other_size) ) | 925 | (0 == other_size) ) |
926 | { | 926 | { |
927 | LOG (GNUNET_ERROR_TYPE_INFO, | 927 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
928 | "Deciding to go for full set transmission (diff=%d, own set=%u)\n", | 928 | "Deciding to go for full set transmission (diff=%d, own set=%u)\n", |
929 | diff, | 929 | diff, |
930 | op->state->initial_size); | 930 | op->state->initial_size); |
@@ -941,7 +941,7 @@ handle_union_p2p_strata_estimator (void *cls, | |||
941 | { | 941 | { |
942 | struct GNUNET_MQ_Envelope *ev; | 942 | struct GNUNET_MQ_Envelope *ev; |
943 | 943 | ||
944 | LOG (GNUNET_ERROR_TYPE_INFO, | 944 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
945 | "Telling other peer that we expect its full set\n"); | 945 | "Telling other peer that we expect its full set\n"); |
946 | op->state->phase = PHASE_EXPECT_IBF; | 946 | op->state->phase = PHASE_EXPECT_IBF; |
947 | ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_UNION_P2P_REQUEST_FULL); | 947 | ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_UNION_P2P_REQUEST_FULL); |
@@ -1299,7 +1299,7 @@ handle_union_p2p_ibf (void *cls, | |||
1299 | else | 1299 | else |
1300 | { | 1300 | { |
1301 | GNUNET_assert (op->state->phase == PHASE_EXPECT_IBF_CONT); | 1301 | GNUNET_assert (op->state->phase == PHASE_EXPECT_IBF_CONT); |
1302 | LOG (GNUNET_ERROR_TYPE_INFO, | 1302 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1303 | "Received more of IBF\n"); | 1303 | "Received more of IBF\n"); |
1304 | } | 1304 | } |
1305 | GNUNET_assert (NULL != op->state->remote_ibf); | 1305 | GNUNET_assert (NULL != op->state->remote_ibf); |
@@ -1369,18 +1369,55 @@ send_client_element (struct Operation *op, | |||
1369 | 1369 | ||
1370 | 1370 | ||
1371 | /** | 1371 | /** |
1372 | * Destroy remote channel. | ||
1373 | * | ||
1374 | * @param op operation | ||
1375 | */ | ||
1376 | void destroy_channel (struct Operation *op) | ||
1377 | { | ||
1378 | struct GNUNET_CADET_Channel *channel; | ||
1379 | |||
1380 | if (NULL != (channel = op->channel)) | ||
1381 | { | ||
1382 | /* This will free op; called conditionally as this helper function | ||
1383 | is also called from within the channel disconnect handler. */ | ||
1384 | op->channel = NULL; | ||
1385 | GNUNET_CADET_channel_destroy (channel); | ||
1386 | } | ||
1387 | } | ||
1388 | |||
1389 | |||
1390 | /** | ||
1372 | * Signal to the client that the operation has finished and | 1391 | * Signal to the client that the operation has finished and |
1373 | * destroy the operation. | 1392 | * destroy the operation. |
1374 | * | 1393 | * |
1375 | * @param cls operation to destroy | 1394 | * @param cls operation to destroy |
1376 | */ | 1395 | */ |
1377 | static void | 1396 | static void |
1378 | send_done_and_destroy (void *cls) | 1397 | send_client_done (void *cls) |
1379 | { | 1398 | { |
1380 | struct Operation *op = cls; | 1399 | struct Operation *op = cls; |
1381 | struct GNUNET_MQ_Envelope *ev; | 1400 | struct GNUNET_MQ_Envelope *ev; |
1382 | struct GNUNET_SET_ResultMessage *rm; | 1401 | struct GNUNET_SET_ResultMessage *rm; |
1383 | 1402 | ||
1403 | if (GNUNET_YES == op->state->client_done_sent) { | ||
1404 | return; | ||
1405 | } | ||
1406 | |||
1407 | if (PHASE_DONE != op->state->phase) { | ||
1408 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1409 | "union operation failed\n"); | ||
1410 | ev = GNUNET_MQ_msg (rm, GNUNET_MESSAGE_TYPE_SET_RESULT); | ||
1411 | rm->result_status = htons (GNUNET_SET_STATUS_FAILURE); | ||
1412 | rm->request_id = htonl (op->client_request_id); | ||
1413 | rm->element_type = htons (0); | ||
1414 | GNUNET_MQ_send (op->set->cs->mq, | ||
1415 | ev); | ||
1416 | return; | ||
1417 | } | ||
1418 | |||
1419 | op->state->client_done_sent = GNUNET_YES; | ||
1420 | |||
1384 | LOG (GNUNET_ERROR_TYPE_INFO, | 1421 | LOG (GNUNET_ERROR_TYPE_INFO, |
1385 | "Signalling client that union operation is done\n"); | 1422 | "Signalling client that union operation is done\n"); |
1386 | ev = GNUNET_MQ_msg (rm, | 1423 | ev = GNUNET_MQ_msg (rm, |
@@ -1391,9 +1428,6 @@ send_done_and_destroy (void *cls) | |||
1391 | rm->current_size = GNUNET_htonll (GNUNET_CONTAINER_multihashmap32_size (op->state->key_to_element)); | 1428 | rm->current_size = GNUNET_htonll (GNUNET_CONTAINER_multihashmap32_size (op->state->key_to_element)); |
1392 | GNUNET_MQ_send (op->set->cs->mq, | 1429 | GNUNET_MQ_send (op->set->cs->mq, |
1393 | ev); | 1430 | ev); |
1394 | /* Will also call the union-specific cancel function. */ | ||
1395 | _GSS_operation_destroy (op, | ||
1396 | GNUNET_YES); | ||
1397 | } | 1431 | } |
1398 | 1432 | ||
1399 | 1433 | ||
@@ -1422,7 +1456,7 @@ maybe_finish (struct Operation *op) | |||
1422 | ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_UNION_P2P_DONE); | 1456 | ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_UNION_P2P_DONE); |
1423 | GNUNET_MQ_send (op->mq, | 1457 | GNUNET_MQ_send (op->mq, |
1424 | ev); | 1458 | ev); |
1425 | /* We now wait until the other peer closes the channel | 1459 | /* We now wait until the other peer sends P2P_OVER |
1426 | * after it got all elements from us. */ | 1460 | * after it got all elements from us. */ |
1427 | } | 1461 | } |
1428 | } | 1462 | } |
@@ -1433,8 +1467,11 @@ maybe_finish (struct Operation *op) | |||
1433 | num_demanded); | 1467 | num_demanded); |
1434 | if (0 == num_demanded) | 1468 | if (0 == num_demanded) |
1435 | { | 1469 | { |
1470 | struct GNUNET_MQ_Envelope *ev; | ||
1471 | |||
1436 | op->state->phase = PHASE_DONE; | 1472 | op->state->phase = PHASE_DONE; |
1437 | send_done_and_destroy (op); | 1473 | send_client_done (op); |
1474 | destroy_channel (op); | ||
1438 | } | 1475 | } |
1439 | } | 1476 | } |
1440 | } | 1477 | } |
@@ -1732,7 +1769,7 @@ handle_union_p2p_inquiry (void *cls, | |||
1732 | const struct IBF_Key *ibf_key; | 1769 | const struct IBF_Key *ibf_key; |
1733 | unsigned int num_keys; | 1770 | unsigned int num_keys; |
1734 | 1771 | ||
1735 | LOG (GNUNET_ERROR_TYPE_INFO, | 1772 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1736 | "Received union inquiry\n"); | 1773 | "Received union inquiry\n"); |
1737 | num_keys = (ntohs (msg->header.size) - sizeof (struct InquiryMessage)) | 1774 | num_keys = (ntohs (msg->header.size) - sizeof (struct InquiryMessage)) |
1738 | / sizeof (struct IBF_Key); | 1775 | / sizeof (struct IBF_Key); |
@@ -1800,7 +1837,7 @@ handle_union_p2p_request_full (void *cls, | |||
1800 | { | 1837 | { |
1801 | struct Operation *op = cls; | 1838 | struct Operation *op = cls; |
1802 | 1839 | ||
1803 | LOG (GNUNET_ERROR_TYPE_INFO, | 1840 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1804 | "Received request for full set transmission\n"); | 1841 | "Received request for full set transmission\n"); |
1805 | if (GNUNET_SET_OPERATION_UNION != op->set->operation) | 1842 | if (GNUNET_SET_OPERATION_UNION != op->set->operation) |
1806 | { | 1843 | { |
@@ -1849,28 +1886,28 @@ handle_union_p2p_full_done (void *cls, | |||
1849 | op); | 1886 | op); |
1850 | 1887 | ||
1851 | ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_DONE); | 1888 | ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_DONE); |
1852 | GNUNET_MQ_notify_sent (ev, | ||
1853 | &send_done_and_destroy, | ||
1854 | op); | ||
1855 | GNUNET_MQ_send (op->mq, | 1889 | GNUNET_MQ_send (op->mq, |
1856 | ev); | 1890 | ev); |
1857 | op->state->phase = PHASE_DONE; | 1891 | op->state->phase = PHASE_DONE; |
1858 | /* we now wait until the other peer shuts the tunnel down*/ | 1892 | /* we now wait until the other peer sends us the OVER message*/ |
1859 | } | 1893 | } |
1860 | break; | 1894 | break; |
1861 | case PHASE_FULL_SENDING: | 1895 | case PHASE_FULL_SENDING: |
1862 | { | 1896 | { |
1897 | struct GNUNET_MQ_Envelope *ev; | ||
1898 | |||
1863 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1899 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1864 | "got FULL DONE, finishing\n"); | 1900 | "got FULL DONE, finishing\n"); |
1865 | /* We sent the full set, and got the response for that. We're done. */ | 1901 | /* We sent the full set, and got the response for that. We're done. */ |
1866 | op->state->phase = PHASE_DONE; | 1902 | op->state->phase = PHASE_DONE; |
1867 | GNUNET_CADET_receive_done (op->channel); | 1903 | GNUNET_CADET_receive_done (op->channel); |
1868 | send_done_and_destroy (op); | 1904 | send_client_done (op); |
1905 | destroy_channel (op); | ||
1869 | return; | 1906 | return; |
1870 | } | 1907 | } |
1871 | break; | 1908 | break; |
1872 | default: | 1909 | default: |
1873 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 1910 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1874 | "Handle full done phase is %u\n", | 1911 | "Handle full done phase is %u\n", |
1875 | (unsigned) op->state->phase); | 1912 | (unsigned) op->state->phase); |
1876 | GNUNET_break_op (0); | 1913 | GNUNET_break_op (0); |
@@ -2144,6 +2181,19 @@ handle_union_p2p_done (void *cls, | |||
2144 | } | 2181 | } |
2145 | } | 2182 | } |
2146 | 2183 | ||
2184 | /** | ||
2185 | * Handle a over message from a remote peer | ||
2186 | * | ||
2187 | * @param cls the union operation | ||
2188 | * @param mh the message | ||
2189 | */ | ||
2190 | void | ||
2191 | handle_union_p2p_over (void *cls, | ||
2192 | const struct GNUNET_MessageHeader *mh) | ||
2193 | { | ||
2194 | send_client_done (cls); | ||
2195 | } | ||
2196 | |||
2147 | 2197 | ||
2148 | /** | 2198 | /** |
2149 | * Initiate operation to evaluate a set union with a remote peer. | 2199 | * Initiate operation to evaluate a set union with a remote peer. |
@@ -2372,6 +2422,7 @@ union_copy_state (struct SetState *state) | |||
2372 | static void | 2422 | static void |
2373 | union_channel_death (struct Operation *op) | 2423 | union_channel_death (struct Operation *op) |
2374 | { | 2424 | { |
2425 | send_client_done (op); | ||
2375 | _GSS_operation_destroy (op, | 2426 | _GSS_operation_destroy (op, |
2376 | GNUNET_YES); | 2427 | GNUNET_YES); |
2377 | } | 2428 | } |
diff --git a/src/set/gnunet-service-set_union.h b/src/set/gnunet-service-set_union.h index cbf60bcbc..086666770 100644 --- a/src/set/gnunet-service-set_union.h +++ b/src/set/gnunet-service-set_union.h | |||
@@ -235,5 +235,15 @@ void | |||
235 | handle_union_p2p_done (void *cls, | 235 | handle_union_p2p_done (void *cls, |
236 | const struct GNUNET_MessageHeader *mh); | 236 | const struct GNUNET_MessageHeader *mh); |
237 | 237 | ||
238 | /** | ||
239 | * Handle an over message from a remote peer | ||
240 | * | ||
241 | * @param cls the union operation | ||
242 | * @param mh the message | ||
243 | */ | ||
244 | void | ||
245 | handle_union_p2p_over (void *cls, | ||
246 | const struct GNUNET_MessageHeader *mh); | ||
247 | |||
238 | 248 | ||
239 | #endif | 249 | #endif |
diff --git a/src/set/set_api.c b/src/set/set_api.c index f5c43a9a7..27e2ccf04 100644 --- a/src/set/set_api.c +++ b/src/set/set_api.c | |||
@@ -689,7 +689,7 @@ GNUNET_SET_add_element (struct GNUNET_SET_Handle *set, | |||
689 | struct GNUNET_MQ_Envelope *mqm; | 689 | struct GNUNET_MQ_Envelope *mqm; |
690 | struct GNUNET_SET_ElementMessage *msg; | 690 | struct GNUNET_SET_ElementMessage *msg; |
691 | 691 | ||
692 | LOG (GNUNET_ERROR_TYPE_INFO, | 692 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
693 | "adding element of type %u to set %p\n", | 693 | "adding element of type %u to set %p\n", |
694 | (unsigned int) element->element_type, | 694 | (unsigned int) element->element_type, |
695 | set); | 695 | set); |
diff --git a/src/social/gnunet-social.c b/src/social/gnunet-social.c index 228d69d58..0e52dccfa 100644 --- a/src/social/gnunet-social.c +++ b/src/social/gnunet-social.c | |||
@@ -718,7 +718,7 @@ guest_recv_local_enter (void *cls, int result, | |||
718 | 718 | ||
719 | 719 | ||
720 | /** | 720 | /** |
721 | * Create entry requset message. | 721 | * Create entry request message. |
722 | */ | 722 | */ |
723 | static struct GNUNET_PSYC_Message * | 723 | static struct GNUNET_PSYC_Message * |
724 | guest_enter_msg_create () | 724 | guest_enter_msg_create () |
@@ -1227,11 +1227,6 @@ main (int argc, char *const *argv) | |||
1227 | gettext_noop ("create a place"), | 1227 | gettext_noop ("create a place"), |
1228 | &op_host_enter), | 1228 | &op_host_enter), |
1229 | 1229 | ||
1230 | GNUNET_GETOPT_option_flag ('C', | ||
1231 | "host-enter", | ||
1232 | gettext_noop ("create a place"), | ||
1233 | &op_host_enter), | ||
1234 | |||
1235 | GNUNET_GETOPT_option_flag ('D', | 1230 | GNUNET_GETOPT_option_flag ('D', |
1236 | "host-leave", | 1231 | "host-leave", |
1237 | gettext_noop ("destroy a place we were hosting"), | 1232 | gettext_noop ("destroy a place we were hosting"), |
diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am index 7687f2348..d65da6bb6 100644 --- a/src/transport/Makefile.am +++ b/src/transport/Makefile.am | |||
@@ -10,7 +10,6 @@ libexecdir= $(pkglibdir)/libexec/ | |||
10 | pkgcfg_DATA = \ | 10 | pkgcfg_DATA = \ |
11 | transport.conf | 11 | transport.conf |
12 | 12 | ||
13 | |||
14 | if HAVE_MHD | 13 | if HAVE_MHD |
15 | GN_LIBMHD = -lmicrohttpd | 14 | GN_LIBMHD = -lmicrohttpd |
16 | HTTP_SERVER_PLUGIN_LA = libgnunet_plugin_transport_http_server.la | 15 | HTTP_SERVER_PLUGIN_LA = libgnunet_plugin_transport_http_server.la |
@@ -79,6 +78,7 @@ if USE_COVERAGE | |||
79 | AM_CFLAGS = --coverage -O0 | 78 | AM_CFLAGS = --coverage -O0 |
80 | endif | 79 | endif |
81 | 80 | ||
81 | if HAVE_EXPERIMENTAL | ||
82 | if LINUX | 82 | if LINUX |
83 | WLAN_BIN = gnunet-helper-transport-wlan | 83 | WLAN_BIN = gnunet-helper-transport-wlan |
84 | WLAN_BIN_DUMMY = gnunet-helper-transport-wlan-dummy | 84 | WLAN_BIN_DUMMY = gnunet-helper-transport-wlan-dummy |
@@ -121,6 +121,8 @@ if MINGW | |||
121 | endif | 121 | endif |
122 | endif | 122 | endif |
123 | 123 | ||
124 | # end of HAVE_EXPERIMENTAL | ||
125 | endif | ||
124 | 126 | ||
125 | 127 | ||
126 | if !MINGW | 128 | if !MINGW |
diff --git a/src/transport/plugin_transport_http_server.c b/src/transport/plugin_transport_http_server.c index ff2d68602..892d97050 100644 --- a/src/transport/plugin_transport_http_server.c +++ b/src/transport/plugin_transport_http_server.c | |||
@@ -92,6 +92,11 @@ struct ServerRequest | |||
92 | */ | 92 | */ |
93 | int connected; | 93 | int connected; |
94 | 94 | ||
95 | /** | ||
96 | * Currently suspended | ||
97 | */ | ||
98 | bool suspended; | ||
99 | |||
95 | }; | 100 | }; |
96 | 101 | ||
97 | 102 | ||
@@ -501,7 +506,9 @@ server_wake_up (void *cls) | |||
501 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 506 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
502 | "Session %p: Waking up PUT handle\n", | 507 | "Session %p: Waking up PUT handle\n", |
503 | s); | 508 | s); |
509 | GNUNET_assert (s->server_recv->suspended); | ||
504 | MHD_resume_connection (s->server_recv->mhd_conn); | 510 | MHD_resume_connection (s->server_recv->mhd_conn); |
511 | s->server_recv->suspended = false; | ||
505 | } | 512 | } |
506 | 513 | ||
507 | 514 | ||
@@ -541,7 +548,11 @@ server_delete_session (struct GNUNET_ATS_Session *s) | |||
541 | GNUNET_SCHEDULER_cancel (s->recv_wakeup_task); | 548 | GNUNET_SCHEDULER_cancel (s->recv_wakeup_task); |
542 | s->recv_wakeup_task = NULL; | 549 | s->recv_wakeup_task = NULL; |
543 | if (NULL != s->server_recv) | 550 | if (NULL != s->server_recv) |
551 | { | ||
552 | GNUNET_assert (s->server_recv->suspended); | ||
553 | s->server_recv->suspended = false; | ||
544 | MHD_resume_connection (s->server_recv->mhd_conn); | 554 | MHD_resume_connection (s->server_recv->mhd_conn); |
555 | } | ||
545 | } | 556 | } |
546 | GNUNET_assert (GNUNET_OK == | 557 | GNUNET_assert (GNUNET_OK == |
547 | GNUNET_CONTAINER_multipeermap_remove (plugin->sessions, | 558 | GNUNET_CONTAINER_multipeermap_remove (plugin->sessions, |
@@ -578,6 +589,11 @@ server_delete_session (struct GNUNET_ATS_Session *s) | |||
578 | MHD_set_connection_option (s->server_send->mhd_conn, | 589 | MHD_set_connection_option (s->server_send->mhd_conn, |
579 | MHD_CONNECTION_OPTION_TIMEOUT, | 590 | MHD_CONNECTION_OPTION_TIMEOUT, |
580 | 1 /* 0 = no timeout, so this is MIN */); | 591 | 1 /* 0 = no timeout, so this is MIN */); |
592 | if (s->server_send->suspended) | ||
593 | { | ||
594 | s->server_send->suspended = false; | ||
595 | MHD_resume_connection (s->server_send->mhd_conn); | ||
596 | } | ||
581 | server_reschedule (plugin, | 597 | server_reschedule (plugin, |
582 | s->server_send->mhd_daemon, | 598 | s->server_send->mhd_daemon, |
583 | GNUNET_YES); | 599 | GNUNET_YES); |
@@ -760,9 +776,16 @@ http_server_plugin_send (void *cls, | |||
760 | GNUNET_free (stat_txt); | 776 | GNUNET_free (stat_txt); |
761 | 777 | ||
762 | if (NULL != session->server_send) | 778 | if (NULL != session->server_send) |
779 | { | ||
780 | if (session->server_send->suspended) | ||
781 | { | ||
782 | MHD_resume_connection (session->server_send->mhd_conn); | ||
783 | session->server_send->suspended = false; | ||
784 | } | ||
763 | server_reschedule (session->plugin, | 785 | server_reschedule (session->plugin, |
764 | session->server_send->mhd_daemon, | 786 | session->server_send->mhd_daemon, |
765 | GNUNET_YES); | 787 | GNUNET_YES); |
788 | } | ||
766 | return bytes_sent; | 789 | return bytes_sent; |
767 | } | 790 | } |
768 | 791 | ||
@@ -1613,6 +1636,12 @@ server_send_callback (void *cls, | |||
1613 | s); | 1636 | s); |
1614 | return MHD_CONTENT_READER_END_OF_STREAM; | 1637 | return MHD_CONTENT_READER_END_OF_STREAM; |
1615 | } | 1638 | } |
1639 | else | ||
1640 | { | ||
1641 | MHD_suspend_connection (s->server_send->mhd_conn); | ||
1642 | s->server_send->suspended = true; | ||
1643 | return 0; | ||
1644 | } | ||
1616 | return bytes_read; | 1645 | return bytes_read; |
1617 | } | 1646 | } |
1618 | 1647 | ||
@@ -1868,6 +1897,7 @@ server_access_cb (void *cls, | |||
1868 | GNUNET_YES)); | 1897 | GNUNET_YES)); |
1869 | GNUNET_assert(s->server_recv->mhd_conn == mhd_connection); | 1898 | GNUNET_assert(s->server_recv->mhd_conn == mhd_connection); |
1870 | MHD_suspend_connection (s->server_recv->mhd_conn); | 1899 | MHD_suspend_connection (s->server_recv->mhd_conn); |
1900 | s->server_recv->suspended = true; | ||
1871 | if (NULL == s->recv_wakeup_task) | 1901 | if (NULL == s->recv_wakeup_task) |
1872 | s->recv_wakeup_task | 1902 | s->recv_wakeup_task |
1873 | = GNUNET_SCHEDULER_add_delayed (delay, | 1903 | = GNUNET_SCHEDULER_add_delayed (delay, |
diff --git a/src/util/crypto_hash.c b/src/util/crypto_hash.c index 49dbacd0b..20c7ca7ff 100644 --- a/src/util/crypto_hash.c +++ b/src/util/crypto_hash.c | |||
@@ -440,8 +440,8 @@ GNUNET_CRYPTO_hash_context_start () | |||
440 | */ | 440 | */ |
441 | void | 441 | void |
442 | GNUNET_CRYPTO_hash_context_read (struct GNUNET_HashContext *hc, | 442 | GNUNET_CRYPTO_hash_context_read (struct GNUNET_HashContext *hc, |
443 | const void *buf, | 443 | const void *buf, |
444 | size_t size) | 444 | size_t size) |
445 | { | 445 | { |
446 | gcry_md_write (hc->hd, buf, size); | 446 | gcry_md_write (hc->hd, buf, size); |
447 | } | 447 | } |
diff --git a/src/util/gnunet-ecc.c b/src/util/gnunet-ecc.c index 2a712f4eb..42ecc2101 100644 --- a/src/util/gnunet-ecc.c +++ b/src/util/gnunet-ecc.c | |||
@@ -49,6 +49,11 @@ static unsigned int list_keys_count; | |||
49 | static int print_public_key; | 49 | static int print_public_key; |
50 | 50 | ||
51 | /** | 51 | /** |
52 | * Flag for printing public key in hex. | ||
53 | */ | ||
54 | static int print_public_key_hex; | ||
55 | |||
56 | /** | ||
52 | * Flag for printing the output of random example operations. | 57 | * Flag for printing the output of random example operations. |
53 | */ | 58 | */ |
54 | static int print_examples_flag; | 59 | static int print_examples_flag; |
@@ -195,12 +200,10 @@ print_hex (const char *msg, | |||
195 | const void *buf, | 200 | const void *buf, |
196 | size_t size) | 201 | size_t size) |
197 | { | 202 | { |
198 | size_t i; | ||
199 | |||
200 | printf ("%s: ", msg); | 203 | printf ("%s: ", msg); |
201 | for (i = 0; i < size; i++) | 204 | for (size_t i = 0; i < size; i++) |
202 | { | 205 | { |
203 | printf ("%02hhx", ((const char *)buf)[i]); | 206 | printf ("%02hhx", ((const uint8_t *)buf)[i]); |
204 | } | 207 | } |
205 | printf ("\n"); | 208 | printf ("\n"); |
206 | } | 209 | } |
@@ -374,7 +377,7 @@ run (void *cls, char *const *args, const char *cfgfile, | |||
374 | create_keys (args[0], args[1]); | 377 | create_keys (args[0], args[1]); |
375 | return; | 378 | return; |
376 | } | 379 | } |
377 | if (print_public_key) | 380 | if (print_public_key || print_public_key_hex) |
378 | { | 381 | { |
379 | char *str; | 382 | char *str; |
380 | struct GNUNET_DISK_FileHandle *keyfile; | 383 | struct GNUNET_DISK_FileHandle *keyfile; |
@@ -388,9 +391,16 @@ run (void *cls, char *const *args, const char *cfgfile, | |||
388 | while (sizeof (pk) == GNUNET_DISK_file_read (keyfile, &pk, sizeof (pk))) | 391 | while (sizeof (pk) == GNUNET_DISK_file_read (keyfile, &pk, sizeof (pk))) |
389 | { | 392 | { |
390 | GNUNET_CRYPTO_eddsa_key_get_public (&pk, &pub); | 393 | GNUNET_CRYPTO_eddsa_key_get_public (&pk, &pub); |
391 | str = GNUNET_CRYPTO_eddsa_public_key_to_string (&pub); | 394 | if (print_public_key_hex) |
392 | FPRINTF (stdout, "%s\n", str); | 395 | { |
393 | GNUNET_free (str); | 396 | print_hex ("HEX:", &pub, sizeof (pub)); |
397 | } | ||
398 | else | ||
399 | { | ||
400 | str = GNUNET_CRYPTO_eddsa_public_key_to_string (&pub); | ||
401 | FPRINTF (stdout, "%s\n", str); | ||
402 | GNUNET_free (str); | ||
403 | } | ||
394 | } | 404 | } |
395 | GNUNET_DISK_file_close (keyfile); | 405 | GNUNET_DISK_file_close (keyfile); |
396 | } | 406 | } |
@@ -409,34 +419,38 @@ int | |||
409 | main (int argc, | 419 | main (int argc, |
410 | char *const *argv) | 420 | char *const *argv) |
411 | { | 421 | { |
412 | list_keys_count = UINT32_MAX; | ||
413 | struct GNUNET_GETOPT_CommandLineOption options[] = { | 422 | struct GNUNET_GETOPT_CommandLineOption options[] = { |
414 | GNUNET_GETOPT_option_flag ('i', | 423 | GNUNET_GETOPT_option_flag ('i', |
415 | "iterate", | 424 | "iterate", |
416 | gettext_noop ("list keys included in a file (for testing)"), | 425 | gettext_noop ("list keys included in a file (for testing)"), |
417 | &list_keys), | 426 | &list_keys), |
418 | GNUNET_GETOPT_option_uint ('e', | 427 | GNUNET_GETOPT_option_uint ('e', |
419 | "end=", | 428 | "end=", |
420 | "COUNT", | 429 | "COUNT", |
421 | gettext_noop ("number of keys to list included in a file (for testing)"), | 430 | gettext_noop ("number of keys to list included in a file (for testing)"), |
422 | &list_keys_count), | 431 | &list_keys_count), |
423 | GNUNET_GETOPT_option_uint ('g', | 432 | GNUNET_GETOPT_option_uint ('g', |
424 | "generate-keys", | 433 | "generate-keys", |
425 | "COUNT", | 434 | "COUNT", |
426 | gettext_noop ("create COUNT public-private key pairs (for testing)"), | 435 | gettext_noop ("create COUNT public-private key pairs (for testing)"), |
427 | &make_keys), | 436 | &make_keys), |
428 | GNUNET_GETOPT_option_flag ('p', | 437 | GNUNET_GETOPT_option_flag ('p', |
429 | "print-public-key", | 438 | "print-public-key", |
430 | gettext_noop ("print the public key in ASCII format"), | 439 | gettext_noop ("print the public key in ASCII format"), |
431 | &print_public_key), | 440 | &print_public_key), |
441 | GNUNET_GETOPT_option_flag ('x', | ||
442 | "print-hex", | ||
443 | gettext_noop ("print the public key in HEX format"), | ||
444 | &print_public_key_hex), | ||
432 | GNUNET_GETOPT_option_flag ('E', | 445 | GNUNET_GETOPT_option_flag ('E', |
433 | "examples", | 446 | "examples", |
434 | gettext_noop ("print examples of ECC operations (used for compatibility testing)"), | 447 | gettext_noop ("print examples of ECC operations (used for compatibility testing)"), |
435 | &print_examples_flag), | 448 | &print_examples_flag), |
436 | GNUNET_GETOPT_OPTION_END | 449 | GNUNET_GETOPT_OPTION_END |
437 | }; | 450 | }; |
438 | int ret; | 451 | int ret; |
439 | 452 | ||
453 | list_keys_count = UINT32_MAX; | ||
440 | if (GNUNET_OK != | 454 | if (GNUNET_OK != |
441 | GNUNET_STRINGS_get_utf8_args (argc, argv, | 455 | GNUNET_STRINGS_get_utf8_args (argc, argv, |
442 | &argc, &argv)) | 456 | &argc, &argv)) |
diff --git a/src/util/service.c b/src/util/service.c index f63737e56..fcdf45a51 100644 --- a/src/util/service.c +++ b/src/util/service.c | |||
@@ -1283,15 +1283,14 @@ setup_service (struct GNUNET_SERVICE_Handle *sh) | |||
1283 | slc->sh = sh; | 1283 | slc->sh = sh; |
1284 | slc->listen_socket = open_listen_socket (addrs[i], | 1284 | slc->listen_socket = open_listen_socket (addrs[i], |
1285 | addrlens[i]); | 1285 | addrlens[i]); |
1286 | GNUNET_free (addrs[i]); | ||
1286 | if (NULL == slc->listen_socket) | 1287 | if (NULL == slc->listen_socket) |
1287 | { | 1288 | { |
1288 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, | 1289 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, |
1289 | "bind"); | 1290 | "bind"); |
1290 | GNUNET_free (addrs[i++]); | ||
1291 | GNUNET_free (slc); | 1291 | GNUNET_free (slc); |
1292 | continue; | 1292 | continue; |
1293 | } | 1293 | } |
1294 | GNUNET_free (addrs[i++]); | ||
1295 | GNUNET_CONTAINER_DLL_insert (sh->slc_head, | 1294 | GNUNET_CONTAINER_DLL_insert (sh->slc_head, |
1296 | sh->slc_tail, | 1295 | sh->slc_tail, |
1297 | slc); | 1296 | slc); |
diff --git a/src/zonemaster/gnunet-service-zonemaster.c b/src/zonemaster/gnunet-service-zonemaster.c index 08a09de34..b3a2cb8b3 100644 --- a/src/zonemaster/gnunet-service-zonemaster.c +++ b/src/zonemaster/gnunet-service-zonemaster.c | |||
@@ -648,7 +648,8 @@ handle_monitor_event (void *cls, | |||
648 | static void | 648 | static void |
649 | monitor_sync_event (void *cls) | 649 | monitor_sync_event (void *cls) |
650 | { | 650 | { |
651 | GNUNET_assert (NULL == zone_publish_task); | 651 | if ( (NULL == zone_publish_task) && |
652 | (NULL == namestore_iter) ) | ||
652 | zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start, | 653 | zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start, |
653 | NULL); | 654 | NULL); |
654 | } | 655 | } |