aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README5
-rw-r--r--configure.ac92
-rw-r--r--po/POTFILES.in5
-rw-r--r--src/Makefile.am5
-rw-r--r--src/datastore/Makefile.am64
-rw-r--r--src/datastore/perf_plugin_datastore_data_mysql.conf10
-rw-r--r--src/datastore/plugin_datastore_mysql.c1204
-rw-r--r--src/datastore/test_datastore_api_data_mysql.conf10
-rw-r--r--src/datastore/test_plugin_datastore_data_mysql.conf9
-rw-r--r--src/include/Makefile.am3
-rw-r--r--src/include/gnunet_my_lib.h511
-rw-r--r--src/include/gnunet_mysql_compat.h.in57
-rw-r--r--src/include/gnunet_mysql_lib.h151
-rw-r--r--src/my/.gitignore1
-rw-r--r--src/my/Makefile.am41
-rw-r--r--src/my/meson.build15
-rw-r--r--src/my/my.c270
-rw-r--r--src/my/my_query_helper.c401
-rw-r--r--src/my/my_result_helper.c868
-rw-r--r--src/my/test_my.c301
-rw-r--r--src/my/test_my.conf0
-rw-r--r--src/mysql/Makefile.am18
-rw-r--r--src/mysql/meson.build13
-rw-r--r--src/mysql/mysql.c485
-rw-r--r--src/regex/Makefile.am29
25 files changed, 15 insertions, 4553 deletions
diff --git a/README b/README
index 9c6c7081a..2981a9597 100644
--- a/README
+++ b/README
@@ -121,7 +121,6 @@ Direct dependencies of GNUnet:
121Dependencies of optional components/functionality: 121Dependencies of optional components/functionality:
122~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 122~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
123- Database plugins (alternatives to sqlite): 123- Database plugins (alternatives to sqlite):
124 * mysql >= 5.1
125 * postgres >= 9.5 124 * postgres >= 9.5
126- Transport plugins: 125- Transport plugins:
127 * bluez (bluetooth transport) 126 * bluez (bluetooth transport)
@@ -315,9 +314,7 @@ traversal).
315 314
316GNUnet requires the GNU MP library (https://www.gnu.org/software/gmp/) 315GNUnet requires the GNU MP library (https://www.gnu.org/software/gmp/)
317and libgcrypt (https://www.gnupg.org/). You can specify the path to 316and libgcrypt (https://www.gnupg.org/). You can specify the path to
318libgcrypt by passing "--with-gcrypt=PATH" to configure. You will also 317libgcrypt by passing "--with-gcrypt=PATH" to configure.
319need either sqlite (http://www.sqlite.org/), MySQL
320(http://www.mysql.org/) or PostGres (http://www.postgres.org/).
321 318
322If you install from source, you need to install GNU libextractor first 319If you install from source, you need to install GNU libextractor first
323(download from https://www.gnu.org/software/libextractor/). We also 320(download from https://www.gnu.org/software/libextractor/). We also
diff --git a/configure.ac b/configure.ac
index 53a640291..34c8608f3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -904,89 +904,6 @@ AM_CONDITIONAL([HAVE_POSTGRESQL], [test "x$postgres" = "x1"])
904AC_DEFINE_UNQUOTED([HAVE_POSTGRESQL], [$postgres], 904AC_DEFINE_UNQUOTED([HAVE_POSTGRESQL], [$postgres],
905 [Define to 1 if Postgres is available]) 905 [Define to 1 if Postgres is available])
906 906
907# check for mysql
908SAVE_LDFLAGS="$LDFLAGS"
909SAVE_CPPFLAGS="$CPPFLAGS"
910AC_ARG_WITH([mysql],
911 [AS_HELP_STRING([--with-mysql=PFX], [base of mysql installation])],
912 [AS_CASE([$withval],
913 [no],
914 [],
915 [yes|""],
916 [AC_CHECK_HEADERS([mysql/mysql.h],
917 [AC_CHECK_LIB([mysqlclient], [mysql_init],
918 [mysql=true], [mysql=false])])],
919 [LDFLAGS="-L$with_mysql/lib -L$with_mysql/lib/mysql $LDFLAGS $ZLIBS"
920 CPPFLAGS="-I$with_mysql/include $CPPFLAGS"
921 AC_CHECK_HEADERS([mysql/mysql.h],
922 [AC_CHECK_LIB([mysqlclient], [mysql_init],
923 [MYSQL_LDFLAGS="-L$with_mysql/lib -L$with_mysql/lib/mysql"
924 MYSQL_CPPFLAGS="-I$with_mysql/include"
925 mysql=true],
926 [mysql=false])])])],
927 [AS_IF([test -d "/usr/lib64/mysql"],
928 [MYSQL_LIBDIR="/usr/lib64/mysql"],
929 [AS_IF([test -d "/usr/lib/mysql"],
930 [MYSQL_LIBDIR="/usr/lib/mysql"],
931 [MYSQL_LIBDIR="/usr/lib"])])
932 LDFLAGS="-L$MYSQL_LIBDIR $LDFLAGS $ZLIBS"
933 AC_CHECK_LIB([mysqlclient], [mysql_init],
934 [AC_CHECK_HEADERS([mysql/mysql.h],
935 [MYSQL_LDFLAGS="-L$MYSQL_LIBDIR"
936 mysql=true],
937 [mysql=false])],
938 [mysql=false])])
939AC_SUBST(MYSQL_LDFLAGS)
940AC_SUBST(MYSQL_CPPFLAGS)
941
942mysql_bool="bool"
943# check for my_bool
944AS_IF([test "x$mysql" = "xtrue"],
945 [AC_MSG_CHECKING([for my_bool])
946 AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
947 [[#include <mysql/mysql.h>]
948 [typedef int my_bool;]])], # Hint: this fails if my_bool is defined already
949 [AC_MSG_RESULT([no])
950 mysql_bool="bool"],
951 [AC_MSG_RESULT([yes])
952 mysql_bool="my_bool"])])
953
954AC_SUBST([mysql_bool])
955
956# additional version checks for mysql
957AS_IF([test "x$mysql" = "xtrue"],
958 [AC_MSG_CHECKING([for mysql version])
959 AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
960 [[#include <mysql/mysql.h>]],
961 [[#if (MYSQL_VERSION_ID < 40100)
962#error required at least version 4.1
963#endif]])],
964 [mysql=true],
965 [mysql=false])
966 AS_IF([test "x$mysql" = "xfalse"],
967 [AC_MSG_RESULT([< 4.1])
968 AC_MSG_RESULT([mysql version >= 4.1 required. Will not use MySQL])])
969 AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
970 [[#include <mysql/mysql.h>]],
971 [[#if (MYSQL_VERSION_ID < 80000)
972#error needs at least version 8.0
973#endif]])],
974 [mysql8=true],
975 [mysql8=false])])
976
977AS_IF([test "x$mysql" = "xtrue"],
978 [AS_IF([test "x$mysql8" = "xfalse"],
979 [AC_MSG_RESULT([between 4.1 and 8.0])],
980 [AC_MSG_RESULT([> 8.0])
981 AC_DEFINE([HAVE_MYSQL8], [1],
982 [Define to 1 if MySQL is at least version 8])])])
983
984AM_CONDITIONAL([HAVE_MYSQL], [test "x$mysql" = "xtrue"])
985AM_CONDITIONAL([HAVE_MYSQLE], [false])
986
987AS_IF([test "x$sqlite3" = "x0" && test "x$mysql" = "xfalse" && test "x$postgres" = "x0"],
988 [AC_MSG_ERROR([GNUnet requires either SQLite, MySQL/MariaDB or PostgreSQL])])
989
990LDFLAGS="$SAVE_LDFLAGS" 907LDFLAGS="$SAVE_LDFLAGS"
991CPPFLAGS="$SAVE_CPPFLAGS" 908CPPFLAGS="$SAVE_CPPFLAGS"
992 909
@@ -1347,12 +1264,10 @@ src/identity/Makefile
1347src/identity/identity.conf 1264src/identity/identity.conf
1348src/include/Makefile 1265src/include/Makefile
1349src/include/gnunet_config.h 1266src/include/gnunet_config.h
1350src/include/gnunet_mysql_compat.h
1351src/integration-tests/Makefile 1267src/integration-tests/Makefile
1352src/json/Makefile 1268src/json/Makefile
1353src/hostlist/Makefile 1269src/hostlist/Makefile
1354src/my/Makefile 1270src/my/Makefile
1355src/mysql/Makefile
1356src/namecache/Makefile 1271src/namecache/Makefile
1357src/namecache/namecache.conf 1272src/namecache/namecache.conf
1358src/namestore/Makefile 1273src/namestore/Makefile
@@ -1432,7 +1347,6 @@ pkgconfig/gnunetidentity.pc
1432pkgconfig/gnunetjson.pc 1347pkgconfig/gnunetjson.pc
1433pkgconfig/gnunetmessenger.pc 1348pkgconfig/gnunetmessenger.pc
1434pkgconfig/gnunetmicrophone.pc 1349pkgconfig/gnunetmicrophone.pc
1435pkgconfig/gnunetmysql.pc
1436pkgconfig/gnunetnamestore.pc 1350pkgconfig/gnunetnamestore.pc
1437pkgconfig/gnunetnat.pc 1351pkgconfig/gnunetnat.pc
1438pkgconfig/gnunetnse.pc 1352pkgconfig/gnunetnse.pc
@@ -1574,11 +1488,6 @@ AS_IF([test "x$sqlite3" = "x1"],
1574 features_msg="sqlite $features_msg"], 1488 features_msg="sqlite $features_msg"],
1575 [sqlite_msg="no"]) 1489 [sqlite_msg="no"])
1576 1490
1577AS_IF([test "x$mysql" = "xtrue"],
1578 [mysql_msg="yes"
1579 features_msg="mysql $features_msg"],
1580 [mysql_msg="no"])
1581
1582AS_IF([test "x$postgres" = "x1"], 1491AS_IF([test "x$postgres" = "x1"],
1583 [postgres_msg="yes" 1492 [postgres_msg="yes"
1584 features_msg="postgres $features_msg"], 1493 features_msg="postgres $features_msg"],
@@ -1607,7 +1516,6 @@ Build Target: ${build_target}
1607Default Interface: ${interface_msg} 1516Default Interface: ${interface_msg}
1608 1517
1609sqlite3: ${sqlite_msg} 1518sqlite3: ${sqlite_msg}
1610MySQL: ${mysql_msg}
1611PostgreSQL: ${postgres_msg} 1519PostgreSQL: ${postgres_msg}
1612 1520
1613cURL TLS backend: ${curl_tls_backend} 1521cURL TLS backend: ${curl_tls_backend}
diff --git a/po/POTFILES.in b/po/POTFILES.in
index bc8be7a54..3d6c2f6d1 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -89,7 +89,6 @@ src/datastore/datastore_api.c
89src/datastore/gnunet-datastore.c 89src/datastore/gnunet-datastore.c
90src/datastore/gnunet-service-datastore.c 90src/datastore/gnunet-service-datastore.c
91src/datastore/plugin_datastore_heap.c 91src/datastore/plugin_datastore_heap.c
92src/datastore/plugin_datastore_mysql.c
93src/datastore/plugin_datastore_postgres.c 92src/datastore/plugin_datastore_postgres.c
94src/datastore/plugin_datastore_sqlite.c 93src/datastore/plugin_datastore_sqlite.c
95src/datastore/plugin_datastore_template.c 94src/datastore/plugin_datastore_template.c
@@ -233,10 +232,6 @@ src/messenger/messenger_api_util.c
233src/messenger/plugin_gnsrecord_messenger.c 232src/messenger/plugin_gnsrecord_messenger.c
234src/messenger/testing_messenger_barrier.c 233src/messenger/testing_messenger_barrier.c
235src/messenger/testing_messenger_setup.c 234src/messenger/testing_messenger_setup.c
236src/my/my.c
237src/my/my_query_helper.c
238src/my/my_result_helper.c
239src/mysql/mysql.c
240src/namecache/gnunet-namecache.c 235src/namecache/gnunet-namecache.c
241src/namecache/gnunet-service-namecache.c 236src/namecache/gnunet-service-namecache.c
242src/namecache/namecache_api.c 237src/namecache/namecache_api.c
diff --git a/src/Makefile.am b/src/Makefile.am
index d7c0b51f0..8fb984d4b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -25,10 +25,6 @@ if HAVE_SQLITE
25 SQLITE_DIR = sq 25 SQLITE_DIR = sq
26endif 26endif
27 27
28if HAVE_MYSQL
29 MYSQL_DIR = mysql my
30endif
31
32if HAVE_POSTGRESQL 28if HAVE_POSTGRESQL
33 POSTGRES_DIR = pq 29 POSTGRES_DIR = pq
34endif 30endif
@@ -50,7 +46,6 @@ SUBDIRS = \
50 $(REST_DIR) \ 46 $(REST_DIR) \
51 peerinfo \ 47 peerinfo \
52 $(SQLITE_DIR) \ 48 $(SQLITE_DIR) \
53 $(MYSQL_DIR) \
54 $(POSTGRES_DIR) \ 49 $(POSTGRES_DIR) \
55 datacache \ 50 datacache \
56 datastore \ 51 datastore \
diff --git a/src/datastore/Makefile.am b/src/datastore/Makefile.am
index b73a0497b..595c7da3d 100644
--- a/src/datastore/Makefile.am
+++ b/src/datastore/Makefile.am
@@ -56,19 +56,6 @@ gnunet_datastore_LDADD = \
56 $(GN_LIBINTL) 56 $(GN_LIBINTL)
57 57
58 58
59if HAVE_MYSQL
60 MYSQL_PLUGIN = libgnunet_plugin_datastore_mysql.la
61if HAVE_BENCHMARKS
62 MYSQL_BENCHMARKS = \
63 perf_datastore_api_mysql \
64 perf_plugin_datastore_mysql
65endif
66 MYSQL_TESTS = \
67 test_datastore_api_mysql \
68 test_datastore_api_management_mysql \
69 test_plugin_datastore_mysql \
70 $(MYSQL_BENCHMARKS)
71endif
72if HAVE_SQLITE 59if HAVE_SQLITE
73 SQLITE_PLUGIN = libgnunet_plugin_datastore_sqlite.la 60 SQLITE_PLUGIN = libgnunet_plugin_datastore_sqlite.la
74if HAVE_BENCHMARKS 61if HAVE_BENCHMARKS
@@ -98,7 +85,6 @@ endif
98 85
99plugin_LTLIBRARIES = \ 86plugin_LTLIBRARIES = \
100 $(SQLITE_PLUGIN) \ 87 $(SQLITE_PLUGIN) \
101 $(MYSQL_PLUGIN) \
102 $(POSTGRES_PLUGIN) \ 88 $(POSTGRES_PLUGIN) \
103 libgnunet_plugin_datastore_heap.la 89 libgnunet_plugin_datastore_heap.la
104 90
@@ -128,18 +114,6 @@ libgnunet_plugin_datastore_heap_la_LDFLAGS = \
128 $(GN_PLUGIN_LDFLAGS) 114 $(GN_PLUGIN_LDFLAGS)
129 115
130 116
131libgnunet_plugin_datastore_mysql_la_SOURCES = \
132 plugin_datastore_mysql.c
133libgnunet_plugin_datastore_mysql_la_LIBADD = \
134 $(top_builddir)/src/my/libgnunetmy.la \
135 $(top_builddir)/src/mysql/libgnunetmysql.la \
136 $(top_builddir)/src/statistics/libgnunetstatistics.la \
137 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) $(Z_LIBS) -lmysqlclient
138libgnunet_plugin_datastore_mysql_la_LDFLAGS = \
139 $(GN_PLUGIN_LDFLAGS) $(MYSQL_LDFLAGS) -lmysqlclient
140libgnunet_plugin_datastore_mysql_la_CPPFLAGS = \
141 $(MYSQL_CPPFLAGS) $(AM_CPPFLAGS)
142
143libgnunet_plugin_datastore_postgres_la_SOURCES = \ 117libgnunet_plugin_datastore_postgres_la_SOURCES = \
144 plugin_datastore_postgres.c 118 plugin_datastore_postgres.c
145libgnunet_plugin_datastore_postgres_la_LIBADD = \ 119libgnunet_plugin_datastore_postgres_la_LIBADD = \
@@ -167,7 +141,6 @@ check_PROGRAMS = \
167 perf_plugin_datastore_heap \ 141 perf_plugin_datastore_heap \
168 test_plugin_datastore_heap \ 142 test_plugin_datastore_heap \
169 $(SQLITE_TESTS) \ 143 $(SQLITE_TESTS) \
170 $(MYSQL_TESTS) \
171 $(POSTGRES_TESTS) 144 $(POSTGRES_TESTS)
172 145
173if ENABLE_TEST_RUN 146if ENABLE_TEST_RUN
@@ -243,40 +216,6 @@ test_plugin_datastore_sqlite_LDADD = \
243 $(top_builddir)/src/util/libgnunetutil.la 216 $(top_builddir)/src/util/libgnunetutil.la
244 217
245 218
246test_datastore_api_mysql_SOURCES = \
247 test_datastore_api.c
248test_datastore_api_mysql_LDADD = \
249 $(top_builddir)/src/testing/libgnunettesting.la \
250 libgnunetdatastore.la \
251 $(top_builddir)/src/util/libgnunetutil.la
252
253test_datastore_api_management_mysql_SOURCES = \
254 test_datastore_api_management.c
255test_datastore_api_management_mysql_LDADD = \
256 $(top_builddir)/src/testing/libgnunettesting.la \
257 libgnunetdatastore.la \
258 $(top_builddir)/src/util/libgnunetutil.la
259
260perf_datastore_api_mysql_SOURCES = \
261 perf_datastore_api.c
262perf_datastore_api_mysql_LDADD = \
263 $(top_builddir)/src/testing/libgnunettesting.la \
264 libgnunetdatastore.la \
265 $(top_builddir)/src/util/libgnunetutil.la
266
267test_plugin_datastore_mysql_SOURCES = \
268 test_plugin_datastore.c
269test_plugin_datastore_mysql_LDADD = \
270 $(top_builddir)/src/testing/libgnunettesting.la \
271 $(top_builddir)/src/util/libgnunetutil.la
272
273perf_plugin_datastore_mysql_SOURCES = \
274 perf_plugin_datastore.c
275perf_plugin_datastore_mysql_LDADD = \
276 $(top_builddir)/src/testing/libgnunettesting.la \
277 $(top_builddir)/src/util/libgnunetutil.la
278
279
280test_datastore_api_postgres_SOURCES = \ 219test_datastore_api_postgres_SOURCES = \
281 test_datastore_api.c 220 test_datastore_api.c
282test_datastore_api_postgres_LDADD = \ 221test_datastore_api_postgres_LDADD = \
@@ -319,9 +258,6 @@ EXTRA_DIST = \
319 test_datastore_api_data_heap.conf \ 258 test_datastore_api_data_heap.conf \
320 perf_plugin_datastore_data_heap.conf \ 259 perf_plugin_datastore_data_heap.conf \
321 test_plugin_datastore_data_heap.conf \ 260 test_plugin_datastore_data_heap.conf \
322 test_datastore_api_data_mysql.conf \
323 perf_plugin_datastore_data_mysql.conf \
324 test_plugin_datastore_data_mysql.conf \
325 test_datastore_api_data_postgres.conf \ 261 test_datastore_api_data_postgres.conf \
326 perf_plugin_datastore_data_postgres.conf \ 262 perf_plugin_datastore_data_postgres.conf \
327 test_plugin_datastore_data_postgres.conf \ 263 test_plugin_datastore_data_postgres.conf \
diff --git a/src/datastore/perf_plugin_datastore_data_mysql.conf b/src/datastore/perf_plugin_datastore_data_mysql.conf
deleted file mode 100644
index a32b830c3..000000000
--- a/src/datastore/perf_plugin_datastore_data_mysql.conf
+++ /dev/null
@@ -1,10 +0,0 @@
1@INLINE@ test_defaults.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/perf-gnunet-datastore-mysql/
4
5[datastore]
6DATABASE = mysql
7
8[datastore-mysql]
9DATABASE = gnunetcheck
10
diff --git a/src/datastore/plugin_datastore_mysql.c b/src/datastore/plugin_datastore_mysql.c
deleted file mode 100644
index f62c51778..000000000
--- a/src/datastore/plugin_datastore_mysql.c
+++ /dev/null
@@ -1,1204 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2009, 2010, 2011 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file datastore/plugin_datastore_mysql.c
23 * @brief mysql-based datastore backend
24 * @author Igor Wronsky
25 * @author Christian Grothoff
26 * @author Christophe Genevey
27 *
28 * NOTE: This db module does NOT work with mysql prior to 4.1 since
29 * it uses prepared statements. MySQL 5.0.46 promises to fix a bug
30 * in MyISAM that is causing us grief. At the time of this writing,
31 * that version is yet to be released. In anticipation, the code
32 * will use MyISAM with 5.0.46 (and higher). If you run such a
33 * version, please run "make check" to verify that the MySQL bug
34 * was actually fixed in your version (and if not, change the
35 * code below to use MyISAM for gn071).
36 *
37 * HIGHLIGHTS
38 *
39 * Pros
40 * + On up-to-date hardware where mysql can be used comfortably, this
41 * module will have better performance than the other db choices
42 * (according to our tests).
43 * + Its often possible to recover the mysql database from internal
44 * inconsistencies. The other db choices do not support repair!
45 * Cons
46 * - Memory usage (Comment: "I have 1G and it never caused me trouble")
47 * - Manual setup
48 *
49 * MANUAL SETUP INSTRUCTIONS
50 *
51 * 1) in gnunet.conf, set
52 * @verbatim
53 [datastore]
54 DATABASE = "mysql"
55 @endverbatim
56 * 2) Then access mysql as root,
57 * @verbatim
58 $ mysql -u root -p
59 @endverbatim
60 * and do the following. [You should replace $USER with the username
61 * that will be running the gnunetd process].
62 * @verbatim
63 CREATE DATABASE gnunet;
64 GRANT select,insert,update,delete,create,alter,drop,create temporary tables
65 ON gnunet.* TO $USER@localhost;
66 SET PASSWORD FOR $USER@localhost=PASSWORD('$the_password_you_like');
67 FLUSH PRIVILEGES;
68 @endverbatim
69 * 3) In the $HOME directory of $USER, create a ".my.cnf" file
70 * with the following lines
71 * @verbatim
72 [client]
73 user=$USER
74 password=$the_password_you_like
75 @endverbatim
76 *
77 * That's it. Note that .my.cnf file is a security risk unless its on
78 * a safe partition etc. The $HOME/.my.cnf can of course be a symbolic
79 * link. Even greater security risk can be achieved by setting no
80 * password for $USER. Luckily $USER has only privileges to mess
81 * up GNUnet's tables, nothing else (unless you give them more,
82 * of course).<p>
83 *
84 * 4) Still, perhaps you should briefly try if the DB connection
85 * works. First, login as $USER. Then use,
86 *
87 * @verbatim
88 $ mysql -u $USER -p $the_password_you_like
89 mysql> use gnunet;
90 @endverbatim
91 *
92 * If you get the message &quot;Database changed&quot; it probably works.
93 *
94 * [If you get &quot;ERROR 2002: Can't connect to local MySQL server
95 * through socket '/tmp/mysql.sock' (2)&quot; it may be resolvable by
96 * &quot;ln -s /var/run/mysqld/mysqld.sock /tmp/mysql.sock&quot;
97 * so there may be some additional trouble depending on your mysql setup.]
98 *
99 * REPAIRING TABLES
100 *
101 * - Its probably healthy to check your tables for inconsistencies
102 * every now and then.
103 * - If you get odd SEGVs on gnunetd startup, it might be that the mysql
104 * databases have been corrupted.
105 * - The tables can be verified/fixed in two ways;
106 * 1) by running mysqlcheck -A, or
107 * 2) by executing (inside of mysql using the GNUnet database):
108 * @verbatim
109 mysql> REPAIR TABLE gn090;
110 @endverbatim
111 *
112 * PROBLEMS?
113 *
114 * If you have problems related to the mysql module, your best
115 * friend is probably the mysql manual. The first thing to check
116 * is that mysql is basically operational, that you can connect
117 * to it, create tables, issue queries etc.
118 */
119
120#include "platform.h"
121#include "gnunet_datastore_plugin.h"
122#include "gnunet_util_lib.h"
123#include "gnunet_mysql_lib.h"
124#include "gnunet_mysql_compat.h"
125#include "gnunet_my_lib.h"
126
127#define MAX_DATUM_SIZE 65536
128
129
130/**
131 * Context for all functions in this plugin.
132 */
133struct Plugin
134{
135 /**
136 * Our execution environment.
137 */
138 struct GNUNET_DATASTORE_PluginEnvironment *env;
139
140 /**
141 * Handle to talk to MySQL.
142 */
143 struct GNUNET_MYSQL_Context *mc;
144
145 /**
146 * Prepared statements.
147 */
148#define INSERT_ENTRY \
149 "INSERT INTO gn090 (repl,type,prio,anonLevel,expire,rvalue,hash,vhash,value) VALUES (?,?,?,?,?,?,?,?,?)"
150 struct GNUNET_MYSQL_StatementHandle *insert_entry;
151
152#define DELETE_ENTRY_BY_UID "DELETE FROM gn090 WHERE uid=?"
153 struct GNUNET_MYSQL_StatementHandle *delete_entry_by_uid;
154
155#define DELETE_ENTRY_BY_HASH_VALUE "DELETE FROM gn090 " \
156 "WHERE hash = ? AND " \
157 "value = ? " \
158 "LIMIT 1"
159 struct GNUNET_MYSQL_StatementHandle *delete_entry_by_hash_value;
160
161#define RESULT_COLUMNS "repl, type, prio, anonLevel, expire, hash, value, uid"
162
163#define SELECT_ENTRY "SELECT " RESULT_COLUMNS " FROM gn090 " \
164 "WHERE uid >= ? AND " \
165 "(rvalue >= ? OR 0 = ?) " \
166 "ORDER BY uid LIMIT 1"
167 struct GNUNET_MYSQL_StatementHandle *select_entry;
168
169#define SELECT_ENTRY_BY_HASH "SELECT " RESULT_COLUMNS " FROM gn090 " \
170 "FORCE INDEX (idx_hash_type_uid) " \
171 "WHERE hash=? AND " \
172 "uid >= ? AND " \
173 "(rvalue >= ? OR 0 = ?) " \
174 "ORDER BY uid LIMIT 1"
175 struct GNUNET_MYSQL_StatementHandle *select_entry_by_hash;
176
177#define SELECT_ENTRY_BY_HASH_AND_TYPE "SELECT " RESULT_COLUMNS " FROM gn090 " \
178 "FORCE INDEX (idx_hash_type_uid) " \
179 "WHERE hash = ? AND " \
180 "type = ? AND " \
181 "uid >= ? AND " \
182 "(rvalue >= ? OR 0 = ?) " \
183 "ORDER BY uid LIMIT 1"
184 struct GNUNET_MYSQL_StatementHandle *select_entry_by_hash_and_type;
185
186#define UPDATE_ENTRY "UPDATE gn090 SET " \
187 "prio = prio + ?, " \
188 "repl = repl + ?, " \
189 "expire = GREATEST(expire, ?) " \
190 "WHERE hash = ? AND vhash = ?"
191 struct GNUNET_MYSQL_StatementHandle *update_entry;
192
193#define DEC_REPL "UPDATE gn090 SET repl=GREATEST (1, repl) - 1 WHERE uid=?"
194 struct GNUNET_MYSQL_StatementHandle *dec_repl;
195
196#define SELECT_SIZE "SELECT SUM(LENGTH(value)+256) FROM gn090"
197 struct GNUNET_MYSQL_StatementHandle *get_size;
198
199#define SELECT_IT_NON_ANONYMOUS "SELECT " RESULT_COLUMNS " FROM gn090 " \
200 "FORCE INDEX (idx_anonLevel_type_rvalue) " \
201 "WHERE anonLevel=0 AND " \
202 "type=? AND " \
203 "uid >= ? " \
204 "ORDER BY uid LIMIT 1"
205 struct GNUNET_MYSQL_StatementHandle *zero_iter;
206
207#define SELECT_IT_EXPIRATION "SELECT " RESULT_COLUMNS " FROM gn090 " \
208 "FORCE INDEX (idx_expire) " \
209 "WHERE expire < ? " \
210 "ORDER BY expire ASC LIMIT 1"
211 struct GNUNET_MYSQL_StatementHandle *select_expiration;
212
213#define SELECT_IT_PRIORITY "SELECT " RESULT_COLUMNS " FROM gn090 " \
214 "FORCE INDEX (idx_prio) " \
215 "ORDER BY prio ASC LIMIT 1"
216 struct GNUNET_MYSQL_StatementHandle *select_priority;
217
218#define SELECT_IT_REPLICATION "SELECT " RESULT_COLUMNS " FROM gn090 " \
219 "FORCE INDEX (idx_repl_rvalue) " \
220 "WHERE repl=? AND " \
221 " (rvalue>=? OR" \
222 " NOT EXISTS (SELECT 1 FROM gn090 FORCE INDEX (idx_repl_rvalue) WHERE repl=? AND rvalue>=?)) " \
223 "ORDER BY rvalue ASC " \
224 "LIMIT 1"
225 struct GNUNET_MYSQL_StatementHandle *select_replication;
226
227#define SELECT_MAX_REPL "SELECT MAX(repl) FROM gn090"
228 struct GNUNET_MYSQL_StatementHandle *max_repl;
229
230#define GET_ALL_KEYS "SELECT hash from gn090"
231 struct GNUNET_MYSQL_StatementHandle *get_all_keys;
232};
233
234#define MAX_PARAM 16
235
236/**
237 * Delete an entry from the gn090 table.
238 *
239 * @param plugin plugin context
240 * @param uid unique ID of the entry to delete
241 * @return #GNUNET_OK on success, #GNUNET_NO if no such value exists, #GNUNET_SYSERR on error
242 */
243static int
244do_delete_entry (struct Plugin *plugin,
245 unsigned long long uid)
246{
247 int ret;
248 uint64_t uid64 = (uint64_t) uid;
249 struct GNUNET_MY_QueryParam params_delete[] = {
250 GNUNET_MY_query_param_uint64 (&uid64),
251 GNUNET_MY_query_param_end
252 };
253
254 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
255 "Deleting value %llu from gn090 table\n",
256 uid);
257 ret = GNUNET_MY_exec_prepared (plugin->mc,
258 plugin->delete_entry_by_uid,
259 params_delete);
260 if (ret >= 0)
261 {
262 return GNUNET_OK;
263 }
264 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
265 "Deleting value %llu from gn090 table failed\n",
266 (unsigned long long) uid);
267 return ret;
268}
269
270
271/**
272 * Get an estimate of how much space the database is
273 * currently using.
274 *
275 * @param cls our `struct Plugin *`
276 * @return number of bytes used on disk
277 */
278static void
279mysql_plugin_estimate_size (void *cls,
280 unsigned long long *estimate)
281{
282 struct Plugin *plugin = cls;
283 uint64_t total;
284 int ret;
285 struct GNUNET_MY_QueryParam params_get[] = {
286 GNUNET_MY_query_param_end
287 };
288 struct GNUNET_MY_ResultSpec results_get[] = {
289 GNUNET_MY_result_spec_uint64 (&total),
290 GNUNET_MY_result_spec_end
291 };
292
293 ret = GNUNET_MY_exec_prepared (plugin->mc,
294 plugin->get_size,
295 params_get);
296 *estimate = 0;
297 total = UINT64_MAX;
298 if ((GNUNET_OK == ret) &&
299 (GNUNET_OK ==
300 GNUNET_MY_extract_result (plugin->get_size,
301 results_get)))
302 {
303 *estimate = (unsigned long long) total;
304 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
305 "Size estimate for MySQL payload is %lld\n",
306 (long long) total);
307 GNUNET_assert (UINT64_MAX != total);
308 GNUNET_break (GNUNET_NO ==
309 GNUNET_MY_extract_result (plugin->get_size,
310 NULL));
311 }
312}
313
314
315/**
316 * Store an item in the datastore.
317 *
318 * @param cls closure
319 * @param key key for the item
320 * @param absent true if the key was not found in the bloom filter
321 * @param size number of bytes in @a data
322 * @param data content stored
323 * @param type type of the content
324 * @param priority priority of the content
325 * @param anonymity anonymity-level for the content
326 * @param replication replication-level for the content
327 * @param expiration expiration time for the content
328 * @param cont continuation called with success or failure status
329 * @param cont_cls closure for @a cont
330 */
331static void
332mysql_plugin_put (void *cls,
333 const struct GNUNET_HashCode *key,
334 bool absent,
335 uint32_t size,
336 const void *data,
337 enum GNUNET_BLOCK_Type type,
338 uint32_t priority,
339 uint32_t anonymity,
340 uint32_t replication,
341 struct GNUNET_TIME_Absolute expiration,
342 PluginPutCont cont,
343 void *cont_cls)
344{
345 struct Plugin *plugin = cls;
346 uint64_t lexpiration = expiration.abs_value_us;
347 struct GNUNET_HashCode vhash;
348
349 GNUNET_CRYPTO_hash (data,
350 size,
351 &vhash);
352 if (! absent)
353 {
354 struct GNUNET_MY_QueryParam params_update[] = {
355 GNUNET_MY_query_param_uint32 (&priority),
356 GNUNET_MY_query_param_uint32 (&replication),
357 GNUNET_MY_query_param_uint64 (&lexpiration),
358 GNUNET_MY_query_param_auto_from_type (key),
359 GNUNET_MY_query_param_auto_from_type (&vhash),
360 GNUNET_MY_query_param_end
361 };
362
363 if (GNUNET_OK !=
364 GNUNET_MY_exec_prepared (plugin->mc,
365 plugin->update_entry,
366 params_update))
367 {
368 cont (cont_cls,
369 key,
370 size,
371 GNUNET_SYSERR,
372 _ ("MySQL statement run failure"));
373 return;
374 }
375
376 MYSQL_STMT *stmt = GNUNET_MYSQL_statement_get_stmt (plugin->update_entry);
377 my_ulonglong rows = mysql_stmt_affected_rows (stmt);
378
379 GNUNET_break (GNUNET_NO ==
380 GNUNET_MY_extract_result (plugin->update_entry,
381 NULL));
382 if (0 != rows)
383 {
384 cont (cont_cls,
385 key,
386 size,
387 GNUNET_NO,
388 NULL);
389 return;
390 }
391 }
392
393 uint64_t lrvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
394 UINT64_MAX);
395 struct GNUNET_MY_QueryParam params_insert[] = {
396 GNUNET_MY_query_param_uint32 (&replication),
397 GNUNET_MY_query_param_uint32 (&type),
398 GNUNET_MY_query_param_uint32 (&priority),
399 GNUNET_MY_query_param_uint32 (&anonymity),
400 GNUNET_MY_query_param_uint64 (&lexpiration),
401 GNUNET_MY_query_param_uint64 (&lrvalue),
402 GNUNET_MY_query_param_auto_from_type (key),
403 GNUNET_MY_query_param_auto_from_type (&vhash),
404 GNUNET_MY_query_param_fixed_size (data, size),
405 GNUNET_MY_query_param_end
406 };
407
408 if (size > MAX_DATUM_SIZE)
409 {
410 GNUNET_break (0);
411 cont (cont_cls, key, size, GNUNET_SYSERR, _ ("Data too large"));
412 return;
413 }
414
415 if (GNUNET_OK !=
416 GNUNET_MY_exec_prepared (plugin->mc,
417 plugin->insert_entry,
418 params_insert))
419 {
420 cont (cont_cls,
421 key,
422 size,
423 GNUNET_SYSERR,
424 _ ("MySQL statement run failure"));
425 return;
426 }
427 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
428 "Inserted value `%s' with size %u into gn090 table\n",
429 GNUNET_h2s (key),
430 (unsigned int) size);
431 if (size > 0)
432 plugin->env->duc (plugin->env->cls,
433 size);
434 GNUNET_break (GNUNET_NO ==
435 GNUNET_MY_extract_result (plugin->insert_entry,
436 NULL));
437 cont (cont_cls,
438 key,
439 size,
440 GNUNET_OK,
441 NULL);
442}
443
444
445/**
446 * Run the given select statement and call 'proc' on the resulting
447 * values (which must be in particular positions).
448 *
449 * @param plugin the plugin handle
450 * @param stmt select statement to run
451 * @param proc function to call on result
452 * @param proc_cls closure for @a proc
453 * @param params_select arguments to initialize stmt
454 */
455static void
456execute_select (struct Plugin *plugin,
457 struct GNUNET_MYSQL_StatementHandle *stmt,
458 PluginDatumProcessor proc,
459 void *proc_cls,
460 struct GNUNET_MY_QueryParam *params_select)
461{
462 int ret;
463 uint32_t replication;
464 uint32_t type;
465 uint32_t priority;
466 uint32_t anonymity;
467 uint64_t uid;
468 size_t value_size;
469 void *value;
470 struct GNUNET_HashCode key;
471 struct GNUNET_TIME_Absolute expiration;
472 struct GNUNET_MY_ResultSpec results_select[] = {
473 GNUNET_MY_result_spec_uint32 (&replication),
474 GNUNET_MY_result_spec_uint32 (&type),
475 GNUNET_MY_result_spec_uint32 (&priority),
476 GNUNET_MY_result_spec_uint32 (&anonymity),
477 GNUNET_MY_result_spec_absolute_time (&expiration),
478 GNUNET_MY_result_spec_auto_from_type (&key),
479 GNUNET_MY_result_spec_variable_size (&value, &value_size),
480 GNUNET_MY_result_spec_uint64 (&uid),
481 GNUNET_MY_result_spec_end
482 };
483
484 ret = GNUNET_MY_exec_prepared (plugin->mc,
485 stmt,
486 params_select);
487 if (GNUNET_OK != ret)
488 {
489 proc (proc_cls,
490 NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
491 return;
492 }
493
494 ret = GNUNET_MY_extract_result (stmt,
495 results_select);
496 if (GNUNET_OK != ret)
497 {
498 proc (proc_cls,
499 NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
500 return;
501 }
502
503 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
504 "Found %u-byte value under key `%s' with prio %u, anon %u, expire %s selecting from gn090 table\n",
505 (unsigned int) value_size,
506 GNUNET_h2s (&key),
507 (unsigned int) priority,
508 (unsigned int) anonymity,
509 GNUNET_STRINGS_absolute_time_to_string (expiration));
510 GNUNET_assert (value_size < MAX_DATUM_SIZE);
511 GNUNET_break (GNUNET_NO ==
512 GNUNET_MY_extract_result (stmt,
513 NULL));
514 ret = proc (proc_cls,
515 &key,
516 value_size,
517 value,
518 type,
519 priority,
520 anonymity,
521 replication,
522 expiration,
523 uid);
524 GNUNET_MY_cleanup_result (results_select);
525 if (GNUNET_NO == ret)
526 {
527 do_delete_entry (plugin, uid);
528 if (0 != value_size)
529 plugin->env->duc (plugin->env->cls,
530 -value_size);
531 }
532}
533
534
535/**
536 * Get one of the results for a particular key in the datastore.
537 *
538 * @param cls closure
539 * @param next_uid return the result with lowest uid >= next_uid
540 * @param random if true, return a random result instead of using next_uid
541 * @param key key to match, never NULL
542 * @param type entries of which type are relevant?
543 * Use 0 for any type.
544 * @param proc function to call on the matching value,
545 * with NULL for if no value matches
546 * @param proc_cls closure for @a proc
547 */
548static void
549mysql_plugin_get_key (void *cls,
550 uint64_t next_uid,
551 bool random,
552 const struct GNUNET_HashCode *key,
553 enum GNUNET_BLOCK_Type type,
554 PluginDatumProcessor proc,
555 void *proc_cls)
556{
557 struct Plugin *plugin = cls;
558 uint64_t rvalue;
559
560 if (random)
561 {
562 rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
563 UINT64_MAX);
564 next_uid = 0;
565 }
566 else
567 rvalue = 0;
568
569 if (NULL == key)
570 {
571 struct GNUNET_MY_QueryParam params_select[] = {
572 GNUNET_MY_query_param_uint64 (&next_uid),
573 GNUNET_MY_query_param_uint64 (&rvalue),
574 GNUNET_MY_query_param_uint64 (&rvalue),
575 GNUNET_MY_query_param_end
576 };
577
578 execute_select (plugin,
579 plugin->select_entry,
580 proc,
581 proc_cls,
582 params_select);
583 }
584 else if (type != GNUNET_BLOCK_TYPE_ANY)
585 {
586 struct GNUNET_MY_QueryParam params_select[] = {
587 GNUNET_MY_query_param_auto_from_type (key),
588 GNUNET_MY_query_param_uint32 (&type),
589 GNUNET_MY_query_param_uint64 (&next_uid),
590 GNUNET_MY_query_param_uint64 (&rvalue),
591 GNUNET_MY_query_param_uint64 (&rvalue),
592 GNUNET_MY_query_param_end
593 };
594
595 execute_select (plugin,
596 plugin->select_entry_by_hash_and_type,
597 proc,
598 proc_cls,
599 params_select);
600 }
601 else
602 {
603 struct GNUNET_MY_QueryParam params_select[] = {
604 GNUNET_MY_query_param_auto_from_type (key),
605 GNUNET_MY_query_param_uint64 (&next_uid),
606 GNUNET_MY_query_param_uint64 (&rvalue),
607 GNUNET_MY_query_param_uint64 (&rvalue),
608 GNUNET_MY_query_param_end
609 };
610
611 execute_select (plugin,
612 plugin->select_entry_by_hash,
613 proc,
614 proc_cls,
615 params_select);
616 }
617}
618
619
620/**
621 * Get a zero-anonymity datum from the datastore.
622 *
623 * @param cls our `struct Plugin *`
624 * @param next_uid return the result with lowest uid >= next_uid
625 * @param type entries of which type should be considered?
626 * Must not be zero (ANY).
627 * @param proc function to call on a matching value;
628 * will be called with NULL if no value matches
629 * @param proc_cls closure for @a proc
630 */
631static void
632mysql_plugin_get_zero_anonymity (void *cls,
633 uint64_t next_uid,
634 enum GNUNET_BLOCK_Type type,
635 PluginDatumProcessor proc,
636 void *proc_cls)
637{
638 struct Plugin *plugin = cls;
639 uint32_t typei = (uint32_t) type;
640
641 struct GNUNET_MY_QueryParam params_zero_iter[] = {
642 GNUNET_MY_query_param_uint32 (&typei),
643 GNUNET_MY_query_param_uint64 (&next_uid),
644 GNUNET_MY_query_param_end
645 };
646
647 execute_select (plugin,
648 plugin->zero_iter,
649 proc,
650 proc_cls,
651 params_zero_iter);
652}
653
654
655/**
656 * Context for #repl_proc() function.
657 */
658struct ReplCtx
659{
660 /**
661 * Plugin handle.
662 */
663 struct Plugin *plugin;
664
665 /**
666 * Function to call for the result (or the NULL).
667 */
668 PluginDatumProcessor proc;
669
670 /**
671 * Closure for @e proc.
672 */
673 void *proc_cls;
674};
675
676
677/**
678 * Wrapper for the processor for #mysql_plugin_get_replication().
679 * Decrements the replication counter and calls the original
680 * iterator.
681 *
682 * @param cls closure
683 * @param key key for the content
684 * @param size number of bytes in @a data
685 * @param data content stored
686 * @param type type of the content
687 * @param priority priority of the content
688 * @param anonymity anonymity-level for the content
689 * @param replication replication-level for the content
690 * @param expiration expiration time for the content
691 * @param uid unique identifier for the datum;
692 * maybe 0 if no unique identifier is available
693 * @return #GNUNET_SYSERR to abort the iteration, #GNUNET_OK to continue
694 * (continue on call to "next", of course),
695 * #GNUNET_NO to delete the item and continue (if supported)
696 */
697static int
698repl_proc (void *cls,
699 const struct GNUNET_HashCode *key,
700 uint32_t size,
701 const void *data,
702 enum GNUNET_BLOCK_Type type,
703 uint32_t priority,
704 uint32_t anonymity,
705 uint32_t replication,
706 struct GNUNET_TIME_Absolute expiration,
707 uint64_t uid)
708{
709 struct ReplCtx *rc = cls;
710 struct Plugin *plugin = rc->plugin;
711 int ret;
712 int iret;
713
714 ret = rc->proc (rc->proc_cls,
715 key,
716 size,
717 data,
718 type,
719 priority,
720 anonymity,
721 replication,
722 expiration,
723 uid);
724 if (NULL != key)
725 {
726 struct GNUNET_MY_QueryParam params_proc[] = {
727 GNUNET_MY_query_param_uint64 (&uid),
728 GNUNET_MY_query_param_end
729 };
730
731 iret = GNUNET_MY_exec_prepared (plugin->mc,
732 plugin->dec_repl,
733 params_proc);
734 if (GNUNET_SYSERR == iret)
735 {
736 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
737 "Failed to reduce replication counter\n");
738 return GNUNET_SYSERR;
739 }
740 }
741 return ret;
742}
743
744
745/**
746 * Get a random item for replication. Returns a single, not expired,
747 * random item from those with the highest replication counters. The
748 * item's replication counter is decremented by one IF it was positive
749 * before. Call @a proc with all values ZERO or NULL if the datastore
750 * is empty.
751 *
752 * @param cls closure
753 * @param proc function to call the value (once only).
754 * @param proc_cls closure for @a proc
755 */
756static void
757mysql_plugin_get_replication (void *cls,
758 PluginDatumProcessor proc,
759 void *proc_cls)
760{
761 struct Plugin *plugin = cls;
762 uint64_t rvalue;
763 uint32_t repl;
764 struct ReplCtx rc;
765 struct GNUNET_MY_QueryParam params_get[] = {
766 GNUNET_MY_query_param_end
767 };
768 struct GNUNET_MY_ResultSpec results_get[] = {
769 GNUNET_MY_result_spec_uint32 (&repl),
770 GNUNET_MY_result_spec_end
771 };
772 struct GNUNET_MY_QueryParam params_select[] = {
773 GNUNET_MY_query_param_uint32 (&repl),
774 GNUNET_MY_query_param_uint64 (&rvalue),
775 GNUNET_MY_query_param_uint32 (&repl),
776 GNUNET_MY_query_param_uint64 (&rvalue),
777 GNUNET_MY_query_param_end
778 };
779
780 rc.plugin = plugin;
781 rc.proc = proc;
782 rc.proc_cls = proc_cls;
783
784 if (1 !=
785 GNUNET_MY_exec_prepared (plugin->mc,
786 plugin->max_repl,
787 params_get))
788 {
789 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
790 return;
791 }
792
793 if (GNUNET_OK !=
794 GNUNET_MY_extract_result (plugin->max_repl,
795 results_get))
796 {
797 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
798 return;
799 }
800 GNUNET_break (GNUNET_NO ==
801 GNUNET_MY_extract_result (plugin->max_repl,
802 NULL));
803 rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
804 UINT64_MAX);
805
806 execute_select (plugin,
807 plugin->select_replication,
808 &repl_proc,
809 &rc,
810 params_select);
811}
812
813
814/**
815 * Get all of the keys in the datastore.
816 *
817 * @param cls closure
818 * @param proc function to call on each key
819 * @param proc_cls closure for @a proc
820 */
821static void
822mysql_plugin_get_keys (void *cls,
823 PluginKeyProcessor proc,
824 void *proc_cls)
825{
826 struct Plugin *plugin = cls;
827 int ret;
828 MYSQL_STMT *statement;
829 unsigned int cnt;
830 struct GNUNET_HashCode key;
831 struct GNUNET_HashCode last;
832 struct GNUNET_MY_QueryParam params_select[] = {
833 GNUNET_MY_query_param_end
834 };
835 struct GNUNET_MY_ResultSpec results_select[] = {
836 GNUNET_MY_result_spec_auto_from_type (&key),
837 GNUNET_MY_result_spec_end
838 };
839
840 GNUNET_assert (NULL != proc);
841 statement = GNUNET_MYSQL_statement_get_stmt (plugin->get_all_keys);
842 if (GNUNET_OK !=
843 GNUNET_MY_exec_prepared (plugin->mc,
844 plugin->get_all_keys,
845 params_select))
846 {
847 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
848 _ ("`%s' for `%s' failed at %s:%d with error: %s\n"),
849 "mysql_stmt_execute",
850 GET_ALL_KEYS,
851 __FILE__,
852 __LINE__,
853 mysql_stmt_error (statement));
854 GNUNET_MYSQL_statements_invalidate (plugin->mc);
855 proc (proc_cls, NULL, 0);
856 return;
857 }
858 memset (&last, 0, sizeof(last)); /* make static analysis happy */
859 ret = GNUNET_YES;
860 cnt = 0;
861 while (ret == GNUNET_YES)
862 {
863 ret = GNUNET_MY_extract_result (plugin->get_all_keys,
864 results_select);
865 if (0 != GNUNET_memcmp (&last,
866 &key))
867 {
868 if (0 != cnt)
869 proc (proc_cls,
870 &last,
871 cnt);
872 cnt = 1;
873 last = key;
874 }
875 else
876 {
877 cnt++;
878 }
879 }
880 if (0 != cnt)
881 proc (proc_cls,
882 &last,
883 cnt);
884 /* finally, let app know we are done */
885 proc (proc_cls,
886 NULL,
887 0);
888 if (GNUNET_SYSERR == ret)
889 {
890 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
891 _ ("`%s' failed at %s:%d with error: %s\n"),
892 "mysql_stmt_fetch",
893 __FILE__,
894 __LINE__,
895 mysql_stmt_error (statement));
896 GNUNET_MYSQL_statements_invalidate (plugin->mc);
897 return;
898 }
899}
900
901
902/**
903 * Context for #expi_proc() function.
904 */
905struct ExpiCtx
906{
907 /**
908 * Plugin handle.
909 */
910 struct Plugin *plugin;
911
912 /**
913 * Function to call for the result (or the NULL).
914 */
915 PluginDatumProcessor proc;
916
917 /**
918 * Closure for @e proc.
919 */
920 void *proc_cls;
921};
922
923
924/**
925 * Wrapper for the processor for #mysql_plugin_get_expiration().
926 * If no expired value was found, we do a second query for
927 * low-priority content.
928 *
929 * @param cls closure
930 * @param key key for the content
931 * @param size number of bytes in data
932 * @param data content stored
933 * @param type type of the content
934 * @param priority priority of the content
935 * @param anonymity anonymity-level for the content
936 * @param replication replication-level for the content
937 * @param expiration expiration time for the content
938 * @param uid unique identifier for the datum;
939 * maybe 0 if no unique identifier is available
940 * @return #GNUNET_SYSERR to abort the iteration, #GNUNET_OK to continue
941 * (continue on call to "next", of course),
942 * #GNUNET_NO to delete the item and continue (if supported)
943 */
944static int
945expi_proc (void *cls,
946 const struct GNUNET_HashCode *key,
947 uint32_t size,
948 const void *data,
949 enum GNUNET_BLOCK_Type type,
950 uint32_t priority,
951 uint32_t anonymity,
952 uint32_t replication,
953 struct GNUNET_TIME_Absolute expiration,
954 uint64_t uid)
955{
956 struct ExpiCtx *rc = cls;
957 struct Plugin *plugin = rc->plugin;
958 struct GNUNET_MY_QueryParam params_select[] = {
959 GNUNET_MY_query_param_end
960 };
961
962 if (NULL == key)
963 {
964 execute_select (plugin,
965 plugin->select_priority,
966 rc->proc,
967 rc->proc_cls,
968 params_select);
969 return GNUNET_SYSERR;
970 }
971 return rc->proc (rc->proc_cls,
972 key,
973 size,
974 data,
975 type,
976 priority,
977 anonymity,
978 replication,
979 expiration,
980 uid);
981}
982
983
984/**
985 * Get a random item for expiration.
986 * Call @a proc with all values ZERO or NULL if the datastore is empty.
987 *
988 * @param cls closure
989 * @param proc function to call the value (once only).
990 * @param proc_cls closure for @a proc
991 */
992static void
993mysql_plugin_get_expiration (void *cls,
994 PluginDatumProcessor proc,
995 void *proc_cls)
996{
997 struct Plugin *plugin = cls;
998 struct GNUNET_TIME_Absolute now = { 0 };
999 struct GNUNET_MY_QueryParam params_select[] = {
1000 GNUNET_MY_query_param_absolute_time (&now),
1001 GNUNET_MY_query_param_end
1002 };
1003 struct ExpiCtx rc;
1004
1005 rc.plugin = plugin;
1006 rc.proc = proc;
1007 rc.proc_cls = proc_cls;
1008 now = GNUNET_TIME_absolute_get ();
1009 execute_select (plugin,
1010 plugin->select_expiration,
1011 expi_proc,
1012 &rc,
1013 params_select);
1014}
1015
1016
1017/**
1018 * Drop database.
1019 *
1020 * @param cls the `struct Plugin *`
1021 */
1022static void
1023mysql_plugin_drop (void *cls)
1024{
1025 struct Plugin *plugin = cls;
1026
1027 if (GNUNET_OK !=
1028 GNUNET_MYSQL_statement_run (plugin->mc,
1029 "DROP TABLE gn090"))
1030 return; /* error */
1031 plugin->env->duc (plugin->env->cls, 0);
1032}
1033
1034
1035/**
1036 * Remove a particular key in the datastore.
1037 *
1038 * @param cls closure
1039 * @param key key for the content
1040 * @param size number of bytes in data
1041 * @param data content stored
1042 * @param cont continuation called with success or failure status
1043 * @param cont_cls continuation closure for @a cont
1044 */
1045static void
1046mysql_plugin_remove_key (void *cls,
1047 const struct GNUNET_HashCode *key,
1048 uint32_t size,
1049 const void *data,
1050 PluginRemoveCont cont,
1051 void *cont_cls)
1052{
1053 struct Plugin *plugin = cls;
1054 struct GNUNET_MY_QueryParam params_delete[] = {
1055 GNUNET_MY_query_param_auto_from_type (key),
1056 GNUNET_MY_query_param_fixed_size (data, size),
1057 GNUNET_MY_query_param_end
1058 };
1059
1060 if (GNUNET_OK !=
1061 GNUNET_MY_exec_prepared (plugin->mc,
1062 plugin->delete_entry_by_hash_value,
1063 params_delete))
1064 {
1065 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1066 "Removing key `%s' from gn090 table failed\n",
1067 GNUNET_h2s (key));
1068 cont (cont_cls,
1069 key,
1070 size,
1071 GNUNET_SYSERR,
1072 _ ("MySQL statement run failure"));
1073 return;
1074 }
1075
1076 MYSQL_STMT *stmt = GNUNET_MYSQL_statement_get_stmt (
1077 plugin->delete_entry_by_hash_value);
1078 my_ulonglong rows = mysql_stmt_affected_rows (stmt);
1079
1080 if (0 == rows)
1081 {
1082 cont (cont_cls,
1083 key,
1084 size,
1085 GNUNET_NO,
1086 NULL);
1087 return;
1088 }
1089 plugin->env->duc (plugin->env->cls,
1090 -size);
1091 cont (cont_cls,
1092 key,
1093 size,
1094 GNUNET_OK,
1095 NULL);
1096}
1097
1098
1099/**
1100 * Entry point for the plugin.
1101 *
1102 * @param cls the `struct GNUNET_DATASTORE_PluginEnvironment *`
1103 * @return our `struct Plugin *`
1104 */
1105void *
1106libgnunet_plugin_datastore_mysql_init (void *cls)
1107{
1108 struct GNUNET_DATASTORE_PluginEnvironment *env = cls;
1109 struct GNUNET_DATASTORE_PluginFunctions *api;
1110 struct Plugin *plugin;
1111
1112 plugin = GNUNET_new (struct Plugin);
1113 plugin->env = env;
1114 plugin->mc = GNUNET_MYSQL_context_create (env->cfg,
1115 "datastore-mysql");
1116 if (NULL == plugin->mc)
1117 {
1118 GNUNET_free (plugin);
1119 return NULL;
1120 }
1121#define MRUNS(a) (GNUNET_OK != GNUNET_MYSQL_statement_run (plugin->mc, a))
1122#define PINIT(a, b) (NULL == (a = GNUNET_MYSQL_statement_prepare (plugin->mc, \
1123 b)))
1124 if (MRUNS
1125 ("CREATE TABLE IF NOT EXISTS gn090 ("
1126 " repl INT(11) UNSIGNED NOT NULL DEFAULT 0,"
1127 " type INT(11) UNSIGNED NOT NULL DEFAULT 0,"
1128 " prio INT(11) UNSIGNED NOT NULL DEFAULT 0,"
1129 " anonLevel INT(11) UNSIGNED NOT NULL DEFAULT 0,"
1130 " expire BIGINT UNSIGNED NOT NULL DEFAULT 0,"
1131 " rvalue BIGINT UNSIGNED NOT NULL,"
1132 " hash BINARY(64) NOT NULL DEFAULT '',"
1133 " vhash BINARY(64) NOT NULL DEFAULT '',"
1134 " value BLOB NOT NULL DEFAULT '',"
1135 " uid BIGINT NOT NULL AUTO_INCREMENT,"
1136 " PRIMARY KEY (uid),"
1137 " INDEX idx_hash_type_uid (hash(64),type,rvalue),"
1138 " INDEX idx_prio (prio),"
1139 " INDEX idx_repl_rvalue (repl,rvalue),"
1140 " INDEX idx_expire (expire),"
1141 " INDEX idx_anonLevel_type_rvalue (anonLevel,type,rvalue)"
1142 ") ENGINE=InnoDB") || MRUNS ("SET AUTOCOMMIT = 1") ||
1143 PINIT (plugin->insert_entry, INSERT_ENTRY) ||
1144 PINIT (plugin->delete_entry_by_uid, DELETE_ENTRY_BY_UID) ||
1145 PINIT (plugin->delete_entry_by_hash_value, DELETE_ENTRY_BY_HASH_VALUE) ||
1146 PINIT (plugin->select_entry, SELECT_ENTRY) ||
1147 PINIT (plugin->select_entry_by_hash, SELECT_ENTRY_BY_HASH) ||
1148 PINIT (plugin->select_entry_by_hash_and_type,
1149 SELECT_ENTRY_BY_HASH_AND_TYPE) ||
1150 PINIT (plugin->get_size, SELECT_SIZE) ||
1151 PINIT (plugin->update_entry, UPDATE_ENTRY) ||
1152 PINIT (plugin->dec_repl, DEC_REPL) ||
1153 PINIT (plugin->zero_iter, SELECT_IT_NON_ANONYMOUS) ||
1154 PINIT (plugin->select_expiration, SELECT_IT_EXPIRATION) ||
1155 PINIT (plugin->select_priority, SELECT_IT_PRIORITY) ||
1156 PINIT (plugin->max_repl, SELECT_MAX_REPL) ||
1157 PINIT (plugin->get_all_keys, GET_ALL_KEYS) ||
1158 PINIT (plugin->select_replication, SELECT_IT_REPLICATION) ||
1159 false)
1160 {
1161 GNUNET_MYSQL_context_destroy (plugin->mc);
1162 GNUNET_free (plugin);
1163 return NULL;
1164 }
1165#undef PINIT
1166#undef MRUNS
1167
1168 api = GNUNET_new (struct GNUNET_DATASTORE_PluginFunctions);
1169 api->cls = plugin;
1170 api->estimate_size = &mysql_plugin_estimate_size;
1171 api->put = &mysql_plugin_put;
1172 api->get_key = &mysql_plugin_get_key;
1173 api->get_replication = &mysql_plugin_get_replication;
1174 api->get_expiration = &mysql_plugin_get_expiration;
1175 api->get_zero_anonymity = &mysql_plugin_get_zero_anonymity;
1176 api->get_keys = &mysql_plugin_get_keys;
1177 api->drop = &mysql_plugin_drop;
1178 api->remove_key = &mysql_plugin_remove_key;
1179 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "mysql",
1180 _ ("Mysql database running\n"));
1181 return api;
1182}
1183
1184
1185/**
1186 * Exit point from the plugin.
1187 *
1188 * @param cls our `struct Plugin *`
1189 * @return always NULL
1190 */
1191void *
1192libgnunet_plugin_datastore_mysql_done (void *cls)
1193{
1194 struct GNUNET_DATASTORE_PluginFunctions *api = cls;
1195 struct Plugin *plugin = api->cls;
1196
1197 GNUNET_MYSQL_context_destroy (plugin->mc);
1198 GNUNET_free (plugin);
1199 GNUNET_free (api);
1200 return NULL;
1201}
1202
1203
1204/* end of plugin_datastore_mysql.c */
diff --git a/src/datastore/test_datastore_api_data_mysql.conf b/src/datastore/test_datastore_api_data_mysql.conf
deleted file mode 100644
index c0052c5ea..000000000
--- a/src/datastore/test_datastore_api_data_mysql.conf
+++ /dev/null
@@ -1,10 +0,0 @@
1@INLINE@ test_defaults.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-datastore-mysql/
4
5[datastore]
6QUOTA = 10 MB
7DATABASE = mysql
8
9[datastore-mysql]
10DATABASE = gnunetcheck
diff --git a/src/datastore/test_plugin_datastore_data_mysql.conf b/src/datastore/test_plugin_datastore_data_mysql.conf
deleted file mode 100644
index 07d3ec58e..000000000
--- a/src/datastore/test_plugin_datastore_data_mysql.conf
+++ /dev/null
@@ -1,9 +0,0 @@
1@INLINE@ test_defaults.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-datastore-plugin-mysql/
4
5[datastore]
6DATABASE = mysql
7
8[datastore-mysql]
9DATABASE = gnunetcheck
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
index 8519883c9..ef18ab01b 100644
--- a/src/include/Makefile.am
+++ b/src/include/Makefile.am
@@ -75,9 +75,6 @@ gnunetinclude_HEADERS = \
75 gnunet_microphone_lib.h \ 75 gnunet_microphone_lib.h \
76 gnunet_mst_lib.h \ 76 gnunet_mst_lib.h \
77 gnunet_mq_lib.h \ 77 gnunet_mq_lib.h \
78 gnunet_my_lib.h \
79 gnunet_mysql_compat.h \
80 gnunet_mysql_lib.h \
81 gnunet_namecache_plugin.h \ 78 gnunet_namecache_plugin.h \
82 gnunet_namecache_service.h \ 79 gnunet_namecache_service.h \
83 gnunet_namestore_plugin.h \ 80 gnunet_namestore_plugin.h \
diff --git a/src/include/gnunet_my_lib.h b/src/include/gnunet_my_lib.h
deleted file mode 100644
index 283b2f7e6..000000000
--- a/src/include/gnunet_my_lib.h
+++ /dev/null
@@ -1,511 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2016 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @addtogroup lib_extra
22 * @{
23 *
24 * @author Christian Grothoff
25 * @author Christophe Genevey
26 * @author Martin Schanzenbach
27 *
28 * @file
29 * Helper library to access a MySQL database
30 *
31 * @defgroup mysql MySQL library
32 * Helper library to access a MySQL database.
33 * @{
34 */
35#ifndef GNUNET_MY_LIB_H
36#define GNUNET_MY_LIB_H
37
38
39#include "gnunet_util_lib.h"
40#include "gnunet_mysql_lib.h"
41#include <mysql/mysql.h>
42
43#ifndef MYSQL_BOOL
44#error "You need to define MYSQL_BOOL. See (or include) gnunet_mysql_compat.h"
45#endif
46
47#ifdef __cplusplus
48extern "C"
49{
50#if 0 /* keep Emacsens' auto-indent happy */
51}
52#endif
53#endif
54
55
56/**
57 * Information we pass to #GNUNET_MY_exec_prepared() to
58 * initialize the arguments of the prepared statement.
59 */
60struct GNUNET_MY_QueryParam;
61
62
63/**
64 * Function called to convert input argument into SQL parameters.
65 *
66 * @param cls closure
67 * @param pq data about the query
68 * @param qbind array of parameters to initialize
69 * @return -1 on error
70 */
71typedef int
72(*GNUNET_MY_QueryConverter)(void *cls,
73 const struct GNUNET_MY_QueryParam *qp,
74 MYSQL_BIND *qbind);
75
76
77/**
78 * Function called to cleanup result data.
79 *
80 * @param cls closure
81 * @param rs spec to clean up
82 */
83typedef void
84(*GNUNET_MY_QueryCleanup)(void *cls,
85 MYSQL_BIND *qbind);
86/**
87 * Information we pass to #GNUNET_MY_exec_prepared() to
88 * initialize the arguments of the prepared statement.
89 */
90
91
92struct GNUNET_MY_QueryParam
93{
94 /**
95 * Function to call for the type conversion.
96 */
97 GNUNET_MY_QueryConverter conv;
98
99 /**
100 * Function to call for cleaning up the query. Can be NULL.
101 */
102 GNUNET_MY_QueryCleanup cleaner;
103
104 /**
105 * Closure for @e conv.
106 */
107 void *conv_cls;
108
109 /**
110 * Number of arguments the @a conv converter expects to initialize.
111 */
112 unsigned int num_params;
113
114 /**
115 * Information to pass to @e conv.
116 */
117 const void *data;
118
119 /**
120 * Information to pass to @e conv. Size of @a data.
121 */
122 unsigned long data_len;
123};
124
125/**
126 * End of query parameter specification.
127 *
128 * @return array last entry for the result specification to use
129 */
130#define GNUNET_MY_query_param_end { NULL, NULL, NULL, 0, NULL, 0 }
131
132
133/**
134 * Generate query parameter for a buffer @a ptr of
135 * @a ptr_size bytes.FG
136 *
137 * @param ptr pointer to the query parameter to pass
138 * @param ptr_size number of bytes in @a ptr
139 */
140struct GNUNET_MY_QueryParam
141GNUNET_MY_query_param_fixed_size (const void *ptr,
142 size_t ptr_size);
143
144
145/**
146 * Run a prepared SELECT statement.
147 *
148 * @param mc mysql context
149 * @param sh handle to SELECT statement
150 * @param params parameters to the statement
151 * @return TBD
152 */
153int
154GNUNET_MY_exec_prepared (struct GNUNET_MYSQL_Context *mc,
155 struct GNUNET_MYSQL_StatementHandle *sh,
156 struct GNUNET_MY_QueryParam *params);
157
158
159/**
160 * Information we pass to #GNUNET_MY_extract_result() to
161 * initialize the arguments of the prepared statement.
162 */
163struct GNUNET_MY_ResultParam;
164
165/**
166 * Information we pass to #GNUNET_MY_extract_result() to
167 * initialize the arguments of the prepared statement.
168 */
169struct GNUNET_MY_ResultSpec;
170
171/**
172 * Function called to convert input argument into SQL parameters.
173 *
174 * @param cls closure
175 * @param[in,out] rs
176 * @param stmt the mysql statement that is being run
177 * @param column the column that is being processed
178 * @param[out] results
179 * @return -1 on error
180 */
181typedef int
182(*GNUNET_MY_ResultConverter)(void *cls,
183 struct GNUNET_MY_ResultSpec *rs,
184 MYSQL_STMT *stmt,
185 unsigned int column,
186 MYSQL_BIND *results);
187
188/**
189 * Function called to cleanup result data.
190 *
191 * @param cls closure
192 * @param rs spec to clean up
193 */
194typedef void
195(*GNUNET_MY_ResultCleanup)(void *cls,
196 struct GNUNET_MY_ResultSpec *rs);
197
198
199/**
200 * Information we pass to #GNUNET_MY_extract_result() to
201 * initialize the arguments of the prepared statement.
202 */
203struct GNUNET_MY_ResultSpec
204{
205 /**
206 * Function to call to initialize the MYSQL_BIND array.
207 */
208 GNUNET_MY_ResultConverter pre_conv;
209
210 /**
211 * Function to call for converting the result. Can be NULL.
212 */
213 GNUNET_MY_ResultConverter post_conv;
214
215 /**
216 * Function to call for cleaning up the result. Can be NULL.
217 */
218 GNUNET_MY_ResultCleanup cleaner;
219
220 /**
221 * Closure for @e conv.
222 */
223 void *conv_cls;
224
225 /**
226 * Destination for the data.
227 */
228 void *dst;
229
230 /**
231 * Allowed size for the data, 0 for variable-size
232 * (in this case, the type of @e dst is a `void **`
233 * and we need to allocate a buffer of the right size).
234 */
235 size_t dst_size;
236
237 /**
238 * Where to store actual size of the result.
239 */
240 size_t *result_size;
241
242 /**
243 * How many fields does this result specification occupy
244 * in the result returned by MySQL.
245 */
246 unsigned int num_fields;
247
248 /**
249 * Location where we temporarily store the output buffer
250 * length from MySQL. Internal to libgnunetmy.
251 */
252 unsigned long mysql_bind_output_length;
253
254 /**
255 * Memory for MySQL to notify us about NULL values.
256 */
257 MYSQL_BOOL is_null;
258};
259
260
261/**
262 * End of result speceter specification.
263 *
264 * @return array last entry for the result specification to use
265 */
266#define GNUNET_MY_result_spec_end { NULL, NULL, NULL, 0, NULL, 0, 0 }
267
268
269/**
270 * Obtain fixed size result of @a ptr_size bytes from
271 * MySQL, store in already allocated buffer at @a ptr.
272 *
273 * @spec ptr where to write the result
274 * @param ptr_size number of bytes available at @a ptr
275 */
276struct GNUNET_MY_ResultSpec
277GNUNET_MY_result_spec_fixed_size (void *ptr,
278 size_t ptr_size);
279
280/**
281 * Generate query parameter for a string
282 *
283 * @param ptr pointer to the string query parameter to pass
284 */
285struct GNUNET_MY_QueryParam
286GNUNET_MY_query_param_string (const char *ptr);
287
288/**
289 * Generate fixed-size query parameter with size determined
290 * by variable type.
291 *
292 * @param x pointer to the query parameter to pass
293 */
294#define GNUNET_MY_query_param_auto_from_type( \
295 x) GNUNET_MY_query_param_fixed_size ((x), sizeof(*(x)))
296
297/**
298 * Generate query parameter for an RSA public key. The
299 * database must contain a BLOB type in the respective position.
300 *
301 * @param x the query parameter to pass
302 * @return array entry for the query parameters to use
303 */
304struct GNUNET_MY_QueryParam
305GNUNET_MY_query_param_rsa_public_key (const struct
306 GNUNET_CRYPTO_RsaPublicKey *x);
307
308/**
309 * Generate query parameter for an RSA signature. The
310 * database must contain a BLOB type in the respective position
311 *
312 *@param x the query parameter to pass
313 *@return array entry for the query parameters to use
314 */
315struct GNUNET_MY_QueryParam
316GNUNET_MY_query_param_rsa_signature (const struct
317 GNUNET_CRYPTO_RsaSignature *x);
318
319/**
320 * Generate query parameter for an absolute time value.
321 * The database must store a 64-bit integer.
322 *
323 *@param x pointer to the query parameter to pass
324 *@return array entry for the query parameters to use
325 */
326struct GNUNET_MY_QueryParam
327GNUNET_MY_query_param_absolute_time (const struct GNUNET_TIME_Absolute *x);
328
329
330/**
331 * Generate query parameter for an absolute time value.
332 * The database must store a 64-bit integer.
333 *
334 *@param x pointer to the query parameter to pass
335 */
336struct GNUNET_MY_QueryParam
337GNUNET_MY_query_param_absolute_time_nbo (const struct
338 GNUNET_TIME_AbsoluteNBO *x);
339
340/**
341 * Generate query parameter for an uint16_t in host byte order.
342 *
343 * @param x pointer to the query parameter to pass
344 */
345struct GNUNET_MY_QueryParam
346GNUNET_MY_query_param_uint16 (const uint16_t *x);
347
348/**
349 * Generate query parameter for an uint32_t in host byte order
350 *
351 * @param x pointer to the query parameter to pass
352 */
353struct GNUNET_MY_QueryParam
354GNUNET_MY_query_param_uint32 (const uint32_t *x);
355
356/**
357 * Generate query parameter for an uint64_t in host byte order
358 *
359 * @param x pointer to the query parameter to pass
360 */
361struct GNUNET_MY_QueryParam
362GNUNET_MY_query_param_uint64 (const uint64_t *x);
363
364/**
365 * We expect a fixed-size result, with size determined by the type of `* dst`
366 *
367 * @spec name name of the field in the table
368 * @spec dst point to where to store the result, type fits expected result size
369 * @return array entry for the result specification to use
370 */
371#define GNUNET_MY_result_spec_auto_from_type( \
372 dst) GNUNET_MY_result_spec_fixed_size ((dst), sizeof(*(dst)))
373
374
375/**
376 * Variable-size result expected
377 *
378 * @param[out] dst where to store the result, allocated
379 * @param[out] ptr_size where to store the size of @a dst
380 * @return array entry for the result specification to use
381 */
382struct GNUNET_MY_ResultSpec
383GNUNET_MY_result_spec_variable_size (void **dst,
384 size_t *ptr_size);
385
386/**
387 * RSA public key expected
388 *
389 * @param name name of the field in the table
390 * @param[out] rsa where to store the result
391 * @return array entry for the result specification to use
392 */
393struct GNUNET_MY_ResultSpec
394GNUNET_MY_result_spec_rsa_public_key (struct GNUNET_CRYPTO_RsaPublicKey **rsa);
395
396
397/**
398 * RSA signature expected.
399 *
400 * @param[out] sig where to store the result;
401 * @return array entry for the result specification to use
402 */
403struct GNUNET_MY_ResultSpec
404GNUNET_MY_result_spec_rsa_signature (struct GNUNET_CRYPTO_RsaSignature **sig);
405
406/**
407 * 0- terminated string exprected.
408 *
409 * @param[out] dst where to store the result, allocated
410 * @return array entry for the result specification to use
411 */
412struct GNUNET_MY_ResultSpec
413GNUNET_MY_result_spec_string (char **dst);
414
415/**
416 * Absolute time expected
417 *
418 * @param name name of the field in the table
419 * @param[out] at where to store the result
420 * @return array entry for the result specification to use
421 */
422struct GNUNET_MY_ResultSpec
423GNUNET_MY_result_spec_absolute_time (struct GNUNET_TIME_Absolute *at);
424
425/**
426 * Absolute time in network byte order expected
427 *
428 * @param[out] at where to store the result
429 * @return array entry for the result specification to use
430 */
431struct GNUNET_MY_ResultSpec
432GNUNET_MY_result_spec_absolute_time_nbo (struct GNUNET_TIME_AbsoluteNBO *at);
433
434/**
435 * uint16_t expected
436 *
437 * @param[out] u16 where to store the result
438 * @return array entry for the result specification to use
439 */
440struct GNUNET_MY_ResultSpec
441GNUNET_MY_result_spec_uint16 (uint16_t *u16);
442
443/**
444 * uint32_t expected
445 *
446 * @param[out] u32 where to store the result
447 * @return array entry for the result specification to use
448 */
449struct GNUNET_MY_ResultSpec
450GNUNET_MY_result_spec_uint32 (uint32_t *u32);
451
452/**
453 * uint64_t expected.
454 *
455 * @param[out] u64 where to store the result
456 * @return array entry for the result specification to use
457 */
458struct GNUNET_MY_ResultSpec
459GNUNET_MY_result_spec_uint64 (uint64_t *u64);
460
461
462/**
463 * Extract results from a query result according to the given
464 * specification. Always fetches the next row.
465 *
466 * @param sh statement that returned results
467 * @param rs specification to extract for
468 * @return
469 * #GNUNET_YES if all results could be extracted
470 * #GNUNET_NO if there is no more data in the result set
471 * #GNUNET_SYSERR if a result was invalid
472 */
473int
474GNUNET_MY_extract_result (struct GNUNET_MYSQL_StatementHandle *sh,
475 struct GNUNET_MY_ResultSpec *specs);
476
477
478/**
479 * Free all memory that was allocated in @a qp during
480 * #GNUNET_MY_exect_prepared().
481 *
482 * @param qp query specification to clean up
483 * @param qbind mysql query
484 */
485void
486GNUNET_MY_cleanup_query (struct GNUNET_MY_QueryParam *qp,
487 MYSQL_BIND *qbind);
488
489
490/**
491 * Free all memory that was allocated in @a rs during
492 * #GNUNET_MY_extract_result().
493 *
494 * @param rs reult specification to clean up
495 */
496void
497GNUNET_MY_cleanup_result (struct GNUNET_MY_ResultSpec *rs);
498
499
500#if 0 /* keep Emacsens' auto-indent happy */
501{
502#endif
503#ifdef __cplusplus
504}
505#endif
506
507#endif
508
509/** @} */ /* end of group */
510
511/** @} */ /* end of group addition to lib_extra */
diff --git a/src/include/gnunet_mysql_compat.h.in b/src/include/gnunet_mysql_compat.h.in
deleted file mode 100644
index 6218386aa..000000000
--- a/src/include/gnunet_mysql_compat.h.in
+++ /dev/null
@@ -1,57 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2022 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Martin Schanzenbach
22 *
23 * @file
24 * MySQL/MariaDB compatibility insanity helper header
25 * Note: gnunet_mysql_compat.h is AUTOGENERATED from gnunet_mysql_compat.h.in
26 * Please do not modify or commit gnunet_mysql_compat.h
27 *
28 * @defgroup mysql MySQL library
29 * Helper library to access a MySQL database.
30 * @{
31 */
32#ifndef GNUNET_MYSQL_COMPAT_H
33#define GNUNET_MYSQL_COMPAT_H
34
35
36#include <mysql/mysql.h>
37
38#ifdef __cplusplus
39extern "C"
40{
41#if 0 /* keep Emacsens' auto-indent happy */
42}
43#endif
44#endif
45
46#define MYSQL_BOOL @mysql_bool@
47
48#if 0 /* keep Emacsens' auto-indent happy */
49{
50#endif
51#ifdef __cplusplus
52}
53#endif
54
55#endif
56
57/** @} */ /* end of group */
diff --git a/src/include/gnunet_mysql_lib.h b/src/include/gnunet_mysql_lib.h
deleted file mode 100644
index 52be3ff11..000000000
--- a/src/include/gnunet_mysql_lib.h
+++ /dev/null
@@ -1,151 +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 it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Christian Grothoff
22 *
23 * @file
24 * Helper library to access a MySQL database
25 *
26 * @defgroup mysql MySQL library
27 * Helper library to access a MySQL database.
28 * @{
29 */
30#ifndef GNUNET_MYSQL_LIB_H
31#define GNUNET_MYSQL_LIB_H
32
33
34#include "gnunet_util_lib.h"
35#include <mysql/mysql.h>
36
37#ifdef __cplusplus
38extern "C"
39{
40#if 0 /* keep Emacsens' auto-indent happy */
41}
42#endif
43#endif
44
45/**
46 * Mysql context.
47 */
48struct GNUNET_MYSQL_Context;
49
50
51/**
52 * Handle for a prepared statement.
53 */
54struct GNUNET_MYSQL_StatementHandle;
55
56
57/**
58 * Type of a callback that will be called for each
59 * data set returned from MySQL.
60 *
61 * @param cls user-defined argument
62 * @param num_values number of elements in values
63 * @param values values returned by MySQL
64 * @return #GNUNET_OK to continue iterating, #GNUNET_SYSERR to abort
65 */
66typedef int
67(*GNUNET_MYSQL_DataProcessor) (void *cls,
68 unsigned int num_values,
69 MYSQL_BIND *values);
70
71
72/**
73 * Create a mysql context.
74 *
75 * @param cfg configuration
76 * @param section configuration section to use to get MySQL configuration options
77 * @return the mysql context
78 */
79struct GNUNET_MYSQL_Context *
80GNUNET_MYSQL_context_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
81 const char *section);
82
83
84/**
85 * Destroy a mysql context. Also frees all associated prepared statements.
86 *
87 * @param mc context to destroy
88 */
89void
90GNUNET_MYSQL_context_destroy (struct GNUNET_MYSQL_Context *mc);
91
92
93/**
94 * Close database connection and all prepared statements (we got a DB
95 * error). The connection will automatically be re-opened and
96 * statements will be re-prepared if they are needed again later.
97 *
98 * @param mc mysql context
99 */
100void
101GNUNET_MYSQL_statements_invalidate (struct GNUNET_MYSQL_Context *mc);
102
103
104/**
105 * Get internal handle for a prepared statement. This function should rarely
106 * be used, and if, with caution! On failures during the interaction with
107 * the handle, you must call #GNUNET_MYSQL_statements_invalidate()!
108 *
109 * @param sh prepared statement to introspect
110 * @return MySQL statement handle, NULL on error
111 */
112MYSQL_STMT *
113GNUNET_MYSQL_statement_get_stmt (struct GNUNET_MYSQL_StatementHandle *sh);
114
115
116/**
117 * Prepare a statement. Prepared statements are automatically discarded
118 * when the MySQL context is destroyed.
119 *
120 * @param mc mysql context
121 * @param query query text
122 * @return prepared statement, NULL on error
123 */
124struct GNUNET_MYSQL_StatementHandle *
125GNUNET_MYSQL_statement_prepare (struct GNUNET_MYSQL_Context *mc,
126 const char *query);
127
128
129/**
130 * Run a SQL statement.
131 *
132 * @param mc mysql context
133 * @param sql SQL statement to run
134 * @return #GNUNET_OK on success
135 * #GNUNET_SYSERR if there was a problem
136 */
137int
138GNUNET_MYSQL_statement_run (struct GNUNET_MYSQL_Context *mc,
139 const char *sql);
140
141
142#if 0 /* keep Emacsens' auto-indent happy */
143{
144#endif
145#ifdef __cplusplus
146}
147#endif
148
149#endif
150
151/** @} */ /* end of group */
diff --git a/src/my/.gitignore b/src/my/.gitignore
deleted file mode 100644
index 3338ba2ea..000000000
--- a/src/my/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
1test_my
diff --git a/src/my/Makefile.am b/src/my/Makefile.am
deleted file mode 100644
index 51e20e6bf..000000000
--- a/src/my/Makefile.am
+++ /dev/null
@@ -1,41 +0,0 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4if USE_COVERAGE
5 AM_CFLAGS = --coverage
6endif
7
8if HAVE_MYSQL
9lib_LTLIBRARIES = libgnunetmy.la
10endif
11
12libgnunetmy_la_SOURCES = \
13 my.c \
14 my_query_helper.c \
15 my_result_helper.c
16
17libgnunetmy_la_LIBADD = $(MYSQL_LDFLAGS) -lmysqlclient \
18 $(top_builddir)/src/mysql/libgnunetmysql.la \
19 $(top_builddir)/src/util/libgnunetutil.la
20libgnunetmy_la_LDFLAGS = \
21 $(GN_LIB_LDFLAGS) \
22 -version-info 0:0:0
23
24if ENABLE_TEST_RUN
25TESTS = \
26 test_my
27endif
28
29EXTRA_DIST = \
30 test_my.conf
31
32check_PROGRAMS= \
33 test_my
34
35test_my_SOURCES = \
36 test_my.c
37test_my_LDADD = \
38 libgnunetmy.la \
39 $(top_builddir)/src/mysql/libgnunetmysql.la \
40 $(top_builddir)/src/util/libgnunetutil.la \
41 -lmysqlclient $(XLIB)
diff --git a/src/my/meson.build b/src/my/meson.build
deleted file mode 100644
index 877e80560..000000000
--- a/src/my/meson.build
+++ /dev/null
@@ -1,15 +0,0 @@
1libgnunetmy_src = ['my.c',
2 'my_query_helper.c',
3 'my_result_helper.c']
4
5if get_option('monolith') == false
6 libgnunetmy = library('gnunetmy',
7 libgnunetmy_src,
8 dependencies: [libgnunetutil_dep, libgnunetmysq_dep, my_dep],
9 include_directories: [incdir, configuration_inc])
10 libgnunetmy_dep = declare_dependency(link_with : libgnunetmy)
11else
12 foreach p : libgnunetmy_src
13 gnunet_src += 'my/' + p
14 endforeach
15endif
diff --git a/src/my/my.c b/src/my/my.c
deleted file mode 100644
index b667af4f9..000000000
--- a/src/my/my.c
+++ /dev/null
@@ -1,270 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2016, 2018 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file my/my.c
22 * @brief library to help with access to a MySQL database
23 * @author Christophe Genevey
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include <mysql/mysql.h>
28#include "gnunet_mysql_compat.h"
29#include "gnunet_my_lib.h"
30
31
32/**
33 * Run a prepared SELECT statement.
34 *
35 * @param mc mysql context
36 * @param sh handle to SELECT statement
37 * @param params parameters to the statement
38 * @return
39 #GNUNET_YES if we can prepare all statement
40 #GNUNET_SYSERR if we can't prepare all statement
41 */
42int
43GNUNET_MY_exec_prepared (struct GNUNET_MYSQL_Context *mc,
44 struct GNUNET_MYSQL_StatementHandle *sh,
45 struct GNUNET_MY_QueryParam *params)
46{
47 const struct GNUNET_MY_QueryParam *p;
48 unsigned int num;
49 MYSQL_STMT *stmt;
50
51 num = 0;
52 for (unsigned int i = 0; NULL != params[i].conv; i++)
53 num += params[i].num_params;
54 {
55 MYSQL_BIND qbind[num];
56 unsigned int off;
57
58 memset (qbind,
59 0,
60 sizeof(qbind));
61 off = 0;
62 for (unsigned int i = 0; NULL != (p = &params[i])->conv; i++)
63 {
64 if (GNUNET_OK !=
65 p->conv (p->conv_cls,
66 p,
67 &qbind[off]))
68 {
69 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
70 "Conversion for MySQL query failed at offset %u\n",
71 i);
72 return GNUNET_SYSERR;
73 }
74 off += p->num_params;
75 }
76 stmt = GNUNET_MYSQL_statement_get_stmt (sh);
77 if (mysql_stmt_bind_param (stmt,
78 qbind))
79 {
80 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
81 "my",
82 _ ("`%s' failed at %s:%d with error: %s\n"),
83 "mysql_stmt_bind_param",
84 __FILE__, __LINE__,
85 mysql_stmt_error (stmt));
86 GNUNET_MYSQL_statements_invalidate (mc);
87 return GNUNET_SYSERR;
88 }
89
90 if (mysql_stmt_execute (stmt))
91 {
92 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
93 "my",
94 _ ("`%s' failed at %s:%d with error: %s\n"),
95 "mysql_stmt_execute", __FILE__, __LINE__,
96 mysql_stmt_error (stmt));
97 GNUNET_MYSQL_statements_invalidate (mc);
98 return GNUNET_SYSERR;
99 }
100 GNUNET_MY_cleanup_query (params,
101 qbind);
102 }
103 return GNUNET_OK;
104}
105
106
107/**
108 * Free all memory that was allocated in @a qp during
109 * #GNUNET_MY_exec_prepared().
110 *
111 * @param qp query specification to clean up
112 * @param qbind array of parameter to clean up
113 */
114void
115GNUNET_MY_cleanup_query (struct GNUNET_MY_QueryParam *qp,
116 MYSQL_BIND *qbind)
117{
118 for (unsigned int i = 0; NULL != qp[i].conv; i++)
119 if (NULL != qp[i].cleaner)
120 qp[i].cleaner (qp[i].conv_cls,
121 &qbind[i]);
122}
123
124
125/**
126 * Extract results from a query result according to the given
127 * specification. Always fetches the next row.
128 *
129 * @param sh statement that returned results
130 * @param rs specification to extract for
131 * @return
132 * #GNUNET_YES if all results could be extracted
133 * #GNUNET_NO if there is no more data in the result set
134 * #GNUNET_SYSERR if a result was invalid
135 */
136int
137GNUNET_MY_extract_result (struct GNUNET_MYSQL_StatementHandle *sh,
138 struct GNUNET_MY_ResultSpec *rs)
139{
140 unsigned int num_fields;
141 int ret;
142 MYSQL_STMT *stmt;
143
144 stmt = GNUNET_MYSQL_statement_get_stmt (sh);
145 if (NULL == stmt)
146 {
147 GNUNET_break (0);
148 return GNUNET_SYSERR;
149 }
150 if (NULL == rs)
151 {
152 mysql_stmt_free_result (stmt);
153 return GNUNET_NO;
154 }
155
156 num_fields = 0;
157 for (unsigned int i = 0; NULL != rs[i].pre_conv; i++)
158 num_fields += rs[i].num_fields;
159
160 if (mysql_stmt_field_count (stmt) != num_fields)
161 {
162 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
163 "Number of fields mismatch between SQL result and result specification\n");
164 return GNUNET_SYSERR;
165 }
166
167 {
168 MYSQL_BIND result[num_fields];
169 unsigned int field_off;
170
171 memset (result, 0, sizeof(MYSQL_BIND) * num_fields);
172 field_off = 0;
173 for (unsigned int i = 0; NULL != rs[i].pre_conv; i++)
174 {
175 struct GNUNET_MY_ResultSpec *rp = &rs[i];
176
177 if (GNUNET_OK !=
178 rp->pre_conv (rp->conv_cls,
179 rp,
180 stmt,
181 field_off,
182 &result[field_off]))
183
184 {
185 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
186 "Pre-conversion for MySQL result failed at offset %u\n",
187 i);
188 return GNUNET_SYSERR;
189 }
190 field_off += rp->num_fields;
191 }
192
193 if (mysql_stmt_bind_result (stmt, result))
194 {
195 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
196 "my",
197 _ ("%s failed at %s:%d with error: %s\n"),
198 "mysql_stmt_bind_result",
199 __FILE__, __LINE__,
200 mysql_stmt_error (stmt));
201 return GNUNET_SYSERR;
202 }
203#if TEST_OPTIMIZATION
204 (void) mysql_stmt_store_result (stmt);
205#endif
206 ret = mysql_stmt_fetch (stmt);
207 if (MYSQL_NO_DATA == ret)
208 {
209 mysql_stmt_free_result (stmt);
210 return GNUNET_NO;
211 }
212 if (1 == ret)
213 {
214 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
215 "my",
216 _ ("%s failed at %s:%d with error: %s\n"),
217 "mysql_stmt_fetch",
218 __FILE__, __LINE__,
219 mysql_stmt_error (stmt));
220 GNUNET_MY_cleanup_result (rs);
221 mysql_stmt_free_result (stmt);
222 return GNUNET_SYSERR;
223 }
224 field_off = 0;
225 for (unsigned int i = 0; NULL != rs[i].post_conv; i++)
226 {
227 struct GNUNET_MY_ResultSpec *rp = &rs[i];
228
229 if (NULL != rp->post_conv)
230 if (GNUNET_OK !=
231 rp->post_conv (rp->conv_cls,
232 rp,
233 stmt,
234 field_off,
235 &result[field_off]))
236 {
237 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
238 "Post-conversion for MySQL result failed at offset %u\n",
239 i);
240 mysql_stmt_free_result (stmt);
241 for (unsigned int j = 0; j < i; j++)
242 if (NULL != rs[j].cleaner)
243 rs[j].cleaner (rs[j].conv_cls,
244 rs[j].dst);
245 return GNUNET_SYSERR;
246 }
247 field_off += rp->num_fields;
248 }
249 }
250 return GNUNET_OK;
251}
252
253
254/**
255 * Free all memory that was allocated in @a rs during
256 * #GNUNET_MY_extract_result().
257 *
258 * @param rs result specification to clean up
259 */
260void
261GNUNET_MY_cleanup_result (struct GNUNET_MY_ResultSpec *rs)
262{
263 for (unsigned int i = 0; NULL != rs[i].post_conv; i++)
264 if (NULL != rs[i].cleaner)
265 rs[i].cleaner (rs[i].conv_cls,
266 &rs[i]);
267}
268
269
270/* end of my.c */
diff --git a/src/my/my_query_helper.c b/src/my/my_query_helper.c
deleted file mode 100644
index c12970876..000000000
--- a/src/my/my_query_helper.c
+++ /dev/null
@@ -1,401 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2016 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file my/my_query_helper.c
22 * @brief library to help with access to a MySQL database
23 * @author Christian Grothoff
24 * @author Christophe Genevey
25 */
26#include "platform.h"
27#include <mysql/mysql.h>
28#include "gnunet_mysql_compat.h"
29#include "gnunet_my_lib.h"
30
31
32/**
33 * Function called to clean up memory allocated
34 * by a #GNUNET_MY_QueryConverter.
35 *
36 * @param cls closure
37 * @param qbind array of parameter to clean up
38 */
39static void
40my_clean_query (void *cls,
41 MYSQL_BIND *qbind)
42{
43 (void) cls;
44 GNUNET_free (qbind[0].buffer);
45}
46
47
48/**
49 * Function called to convert input argument into SQL parameters.
50 *
51 * @param cls closure
52 * @param qp data about the query
53 * @param qbind array of parameters to initialize
54 * @return -1 on error
55 */
56static int
57my_conv_fixed_size (void *cls,
58 const struct GNUNET_MY_QueryParam *qp,
59 MYSQL_BIND *qbind)
60{
61 (void) cls;
62 GNUNET_assert (1 == qp->num_params);
63 qbind->buffer = (void *) qp->data;
64 qbind->buffer_length = qp->data_len;
65 qbind->buffer_type = MYSQL_TYPE_BLOB;
66
67 return 1;
68}
69
70
71/**
72 * Generate query parameter for a buffer @a ptr of
73 * @a ptr_size bytes.
74 *
75 * @param ptr pointer to the query parameter to pass
76 * @param ptr_size number of bytes in @a ptr
77 */
78struct GNUNET_MY_QueryParam
79GNUNET_MY_query_param_fixed_size (const void *ptr,
80 size_t ptr_size)
81{
82 struct GNUNET_MY_QueryParam qp = {
83 .conv = &my_conv_fixed_size,
84 .cleaner = NULL,
85 .conv_cls = NULL,
86 .num_params = 1,
87 .data = ptr,
88 .data_len = (unsigned long) ptr_size
89 };
90
91 return qp;
92}
93
94
95/**
96 * Function called to convert input argument into SQL parameters.
97 *
98 * @param cls closure
99 * @param qp data about the query
100 * @param qbind array of parameters to initialize
101 * @return -1 on error
102 */
103static int
104my_conv_string (void *cls,
105 const struct GNUNET_MY_QueryParam *qp,
106 MYSQL_BIND *qbind)
107{
108 (void) cls;
109 GNUNET_assert (1 == qp->num_params);
110 qbind->buffer = (void *) qp->data;
111 qbind->buffer_length = qp->data_len;
112 qbind->buffer_type = MYSQL_TYPE_STRING;
113 return 1;
114}
115
116
117/**
118 * Generate query parameter for a string
119 *
120 * @param ptr pointer to the string query parameter to pass
121 */
122struct GNUNET_MY_QueryParam
123GNUNET_MY_query_param_string (const char *ptr)
124{
125 struct GNUNET_MY_QueryParam qp = {
126 .conv = &my_conv_string,
127 .cleaner = NULL,
128 .conv_cls = NULL,
129 .num_params = 1,
130 .data = ptr,
131 .data_len = strlen (ptr)
132 };
133
134 return qp;
135}
136
137
138/**
139 * Function called to convert input argument into SQL parameters
140 *
141 * @param cls closure
142 * @param qp data about the query
143 * @param qbind array of parameters to initialize
144 * @return -1 on error
145 */
146static int
147my_conv_uint16 (void *cls,
148 const struct GNUNET_MY_QueryParam *qp,
149 MYSQL_BIND *qbind)
150{
151 (void) cls;
152 GNUNET_assert (1 == qp->num_params);
153 qbind->buffer = (void *) qp->data;
154 qbind->buffer_length = sizeof(uint16_t);
155 qbind->buffer_type = MYSQL_TYPE_SHORT;
156 qbind->is_unsigned = 1;
157 return 1;
158}
159
160
161/**
162 * Generate query parameter for an uint16_t in host byte order.
163 *
164 * @param x pointer to the query parameter to pass
165 */
166struct GNUNET_MY_QueryParam
167GNUNET_MY_query_param_uint16 (const uint16_t *x)
168{
169 struct GNUNET_MY_QueryParam res = {
170 .conv = &my_conv_uint16,
171 .cleaner = NULL,
172 .conv_cls = NULL,
173 .num_params = 1,
174 .data = x,
175 .data_len = sizeof(*x)
176 };
177
178 return res;
179}
180
181
182/**
183 * Function called to convert input argument into SQL parameters
184 *
185 * @param cls closure
186 * @param qp data about the query
187 * @param qbind array of parameters to initialize
188 * @return -1 on error
189 */
190static int
191my_conv_uint32 (void *cls,
192 const struct GNUNET_MY_QueryParam *qp,
193 MYSQL_BIND *qbind)
194{
195 (void) cls;
196 GNUNET_assert (1 == qp->num_params);
197 qbind->buffer = (void *) qp->data;
198 qbind->buffer_length = sizeof(uint32_t);
199 qbind->buffer_type = MYSQL_TYPE_LONG;
200 qbind->is_unsigned = 1;
201 return 1;
202}
203
204
205/**
206 * Generate query parameter for an uint32_t in host byte order
207 *
208 * @param x pointer to the query parameter to pass
209 */
210struct GNUNET_MY_QueryParam
211GNUNET_MY_query_param_uint32 (const uint32_t *x)
212{
213 struct GNUNET_MY_QueryParam res = {
214 .conv = &my_conv_uint32,
215 .cleaner = NULL,
216 .conv_cls = NULL,
217 .num_params = 1,
218 .data = x,
219 .data_len = sizeof(*x)
220 };
221
222 return res;
223}
224
225
226/**
227 * Function called to convert input argument into SQL parameters
228 *
229 * @param cls closure
230 * @param qp data about the query
231 * @param qbind array of parameters to initialize
232 * @return -1 on error
233 */
234static int
235my_conv_uint64 (void *cls,
236 const struct GNUNET_MY_QueryParam *qp,
237 MYSQL_BIND *qbind)
238{
239 (void) cls;
240 GNUNET_assert (1 == qp->num_params);
241 qbind->buffer = (void *) qp->data;
242 qbind->buffer_length = sizeof(uint64_t);
243 qbind->buffer_type = MYSQL_TYPE_LONGLONG;
244 qbind->is_unsigned = 1;
245 return 1;
246}
247
248
249/**
250 * Generate query parameter for an uint64_t in host byte order
251 *
252 * @param x pointer to the query parameter to pass
253 */
254struct GNUNET_MY_QueryParam
255GNUNET_MY_query_param_uint64 (const uint64_t *x)
256{
257 struct GNUNET_MY_QueryParam res = {
258 .conv = &my_conv_uint64,
259 .cleaner = NULL,
260 .conv_cls = NULL,
261 .num_params = 1,
262 .data = x,
263 .data_len = sizeof(*x)
264 };
265
266 return res;
267}
268
269
270/**
271 * Function called to convert input argument into SQL parameters
272 *
273 * @param cls closure
274 * @param qp data about the query
275 * @param qbind array of parameters to initialize
276 * @return -1 on error
277 */
278static int
279my_conv_rsa_public_key (void *cls,
280 const struct GNUNET_MY_QueryParam *qp,
281 MYSQL_BIND *qbind)
282{
283 const struct GNUNET_CRYPTO_RsaPublicKey *rsa = qp->data;
284 void *buf;
285 size_t buf_size;
286
287 (void) cls;
288 GNUNET_assert (1 == qp->num_params);
289 buf_size = GNUNET_CRYPTO_rsa_public_key_encode (rsa,
290 &buf);
291 qbind->buffer = buf;
292 qbind->buffer_length = buf_size;
293 qbind->buffer_type = MYSQL_TYPE_BLOB;
294 return 1;
295}
296
297
298/**
299 * Generate query parameter for an RSA public key. The
300 * database must contain a BLOB type in the respective position.
301 *
302 * @param x the query parameter to pass
303 * @return array entry for the query parameters to use
304 */
305struct GNUNET_MY_QueryParam
306GNUNET_MY_query_param_rsa_public_key (const struct
307 GNUNET_CRYPTO_RsaPublicKey *x)
308{
309 struct GNUNET_MY_QueryParam res = {
310 .conv = &my_conv_rsa_public_key,
311 .cleaner = &my_clean_query,
312 .conv_cls = NULL,
313 .num_params = 1,
314 .data = x,
315 .data_len = 0
316 };
317
318 return res;
319}
320
321
322/**
323 * Function called to convert input argument into SQL parameters
324 *
325 *@param cls closure
326 *@param qp data about the query
327 *@param qbind array of parameters to initialize
328 *@return -1 on error
329 */
330static int
331my_conv_rsa_signature (void *cls,
332 const struct GNUNET_MY_QueryParam *qp,
333 MYSQL_BIND *qbind)
334{
335 const struct GNUNET_CRYPTO_RsaSignature *sig = qp->data;
336 void *buf;
337 size_t buf_size;
338
339 (void) cls;
340 GNUNET_assert (1 == qp->num_params);
341 buf_size = GNUNET_CRYPTO_rsa_signature_encode (sig,
342 &buf);
343 qbind->buffer = buf;
344 qbind->buffer_length = buf_size;
345 qbind->buffer_type = MYSQL_TYPE_BLOB;
346 return 1;
347}
348
349
350/**
351 * Generate query parameter for an RSA signature. The
352 * database must contain a BLOB type in the respective position
353 *
354 * @param x the query parameter to pass
355 * @return array entry for the query parameters to use
356 */
357struct GNUNET_MY_QueryParam
358GNUNET_MY_query_param_rsa_signature (const struct GNUNET_CRYPTO_RsaSignature *x)
359{
360 struct GNUNET_MY_QueryParam res = {
361 .conv = &my_conv_rsa_signature,
362 .cleaner = &my_clean_query,
363 .conv_cls = NULL,
364 .num_params = 1,
365 .data = (x),
366 .data_len = 0
367 };
368
369 return res;
370}
371
372
373/**
374 * Generate query parameter for an absolute time value.
375 * The database must store a 64-bit integer.
376 *
377 * @param x pointer to the query parameter to pass
378 * @return array entry for the query parameters to use
379 */
380struct GNUNET_MY_QueryParam
381GNUNET_MY_query_param_absolute_time (const struct GNUNET_TIME_Absolute *x)
382{
383 return GNUNET_MY_query_param_uint64 (&x->abs_value_us);
384}
385
386
387/**
388 * Generate query parameter for an absolute time value.
389 * The database must store a 64-bit integer.
390 *
391 * @param x pointer to the query parameter to pass
392 */
393struct GNUNET_MY_QueryParam
394GNUNET_MY_query_param_absolute_time_nbo (const struct
395 GNUNET_TIME_AbsoluteNBO *x)
396{
397 return GNUNET_MY_query_param_auto_from_type (&x->abs_value_us__);
398}
399
400
401/* end of my_query_helper.c */
diff --git a/src/my/my_result_helper.c b/src/my/my_result_helper.c
deleted file mode 100644
index ceebc6f37..000000000
--- a/src/my/my_result_helper.c
+++ /dev/null
@@ -1,868 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2014, 2015, 2016 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file my/my_result_helper.c
22 * @brief functions to extract result values
23 * @author Christophe Genevey
24 */
25
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_mysql_compat.h"
29#include "gnunet_my_lib.h"
30
31
32/**
33 * extract data from a Mysql database @a result at row @a row
34 *
35 * @param cls closure
36 * @param[in,out] rs
37 * @param stmt the mysql statement that is being run
38 * @param column the column that is being processed
39 * @param[out] result mysql result
40 * @return
41 * #GNUNET_OK if all results could be extracted
42 * #GNUNET_SYSERR if a result was invalid
43 */
44static int
45pre_extract_varsize_blob (void *cls,
46 struct GNUNET_MY_ResultSpec *rs,
47 MYSQL_STMT *stmt,
48 unsigned int column,
49 MYSQL_BIND *results)
50{
51 results[0].buffer = NULL;
52 results[0].buffer_length = 0;
53 results[0].length = &rs->mysql_bind_output_length;
54 results[0].is_null = &rs->is_null;
55 rs->is_null = 0;
56
57 return GNUNET_OK;
58}
59
60
61/**
62 * extract data from a Mysql database @a result at row @a row
63 *
64 * @param cls closure
65 * @param[in,out] rs
66 * @param stmt the mysql statement that is being run
67 * @param column the column that is being processed
68 * @param[out] results
69 * @return
70 * #GNUNET_OK if all results could be extracted
71 * #GNUNET_SYSERR if a result was invalid
72 */
73static int
74post_extract_varsize_blob (void *cls,
75 struct GNUNET_MY_ResultSpec *rs,
76 MYSQL_STMT *stmt,
77 unsigned int column,
78 MYSQL_BIND *results)
79{
80 void *buf;
81 size_t size;
82
83 if (*results->is_null)
84 return GNUNET_SYSERR;
85 size = (size_t) rs->mysql_bind_output_length;
86
87 if (rs->mysql_bind_output_length != size)
88 return GNUNET_SYSERR; /* 'unsigned long' does not fit in size_t!? */
89
90 buf = GNUNET_malloc (size);
91
92 results[0].buffer = buf;
93 results[0].buffer_length = size;
94 results[0].buffer_type = MYSQL_TYPE_BLOB;
95
96 if (0 !=
97 mysql_stmt_fetch_column (stmt,
98 results,
99 column,
100 0))
101 {
102 GNUNET_free (buf);
103 return GNUNET_SYSERR;
104 }
105
106 *(void **) rs->dst = buf;
107 *rs->result_size = size;
108
109 return GNUNET_OK;
110}
111
112
113/**
114 * extract data from a Mysql database @a result at row @a row
115 *
116 * @param cls closure
117 * @param[in,out] rs
118 */
119static void
120cleanup_varsize_blob (void *cls,
121 struct GNUNET_MY_ResultSpec *rs)
122{
123 void **ptr = (void **) rs->dst;
124
125 if (NULL != *ptr)
126 {
127 GNUNET_free (*ptr);
128 *ptr = NULL;
129 }
130}
131
132
133struct GNUNET_MY_ResultSpec
134GNUNET_MY_result_spec_variable_size (void **dst,
135 size_t *ptr_size)
136{
137 struct GNUNET_MY_ResultSpec res = {
138 .pre_conv = &pre_extract_varsize_blob,
139 .post_conv = &post_extract_varsize_blob,
140 .cleaner = &cleanup_varsize_blob,
141 .dst = (void *) (dst),
142 .result_size = ptr_size,
143 .num_fields = 1
144 };
145
146 return res;
147}
148
149
150/**
151 * Extract data from a Mysql database @a result at row @a row
152 *
153 * @param cls closure
154 * @param[in,out] rs
155 * @param stmt the mysql statement that is being run
156 * @param column the column that is being processed
157 * @param[out] results
158 * @return
159 * #GNUNET_OK if all results could be extracted
160 * #GNUNET_SYSERR if a result was invalid(non-existing field or NULL)
161 */
162static int
163pre_extract_fixed_blob (void *cls,
164 struct GNUNET_MY_ResultSpec *rs,
165 MYSQL_STMT *stmt,
166 unsigned int column,
167 MYSQL_BIND *results)
168{
169 results[0].buffer = rs->dst;
170 results[0].buffer_length = rs->dst_size;
171 results[0].length = &rs->mysql_bind_output_length;
172 results[0].buffer_type = MYSQL_TYPE_BLOB;
173 results[0].is_null = &rs->is_null;
174 rs->is_null = 0;
175
176 return GNUNET_OK;
177}
178
179
180/**
181 * Check size of extracted fixed size data from a Mysql database @a
182 * result at row @a row
183 *
184 * @param cls closure
185 * @param[in,out] rs
186 * @param stmt the mysql statement that is being run
187 * @param column the column that is being processed
188 * @param[out] results
189 * @return
190 * #GNUNET_OK if all results could be extracted
191 * #GNUNET_SYSERR if a result was invalid(non-existing field or NULL)
192 */
193static int
194post_extract_fixed_blob (void *cls,
195 struct GNUNET_MY_ResultSpec *rs,
196 MYSQL_STMT *stmt,
197 unsigned int column,
198 MYSQL_BIND *results)
199{
200 if (*results->is_null)
201 return GNUNET_SYSERR;
202 if (rs->dst_size != rs->mysql_bind_output_length)
203 return GNUNET_SYSERR;
204 return GNUNET_OK;
205}
206
207
208/**
209 * Fixed-size result expected.
210 *
211 * @param name name of the field in the table
212 * @param[out] dst where to store the result
213 * @param ptr_size number of bytes in @a dst
214 * @return array entry for the result specification to use
215 */
216struct GNUNET_MY_ResultSpec
217GNUNET_MY_result_spec_fixed_size (void *ptr,
218 size_t ptr_size)
219{
220 struct GNUNET_MY_ResultSpec res = {
221 .pre_conv = &pre_extract_fixed_blob,
222 .post_conv = &post_extract_fixed_blob,
223 .cleaner = NULL,
224 .dst = (void *) (ptr),
225 .dst_size = ptr_size,
226 .num_fields = 1
227 };
228
229 return res;
230}
231
232
233/**
234 * Extract data from a Mysql database @a result at row @a row
235 *
236 * @param cls closure
237 * @param[in,out] rs
238 * @param stmt the mysql statement that is being run
239 * @param column the column that is being processed
240 * @param[out] results
241 * @return
242 * #GNUNET_OK if all results could be extracted
243 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
244 */
245static int
246pre_extract_rsa_public_key (void *cls,
247 struct GNUNET_MY_ResultSpec *rs,
248 MYSQL_STMT *stmt,
249 unsigned int column,
250 MYSQL_BIND *results)
251{
252 results[0].buffer = NULL;
253 results[0].buffer_length = 0;
254 results[0].length = &rs->mysql_bind_output_length;
255 results[0].buffer_type = MYSQL_TYPE_BLOB;
256 results[0].is_null = &rs->is_null;
257 rs->is_null = 0;
258
259 return GNUNET_OK;
260}
261
262
263/**
264 * Check size of extracted fixed size data from a Mysql database @a
265 * result at row @a row
266 *
267 * @param cls closure
268 * @param[in,out] rs
269 * @param stmt the mysql statement that is being run
270 * @param column the column that is being processed
271 * @param[out] results
272 * @return
273 * #GNUNET_OK if all results could be extracted
274 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
275 */
276static int
277post_extract_rsa_public_key (void *cls,
278 struct GNUNET_MY_ResultSpec *rs,
279 MYSQL_STMT *stmt,
280 unsigned int column,
281 MYSQL_BIND *results)
282
283{
284 struct GNUNET_CRYPTO_RsaPublicKey **pk = rs->dst;
285 void *buf;
286 size_t size;
287
288 if (*results->is_null)
289 return GNUNET_SYSERR;
290 size = (size_t) rs->mysql_bind_output_length;
291
292 if (rs->mysql_bind_output_length != size)
293 return GNUNET_SYSERR; /* 'unsigned long' does not fit in size_t!? */
294 buf = GNUNET_malloc (size);
295
296 results[0].buffer = buf;
297 results[0].buffer_length = size;
298 results[0].buffer_type = MYSQL_TYPE_BLOB;
299 if (0 !=
300 mysql_stmt_fetch_column (stmt,
301 results,
302 column,
303 0))
304 {
305 GNUNET_free (buf);
306 return GNUNET_SYSERR;
307 }
308
309 *pk = GNUNET_CRYPTO_rsa_public_key_decode (buf,
310 size);
311 GNUNET_free (buf);
312 if (NULL == *pk)
313 {
314 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
315 "Results contains bogus public key value (fail to decode)\n");
316 return GNUNET_SYSERR;
317 }
318
319 return GNUNET_OK;
320}
321
322
323/**
324 * Function called to clean up memory allocated
325 * by a #GNUNET_MY_ResultConverter.
326 *
327 * @param cls closure
328 * @param rs result data to clean up
329 */
330static void
331clean_rsa_public_key (void *cls,
332 struct GNUNET_MY_ResultSpec *rs)
333{
334 struct GNUNET_CRYPTO_RsaPublicKey **pk = rs->dst;
335
336 if (NULL != *pk)
337 {
338 GNUNET_CRYPTO_rsa_public_key_free (*pk);
339 *pk = NULL;
340 }
341}
342
343
344/**
345 * RSA public key expected
346 *
347 * @param name name of the field in the table
348 * @param[out] rsa where to store the result
349 * @return array entry for the result specification to use
350 */
351struct GNUNET_MY_ResultSpec
352GNUNET_MY_result_spec_rsa_public_key (struct GNUNET_CRYPTO_RsaPublicKey **rsa)
353{
354 struct GNUNET_MY_ResultSpec res = {
355 .pre_conv = &pre_extract_rsa_public_key,
356 .post_conv = &post_extract_rsa_public_key,
357 .cleaner = &clean_rsa_public_key,
358 .dst = (void *) rsa,
359 .dst_size = 0,
360 .num_fields = 1
361 };
362
363 return res;
364}
365
366
367/**
368 * Extract data from a Mysql database @a result at row @a row.
369 *
370 * @param cls closure
371 * @param[in,out] rs
372 * @param stmt the mysql statement that is being run
373 * @param column the column that is being processed
374 * @param[out] results
375 * @return
376 * #GNUNET_OK if all results could be extracted
377 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
378 */
379static int
380pre_extract_rsa_signature (void *cls,
381 struct GNUNET_MY_ResultSpec *rs,
382 MYSQL_STMT *stmt,
383 unsigned int column,
384 MYSQL_BIND *results)
385{
386 results[0].buffer = 0;
387 results[0].buffer_length = 0;
388 results[0].length = &rs->mysql_bind_output_length;
389 results[0].buffer_type = MYSQL_TYPE_BLOB;
390 results[0].is_null = &rs->is_null;
391 rs->is_null = 0;
392
393 return GNUNET_OK;
394}
395
396
397/**
398 * Extract data from a Mysql database @a result at row @a row.
399 *
400 * @param cls closure
401 * @param[in,out] rs
402 * @param stmt the mysql statement that is being run
403 * @param column the column that is being processed
404 * @param[out] results
405 * @return
406 * #GNUNET_OK if all results could be extracted
407 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
408 */
409static int
410post_extract_rsa_signature (void *cls,
411 struct GNUNET_MY_ResultSpec *rs,
412 MYSQL_STMT *stmt,
413 unsigned int column,
414 MYSQL_BIND *results)
415{
416 struct GNUNET_CRYPTO_RsaSignature **sig = rs->dst;
417 void *buf;
418 size_t size;
419
420 if (*results->is_null)
421 return GNUNET_SYSERR;
422 size = (size_t) rs->mysql_bind_output_length;
423
424 if (rs->mysql_bind_output_length != size)
425 return GNUNET_SYSERR; /* 'unsigned long' does not fit in size_t!? */
426 buf = GNUNET_malloc (size);
427
428 results[0].buffer = buf;
429 results[0].buffer_length = size;
430 results[0].buffer_type = MYSQL_TYPE_BLOB;
431 if (0 !=
432 mysql_stmt_fetch_column (stmt,
433 results,
434 column,
435 0))
436 {
437 GNUNET_free (buf);
438 return GNUNET_SYSERR;
439 }
440
441 *sig = GNUNET_CRYPTO_rsa_signature_decode (buf,
442 size);
443 GNUNET_free (buf);
444 if (NULL == *sig)
445 {
446 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
447 "Resuls contains bogus signature value (fails to decode)\n");
448 return GNUNET_SYSERR;
449 }
450 return GNUNET_OK;
451}
452
453
454/**
455 * Function called to clean up memory allocated
456 * by a #GNUNET_MY_ResultConverter.
457 *
458 * @param cls closure
459 * @param rd result data to clean up
460 */
461static void
462clean_rsa_signature (void *cls,
463 struct GNUNET_MY_ResultSpec *rs)
464{
465 struct GNUNET_CRYPTO_RsaSignature **sig = rs->dst;
466
467 if (NULL != *sig)
468 {
469 GNUNET_CRYPTO_rsa_signature_free (*sig);
470 *sig = NULL;
471 }
472}
473
474
475/**
476 * RSA signature expected.
477 *
478 * @param[out] sig where to store the result;
479 * @return array entry for the result specification to use
480 */
481struct GNUNET_MY_ResultSpec
482GNUNET_MY_result_spec_rsa_signature (struct GNUNET_CRYPTO_RsaSignature **sig)
483{
484 struct GNUNET_MY_ResultSpec res = {
485 .pre_conv = &pre_extract_rsa_signature,
486 .post_conv = &post_extract_rsa_signature,
487 .cleaner = &clean_rsa_signature,
488 .dst = (void *) sig,
489 .dst_size = 0,
490 .num_fields = 1
491 };
492
493 return res;
494}
495
496
497/**
498 * Extract data from a Mysql database @a result at row @a row
499 *
500 * @param cls closure
501 * @param[in,out] rs
502 * @param stmt the mysql statement that is being run
503 * @param column the column that is being processed
504 * @param[out] results
505 * @return
506 * #GNUNET_OK if all results could be extracted
507 * #GNUNET_SYSERR if a result was invalid (non existing field or NULL)
508 */
509static int
510pre_extract_string (void *cls,
511 struct GNUNET_MY_ResultSpec *rs,
512 MYSQL_STMT *stmt,
513 unsigned int column,
514 MYSQL_BIND *results)
515{
516 results[0].buffer = NULL;
517 results[0].buffer_length = 0;
518 results[0].length = &rs->mysql_bind_output_length;
519 results[0].buffer_type = MYSQL_TYPE_BLOB;
520 results[0].is_null = &rs->is_null;
521 rs->is_null = 0;
522
523 return GNUNET_OK;
524}
525
526
527/**
528 * Check size of extracted fixed size data from a Mysql database
529 *
530 * @param cls closure
531 * @param[in,out] rs
532 * @param stmt the mysql statement that is being run
533 * @param column the column that is being processed
534 * @param[out] results
535 * @return
536 * #GNUNET_OK if all results could be extracted
537 * #GNUNET_SYSERR if a result was invalid (non existing field or NULL)
538 */
539static int
540post_extract_string (void *cls,
541 struct GNUNET_MY_ResultSpec *rs,
542 MYSQL_STMT *stmt,
543 unsigned int column,
544 MYSQL_BIND *results)
545{
546 size_t size = (size_t) rs->mysql_bind_output_length;
547 char *buf;
548
549 if (rs->mysql_bind_output_length != size)
550 return GNUNET_SYSERR;
551 if (*results->is_null)
552 {
553 *(void **) rs->dst = NULL;
554 return GNUNET_OK;
555 }
556
557 buf = GNUNET_malloc (size);
558 results[0].buffer = buf;
559 results[0].buffer_length = size;
560 results[0].buffer_type = MYSQL_TYPE_BLOB;
561
562 if (0 !=
563 mysql_stmt_fetch_column (stmt,
564 results,
565 column,
566 0))
567 {
568 GNUNET_free (buf);
569 return GNUNET_SYSERR;
570 }
571 buf[size] = '\0';
572 *(void **) rs->dst = buf;
573 return GNUNET_OK;
574}
575
576
577/**
578 * 0- terminated string exprected.
579 *
580 * @param[out] dst where to store the result, allocated
581 * @return array entry for the result specification to use
582 */
583struct GNUNET_MY_ResultSpec
584GNUNET_MY_result_spec_string (char **dst)
585{
586 struct GNUNET_MY_ResultSpec res = {
587 .pre_conv = &pre_extract_string,
588 .post_conv = &post_extract_string,
589 .cleaner = NULL,
590 .dst = (void *) dst,
591 .dst_size = 0,
592 .num_fields = 1
593 };
594
595 return res;
596}
597
598
599/**
600 * Absolute time expected
601 *
602 * @param name name of the field in the table
603 * @param[out] at where to store the result
604 * @return array entry for the result specification to use
605 */
606struct GNUNET_MY_ResultSpec
607GNUNET_MY_result_spec_absolute_time (struct GNUNET_TIME_Absolute *at)
608{
609 return GNUNET_MY_result_spec_uint64 (&at->abs_value_us);
610}
611
612
613/**
614 * Absolute time in network byte order expected
615 *
616 * @param[out] at where to store the result
617 * @return array entry for the result specification to use
618 */
619struct GNUNET_MY_ResultSpec
620GNUNET_MY_result_spec_absolute_time_nbo (struct GNUNET_TIME_AbsoluteNBO *at)
621{
622 struct GNUNET_MY_ResultSpec res =
623 GNUNET_MY_result_spec_auto_from_type (&at->abs_value_us__);
624
625 return res;
626}
627
628
629/**
630 * Extract data from a Postgres database @a result at row @a row.
631 *
632 * @param cls closure
633 * @param[in,out] rs
634 * @param stmt the mysql statement that is being run
635 * @param column the column that is being processed
636 * @param[out] results
637 * @return
638 * #GNUNET_YES if all results could be extracted
639 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
640 */
641static int
642pre_extract_uint16 (void *cls,
643 struct GNUNET_MY_ResultSpec *rs,
644 MYSQL_STMT *stmt,
645 unsigned int column,
646 MYSQL_BIND *results)
647{
648 results[0].buffer = rs->dst;
649 results[0].buffer_length = rs->dst_size;
650 results[0].length = &rs->mysql_bind_output_length;
651 results[0].buffer_type = MYSQL_TYPE_SHORT;
652 results[0].is_null = &rs->is_null;
653 rs->is_null = 0;
654
655 return GNUNET_OK;
656}
657
658
659/**
660 * Check size of extracted fixed size data from a Mysql database.
661 *
662 * @param cls closure
663 * @param[in,out] rs
664 * @param stmt the mysql statement that is being run
665 * @param column the column that is being processed
666 * @param[out] results
667 * @return
668 * #GNUNET_YES if all results could be extracted
669 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
670 */
671static int
672post_extract_uint16 (void *cls,
673 struct GNUNET_MY_ResultSpec *rs,
674 MYSQL_STMT *stmt,
675 unsigned int column,
676 MYSQL_BIND *results)
677{
678 if (rs->dst_size != rs->mysql_bind_output_length)
679 return GNUNET_SYSERR;
680 if (*results->is_null)
681 return GNUNET_SYSERR;
682 return GNUNET_OK;
683}
684
685
686/**
687 * uint16_t expected
688 *
689 * @param[out] u16 where to store the result
690 * @return array entry for the result specification to use
691 */
692struct GNUNET_MY_ResultSpec
693GNUNET_MY_result_spec_uint16 (uint16_t *u16)
694{
695 struct GNUNET_MY_ResultSpec res = {
696 .pre_conv = &pre_extract_uint16,
697 .post_conv = &post_extract_uint16,
698 .cleaner = NULL,
699 .dst = (void *) u16,
700 .dst_size = sizeof(*u16),
701 .num_fields = 1
702 };
703
704 return res;
705}
706
707
708/**
709 * Extract data from a MYSQL database @a result at row @a row
710 *
711 * @param cls closure
712 * @param[in,out] rs
713 * @param stmt the mysql statement that is being run
714 * @param column the column that is being processed
715 * @param[out] results
716 * @return
717 * #GNUNET_OK if all results could be extracted
718 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
719 */
720static int
721pre_extract_uint32 (void *cls,
722 struct GNUNET_MY_ResultSpec *rs,
723 MYSQL_STMT *stmt,
724 unsigned int column,
725 MYSQL_BIND *results)
726{
727 results[0].buffer = rs->dst;
728 results[0].buffer_length = rs->dst_size;
729 results[0].length = &rs->mysql_bind_output_length;
730 results[0].buffer_type = MYSQL_TYPE_LONG;
731 results[0].is_null = &rs->is_null;
732 rs->is_null = 0;
733
734 return GNUNET_OK;
735}
736
737
738/**
739 * Extract data from a MYSQL database @a result at row @a row
740 *
741 * @param cls closure
742 * @param[in,out] rs
743 * @param stmt the mysql statement that is being run
744 * @param column the column that is being processed
745 * @param[out] results
746 * @return
747 * #GNUNET_OK if all results could be extracted
748 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
749 */
750static int
751post_extract_uint32 (void *cls,
752 struct GNUNET_MY_ResultSpec *rs,
753 MYSQL_STMT *stmt,
754 unsigned int column,
755 MYSQL_BIND *results)
756{
757 if (rs->dst_size != rs->mysql_bind_output_length)
758 return GNUNET_SYSERR;
759 if (*results->is_null)
760 return GNUNET_SYSERR;
761 return GNUNET_OK;
762}
763
764
765/**
766 * uint32_t expected
767 *
768 * @param[out] u32 where to store the result
769 * @return array entry for the result specification to use
770 */
771struct GNUNET_MY_ResultSpec
772GNUNET_MY_result_spec_uint32 (uint32_t *u32)
773{
774 struct GNUNET_MY_ResultSpec res = {
775 .pre_conv = &pre_extract_uint32,
776 .post_conv = &post_extract_uint32,
777 .cleaner = NULL,
778 .dst = (void *) u32,
779 .dst_size = sizeof(*u32),
780 .num_fields = 1
781 };
782
783 return res;
784}
785
786
787/**
788 * Extract data from a MYSQL database @a result at row @a row
789 *
790 * @param cls closure
791 * @param[in,out] rs
792 * @param stmt the mysql statement that is being run
793 * @param column the column that is being processed
794 * @param[out] results
795 * @return
796 * #GNUNET_OK if all results could be extracted
797 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
798 */
799static int
800pre_extract_uint64 (void *cls,
801 struct GNUNET_MY_ResultSpec *rs,
802 MYSQL_STMT *stmt,
803 unsigned int column,
804 MYSQL_BIND *results)
805{
806 if (sizeof(uint64_t) != rs->dst_size)
807 return GNUNET_SYSERR;
808 results[0].buffer = rs->dst;
809 results[0].buffer_length = rs->dst_size;
810 results[0].length = &rs->mysql_bind_output_length;
811 results[0].buffer_type = MYSQL_TYPE_LONGLONG;
812 results[0].is_null = &rs->is_null;
813 rs->is_null = 0;
814
815 return GNUNET_OK;
816}
817
818
819/**
820 * Check size of extracted fixed-size data from a Mysql database
821 *
822 * @param cls closure
823 * @param[in,out] rs
824 * @param stmt the mysql statement that is being run
825 * @param column the column that is being processed
826 * @param[out] results
827 * @return
828 * #GNUNET_OK if all results could be extracted
829 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
830 */
831static int
832post_extract_uint64 (void *cls,
833 struct GNUNET_MY_ResultSpec *rs,
834 MYSQL_STMT *stmt,
835 unsigned int column,
836 MYSQL_BIND *results)
837{
838 if (sizeof(uint64_t) != rs->dst_size)
839 return GNUNET_SYSERR;
840 if (*results->is_null)
841 return GNUNET_SYSERR;
842 return GNUNET_OK;
843}
844
845
846/**
847 * uint64_t expected.
848 *
849 * @param[out] u64 where to store the result
850 * @return array entry for the result specification to use
851 */
852struct GNUNET_MY_ResultSpec
853GNUNET_MY_result_spec_uint64 (uint64_t *u64)
854{
855 struct GNUNET_MY_ResultSpec res = {
856 .pre_conv = &pre_extract_uint64,
857 .post_conv = &post_extract_uint64,
858 .cleaner = NULL,
859 .dst = (void *) u64,
860 .dst_size = sizeof(*u64),
861 .num_fields = 1
862 };
863
864 return res;
865}
866
867
868/* end of my_result_helper.c */
diff --git a/src/my/test_my.c b/src/my/test_my.c
deleted file mode 100644
index e646c0fd5..000000000
--- a/src/my/test_my.c
+++ /dev/null
@@ -1,301 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2016 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file my/test_my.c
22 * @brief Tests for convenience MySQL database
23 * @author Christophe Genevey
24 */
25#include "platform.h"
26#include <mysql/mysql.h>
27#include "gnunet_mysql_compat.h"
28#include "gnunet_my_lib.h"
29#include "gnunet_mysql_lib.h"
30#include "gnunet_util_lib.h"
31
32
33/**
34 * Run actual test queries.
35 *
36 * @param contexte the current context of mysql
37 * @return 0 on success
38 */
39static int
40run_queries (struct GNUNET_MYSQL_Context *context)
41{
42 struct GNUNET_CRYPTO_RsaPublicKey *pub = NULL;
43 struct GNUNET_CRYPTO_RsaPublicKey *pub2 = NULL;
44 struct GNUNET_CRYPTO_RsaSignature *sig = NULL;;
45 struct GNUNET_CRYPTO_RsaSignature *sig2 = NULL;
46 struct GNUNET_TIME_Absolute abs_time = GNUNET_TIME_absolute_get ();
47 struct GNUNET_TIME_Absolute abs_time2;
48 struct GNUNET_TIME_Absolute forever = GNUNET_TIME_UNIT_FOREVER_ABS;
49 struct GNUNET_TIME_Absolute forever2;
50 const struct GNUNET_TIME_AbsoluteNBO abs_time_nbo =
51 GNUNET_TIME_absolute_hton (abs_time);
52 struct GNUNET_HashCode hc;
53 struct GNUNET_HashCode hc2;
54 const char msg[] = "hello";
55 void *msg2 = NULL;
56 size_t msg2_len;
57
58 const char msg3[] = "world";
59 char *msg4 = "";
60
61 uint16_t u16;
62 uint16_t u162;
63 uint32_t u32;
64 uint32_t u322;
65 uint64_t u64;
66 uint64_t u642;
67
68 int ret;
69
70 struct GNUNET_MYSQL_StatementHandle *statements_handle_insert = NULL;
71 struct GNUNET_MYSQL_StatementHandle *statements_handle_select = NULL;
72
73 struct GNUNET_CRYPTO_RsaPrivateKey *priv = NULL;
74 struct GNUNET_HashCode hmsg;
75
76 priv = GNUNET_CRYPTO_rsa_private_key_create (1024);
77 pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv);
78 memset (&hmsg, 42, sizeof(hmsg));
79 sig = GNUNET_CRYPTO_rsa_sign_fdh (priv,
80 &hmsg);
81 u16 = 16;
82 u32 = 32;
83 u64 = UINT64_MAX;
84
85 memset (&hc, 0, sizeof(hc));
86 memset (&hc2, 0, sizeof(hc2));
87
88 statements_handle_insert
89 = GNUNET_MYSQL_statement_prepare (context,
90 "INSERT INTO test_my2 ("
91 " pub"
92 ",sig"
93 ",abs_time"
94 ",forever"
95 ",abs_time_nbo"
96 ",hash"
97 ",vsize"
98 ",str"
99 ",u16"
100 ",u32"
101 ",u64"
102 ") VALUES "
103 "( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
104
105 if (NULL == statements_handle_insert)
106 {
107 fprintf (stderr, "Failed to prepared statement INSERT\n");
108 GNUNET_CRYPTO_rsa_signature_free (sig);
109 GNUNET_CRYPTO_rsa_private_key_free (priv);
110 GNUNET_CRYPTO_rsa_public_key_free (pub);
111 return 1;
112 }
113
114 struct GNUNET_MY_QueryParam params_insert[] = {
115 GNUNET_MY_query_param_rsa_public_key (pub),
116 GNUNET_MY_query_param_rsa_signature (sig),
117 GNUNET_MY_query_param_absolute_time (&abs_time),
118 GNUNET_MY_query_param_absolute_time (&forever),
119 GNUNET_MY_query_param_absolute_time_nbo (&abs_time_nbo),
120 GNUNET_MY_query_param_auto_from_type (&hc),
121 GNUNET_MY_query_param_fixed_size (msg, strlen (msg)),
122 GNUNET_MY_query_param_string (msg3),
123 GNUNET_MY_query_param_uint16 (&u16),
124 GNUNET_MY_query_param_uint32 (&u32),
125 GNUNET_MY_query_param_uint64 (&u64),
126 GNUNET_MY_query_param_end
127 };
128
129 if (GNUNET_OK != GNUNET_MY_exec_prepared (context,
130 statements_handle_insert,
131 params_insert))
132 {
133 fprintf (stderr, "Failed to execute prepared statement INSERT\n");
134 GNUNET_CRYPTO_rsa_signature_free (sig);
135 GNUNET_CRYPTO_rsa_private_key_free (priv);
136 GNUNET_CRYPTO_rsa_public_key_free (pub);
137 return 1;
138 }
139
140 statements_handle_select
141 = GNUNET_MYSQL_statement_prepare (context,
142 "SELECT"
143 " pub"
144 ",sig"
145 ",abs_time"
146 ",forever"
147 ",hash"
148 ",vsize"
149 ",str"
150 ",u16"
151 ",u32"
152 ",u64"
153 " FROM test_my2");
154
155 if (NULL == statements_handle_select)
156 {
157 fprintf (stderr, "Failed to prepared statement SELECT\n");
158 GNUNET_CRYPTO_rsa_signature_free (sig);
159 GNUNET_CRYPTO_rsa_private_key_free (priv);
160 GNUNET_CRYPTO_rsa_public_key_free (pub);
161 return 1;
162 }
163
164 struct GNUNET_MY_QueryParam params_select[] = {
165 GNUNET_MY_query_param_end
166 };
167
168 if (GNUNET_OK != GNUNET_MY_exec_prepared (context,
169 statements_handle_select,
170 params_select))
171 {
172 fprintf (stderr, "Failed to execute prepared statement SELECT\n");
173 GNUNET_CRYPTO_rsa_signature_free (sig);
174 GNUNET_CRYPTO_rsa_private_key_free (priv);
175 GNUNET_CRYPTO_rsa_public_key_free (pub);
176 return 1;
177 }
178
179 struct GNUNET_MY_ResultSpec results_select[] = {
180 GNUNET_MY_result_spec_rsa_public_key (&pub2),
181 GNUNET_MY_result_spec_rsa_signature (&sig2),
182 GNUNET_MY_result_spec_absolute_time (&abs_time2),
183 GNUNET_MY_result_spec_absolute_time (&forever2),
184 GNUNET_MY_result_spec_auto_from_type (&hc2),
185 GNUNET_MY_result_spec_variable_size (&msg2, &msg2_len),
186 GNUNET_MY_result_spec_string (&msg4),
187 GNUNET_MY_result_spec_uint16 (&u162),
188 GNUNET_MY_result_spec_uint32 (&u322),
189 GNUNET_MY_result_spec_uint64 (&u642),
190 GNUNET_MY_result_spec_end
191 };
192
193 ret = GNUNET_MY_extract_result (statements_handle_select,
194 results_select);
195
196 GNUNET_assert (GNUNET_YES == ret);
197 GNUNET_break (abs_time.abs_value_us == abs_time2.abs_value_us);
198 GNUNET_break (forever.abs_value_us == forever2.abs_value_us);
199 GNUNET_break (0 ==
200 memcmp (&hc,
201 &hc2,
202 sizeof(struct GNUNET_HashCode)));
203
204 GNUNET_assert (NULL != sig2);
205 GNUNET_assert (NULL != pub2);
206 GNUNET_break (0 ==
207 GNUNET_CRYPTO_rsa_signature_cmp (sig,
208 sig2));
209 GNUNET_break (0 ==
210 GNUNET_CRYPTO_rsa_public_key_cmp (pub,
211 pub2));
212
213 GNUNET_break (strlen (msg) == msg2_len);
214 GNUNET_break (0 ==
215 strncmp (msg,
216 msg2,
217 msg2_len));
218
219 GNUNET_break (strlen (msg3) == strlen (msg4));
220 GNUNET_break (0 ==
221 strcmp (msg3,
222 msg4));
223
224 GNUNET_break (16 == u162);
225 GNUNET_break (32 == u322);
226 GNUNET_break (UINT64_MAX == u642);
227
228 GNUNET_MY_cleanup_result (results_select);
229
230 GNUNET_CRYPTO_rsa_signature_free (sig);
231 GNUNET_CRYPTO_rsa_private_key_free (priv);
232 GNUNET_CRYPTO_rsa_public_key_free (pub);
233
234 if (GNUNET_OK != ret)
235 return 1;
236
237 return 0;
238}
239
240
241int
242main (int argc, const char *const argv[])
243{
244 struct GNUNET_CONFIGURATION_Handle *config;
245 struct GNUNET_MYSQL_Context *context;
246 int ret;
247
248 GNUNET_log_setup ("test-my",
249 "WARNING",
250 NULL);
251
252 config = GNUNET_CONFIGURATION_create ();
253 if (GNUNET_OK !=
254 GNUNET_CONFIGURATION_parse (config, "test_my.conf"))
255 {
256 fprintf (stderr, "Failed to parse configuration\n");
257 return 1;
258 }
259
260 context = GNUNET_MYSQL_context_create (config,
261 "datastore-mysql");
262 if (NULL == context)
263 {
264 fprintf (stderr, "Failed to connect to database\n");
265 return 77;
266 }
267
268 (void) GNUNET_MYSQL_statement_run (context,
269 "DROP TABLE test_my2;");
270
271 if (GNUNET_OK !=
272 GNUNET_MYSQL_statement_run (context,
273 "CREATE TABLE IF NOT EXISTS test_my2("
274 " pub BLOB NOT NULL"
275 ",sig BLOB NOT NULL"
276 ",abs_time BIGINT NOT NULL"
277 ",forever BIGINT NOT NULL"
278 ",abs_time_nbo BIGINT NOT NULL"
279 ",hash BLOB NOT NULL CHECK(LENGTH(hash)=64)"
280 ",vsize BLOB NOT NULL"
281 ",str BLOB NOT NULL"
282 ",u16 SMALLINT NOT NULL"
283 ",u32 INT NOT NULL"
284 ",u64 BIGINT NOT NULL"
285 ")"))
286 {
287 fprintf (stderr,
288 "Failed to create table. Database likely not setup correctly.\n");
289 GNUNET_MYSQL_statements_invalidate (context);
290 GNUNET_MYSQL_context_destroy (context);
291
292 return 77;
293 }
294
295 ret = run_queries (context);
296
297 GNUNET_MYSQL_context_destroy (context);
298 GNUNET_free (config);
299
300 return ret;
301}
diff --git a/src/my/test_my.conf b/src/my/test_my.conf
deleted file mode 100644
index e69de29bb..000000000
--- a/src/my/test_my.conf
+++ /dev/null
diff --git a/src/mysql/Makefile.am b/src/mysql/Makefile.am
deleted file mode 100644
index 3bfb929cd..000000000
--- a/src/mysql/Makefile.am
+++ /dev/null
@@ -1,18 +0,0 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4if USE_COVERAGE
5 AM_CFLAGS = --coverage
6endif
7
8if HAVE_MYSQL
9lib_LTLIBRARIES = libgnunetmysql.la
10endif
11
12libgnunetmysql_la_SOURCES = \
13 mysql.c
14libgnunetmysql_la_LIBADD = $(MYSQL_LDFLAGS) -lmysqlclient \
15 $(top_builddir)/src/util/libgnunetutil.la
16libgnunetmysql_la_LDFLAGS = \
17 $(GN_LIB_LDFLAGS) \
18 -version-info 0:0:0
diff --git a/src/mysql/meson.build b/src/mysql/meson.build
deleted file mode 100644
index 1464fc45e..000000000
--- a/src/mysql/meson.build
+++ /dev/null
@@ -1,13 +0,0 @@
1libgnunetmysq_src = ['mysql.c']
2
3if get_option('monolith') == false
4 libgnunetmysq = library('gnunetmysq',
5 libgnunetmysq_src,
6 dependencies: [libgnunetutil_dep, my_dep],
7 include_directories: [incdir, configuration_inc])
8 libgnunetmysq_dep = declare_dependency(link_with : libgnunetmysq)
9else
10 foreach p : libgnunetmysq_src
11 gnunet_src += 'mysql/' + p
12 endforeach
13endif
diff --git a/src/mysql/mysql.c b/src/mysql/mysql.c
deleted file mode 100644
index 056c2f07f..000000000
--- a/src/mysql/mysql.c
+++ /dev/null
@@ -1,485 +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 it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file mysql/mysql.c
22 * @brief library to help with access to a MySQL database
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include <mysql/mysql.h>
27#include "gnunet_mysql_lib.h"
28#include "gnunet_mysql_compat.h"
29
30/**
31 * Maximum number of supported parameters for a prepared
32 * statement. Increase if needed.
33 */
34#define MAX_PARAM 16
35
36
37/**
38 * Die with an error message that indicates
39 * a failure of the command 'cmd' with the message given
40 * by strerror(errno).
41 */
42#define DIE_MYSQL(cmd, dbh) \
43 do \
44 { \
45 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, \
46 "mysql", \
47 _ ("`%s' failed at %s:%d with error: %s\n"), \
48 cmd, \
49 __FILE__, \
50 __LINE__, \
51 mysql_error ((dbh)->dbf)); \
52 GNUNET_assert (0); \
53 } while (0);
54
55/**
56 * Log an error message at log-level 'level' that indicates
57 * a failure of the command 'cmd' on file 'filename'
58 * with the message given by strerror(errno).
59 */
60#define LOG_MYSQL(level, cmd, dbh) \
61 do \
62 { \
63 GNUNET_log_from (level, \
64 "mysql", \
65 _ ("`%s' failed at %s:%d with error: %s\n"), \
66 cmd, \
67 __FILE__, \
68 __LINE__, \
69 mysql_error ((dbh)->dbf)); \
70 } while (0);
71
72
73/**
74 * Mysql context.
75 */
76struct GNUNET_MYSQL_Context
77{
78 /**
79 * Our configuration.
80 */
81 const struct GNUNET_CONFIGURATION_Handle *cfg;
82
83 /**
84 * Our section.
85 */
86 const char *section;
87
88 /**
89 * Handle to the mysql database.
90 */
91 MYSQL *dbf;
92
93 /**
94 * Head of list of our prepared statements.
95 */
96 struct GNUNET_MYSQL_StatementHandle *shead;
97
98 /**
99 * Tail of list of our prepared statements.
100 */
101 struct GNUNET_MYSQL_StatementHandle *stail;
102
103 /**
104 * Filename of "my.cnf" (msyql configuration).
105 */
106 char *cnffile;
107};
108
109
110/**
111 * Handle for a prepared statement.
112 */
113struct GNUNET_MYSQL_StatementHandle
114{
115 /**
116 * Kept in a DLL.
117 */
118 struct GNUNET_MYSQL_StatementHandle *next;
119
120 /**
121 * Kept in a DLL.
122 */
123 struct GNUNET_MYSQL_StatementHandle *prev;
124
125 /**
126 * Mysql Context the statement handle belongs to.
127 */
128 struct GNUNET_MYSQL_Context *mc;
129
130 /**
131 * Original query string.
132 */
133 char *query;
134
135 /**
136 * Handle to MySQL prepared statement.
137 */
138 MYSQL_STMT *statement;
139
140 /**
141 * Is the MySQL prepared statement valid, or do we need to re-initialize it?
142 */
143 int valid;
144};
145
146
147/**
148 * Obtain the location of ".my.cnf".
149 *
150 * @param cfg our configuration
151 * @param section the section
152 * @return NULL on error
153 */
154static char *
155get_my_cnf_path (const struct GNUNET_CONFIGURATION_Handle *cfg,
156 const char *section)
157{
158 char *cnffile;
159 char *home_dir;
160 struct stat st;
161
162 struct passwd *pw;
163
164 int configured;
165
166 pw = getpwuid (getuid ());
167 if (! pw)
168 {
169 GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_ERROR, "mysql", "getpwuid");
170 return NULL;
171 }
172 if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (cfg, section, "CONFIG"))
173 {
174 GNUNET_assert (GNUNET_OK ==
175 GNUNET_CONFIGURATION_get_value_filename (cfg,
176 section,
177 "CONFIG",
178 &cnffile));
179 configured = GNUNET_YES;
180 }
181 else
182 {
183 home_dir = GNUNET_strdup (pw->pw_dir);
184 GNUNET_asprintf (&cnffile, "%s/.my.cnf", home_dir);
185 GNUNET_free (home_dir);
186 configured = GNUNET_NO;
187 }
188
189 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO,
190 "mysql",
191 _ ("Trying to use file `%s' for MySQL configuration.\n"),
192 cnffile);
193 if ((0 != stat (cnffile, &st)) || (0 != access (cnffile, R_OK)) ||
194 (! S_ISREG (st.st_mode)))
195 {
196 if (configured == GNUNET_YES)
197 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
198 "mysql",
199 _ ("Could not access file `%s': %s\n"),
200 cnffile,
201 strerror (errno));
202 GNUNET_free (cnffile);
203 return NULL;
204 }
205 return cnffile;
206}
207
208
209/**
210 * Open the connection with the database (and initialize
211 * our default options).
212 *
213 * @param mc database context to initialize
214 * @return #GNUNET_OK on success
215 */
216static int
217iopen (struct GNUNET_MYSQL_Context *mc)
218{
219 char *mysql_dbname;
220 char *mysql_server;
221 char *mysql_user;
222 char *mysql_password;
223 unsigned long long mysql_port;
224 MYSQL_BOOL reconnect;
225 unsigned int timeout;
226
227 mc->dbf = mysql_init (NULL);
228 if (mc->dbf == NULL)
229 return GNUNET_SYSERR;
230 if (mc->cnffile != NULL)
231 mysql_options (mc->dbf, MYSQL_READ_DEFAULT_FILE, mc->cnffile);
232 mysql_options (mc->dbf, MYSQL_READ_DEFAULT_GROUP, "client");
233 reconnect = 0;
234 mysql_options (mc->dbf, MYSQL_OPT_RECONNECT, &reconnect);
235 mysql_options (mc->dbf, MYSQL_OPT_CONNECT_TIMEOUT, (const void *) &timeout);
236 mysql_options (mc->dbf, MYSQL_SET_CHARSET_NAME, "UTF8");
237 timeout = 60; /* in seconds */
238 mysql_options (mc->dbf, MYSQL_OPT_READ_TIMEOUT, (const void *) &timeout);
239 mysql_options (mc->dbf, MYSQL_OPT_WRITE_TIMEOUT, (const void *) &timeout);
240 mysql_dbname = NULL;
241 if (GNUNET_YES ==
242 GNUNET_CONFIGURATION_have_value (mc->cfg, mc->section, "DATABASE"))
243 GNUNET_assert (GNUNET_OK ==
244 GNUNET_CONFIGURATION_get_value_string (mc->cfg,
245 mc->section,
246 "DATABASE",
247 &mysql_dbname));
248 else
249 mysql_dbname = GNUNET_strdup ("gnunet");
250 mysql_user = NULL;
251 if (GNUNET_YES ==
252 GNUNET_CONFIGURATION_have_value (mc->cfg, mc->section, "USER"))
253 {
254 GNUNET_assert (GNUNET_OK ==
255 GNUNET_CONFIGURATION_get_value_string (mc->cfg,
256 mc->section,
257 "USER",
258 &mysql_user));
259 }
260 mysql_password = NULL;
261 if (GNUNET_YES ==
262 GNUNET_CONFIGURATION_have_value (mc->cfg, mc->section, "PASSWORD"))
263 {
264 GNUNET_assert (GNUNET_OK ==
265 GNUNET_CONFIGURATION_get_value_string (mc->cfg,
266 mc->section,
267 "PASSWORD",
268 &mysql_password));
269 }
270 mysql_server = NULL;
271 if (GNUNET_YES ==
272 GNUNET_CONFIGURATION_have_value (mc->cfg, mc->section, "HOST"))
273 {
274 GNUNET_assert (GNUNET_OK ==
275 GNUNET_CONFIGURATION_get_value_string (mc->cfg,
276 mc->section,
277 "HOST",
278 &mysql_server));
279 }
280 mysql_port = 0;
281 if (GNUNET_YES ==
282 GNUNET_CONFIGURATION_have_value (mc->cfg, mc->section, "PORT"))
283 {
284 GNUNET_assert (GNUNET_OK ==
285 GNUNET_CONFIGURATION_get_value_number (mc->cfg,
286 mc->section,
287 "PORT",
288 &mysql_port));
289 }
290
291 GNUNET_assert (mysql_dbname != NULL);
292 mysql_real_connect (mc->dbf,
293 mysql_server,
294 mysql_user,
295 mysql_password,
296 mysql_dbname,
297 (unsigned int) mysql_port,
298 NULL,
299 CLIENT_IGNORE_SIGPIPE);
300 GNUNET_free (mysql_server);
301 GNUNET_free (mysql_user);
302 GNUNET_free (mysql_password);
303 GNUNET_free (mysql_dbname);
304 if (mysql_error (mc->dbf)[0])
305 {
306 LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR, "mysql_real_connect", mc);
307 return GNUNET_SYSERR;
308 }
309 return GNUNET_OK;
310}
311
312
313/**
314 * Create a mysql context.
315 *
316 * @param cfg configuration
317 * @param section configuration section to use to get MySQL configuration options
318 * @return the mysql context
319 */
320struct GNUNET_MYSQL_Context *
321GNUNET_MYSQL_context_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
322 const char *section)
323{
324 struct GNUNET_MYSQL_Context *mc;
325
326 mc = GNUNET_new (struct GNUNET_MYSQL_Context);
327 mc->cfg = cfg;
328 mc->section = section;
329 mc->cnffile = get_my_cnf_path (cfg, section);
330
331 return mc;
332}
333
334
335/**
336 * Close database connection and all prepared statements (we got a DB
337 * error).
338 *
339 * @param mc mysql context
340 */
341void
342GNUNET_MYSQL_statements_invalidate (struct GNUNET_MYSQL_Context *mc)
343{
344 struct GNUNET_MYSQL_StatementHandle *sh;
345
346 for (sh = mc->shead; NULL != sh; sh = sh->next)
347 {
348 if (GNUNET_YES == sh->valid)
349 {
350 mysql_stmt_close (sh->statement);
351 sh->valid = GNUNET_NO;
352 }
353 sh->statement = NULL;
354 }
355 if (NULL != mc->dbf)
356 {
357 mysql_close (mc->dbf);
358 mc->dbf = NULL;
359 }
360}
361
362
363/**
364 * Destroy a mysql context. Also frees all associated prepared statements.
365 *
366 * @param mc context to destroy
367 */
368void
369GNUNET_MYSQL_context_destroy (struct GNUNET_MYSQL_Context *mc)
370{
371 struct GNUNET_MYSQL_StatementHandle *sh;
372
373 GNUNET_MYSQL_statements_invalidate (mc);
374 while (NULL != (sh = mc->shead))
375 {
376 GNUNET_CONTAINER_DLL_remove (mc->shead, mc->stail, sh);
377 GNUNET_free (sh->query);
378 GNUNET_free (sh);
379 }
380 GNUNET_free (mc);
381 mysql_library_end ();
382}
383
384
385/**
386 * Prepare a statement. Prepared statements are automatically discarded
387 * when the MySQL context is destroyed.
388 *
389 * @param mc mysql context
390 * @param query query text
391 * @return prepared statement, NULL on error
392 */
393struct GNUNET_MYSQL_StatementHandle *
394GNUNET_MYSQL_statement_prepare (struct GNUNET_MYSQL_Context *mc,
395 const char *query)
396{
397 struct GNUNET_MYSQL_StatementHandle *sh;
398
399 sh = GNUNET_new (struct GNUNET_MYSQL_StatementHandle);
400 sh->mc = mc;
401 sh->query = GNUNET_strdup (query);
402 GNUNET_CONTAINER_DLL_insert (mc->shead, mc->stail, sh);
403 return sh;
404}
405
406
407/**
408 * Run a SQL statement.
409 *
410 * @param mc mysql context
411 * @param sql SQL statement to run
412 * @return #GNUNET_OK on success
413 * #GNUNET_SYSERR if there was a problem
414 */
415int
416GNUNET_MYSQL_statement_run (struct GNUNET_MYSQL_Context *mc, const char *sql)
417{
418 if ((NULL == mc->dbf) && (GNUNET_OK != iopen (mc)))
419 return GNUNET_SYSERR;
420 mysql_query (mc->dbf, sql);
421 if (mysql_error (mc->dbf)[0])
422 {
423 LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR, "mysql_query", mc);
424 GNUNET_MYSQL_statements_invalidate (mc);
425 return GNUNET_SYSERR;
426 }
427 return GNUNET_OK;
428}
429
430
431/**
432 * Prepare a statement for running.
433 *
434 * @param sh statement handle to prepare
435 * @return #GNUNET_OK on success
436 */
437static int
438prepare_statement (struct GNUNET_MYSQL_StatementHandle *sh)
439{
440 struct GNUNET_MYSQL_Context *mc = sh->mc;
441
442 if (GNUNET_YES == sh->valid)
443 return GNUNET_OK;
444 if ((NULL == mc->dbf) && (GNUNET_OK != iopen (mc)))
445 return GNUNET_SYSERR;
446 sh->statement = mysql_stmt_init (mc->dbf);
447 if (NULL == sh->statement)
448 {
449 GNUNET_MYSQL_statements_invalidate (mc);
450 return GNUNET_SYSERR;
451 }
452 if (0 != mysql_stmt_prepare (sh->statement, sh->query, strlen (sh->query)))
453 {
454 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
455 "mysql",
456 "prepare_statement: %s\n",
457 sh->query);
458 LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR, "mysql_stmt_prepare", mc);
459 mysql_stmt_close (sh->statement);
460 sh->statement = NULL;
461 GNUNET_MYSQL_statements_invalidate (mc);
462 return GNUNET_SYSERR;
463 }
464 sh->valid = GNUNET_YES;
465 return GNUNET_OK;
466}
467
468
469/**
470 * Get internal handle for a prepared statement. This function should rarely
471 * be used, and if, with caution! On failures during the interaction with
472 * the handle, you must call 'GNUNET_MYSQL_statements_invalidate'!
473 *
474 * @param sh prepared statement to introspect
475 * @return MySQL statement handle, NULL on error
476 */
477MYSQL_STMT *
478GNUNET_MYSQL_statement_get_stmt (struct GNUNET_MYSQL_StatementHandle *sh)
479{
480 (void) prepare_statement (sh);
481 return sh->statement;
482}
483
484
485/* end of mysql.c */
diff --git a/src/regex/Makefile.am b/src/regex/Makefile.am
index a6c9c0903..b7d14bc41 100644
--- a/src/regex/Makefile.am
+++ b/src/regex/Makefile.am
@@ -78,21 +78,20 @@ libgnunet_plugin_block_regex_la_LDFLAGS = \
78 $(GN_LIBINTL) \ 78 $(GN_LIBINTL) \
79 $(GN_PLUGIN_LDFLAGS) 79 $(GN_PLUGIN_LDFLAGS)
80 80
81if HAVE_MYSQL 81# FIXME we phased out mysql. If we want to keep, needs rewrite
82noinst_mysql_progs = \ 82#if HAVE_MYSQL
83 gnunet-regex-simulation-profiler 83#noinst_mysql_progs = \
84 84# gnunet-regex-simulation-profiler
85gnunet_regex_simulation_profiler_SOURCES = \ 85
86 $(REGEX_INTERNAL) gnunet-regex-simulation-profiler.c 86#gnunet_regex_simulation_profiler_SOURCES = \
87gnunet_regex_simulation_profiler_LDADD = \ 87# $(REGEX_INTERNAL) gnunet-regex-simulation-profiler.c
88 libgnunetregexblock.la \ 88#gnunet_regex_simulation_profiler_LDADD = \
89 $(top_builddir)/src/util/libgnunetutil.la \ 89# libgnunetregexblock.la \
90 $(top_builddir)/src/dht/libgnunetdht.la \ 90# $(top_builddir)/src/util/libgnunetutil.la \
91 $(top_builddir)/src/my/libgnunetmy.la \ 91# $(top_builddir)/src/dht/libgnunetdht.la \
92 $(top_builddir)/src/mysql/libgnunetmysql.la \ 92# $(top_builddir)/src/block/libgnunetblock.la \
93 $(top_builddir)/src/block/libgnunetblock.la \ 93# $(top_builddir)/src/statistics/libgnunetstatistics.la
94 $(top_builddir)/src/statistics/libgnunetstatistics.la 94#endif
95endif
96 95
97noinst_PROGRAMS = $(noinst_mysql_progs) \ 96noinst_PROGRAMS = $(noinst_mysql_progs) \
98 perf-regex \ 97 perf-regex \