aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS1
-rw-r--r--configure.ac59
-rwxr-xr-xcontrib/gnunet-gns-import.sh13
-rw-r--r--doc/man/gnunet-ecc.16
-rw-r--r--guix-env.scm8
-rw-r--r--pkgconfig/Makefile.am1
-rw-r--r--po/POTFILES.in6
-rw-r--r--src/Makefile.am4
-rw-r--r--src/consensus/gnunet-service-consensus.c47
-rw-r--r--src/consensus/test_consensus.conf2
-rw-r--r--src/conversation/test_conversation.conf2
-rw-r--r--src/datacache/Makefile.am2
-rw-r--r--src/datacache/plugin_datacache_postgres.c750
-rw-r--r--src/datastore/Makefile.am1
-rw-r--r--src/datastore/plugin_datastore_postgres.c834
-rw-r--r--src/datastore/plugin_datastore_sqlite.c54
-rw-r--r--src/gns/gnunet-gns-import.c39
-rw-r--r--src/include/Makefile.am2
-rw-r--r--src/include/gnunet_db_lib.h61
-rw-r--r--src/include/gnunet_postgres_lib.h178
-rw-r--r--src/include/gnunet_pq_lib.h268
-rw-r--r--src/include/gnunet_protocols.h7
-rw-r--r--src/include/gnunet_strings_lib.h4
-rw-r--r--src/multicast/Makefile.am2
-rw-r--r--src/multicast/gnunet-service-multicast.c9
-rw-r--r--src/multicast/test_multicast.conf45
-rw-r--r--src/multicast/test_multicast_multipeer.c93
-rw-r--r--src/namecache/Makefile.am1
-rw-r--r--src/namecache/plugin_namecache_postgres.c280
-rw-r--r--src/namestore/Makefile.am1
-rw-r--r--src/namestore/gnunet-service-namestore.c7
-rw-r--r--src/namestore/namestore_api.c13
-rw-r--r--src/namestore/plugin_namestore_postgres.c566
-rw-r--r--src/postgres/Makefile.am24
-rw-r--r--src/postgres/postgres.c247
-rw-r--r--src/pq/Makefile.am4
-rw-r--r--src/pq/pq_connect.c127
-rw-r--r--src/pq/pq_eval.c281
-rw-r--r--src/pq/pq_exec.c106
-rw-r--r--src/pq/pq_prepare.c93
-rw-r--r--src/psycstore/Makefile.am1
-rw-r--r--src/psycstore/plugin_psycstore_postgres.c1198
-rw-r--r--src/set/gnunet-service-set.c8
-rw-r--r--src/set/gnunet-service-set_union.c89
-rw-r--r--src/set/gnunet-service-set_union.h10
-rw-r--r--src/set/set_api.c2
-rw-r--r--src/social/gnunet-social.c7
-rw-r--r--src/transport/Makefile.am4
-rw-r--r--src/transport/plugin_transport_http_server.c30
-rw-r--r--src/util/crypto_hash.c4
-rw-r--r--src/util/gnunet-ecc.c66
-rw-r--r--src/util/service.c3
-rw-r--r--src/zonemaster/gnunet-service-zonemaster.c3
53 files changed, 2987 insertions, 2686 deletions
diff --git a/AUTHORS b/AUTHORS
index d5bf15543..8b3910776 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -10,6 +10,7 @@ Alejandra Morales
10Andreas Fuchs 10Andreas Fuchs
11Bart Polot <bart@net.in.tum.de> 11Bart Polot <bart@net.in.tum.de>
12Bruno Cabral <bcabral@uw.edu> 12Bruno Cabral <bcabral@uw.edu>
13Carlo von lynX <psyc://loupsycedyglgamf.onion/~lynX>
13Christian Fuchs <christian.fuchs@cfuchs.net> 14Christian Fuchs <christian.fuchs@cfuchs.net>
14Christian Grothoff <christian@grothoff.org> 15Christian Grothoff <christian@grothoff.org>
15Claudiu Olteanu 16Claudiu 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)
523if test "$gnurl" = 0 523if test "$gnurl" = 0
524then 524then
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])
526fi 526fi
527else 527else
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>]])
542if test x$gplk = xfalse 542if test x$gplk = xfalse
543then 543then
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])
546else 546else
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])
549fi 549fi
550 550
551 551
552
553AC_CHECK_HEADERS([nss.h],[nss=true],[nss=false]) 552AC_CHECK_HEADERS([nss.h],[nss=true],[nss=false])
554if test x$nss = xfalse 553if test x$nss = xfalse
555then 554then
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])
558else 557else
559 AM_CONDITIONAL(HAVE_GLIBCNSS, true) 558 AM_CONDITIONAL(HAVE_GLIBCNSS, true)
560fi 559fi
@@ -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 ])
1152AC_SUBST(NSS_DIR) 1155AC_SUBST(NSS_DIR)
1153AM_CONDITIONAL([INSTALL_NSS], [test "x$install_nss" != "x0"]) 1156AM_CONDITIONAL([INSTALL_NSS], [test "x$install_nss" != "x0"])
@@ -1612,7 +1615,6 @@ src/peerinfo-tool/Makefile
1612src/peerstore/Makefile 1615src/peerstore/Makefile
1613src/peerstore/peerstore.conf 1616src/peerstore/peerstore.conf
1614src/pq/Makefile 1617src/pq/Makefile
1615src/postgres/Makefile
1616src/psycutil/Makefile 1618src/psycutil/Makefile
1617src/psyc/Makefile 1619src/psyc/Makefile
1618src/psyc/psyc.conf 1620src/psyc/psyc.conf
@@ -1683,7 +1685,6 @@ pkgconfig/gnunetnat.pc
1683pkgconfig/gnunetnse.pc 1685pkgconfig/gnunetnse.pc
1684pkgconfig/gnunetpeerinfo.pc 1686pkgconfig/gnunetpeerinfo.pc
1685pkgconfig/gnunetpq.pc 1687pkgconfig/gnunetpq.pc
1686pkgconfig/gnunetpostgres.pc
1687pkgconfig/gnunetpsyc.pc 1688pkgconfig/gnunetpsyc.pc
1688pkgconfig/gnunetpsycstore.pc 1689pkgconfig/gnunetpsycstore.pc
1689pkgconfig/gnunetregex.pc 1690pkgconfig/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
1709if test "$mysqlfail" = "true" 1710if test "$mysqlfail" = "true"
1710then 1711then
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.])
1712fi 1713fi
1713 1714
1714# sqlite 1715# sqlite
@@ -1722,7 +1723,7 @@ if test "$gnurl" = "0"
1722then 1723then
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
1734if test "x$bluetooth" = "x0" 1735if test "x$bluetooth" = "x0"
1735then 1736then
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.])
1737fi 1738fi
1738 1739
1739# jansson 1740# jansson
1740if test "x$jansson" = "x0" 1741if test "x$jansson" = "x0"
1741then 1742then
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.])
1743fi 1744fi
1744 1745
1745#gnutls 1746#gnutls
1746if test x$gnutls != xtrue 1747if test x$gnutls != xtrue
1747then 1748then
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])
1749else 1750else
1750if test "x$gnutls_dane" != "x1" 1751if test "x$gnutls_dane" != "x1"
1751then 1752then
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])
1753fi 1754fi
1754fi 1755fi
1755 1756
1756# java ports 1757# java ports
1757if test "x$enable_java_ports" = "xyes" 1758if test "x$enable_java_ports" = "xyes"
1758then 1759then
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.])
1760fi 1761fi
1761 1762
1762# MHD 1763# MHD
1763if test "x$lmhd" != "x1" 1764if test "x$lmhd" != "x1"
1764then 1765then
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.])
1766fi 1767fi
1767 1768
1768# conversation 1769# conversation
@@ -1770,35 +1771,35 @@ if test "x$conversation_backend" = "xnone"
1770then 1771then
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
1783fi 1784fi
1784 1785
1785if test "$extractor" != 1 1786if test "$extractor" != 1
1786then 1787then
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])
1788fi 1789fi
1789 1790
1790AC_MSG_NOTICE([NOTICE: Database support is set to MySQL: $mysql, SQLite: $sqlite, Postgres: $postgres]) 1791AC_MSG_NOTICE([NOTICE: Database support is set to MySQL: $mysql, SQLite: $sqlite, Postgres: $postgres])
1791 1792
1792if test "$enable_framework_build" = "yes" 1793if test "$enable_framework_build" = "yes"
1793then 1794then
1794 AC_MSG_NOTICE([NOTICE: Mac OS X framework build enabled.]) 1795 AC_MSG_NOTICE([Mac OS X framework build enabled.])
1795fi 1796fi
1796 1797
1797if test "x$install_nss" = "x0" 1798if test "x$install_nss" = "x0"
1798then 1799then
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])
1800else 1801else
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])
1802fi 1803fi
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)
53gnunet-identity -e short-zone -s gns-short $options
54
55# Default zone for 'gnunet-gns' lookups 51# Default zone for 'gnunet-gns' lookups
56gnunet-identity -e master-zone -s gns-master $options 52gnunet-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)
78MASTER=`gnunet-identity -d $options | grep master-zone | awk '{print $3}'` 74MASTER=`gnunet-identity -d $options | grep master-zone | awk '{print $3}'`
79SHORT=`gnunet-identity -d $options | grep short-zone | awk '{print $3}'`
80PRIVATE=`gnunet-identity -d $options | grep private-zone | awk '{print $3}'` 75PRIVATE=`gnunet-identity -d $options | grep private-zone | awk '{print $3}'`
81PIN=DWJASSPE33MRN8T6Q0PENRNBTQY0E6ZYGTRCDP5DGPBF2CRJMJEG 76PIN=DWJASSPE33MRN8T6Q0PENRNBTQY0E6ZYGTRCDP5DGPBF2CRJMJEG
82 77
83# Link short and private zones into master zone 78# Link private zone into master zone
84if (gnunet-namestore -z master-zone -D -n private -t PKEY | grep "PKEY: $PRIVATE" 1>/dev/null) 79if (gnunet-namestore -z master-zone -D -n private -t PKEY | grep "PKEY: $PRIVATE" 1>/dev/null)
85then 80then
86 echo "Private zone link exists, skipping" 81 echo "Private zone link exists, skipping"
87else 82else
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
89fi 84fi
90if (gnunet-namestore -z master-zone -D -n short -t PKEY | grep "PKEY: $SHORT" 1>/dev/null)
91then
92 echo "Shorten zone link exists, skipping"
93else
94 gnunet-namestore -z master-zone -a -e never -n short -p -t PKEY -V $SHORT $options
95fi
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"
98if (gnunet-namestore -z master-zone -D -n pin -t PKEY | grep "PKEY: $PIN" 1>/dev/null) 87if (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
4gnunet\-ecc \- manipulate GNUnet ECC key files 4gnunet\-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"
20Print the corresponding public key to stdout. This is the value used for PKEY records in GNS. 20Print 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"
23Print 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"
23Print the corresponding peer identity (hash of the public key) to stdout. This hash is used for the name of peers. 26Print 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
39Report bugs by using Mantis <https://gnunet.org/bugs/> or by sending electronic mail to <gnunet\-developers@gnu.org> 42Report 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
269src/peerstore/peerstore_common.c 269src/peerstore/peerstore_common.c
270src/peerstore/plugin_peerstore_flat.c 270src/peerstore/plugin_peerstore_flat.c
271src/peerstore/plugin_peerstore_sqlite.c 271src/peerstore/plugin_peerstore_sqlite.c
272src/postgres/postgres.c
273src/pq/pq.c 272src/pq/pq.c
273src/pq/pq_connect.c
274src/pq/pq_eval.c
275src/pq/pq_exec.c
276src/pq/pq_prepare.c
274src/pq/pq_query_helper.c 277src/pq/pq_query_helper.c
275src/pq/pq_result_helper.c 278src/pq/pq_result_helper.c
276src/psyc/gnunet-service-psyc.c 279src/psyc/gnunet-service-psyc.c
@@ -497,7 +500,6 @@ src/zonemaster/gnunet-service-zonemaster.c
497src/fs/fs_api.h 500src/fs/fs_api.h
498src/include/gnunet_common.h 501src/include/gnunet_common.h
499src/include/gnunet_mq_lib.h 502src/include/gnunet_mq_lib.h
500src/include/gnunet_postgres_lib.h
501src/include/gnunet_time_lib.h 503src/include/gnunet_time_lib.h
502src/rps/rps-test_util.h 504src/rps/rps-test_util.h
503src/scalarproduct/scalarproduct.h 505src/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
12if HAVE_EXPERIMENTAL 12if HAVE_EXPERIMENTAL
13 EXP_DIR = \ 13 EXP_DIR = \
14 dv \
15 rps 14 rps
16endif 15endif
16# dv (FTBFS)
17 17
18if HAVE_JSON 18if HAVE_JSON
19if HAVE_MHD 19if HAVE_MHD
@@ -49,7 +49,7 @@ if HAVE_MYSQL
49endif 49endif
50 50
51if HAVE_POSTGRESQL 51if HAVE_POSTGRESQL
52 POSTGRES_DIR = pq postgres 52 POSTGRES_DIR = pq
53endif 53endif
54 54
55if HAVE_MHD 55if 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
6BINARY = gnunet-service-evil-consensus 6BINARY = gnunet-service-evil-consensus
7 7
8PREFIX = 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]
4LINE=1 4LINE=1
5PREFIX = valgrind 5#PREFIX = valgrind
6 6
7[nse] 7[nse]
8WORKBITS = 0 8WORKBITS = 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 = \
71libgnunet_plugin_datacache_postgres_la_SOURCES = \ 71libgnunet_plugin_datacache_postgres_la_SOURCES = \
72 plugin_datacache_postgres.c 72 plugin_datacache_postgres.c
73libgnunet_plugin_datacache_postgres_la_LIBADD = \ 73libgnunet_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
66static int 66static int
67init_connection (struct Plugin *plugin) 67init_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)
200static ssize_t 152static ssize_t
201postgres_plugin_put (void *cls, 153postgres_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 */
188struct 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 */
217static void
218handle_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
362postgres_plugin_del (void *cls) 339postgres_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 */
483struct 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 */
507static void
508extract_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
149libgnunet_plugin_datastore_postgres_la_LIBADD = \ 149libgnunet_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
154libgnunet_plugin_datastore_postgres_la_LDFLAGS = \ 153libgnunet_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
70static int 68static int
71init_connection (struct Plugin *plugin) 69init_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 */
243static void 187static void
244postgres_plugin_estimate_size (void *cls, unsigned long long *estimate) 188postgres_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 */
336struct 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 */
416static void 365static void
417process_result (struct Plugin *plugin, 366process_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 */
747struct 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 */
770static void
771process_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
834postgres_plugin_drop (void *cls) 839postgres_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;
60static struct GNUNET_CRYPTO_EcdsaPrivateKey master_pk; 60static struct GNUNET_CRYPTO_EcdsaPrivateKey master_pk;
61 61
62/** 62/**
63 * String version of PKEY for short-zone.
64 */
65static char *short_zone_pkey;
66
67/**
68 * String version of PKEY for private-zone. 63 * String version of PKEY for private-zone.
69 */ 64 */
70static char *private_zone_pkey; 65static char *private_zone_pkey;
@@ -80,11 +75,6 @@ static char *pin_zone_pkey = "72QC35CO20UJN1E91KPJFNT9TG4CLKAPB4VK9S3Q758S9MLBRK
80static int found_private_rec = GNUNET_NO; 75static int found_private_rec = GNUNET_NO;
81 76
82/** 77/**
83 * Set to GNUNET_YES if short record was found;
84 */
85static 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 */
90static int found_pin_rec = GNUNET_NO; 80static 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 */
30enum 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
37extern "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 */
59int
60GNUNET_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 */
93int
94GNUNET_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 */
121int
122GNUNET_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 */
149PGconn *
150GNUNET_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 */
163int
164GNUNET_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
188GNUNET_PQ_query_param_uint64 (const uint64_t *x); 191GNUNET_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 */
423PGresult * 432PGresult *
424GNUNET_PQ_exec_prepared (PGconn *db_conn, 433GNUNET_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 */
439int 449int
440GNUNET_PQ_extract_result (PGresult *result, 450GNUNET_PQ_extract_result (PGresult *result,
@@ -452,6 +462,262 @@ void
452GNUNET_PQ_cleanup_result (struct GNUNET_PQ_ResultSpec *rs); 462GNUNET_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 */
481enum GNUNET_DB_QueryStatus
482GNUNET_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 */
503enum GNUNET_DB_QueryStatus
504GNUNET_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 */
517typedef 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 */
538enum GNUNET_DB_QueryStatus
539GNUNET_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 */
561enum GNUNET_DB_QueryStatus
562GNUNET_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 */
575struct 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 */
609struct GNUNET_PQ_PreparedStatement
610GNUNET_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 */
624int
625GNUNET_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 */
636struct 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 */
663struct GNUNET_PQ_ExecuteStatement
664GNUNET_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 */
674struct GNUNET_PQ_ExecuteStatement
675GNUNET_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 */
687int
688GNUNET_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 */
703PGconn *
704GNUNET_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 */
715PGconn *
716GNUNET_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
53check_PROGRAMS = \ 53check_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]
2HOSTNAME = localhost 2HOSTNAME = localhost
3#OVERLAY_TOPOLOGY = LINE
3 4
4[arm] 5[arm]
5GLOBAL_POSTFIX=-L ERROR 6GLOBAL_POSTFIX=-L ERROR
6 7
8[hostlist]
9SERVERS = 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
9UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-multicast.sock 13UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-multicast.sock
10 14
11[vpn] 15[vpn]
12AUTOSTART = NO 16AUTOSTART = NO
17
18[peerinfo]
19# Do not use shipped gnunet HELLOs
20USE_INCLUDED_HELLOS = NO
21
22# Option to disable all disk IO; only useful for testbed runs
23# (large-scale experiments); disables persistence of HELLOs!
24NO_IO = YES
25
26[nat]
27ENABLE_UPNP = NO
28
29[fs]
30FORCESTART = NO
31AUTOSTART = NO
32
33[vpn]
34FORCESTART = NO
35AUTOSTART = NO
36
37[revocation]
38FORCESTART = NO
39AUTOSTART = NO
40
41[gns]
42FORCESTART = NO
43AUTOSTART = NO
44
45[namestore]
46FORCESTART = NO
47AUTOSTART = NO
48
49[namecache]
50FORCESTART = NO
51AUTOSTART = NO
52
53[topology]
54FORCESTART = NO
55AUTOSTART = 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
38struct multicast_peer 38struct 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
46static void service_connect (void *cls, 47static void service_connect (void *cls,
@@ -54,7 +55,6 @@ static struct GNUNET_TESTBED_Peer **peers;
54// FIXME: refactor 55// FIXME: refactor
55static struct GNUNET_TESTBED_Operation *op[NUM_PEERS]; 56static struct GNUNET_TESTBED_Operation *op[NUM_PEERS];
56static struct GNUNET_TESTBED_Operation *pi_op[NUM_PEERS]; 57static struct GNUNET_TESTBED_Operation *pi_op[NUM_PEERS];
57static const struct GNUNET_PeerIdentity *peer_id[NUM_PEERS];
58 58
59static struct GNUNET_MULTICAST_Origin *origin; 59static struct GNUNET_MULTICAST_Origin *origin;
60static struct GNUNET_MULTICAST_Member *member[NUM_PEERS]; /* first element always empty */ 60static struct GNUNET_MULTICAST_Member *member[NUM_PEERS]; /* first element always empty */
@@ -80,16 +80,6 @@ static int result;
80static void 80static void
81shutdown_task (void *cls) 81shutdown_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
134libgnunet_plugin_namecache_postgres_la_LIBADD = \ 134libgnunet_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 */
79static void
80create_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 */
102static int 61static int
103database_setup (struct Plugin *plugin) 62database_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
185namecache_postgres_expire_blocks (struct Plugin *plugin) 149namecache_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,
301static int 247static int
302namecache_postgres_lookup_block (void *cls, 248namecache_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
200libgnunet_plugin_namestore_postgres_la_LIBADD = \ 200libgnunet_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 */
82static void
83create_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)
109static int 64static int
110database_setup (struct Plugin *plugin) 65database_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 */
242struct 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 */
300static int 269static void
301get_record_and_call_iterator (struct Plugin *plugin, 270parse_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
435namestore_postgres_iterate_records (void *cls, 393namestore_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
2AM_CPPFLAGS = -I$(top_srcdir)/src/include $(POSTGRESQL_CPPFLAGS)
3
4if MINGW
5 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
6endif
7
8if USE_COVERAGE
9 AM_CFLAGS = --coverage
10endif
11
12if HAVE_POSTGRESQL
13lib_LTLIBRARIES = libgnunetpostgres.la
14endif
15
16libgnunetpostgres_la_SOURCES = \
17 postgres.c
18libgnunetpostgres_la_LIBADD = -lpq \
19 $(top_builddir)/src/util/libgnunetutil.la
20libgnunetpostgres_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 */
43int
44GNUNET_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 */
89int
90GNUNET_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 */
129int
130GNUNET_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 */
170PGconn *
171GNUNET_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 */
214int
215GNUNET_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
16libgnunetpq_la_SOURCES = \ 16libgnunetpq_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
20libgnunetpq_la_LIBADD = -lpq \ 24libgnunetpq_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 */
34static void
35pq_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 */
49static void
50pq_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 */
68PGconn *
69GNUNET_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 */
107PGconn *
108GNUNET_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 */
55enum GNUNET_DB_QueryStatus
56GNUNET_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 */
146enum GNUNET_DB_QueryStatus
147GNUNET_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 */
189enum GNUNET_DB_QueryStatus
190GNUNET_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 */
236enum GNUNET_DB_QueryStatus
237GNUNET_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 */
32struct GNUNET_PQ_ExecuteStatement
33GNUNET_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 */
51struct GNUNET_PQ_ExecuteStatement
52GNUNET_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 */
72int
73GNUNET_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 */
34struct GNUNET_PQ_PreparedStatement
35GNUNET_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 */
58int
59GNUNET_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
89libgnunet_plugin_psycstore_postgres_la_LIBADD = \ 89libgnunet_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 */
89static int 89static int
90database_setup (struct Plugin *plugin) 90database_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
452exec_channel (struct Plugin *plugin, const char *stmt, 386exec_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,
478static int 405static int
479transaction_begin (struct Plugin *plugin, enum Transactions transaction) 406transaction_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)
505static int 424static int
506transaction_commit (struct Plugin *plugin) 425transaction_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)
533static int 443static int
534transaction_rollback (struct Plugin *plugin) 444transaction_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
559channel_key_store (struct Plugin *plugin, 460channel_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
585slave_key_store (struct Plugin *plugin, 477slave_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
832static int 675/**
833fragment_row (struct Plugin *plugin, 676 * Closure for #fragment_rows.
834 const char *stmt, 677 */
835 PGresult *res, 678struct 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 */
701void 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
1257static int 1065static int
1258update_message_id (struct Plugin *plugin, const char *stmt, 1066update_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
1487state_get (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, 1287state_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 */
1322struct 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 */
1347static void
1348get_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 */
1376void 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 */
1377static void 1396static void
1378send_done_and_destroy (void *cls) 1397send_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 */
2190void
2191handle_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)
2372static void 2422static void
2373union_channel_death (struct Operation *op) 2423union_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
235handle_union_p2p_done (void *cls, 235handle_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 */
244void
245handle_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 */
723static struct GNUNET_PSYC_Message * 723static struct GNUNET_PSYC_Message *
724guest_enter_msg_create () 724guest_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/
10pkgcfg_DATA = \ 10pkgcfg_DATA = \
11 transport.conf 11 transport.conf
12 12
13
14if HAVE_MHD 13if 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
80endif 79endif
81 80
81if HAVE_EXPERIMENTAL
82if LINUX 82if 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
121endif 121endif
122endif 122endif
123 123
124# end of HAVE_EXPERIMENTAL
125endif
124 126
125 127
126if !MINGW 128if !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 */
441void 441void
442GNUNET_CRYPTO_hash_context_read (struct GNUNET_HashContext *hc, 442GNUNET_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;
49static int print_public_key; 49static int print_public_key;
50 50
51/** 51/**
52 * Flag for printing public key in hex.
53 */
54static 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 */
54static int print_examples_flag; 59static 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
409main (int argc, 419main (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,
648static void 648static void
649monitor_sync_event (void *cls) 649monitor_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}