aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2010-08-13 19:43:17 +0000
committerChristian Grothoff <christian@grothoff.org>2010-08-13 19:43:17 +0000
commit54edcbe9ce37e934a0d045fdde27e9caa3ac145a (patch)
tree1f87dffbbb93f09bb4d0b606022ad9595d11bad8
parent2151b951b91971bd9c906b12ab940b0ee0038001 (diff)
downloadgnunet-54edcbe9ce37e934a0d045fdde27e9caa3ac145a.tar.gz
gnunet-54edcbe9ce37e934a0d045fdde27e9caa3ac145a.zip
mysql hackery
-rw-r--r--README56
-rw-r--r--TODO150
-rw-r--r--contrib/defaults.conf8
-rw-r--r--src/datacache/Makefile.am70
-rw-r--r--src/datacache/perf_datacache.c52
-rw-r--r--src/datacache/perf_datacache_data_mysql.conf12
-rw-r--r--src/datacache/perf_datacache_data_sqlite.conf (renamed from src/datacache/perf_datacache_data.conf)0
-rw-r--r--src/datacache/plugin_datacache_mysql.c1092
-rw-r--r--src/datacache/test_datacache.c50
-rw-r--r--src/datacache/test_datacache_data_mysql.conf12
-rw-r--r--src/datacache/test_datacache_data_sqlite.conf (renamed from src/datacache/test_datacache_data.conf)0
-rw-r--r--src/datacache/test_datacache_quota.c50
-rw-r--r--src/datastore/Makefile.am4
-rw-r--r--src/datastore/plugin_datastore_mysql.c40
14 files changed, 1385 insertions, 211 deletions
diff --git a/README b/README
index 905d97d3b..2bf9f6e27 100644
--- a/README
+++ b/README
@@ -19,17 +19,23 @@ https://gnunet.org/.
19Dependencies: 19Dependencies:
20============= 20=============
21 21
22For the impatient, here is the list of immediate dependencies for 22Please note that for many of its dependencies GNUnet requires very
23running GNUnet: 23recent versions of the libraries which are often NOT to be found in
24stable distributions in 2010. While using older packages may in some
25cases on some operating systems may seem to work in some limited
26fashion, we are in many cases aware of serious problems with older
27packages. Hence please make sure to use the versions listed below.
28
29These are the direct dependencies for running GNUnet:
24 30
25- libextractor >= 0.6.1 31- libextractor >= 0.6.1
26- libmicrohttpd >= 0.4.6 32- libmicrohttpd >= 0.9.0
27- libgcrypt >= 1.2 33- libgcrypt >= 1.2
28- libgmp >= 4.0 34- libgmp >= 4.0
29- libcurl >= 7.15.4 35- libcurl >= 7.21.0
30- libltdl >= 2.2 (part of GNU libtool) 36- libltdl >= 2.2 (part of GNU libtool)
31- sqlite >= 3.0 (alternative to MySQL) 37- sqlite >= 3.0 (alternative to MySQL)
32- mysql >= ??? (not yet supported) 38- mysql >= 5.1 (alternative to sqLite)
33- postgres >= ??? (not yet supported) 39- postgres >= ??? (not yet supported)
34 40
35Recommended autotools for compiling the SVN version are: 41Recommended autotools for compiling the SVN version are:
@@ -37,8 +43,6 @@ Recommended autotools for compiling the SVN version are:
37- automake >= 1.11.1 43- automake >= 1.11.1
38- libtool >= 2.2 44- libtool >= 2.2
39 45
40See also README.debian for a list of Debian packages.
41
42 46
43How to install? 47How to install?
44=============== 48===============
@@ -47,6 +51,12 @@ The fastest way is to use a binary package if it is available for your
47system. For a more detailed description, read the installation 51system. For a more detailed description, read the installation
48instructions on the webpage at https://gnunet.org/installation. 52instructions on the webpage at https://gnunet.org/installation.
49 53
54Note that some functions of GNUnet require "root" access. GNUnet will
55install (tiny) SUID binaries for those functions is you run "make
56install" as root. If you do not, GNUnet will still work, but some
57functionality will not be available (including certain forms of NAT
58traversal).
59
50GNUnet requires the GNU MP library (http://www.gnu.org/software/gmp/) 60GNUnet requires the GNU MP library (http://www.gnu.org/software/gmp/)
51and libgcrypt (http://www.gnupg.org/). You can specify the path to 61and libgcrypt (http://www.gnupg.org/). You can specify the path to
52libgcrypt by passing "--with-gcrypt=PATH" to configure. You will also 62libgcrypt by passing "--with-gcrypt=PATH" to configure. You will also
@@ -195,20 +205,30 @@ testcase to the Mantis bugtracking system at
195https://gnunet.org/bugs/. 205https://gnunet.org/bugs/.
196 206
197 207
198Running http on port 80 208Running http on port 80 and https on port 443
199======================= 209=============================================
200 210
201In order to hide GNUnet's HTTP traffic perfectly, you might consider 211In order to hide GNUnet's HTTP/HTTPS traffic perfectly, you might
202running GNUnet's HTTP transport on port 80. However, we do not 212consider running GNUnet's HTTP/HTTPS transport on port 80/443.
203recommend running GNUnet as root. Instead, forward port 80 to say 213However, we do not recommend running GNUnet as root. Instead, forward
2048080 with this command (as root, in your startup scripts): 214port 80 to say 8080 with this command (as root, in your startup
215scripts):
205 216
206# iptables -t nat -A PREROUTING -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 8080 217# iptables -t nat -A PREROUTING -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 8080
207 218
208Then set in the HTTP section of gnunet.conf the "ADVERTISED-PORT" 219or for HTTPS
209to "80" and "PORT" to 8080. You can do the same trick for the 220
210TCP and UDP transports if you want to map them to a priviledged 221# iptables -t nat -A PREROUTING -p tcp -m tcp --dport 443 -j REDIRECT --to-ports 4433
211port (from the point of view of the network). 222
223Then set in the HTTP section of gnunet.conf the "ADVERTISED-PORT" to
224"80" and "PORT" to 8080 and similarly in the HTTPS section the
225"ADVERTISED-PORT" to "443" and "PORT" to 4433.
226
227You can do the same trick for the TCP and UDP transports if you want
228to map them to a priviledged port (from the point of view of the
229network). However, we are not aware of this providing any advantages
230at this point.
231
212 232
213 233
214Running the SMTP transport 234Running the SMTP transport
@@ -218,7 +238,7 @@ Running the SMTP transport
218Running GNUnet over SMTP (e-mail) is a bit more involved. Note that 238Running GNUnet over SMTP (e-mail) is a bit more involved. Note that
219you do not need to run all transports (only running the NAT transport 239you do not need to run all transports (only running the NAT transport
220is the only thing that will not work). If you really want to do 240is the only thing that will not work). If you really want to do
221P2P over SMTP, read the instructions at http://gnunet.org/smtp.php3 241P2P over SMTP, read the instructions at http://gnunet.org/smtp
222 242
223 243
224Stay tuned 244Stay tuned
diff --git a/TODO b/TODO
index 369528688..c6906eef6 100644
--- a/TODO
+++ b/TODO
@@ -3,6 +3,7 @@
3 - only connect() sockets that are ready (select()) [Nils] 3 - only connect() sockets that are ready (select()) [Nils]
4 [On W32, we need to select after calling socket before doing connect etc.] 4 [On W32, we need to select after calling socket before doing connect etc.]
5* CORE: 5* CORE:
6 - derived key generation [Nils]
6 - Jun 27 11:51:54 core-7670 ERROR Assertion failed at gnunet-service-core.c:3616. 7 - Jun 27 11:51:54 core-7670 ERROR Assertion failed at gnunet-service-core.c:3616.
7 (transport notified us that we connected to ourselves!!!) 8 (transport notified us that we connected to ourselves!!!)
8 - transport-level disconnect (i.e. TCP) does not cause core-level 9 - transport-level disconnect (i.e. TCP) does not cause core-level
@@ -12,36 +13,34 @@
12 => may have been fixed with instant-notification of disconnect 13 => may have been fixed with instant-notification of disconnect
13 to core on session-oriented connection hick-up; not perfect but 14 to core on session-oriented connection hick-up; not perfect but
14 likely good enough until we get ATS going; still should be tested... 15 likely good enough until we get ATS going; still should be tested...
15 => "peers connected (transport)" now instantly goes to ZERO (core statistic), 16` => "peers connected (transport)" now instantly goes to ZERO (core statistic),
16 but "established sessions" stays up... 17 but "established sessions" stays up...
17 - derived key generation [Nils] 18 * PWNAT: [Nate/MW/Nils]
18* PWNAT: [Nate/MW/Nils]
19 - W32 port 19 - W32 port
20* GNUNET-GTK: [CG] 20* GNUNET-GTK: [CG]
21 - bugs: 21 - handle 'lost parent' case for recursive downloads (need to move children!)
22 + handle 'lost parent' case for recursive downloads (need to move children!)
23 22
240.9.0pre3: 230.9.0pre3:
25* Determine RC bugs and fix those! 24* Determine RC bugs and fix those (release should have no known real bugs)
26* DATASTORE: [LT] 25* DATASTORE: [LT]
27 - GNUNET_DATASTORE_cancel method not tested [LT] 26 - GNUNET_DATASTORE_cancel method not tested [LT]
28* TESTING: [Nate] 27* TESTING: [Nate]
29 - test basic peer re-configure 28 - test basic peer re-configure
30 - consider changing API for peer-group termination to 29* TOPOLOGY: [Nate]
31 call continuation when done
32* TOPOLOGY:
33 - needs more testing (especially F2F topology) & transport blacklisting 30 - needs more testing (especially F2F topology) & transport blacklisting
31* TRANSPORT-TCP [MW]:
32 - should use hash map to look up sessions
34* NAT/UPNP: [MW] 33* NAT/UPNP: [MW]
35 - finalize API design 34 - finalize API design
36 - code clean up 35 - code clean up
37 - testing 36 - testing
38 - integration with transport service 37 - integration with transport service
39* MYSQL database backends: [CG] 38 - also do UPnP-based (external) IP detection
40 - datacache 39 (Note: build library always, build UPnP service when dependencies like libxml2 are available)
41* FS: [CG] 40* FS: [CG]
42 - library: 41 - library:
43 + reconstruct IBLOCKS from DBLOCKS if possible (during download; see FIXME in fs_download) 42 + reconstruct IBLOCKS from DBLOCKS if possible (during download; see FIXME in fs_download)
44 + add support for pushing "already seen" search results to FS service for bloomfilter (can wait) 43 + add support for pushing "already seen" search results to FS service for bloomfilter
45 + use different 'priority' for probe downloads vs. normal downloads 44 + use different 'priority' for probe downloads vs. normal downloads
46 - service: 45 - service:
47 + trust: do not charge when "idle" / load considerations (migration, routing) 46 + trust: do not charge when "idle" / load considerations (migration, routing)
@@ -56,25 +55,26 @@
56 + download 55 + download
57 + search 56 + search
58 + unindex 57 + unindex
59* ARM: [CG/Safey] 58 - re-implement gnunet-auto-share
60 - better tracking of which config changes actually need to cause process restarts by ARM.
61 - handle gnunet-arm -k in combination with auto-start magic (what is the right thing here?)
62 - discover dependencies between services
63* GNUNET-GTK: 59* GNUNET-GTK:
64 - optimize meta-data for directories in 'add_dir_at_iter' 60 - optimize meta-data for directories in 'add_dir_at_iter'
65 - add progress dialog for 'add_dir_at_iter' scan (can take a while...)
66 - finish publish dialog details: 61 - finish publish dialog details:
67 + normalize keywords (edit subdialog) 62 + normalize keywords (edit subdialog)
68 + set/view previews (edit subdialog) 63 + set/view previews (edit subdialog)
69 - add tool bar
70 - implement download by URI dialog; figure out where to display those downloads! 64 - implement download by URI dialog; figure out where to display those downloads!
71 - figure out where in the GUI we should show active uploads/unindex operations and allow aborts 65 - figure out where in the GUI we should show active uploads/unindex operations and allow aborts
72 - implement unindex operation (use dialog with all indexed files for selection) 66 - implement unindex operation (use dialog with all indexed files for selection)
73 - do meaningful update to status line (starting up, peer running, #connections, shutdown, ...)
74 - events: 67 - events:
75 + search error 68 + search error
76 + publish error 69 + publish error
77 + unindex error 70 + unindex error
71* POSTGRES database backends: [CG]
72 - datacache
73 - datastore
74* ARM: [CG/Safey]
75 - better tracking of which config changes actually need to cause process restarts by ARM.
76 - handle gnunet-arm -k in combination with auto-start magic (what is the right thing here?)
77 - discover dependencies between services
78* MONKEY: [Safey] 78* MONKEY: [Safey]
79 - better crash management (attach debugging support, capture and analyze 79 - better crash management (attach debugging support, capture and analyze
80 debug output, detect random vs. deterministic crashes) 80 debug output, detect random vs. deterministic crashes)
@@ -82,38 +82,26 @@
82 - '-f FILENAME' option to write report to file instead of e-mail (for testing!) 82 - '-f FILENAME' option to write report to file instead of e-mail (for testing!)
83 83
840.9.0: 840.9.0:
85* new webpage: 85* Determine RC bugs and fix those (release should have no known real bugs)
86* new webpage: [BL]
86 - convert documentation pages to books 87 - convert documentation pages to books
87 - update books (especially for developers) 88 - update books (especially for developers)
88 - make a NICE download page and figure out how to enable developers to publish TGZs nicely 89 - make a NICE download page and figure out how to enable developers to publish TGZs nicely
89 - port "contact" page 90 - port "contact" page
90 - add content type for "todo" items? 91 - add content type for "todo" items
91* POSTGRES database backends: [CG] 92* SETUP: [CG]
92 - datacache
93 - datastore
94* Determine RC bugs and fix those!
95* SETUP:
96 - design & implement new setup tool 93 - design & implement new setup tool
97* TBENCH: [MW] 94* TBENCH: [MW]
98 - good to have for transport/DV evaluation! 95 - good to have for transport/DV evaluation!
99* TRACEKIT: [MW] 96* TRACEKIT: [MW]
100 - good to have for DV/DHT evaluation! 97 - good to have for DHT evaluation!
101* DV:
102 - performance tests
103* DHT: [Nate] 98* DHT: [Nate]
104 - performance tests 99 - performance tests
105* STATISTICS:
106 - test notification-based statistics API [LT]
107 - implement statistics GUI
108* PEERINFO: [NN]
109 - move peerinfo to new GUI?
110 - extend peer dialog with green-yellow-red connectivity status lights
111 - extend peer dialog with country flags and names
112 100
1130.9.x: 1010.9.1:
114* TRANSPORT: [MW] 102* TRANSPORT: [MW]
115 - WiFi transport backend [DB] 103 - WiFi transport backend [DB]
116 - SMTP transport backend 104 - implement gnunet-transport (transport configurator / tester)
117 - Implement method of learning our external addresses from 105 - Implement method of learning our external addresses from
118 other peers; need some kind of threshold-based 106 other peers; need some kind of threshold-based
119 scheme, limiting both the total number of addresses that we accept 107 scheme, limiting both the total number of addresses that we accept
@@ -129,50 +117,70 @@
129 a way to easily "veto" addresses off the list! 117 a way to easily "veto" addresses off the list!
130 => If MiM attacker uses vetoed address, blacklist the specific IP for 118 => If MiM attacker uses vetoed address, blacklist the specific IP for
131 the presumed neighbour! 119 the presumed neighbour!
132 - implement gnunet-transport (transport configurator / tester)
133 - UPnP-based IP detection
134 (Note: build library always, build service when libxml2/etc. are available)
135* DV:
136 - proper bandwidth allocation
137* FS: [CG]
138 - Remove KBlocks in gnunet-unindex (see discussion with Kenneth Almquist on gnunet-devs in 9/2009)
139* PEERINFO: [NN]
140 - expire 'ancient' HELLOs (those without valid addresses AND that
141 we have not 'used' (for their public keys) in a while; need a way
142 to track actual 'use')
143 - make sue we also trigger notifications whenever HELLOs expire
144* VPN [PT]
145* UTIL: [CG]
146 - allow limiting UNIX socket access by UID/GID
147
148
149
150Optimizations:
151* TCP:
152 - should use hash map to look up sessions
153* STATISTICS:
154 - should use BIO instead of mmap
155* TRANSPORT:
156 - need to periodically probe latency/transport cost changes & possibly switch transport 120 - need to periodically probe latency/transport cost changes & possibly switch transport
157 - should use hash map to look up Neighbours (service AND plugins!) 121 - should use hash map to look up Neighbours (service AND plugins!)
122* DV: [Nate]
123 - proper bandwidth allocation
124 - performance tests
158* PEERINFO: 125* PEERINFO:
159 - merge multiple HELLOs of the same peer in the transmission queue 126 - merge multiple HELLOs of the same peer in the transmission queue
160 (theoretically reduces overhead; bounds message queue size) 127 (theoretically reduces overhead; bounds message queue size)
161 - merge multiple iteration requests over "all" peers in the queue 128 - merge multiple iteration requests over "all" peers in the queue
162 (theoretically reduces overhead; bounds messgae queue size) 129 (theoretically reduces overhead; bounds messgae queue size)
163* FS: 130* STATISTICS: [CG]
164 - use different queue prioritization for probe-downloads vs. normal downloads (!?) 131 - should use BIO instead of mmap
132* FS: [CG]
133 - Remove KBlocks in gnunet-unindex (see discussion with Kenneth Almquist on gnunet-devs in 9/2009)
134 - use different queue prioritization for probe-downloads vs. normal downloads
135* UTIL: [CG]
136 - allow limiting UNIX socket access by UID/GID
137* GNUNET-GTK: [CG]
138 - add tool bar
139 - do meaningful update to status line (starting up, peer running, #connections, shutdown, ...)
140 - add progress dialog for 'add_dir_at_iter' scan (can take a while...)
141 - NS list in search dialog should use colors to offset our own namespaces from the others
142 - right-clicking on NS list in search dialog should open menu that allows
143 * viewing full meta data
144 * deletion of namespace info
165 145
166Minor features: 1460.9.2:
147* PEERINFO: [NN]
148 - expire 'ancient' HELLOs (those without valid addresses AND that
149 we have not 'used' (for their public keys) in a while; need a way
150 to track actual 'use')
151 - make sue we also trigger notifications whenever HELLOs expire
167* TCP: 152* TCP:
168 - repeatedly resolve hostname and look up interfaces to determine our own IP 153 - repeatedly resolve hostname and look up interfaces to determine our own IP
169 - [./transport/plugin_transport_tcp.c:391]: (style) struct or union member 'Plugin::address_update_task' is never used (related to issue above) 154 - [./transport/plugin_transport_tcp.c:391]: (style) struct or union member 'Plugin::address_update_task' is never used (related to issue above)
170* TRANSPORT: 155* TRANSPORT:
171 - [./transport/gnunet-service-transport.c:173]: (style) struct or union member 'TransportPlugin::rebuild' is never used (related to TCP not refreshing external addresses?) 156 - [./transport/gnunet-service-transport.c:173]: (style) struct or union member 'TransportPlugin::rebuild' is never used (related to TCP not refreshing external addresses?)
157 - WiFi transport backend
158 * nice signal strength adjustment [MW]
159 * energy cost in ATS [MW]
172* BLOCKS: 160* BLOCKS:
173 - testcase would be nice... 161 - testcase would be nice
174* GNUNET-GTK: 162 - generic block support for DHT
175 - NS list in search dialog should use colors to offset our own namespaces from the others 163* STATISTICS:
176 - right-clicking on NS list in search dialog should open menu that allows 164 - test notification-based statistics API [LT]
177 * viewing full meta data 165 - implement statistics GUI (=> start from gnunet-gtk by button!)
178 * deletion of namespace info 166* PEERINFO: [NN]
167 - move peerinfo to new GUI (=> start from gnunet-gtk by button!)
168 - extend peer dialog with green-yellow-red connectivity status lights
169 - extend peer dialog with country flags and names
170
1710.9.3:
172* SMTP transport backend:
173 - sending (SMTP/SMTPS)
174 - receiving (IMAP/IMAPS/POP?)
175 - rate limiting
176 - improved batching
177 - resource limit integration with ATS
178* VPN [PT]
179 - DNS hijacking
180 - DNS exit
181 - TCP entry/exit
182 - UDP entry/exit
183 - internal services
184 - integration with DHT routing
185 - optimized routes (beyond DHT/DV)
186 - "DNS" .gnunet
diff --git a/contrib/defaults.conf b/contrib/defaults.conf
index 74efa2260..94d64d932 100644
--- a/contrib/defaults.conf
+++ b/contrib/defaults.conf
@@ -205,6 +205,14 @@ USER = gnunet
205# HOST = 205# HOST =
206# PORT = 206# PORT =
207 207
208[datacache-mysql]
209DATABASE = gnunetcheck
210# CONFIG = ~/.my.cnf
211USER = gnunet
212# PASSWORD =
213# HOST =
214# PORT =
215
208[fs] 216[fs]
209AUTOSTART = YES 217AUTOSTART = YES
210INDEXDB = $SERVICEHOME/idxinfo.lst 218INDEXDB = $SERVICEHOME/idxinfo.lst
diff --git a/src/datacache/Makefile.am b/src/datacache/Makefile.am
index a10343046..0598c2673 100644
--- a/src/datacache/Makefile.am
+++ b/src/datacache/Makefile.am
@@ -14,6 +14,9 @@ endif
14if HAVE_SQLITE 14if HAVE_SQLITE
15 SQLITE_PLUGIN = libgnunet_plugin_datacache_sqlite.la 15 SQLITE_PLUGIN = libgnunet_plugin_datacache_sqlite.la
16endif 16endif
17if HAVE_MYSQL
18 MYSQL_PLUGIN = libgnunet_plugin_datacache_mysql.la
19endif
17 20
18lib_LTLIBRARIES = \ 21lib_LTLIBRARIES = \
19 libgnunetdatacache.la 22 libgnunetdatacache.la
@@ -31,6 +34,7 @@ libgnunetdatacache_la_LDFLAGS = \
31 34
32plugin_LTLIBRARIES = \ 35plugin_LTLIBRARIES = \
33 $(SQLITE_PLUGIN) \ 36 $(SQLITE_PLUGIN) \
37 $(MYSQL_PLUGIN) \
34 libgnunet_plugin_datacache_template.la 38 libgnunet_plugin_datacache_template.la
35 39
36 40
@@ -42,6 +46,17 @@ libgnunet_plugin_datacache_sqlite_la_LIBADD = \
42libgnunet_plugin_datacache_sqlite_la_LDFLAGS = \ 46libgnunet_plugin_datacache_sqlite_la_LDFLAGS = \
43 $(GN_PLUGIN_LDFLAGS) 47 $(GN_PLUGIN_LDFLAGS)
44 48
49libgnunet_plugin_datacache_mysql_la_SOURCES = \
50 plugin_datacache_mysql.c
51libgnunet_plugin_datacache_mysql_la_LIBADD = \
52 $(top_builddir)/src/statistics/libgnunetstatistics.la \
53 $(top_builddir)/src/util/libgnunetutil.la \
54 $(GN_PLUGIN_LDFLAGS) $(MYSQL_LDFLAGS) -lmysqlclient
55libgnunet_plugin_datacache_mysql_la_CPPFLAGS = \
56 $(MYSQL_CPPFLAGS)
57libgnunet_plugin_datacache_mysql_la_LDFLAGS = \
58 $(GN_PLUGIN_LDFLAGS) $(MYSQL_LDFLAGS) -lmysqlclient
59
45libgnunet_plugin_datacache_template_la_SOURCES = \ 60libgnunet_plugin_datacache_template_la_SOURCES = \
46 plugin_datacache_template.c 61 plugin_datacache_template.c
47libgnunet_plugin_datacache_template_la_LIBADD = \ 62libgnunet_plugin_datacache_template_la_LIBADD = \
@@ -51,36 +66,65 @@ libgnunet_plugin_datacache_template_la_LDFLAGS = \
51 66
52 67
53if HAVE_SQLITE 68if HAVE_SQLITE
54 SQLITE_TESTS = \ 69SQLITE_TESTS = \
55 test_datacache \ 70 test_datacache_sqlite \
56 test_datacache_quota \ 71 test_datacache_quota_sqlite \
57 perf_datacache 72 perf_datacache_sqlite
58endif 73endif
59 74
60check_PROGRAMS = $(SQLITE_TESTS) 75if HAVE_MYSQL
76MYSQL_TESTS = \
77 test_datacache_mysql \
78 test_datacache_quota_mysql \
79 perf_datacache_mysql
80endif
81
82check_PROGRAMS = \
83 $(SQLITE_TESTS) \
84 $(MYSQL_TESTS)
61 85
62if !DISABLE_TEST_RUN 86if !DISABLE_TEST_RUN
63TESTS = $(check_PROGRAMS) 87TESTS = $(check_PROGRAMS)
64endif 88endif
65 89
66test_datacache_SOURCES = \ 90test_datacache_sqlite_SOURCES = \
91 test_datacache.c
92test_datacache_sqlite_LDADD = \
93 $(top_builddir)/src/datacache/libgnunetdatacache.la \
94 $(top_builddir)/src/util/libgnunetutil.la
95
96test_datacache_quota_sqlite_SOURCES = \
97 test_datacache_quota.c
98test_datacache_quota_sqlite_LDADD = \
99 $(top_builddir)/src/datacache/libgnunetdatacache.la \
100 $(top_builddir)/src/util/libgnunetutil.la
101
102perf_datacache_sqlite_SOURCES = \
103 perf_datacache.c
104perf_datacache_sqlite_LDADD = \
105 $(top_builddir)/src/datacache/libgnunetdatacache.la \
106 $(top_builddir)/src/util/libgnunetutil.la
107
108test_datacache_mysql_SOURCES = \
67 test_datacache.c 109 test_datacache.c
68test_datacache_LDADD = \ 110test_datacache_mysql_LDADD = \
69 $(top_builddir)/src/datacache/libgnunetdatacache.la \ 111 $(top_builddir)/src/datacache/libgnunetdatacache.la \
70 $(top_builddir)/src/util/libgnunetutil.la 112 $(top_builddir)/src/util/libgnunetutil.la
71 113
72test_datacache_quota_SOURCES = \ 114test_datacache_quota_mysql_SOURCES = \
73 test_datacache_quota.c 115 test_datacache_quota.c
74test_datacache_quota_LDADD = \ 116test_datacache_quota_mysql_LDADD = \
75 $(top_builddir)/src/datacache/libgnunetdatacache.la \ 117 $(top_builddir)/src/datacache/libgnunetdatacache.la \
76 $(top_builddir)/src/util/libgnunetutil.la 118 $(top_builddir)/src/util/libgnunetutil.la
77 119
78perf_datacache_SOURCES = \ 120perf_datacache_mysql_SOURCES = \
79 perf_datacache.c 121 perf_datacache.c
80perf_datacache_LDADD = \ 122perf_datacache_mysql_LDADD = \
81 $(top_builddir)/src/datacache/libgnunetdatacache.la \ 123 $(top_builddir)/src/datacache/libgnunetdatacache.la \
82 $(top_builddir)/src/util/libgnunetutil.la 124 $(top_builddir)/src/util/libgnunetutil.la
83 125
84EXTRA_DIST = \ 126EXTRA_DIST = \
85 test_datacache_data.conf \ 127 test_datacache_data_sqlite.conf \
86 perf_datacache_data.conf 128 perf_datacache_data_sqlite.conf \
129 test_datacache_data_mysql.conf \
130 perf_datacache_data_mysql.conf
diff --git a/src/datacache/perf_datacache.c b/src/datacache/perf_datacache.c
index a577927d0..e2eb474d4 100644
--- a/src/datacache/perf_datacache.c
+++ b/src/datacache/perf_datacache.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 (C) 2006, 2009 Christian Grothoff (and other contributing authors) 3 (C) 2006, 2009, 2010 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -36,6 +36,12 @@ static int ok;
36 36
37static unsigned int found; 37static unsigned int found;
38 38
39/**
40 * Name of plugin under test.
41 */
42static const char *plugin_name;
43
44
39static int 45static int
40checkIt (void *cls, 46checkIt (void *cls,
41 struct GNUNET_TIME_Absolute exp, 47 struct GNUNET_TIME_Absolute exp,
@@ -119,12 +125,15 @@ FAILURE:
119} 125}
120 126
121 127
122static int 128int
123check () 129main (int argc, char *argv[])
124{ 130{
125 char *const argv[] = { "perf-datacache-api", 131 const char *pos;
132 char cfg_name[128];
133 char *const xargv[] = {
134 "perf-datacache",
126 "-c", 135 "-c",
127 "perf_datacache_data.conf", 136 cfg_name,
128#if VERBOSE 137#if VERBOSE
129 "-L", "DEBUG", 138 "-L", "DEBUG",
130#endif 139#endif
@@ -133,31 +142,28 @@ check ()
133 struct GNUNET_GETOPT_CommandLineOption options[] = { 142 struct GNUNET_GETOPT_CommandLineOption options[] = {
134 GNUNET_GETOPT_OPTION_END 143 GNUNET_GETOPT_OPTION_END
135 }; 144 };
136 GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1,
137 argv, "perf-datacache-api", "nohelp",
138 options, &run, NULL);
139 if (ok != 0)
140 fprintf (stderr, "Missed some perfcases: %d\n", ok);
141 return ok;
142}
143
144
145int
146main (int argc, char *argv[])
147{
148 int ret;
149 145
150 GNUNET_DISK_directory_remove ("/tmp/perf-gnunetd-datacache"); 146 GNUNET_log_setup ("perf-datacache",
151 GNUNET_log_setup ("perf-datacache-api",
152#if VERBOSE 147#if VERBOSE
153 "DEBUG", 148 "DEBUG",
154#else 149#else
155 "WARNING", 150 "WARNING",
156#endif 151#endif
157 NULL); 152 NULL);
158 ret = check (); 153 /* determine name of plugin to use */
159 154 plugin_name = argv[0];
160 return ret; 155 while (NULL != (pos = strstr(plugin_name, "_")))
156 plugin_name = pos+1;
157 GNUNET_snprintf (cfg_name,
158 sizeof (cfg_name),
159 "perf_datacache_data_%s.conf",
160 plugin_name);
161 GNUNET_PROGRAM_run ((sizeof (xargv) / sizeof (char *)) - 1,
162 xargv, "perf-datacache", "nohelp",
163 options, &run, NULL);
164 if (ok != 0)
165 fprintf (stderr, "Missed some perfcases: %d\n", ok);
166 return ok;
161} 167}
162 168
163/* end of perf_datacache.c */ 169/* end of perf_datacache.c */
diff --git a/src/datacache/perf_datacache_data_mysql.conf b/src/datacache/perf_datacache_data_mysql.conf
new file mode 100644
index 000000000..5a5f97c63
--- /dev/null
+++ b/src/datacache/perf_datacache_data_mysql.conf
@@ -0,0 +1,12 @@
1
2[perfcache]
3QUOTA = 500000
4DATABASE = mysql
5
6[datacache-mysql]
7DATABASE = gnunetcheck
8# CONFIG = ~/.my.cnf
9# USER =
10# PASSWORD =
11# HOST =
12# PORT = \ No newline at end of file
diff --git a/src/datacache/perf_datacache_data.conf b/src/datacache/perf_datacache_data_sqlite.conf
index 55e178d99..55e178d99 100644
--- a/src/datacache/perf_datacache_data.conf
+++ b/src/datacache/perf_datacache_data_sqlite.conf
diff --git a/src/datacache/plugin_datacache_mysql.c b/src/datacache/plugin_datacache_mysql.c
new file mode 100644
index 000000000..4559a9d39
--- /dev/null
+++ b/src/datacache/plugin_datacache_mysql.c
@@ -0,0 +1,1092 @@
1/*
2 This file is part of GNUnet
3 (C) 2006, 2009, 2010 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file datacache/plugin_datacache_mysql.c
23 * @brief mysql for an implementation of a database backend for the datacache
24 * @author Christian Grothoff
25 *
26 * SETUP INSTRUCTIONS:
27 *
28 * 1) Access mysql as root,
29 * <pre>
30 *
31 * $ mysql -u root -p
32 *
33 * </pre>
34 * and do the following. [You should replace $USER with the username
35 * that will be running the gnunetd process].
36 * <pre>
37 *
38 CREATE DATABASE gnunet;
39 GRANT select,insert,update,delete,create,alter,drop,create temporary tables
40 ON gnunet.* TO $USER@localhost;
41 SET PASSWORD FOR $USER@localhost=PASSWORD('$the_password_you_like');
42 FLUSH PRIVILEGES;
43 *
44 * </pre>
45 * 2) In the $HOME directory of $USER, create a ".my.cnf" file
46 * with the following lines
47 * <pre>
48
49 [client]
50 user=$USER
51 password=$the_password_you_like
52
53 * </pre>
54 *
55 * Thats it -- now you can configure your datastores in GNUnet to
56 * use MySQL. Note that .my.cnf file is a security risk unless its on
57 * a safe partition etc. The $HOME/.my.cnf can of course be a symbolic
58 * link. Even greater security risk can be achieved by setting no
59 * password for $USER. Luckily $USER has only priviledges to mess
60 * up GNUnet's tables, nothing else (unless you give him more,
61 * of course).<p>
62 *
63 * 3) Still, perhaps you should briefly try if the DB connection
64 * works. First, login as $USER. Then use,
65 *
66 * <pre>
67 * $ mysql -u $USER -p $the_password_you_like
68 * mysql> use gnunet;
69 * </pre>
70 *
71 * If you get the message &quot;Database changed&quot; it probably works.
72 *
73 * [If you get &quot;ERROR 2002: Can't connect to local MySQL server
74 * through socket '/tmp/mysql.sock' (2)&quot; it may be resolvable by
75 * &quot;ln -s /var/run/mysqld/mysqld.sock /tmp/mysql.sock&quot;
76 * so there may be some additional trouble depending on your mysql setup.]
77 *
78 * REPAIRING TABLES:
79 * - Its probably healthy to check your tables for inconsistencies
80 * every now and then.
81 * - If you get odd SEGVs on gnunetd startup, it might be that the mysql
82 * databases have been corrupted.
83 * - The tables can be verified/fixed in two ways;
84 * 1) by running mysqlcheck -A, or
85 * 2) by executing (inside of mysql using the GNUnet database):
86 * mysql> SHOW TABLES;
87 * mysql> REPAIR TABLE gnXXX;
88 *
89 * Make sure to replace XXX with the actual names of all tables.
90 *
91 * PROBLEMS?
92 *
93 * If you have problems related to the mysql module, your best
94 * friend is probably the mysql manual. The first thing to check
95 * is that mysql is basically operational, that you can connect
96 * to it, create tables, issue queries etc.
97 */
98#include "platform.h"
99#include "gnunet_util_lib.h"
100#include "plugin_datacache.h"
101#include <mysql/mysql.h>
102
103#define DEBUG_DATACACHE_MYSQL GNUNET_NO
104
105/**
106 * Estimate of the per-entry overhead (including indices).
107 */
108#define OVERHEAD ((4*2+4*2+8*2+8*2+sizeof(GNUNET_HashCode)*5+8))
109
110/**
111 * Maximum number of supported parameters for a prepared
112 * statement. Increase if needed.
113 */
114#define MAX_PARAM 16
115
116/**
117 * Die with an error message that indicates
118 * a failure of the command 'cmd' with the message given
119 * by strerror(errno).
120 */
121#define DIE_MYSQL(cmd, dbh) do { GNUNET_log(GNUNET_ERROR_TYPE__ERROR, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, mysql_error((dbh)->dbf)); abort(); } while(0);
122
123/**
124 * Log an error message at log-level 'level' that indicates
125 * a failure of the command 'cmd' on file 'filename'
126 * with the message given by strerror(errno).
127 */
128#define LOG_MYSQL(level, cmd, dbh) do { GNUNET_log(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, mysql_error((dbh)->dbf)); } while(0);
129
130struct GNUNET_MysqlStatementHandle
131{
132 struct GNUNET_MysqlStatementHandle *next;
133
134 struct GNUNET_MysqlStatementHandle *prev;
135
136 char *query;
137
138 MYSQL_STMT *statement;
139
140 int valid;
141
142};
143
144
145/**
146 * Context for all functions in this plugin.
147 */
148struct Plugin
149{
150 /**
151 * Our execution environment.
152 */
153 struct GNUNET_DATACACHE_PluginEnvironment *env;
154
155 /**
156 * Handle to the mysql database.
157 */
158 MYSQL *dbf;
159
160 struct GNUNET_MysqlStatementHandle *shead;
161
162 struct GNUNET_MysqlStatementHandle *stail;
163
164 /**
165 * Filename of "my.cnf" (msyql configuration).
166 */
167 char *cnffile;
168
169#define SELECT_VALUE_STMT "SELECT value,expire FROM gn080dstore FORCE INDEX (hashidx) WHERE hash=? AND type=? AND expire >= ? LIMIT 1 OFFSET ?"
170 struct GNUNET_MysqlStatementHandle *select_value;
171
172#define COUNT_VALUE_STMT "SELECT count(*) FROM gn080dstore FORCE INDEX (hashidx) WHERE hash=? AND type=? AND expire >= ?"
173 struct GNUNET_MysqlStatementHandle *count_value;
174
175#define SELECT_OLD_VALUE_STMT "SELECT hash, vhash, type, value FROM gn080dstore FORCE INDEX (expireidx) ORDER BY puttime ASC LIMIT 1"
176 struct GNUNET_MysqlStatementHandle *select_old_value;
177
178#define DELETE_VALUE_STMT "DELETE FROM gn080dstore WHERE hash = ? AND vhash = ? AND type = ? AND value = ?"
179 struct GNUNET_MysqlStatementHandle *delete_value;
180
181#define INSERT_VALUE_STMT "INSERT INTO gn080dstore (type, puttime, expire, hash, vhash, value) "\
182 "VALUES (?, ?, ?, ?, ?, ?)"
183 struct GNUNET_MysqlStatementHandle *insert_value;
184
185#define UPDATE_VALUE_STMT "UPDATE gn080dstore FORCE INDEX (allidx) SET puttime=?, expire=? "\
186 "WHERE hash=? AND vhash=? AND type=?"
187 struct GNUNET_MysqlStatementHandle *update_value;
188
189};
190
191
192/**
193 * Obtain the location of ".my.cnf".
194 * @return NULL on error
195 */
196static char *
197get_my_cnf_path (const struct GNUNET_CONFIGURATION_Handle *cfg)
198{
199 char *cnffile;
200 char *home_dir;
201 struct stat st;
202#ifndef WINDOWS
203 struct passwd *pw;
204#endif
205 int configured;
206
207#ifndef WINDOWS
208 pw = getpwuid (getuid ());
209 if (!pw)
210 {
211 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
212 "getpwuid");
213 return NULL;
214 }
215 if (GNUNET_YES ==
216 GNUNET_CONFIGURATION_have_value (cfg,
217 "datacache-mysql", "CONFIG"))
218 {
219 GNUNET_assert (GNUNET_OK ==
220 GNUNET_CONFIGURATION_get_value_filename (cfg,
221 "datacache-mysql", "CONFIG", &cnffile));
222 configured = GNUNET_YES;
223 }
224 else
225 {
226 home_dir = GNUNET_strdup (pw->pw_dir);
227#else
228 home_dir = (char *) GNUNET_malloc (_MAX_PATH + 1);
229 plibc_conv_to_win_path ("~/", home_dir);
230#endif
231 GNUNET_asprintf (&cnffile, "%s/.my.cnf", home_dir);
232 GNUNET_free (home_dir);
233 configured = GNUNET_NO;
234 }
235 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
236 _("Trying to use file `%s' for MySQL configuration.\n"),
237 cnffile);
238 if ((0 != STAT (cnffile, &st)) ||
239 (0 != ACCESS (cnffile, R_OK)) || (!S_ISREG (st.st_mode)))
240 {
241 if (configured == GNUNET_YES)
242 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
243 _("Could not access file `%s': %s\n"), cnffile,
244 STRERROR (errno));
245 GNUNET_free (cnffile);
246 return NULL;
247 }
248 return cnffile;
249}
250
251
252/**
253 * Free a prepared statement.
254 */
255static void
256prepared_statement_destroy (struct Plugin *plugin,
257 struct GNUNET_MysqlStatementHandle
258 *s)
259{
260 GNUNET_CONTAINER_DLL_remove (plugin->shead,
261 plugin->stail,
262 s);
263 if (s->valid)
264 mysql_stmt_close (s->statement);
265 GNUNET_free (s->query);
266 GNUNET_free (s);
267}
268
269
270/**
271 * Close database connection and all prepared statements (we got a DB
272 * disconnect error).
273 */
274static int
275iclose (struct Plugin *plugin)
276{
277 struct GNUNET_MysqlStatementHandle *spos;
278
279 spos = plugin->shead;
280 while (NULL != plugin->shead)
281 prepared_statement_destroy (plugin,
282 plugin->shead);
283 if (plugin->dbf != NULL)
284 {
285 mysql_close (plugin->dbf);
286 plugin->dbf = NULL;
287 }
288 return GNUNET_OK;
289}
290
291
292/**
293 * Open the connection with the database (and initialize
294 * our default options).
295 *
296 * @return GNUNET_OK on success
297 */
298static int
299iopen (struct Plugin *ret)
300{
301 char *mysql_dbname;
302 char *mysql_server;
303 char *mysql_user;
304 char *mysql_password;
305 unsigned long long mysql_port;
306 my_bool reconnect;
307 unsigned int timeout;
308
309 ret->dbf = mysql_init (NULL);
310 if (ret->dbf == NULL)
311 return GNUNET_SYSERR;
312 if (ret->cnffile != NULL)
313 mysql_options (ret->dbf, MYSQL_READ_DEFAULT_FILE, ret->cnffile);
314 mysql_options (ret->dbf, MYSQL_READ_DEFAULT_GROUP, "client");
315 reconnect = 0;
316 mysql_options (ret->dbf, MYSQL_OPT_RECONNECT, &reconnect);
317 mysql_options (ret->dbf,
318 MYSQL_OPT_CONNECT_TIMEOUT, (const void *) &timeout);
319 mysql_options(ret->dbf, MYSQL_SET_CHARSET_NAME, "UTF8");
320 timeout = 60; /* in seconds */
321 mysql_options (ret->dbf, MYSQL_OPT_READ_TIMEOUT, (const void *) &timeout);
322 mysql_options (ret->dbf, MYSQL_OPT_WRITE_TIMEOUT, (const void *) &timeout);
323 mysql_dbname = NULL;
324 if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (ret->env->cfg,
325 "datacache-mysql", "DATABASE"))
326 GNUNET_assert (GNUNET_OK ==
327 GNUNET_CONFIGURATION_get_value_string (ret->env->cfg,
328 "datacache-mysql", "DATABASE",
329 &mysql_dbname));
330 else
331 mysql_dbname = GNUNET_strdup ("gnunet");
332 mysql_user = NULL;
333 if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (ret->env->cfg,
334 "datacache-mysql", "USER"))
335 {
336 GNUNET_assert (GNUNET_OK ==
337 GNUNET_CONFIGURATION_get_value_string (ret->env->cfg,
338 "datacache-mysql", "USER",
339 &mysql_user));
340 }
341 mysql_password = NULL;
342 if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (ret->env->cfg,
343 "datacache-mysql", "PASSWORD"))
344 {
345 GNUNET_assert (GNUNET_OK ==
346 GNUNET_CONFIGURATION_get_value_string (ret->env->cfg,
347 "datacache-mysql", "PASSWORD",
348 &mysql_password));
349 }
350 mysql_server = NULL;
351 if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (ret->env->cfg,
352 "datacache-mysql", "HOST"))
353 {
354 GNUNET_assert (GNUNET_OK ==
355 GNUNET_CONFIGURATION_get_value_string (ret->env->cfg,
356 "datacache-mysql", "HOST",
357 &mysql_server));
358 }
359 mysql_port = 0;
360 if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (ret->env->cfg,
361 "datacache-mysql", "PORT"))
362 {
363 GNUNET_assert (GNUNET_OK ==
364 GNUNET_CONFIGURATION_get_value_number (ret->env->cfg, "datacache-mysql",
365 "PORT", &mysql_port));
366 }
367
368 GNUNET_assert (mysql_dbname != NULL);
369 mysql_real_connect (ret->dbf, mysql_server, mysql_user, mysql_password,
370 mysql_dbname, (unsigned int) mysql_port, NULL,
371 CLIENT_IGNORE_SIGPIPE);
372 GNUNET_free_non_null (mysql_server);
373 GNUNET_free_non_null (mysql_user);
374 GNUNET_free_non_null (mysql_password);
375 GNUNET_free (mysql_dbname);
376 if (mysql_error (ret->dbf)[0])
377 {
378 LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR,
379 "mysql_real_connect", ret);
380 return GNUNET_SYSERR;
381 }
382 return GNUNET_OK;
383}
384
385
386/**
387 * Run the given MySQL statement.
388 *
389 * @return GNUNET_OK on success, GNUNET_SYSERR on error
390 */
391static int
392run_statement (struct Plugin *plugin,
393 const char *statement)
394{
395 if ((NULL == plugin->dbf) && (GNUNET_OK != iopen (plugin)))
396 return GNUNET_SYSERR;
397 mysql_query (plugin->dbf, statement);
398 if (mysql_error (plugin->dbf)[0])
399 {
400 LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR,
401 "mysql_query", plugin);
402 iclose (plugin);
403 return GNUNET_SYSERR;
404 }
405 return GNUNET_OK;
406}
407
408/**
409 * Create a prepared statement.
410 *
411 * @return NULL on error
412 */
413static struct GNUNET_MysqlStatementHandle *
414prepared_statement_create (struct Plugin *plugin,
415 const char *statement)
416{
417 struct GNUNET_MysqlStatementHandle *ret;
418
419 ret = GNUNET_malloc (sizeof (struct GNUNET_MysqlStatementHandle));
420 ret->query = GNUNET_strdup (statement);
421 GNUNET_CONTAINER_DLL_insert (plugin->shead,
422 plugin->stail,
423 ret);
424 return ret;
425}
426
427
428/**
429 * Prepare a statement for running.
430 *
431 * @return GNUNET_OK on success
432 */
433static int
434prepare_statement (struct Plugin *plugin,
435 struct GNUNET_MysqlStatementHandle *ret)
436{
437 if (GNUNET_YES == ret->valid)
438 return GNUNET_OK;
439 if ((NULL == plugin->dbf) &&
440 (GNUNET_OK != iopen (plugin)))
441 return GNUNET_SYSERR;
442 ret->statement = mysql_stmt_init (plugin->dbf);
443 if (ret->statement == NULL)
444 {
445 iclose (plugin);
446 return GNUNET_SYSERR;
447 }
448 if (mysql_stmt_prepare (ret->statement,
449 ret->query,
450 strlen (ret->query)))
451 {
452 LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR,
453 "mysql_stmt_prepare",
454 plugin);
455 mysql_stmt_close (ret->statement);
456 ret->statement = NULL;
457 iclose (plugin);
458 return GNUNET_SYSERR;
459 }
460 ret->valid = GNUNET_YES;
461 return GNUNET_OK;
462
463}
464
465
466/**
467 * Bind the parameters for the given MySQL statement
468 * and run it.
469 *
470 * @param s statement to bind and run
471 * @param ap arguments for the binding
472 * @return GNUNET_SYSERR on error, GNUNET_OK on success
473 */
474static int
475init_params (struct Plugin *plugin,
476 struct GNUNET_MysqlStatementHandle *s,
477 va_list ap)
478{
479 MYSQL_BIND qbind[MAX_PARAM];
480 unsigned int pc;
481 unsigned int off;
482 enum enum_field_types ft;
483
484 pc = mysql_stmt_param_count (s->statement);
485 if (pc > MAX_PARAM)
486 {
487 /* increase internal constant! */
488 GNUNET_break (0);
489 return GNUNET_SYSERR;
490 }
491 memset (qbind, 0, sizeof (qbind));
492 off = 0;
493 ft = 0;
494 while ((pc > 0) && (-1 != (ft = va_arg (ap, enum enum_field_types))))
495 {
496 qbind[off].buffer_type = ft;
497 switch (ft)
498 {
499 case MYSQL_TYPE_FLOAT:
500 qbind[off].buffer = va_arg (ap, float *);
501 break;
502 case MYSQL_TYPE_LONGLONG:
503 qbind[off].buffer = va_arg (ap, unsigned long long *);
504 qbind[off].is_unsigned = va_arg (ap, int);
505 break;
506 case MYSQL_TYPE_LONG:
507 qbind[off].buffer = va_arg (ap, unsigned int *);
508 qbind[off].is_unsigned = va_arg (ap, int);
509 break;
510 case MYSQL_TYPE_VAR_STRING:
511 case MYSQL_TYPE_STRING:
512 case MYSQL_TYPE_BLOB:
513 qbind[off].buffer = va_arg (ap, void *);
514 qbind[off].buffer_length = va_arg (ap, unsigned long);
515 qbind[off].length = va_arg (ap, unsigned long *);
516 break;
517 default:
518 /* unsupported type */
519 GNUNET_break (0);
520 return GNUNET_SYSERR;
521 }
522 pc--;
523 off++;
524 }
525 if (!((pc == 0) && (ft != -1) && (va_arg (ap, int) == -1)))
526 {
527 GNUNET_break (0);
528 return GNUNET_SYSERR;
529 }
530 if (mysql_stmt_bind_param (s->statement, qbind))
531 {
532 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
533 _("`%s' failed at %s:%d with error: %s\n"),
534 "mysql_stmt_bind_param",
535 __FILE__, __LINE__, mysql_stmt_error (s->statement));
536 iclose (plugin);
537 return GNUNET_SYSERR;
538 }
539 if (mysql_stmt_execute (s->statement))
540 {
541 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
542 _("`%s' failed at %s:%d with error: %s\n"),
543 "mysql_stmt_execute",
544 __FILE__, __LINE__, mysql_stmt_error (s->statement));
545 iclose (plugin);
546 return GNUNET_SYSERR;
547 }
548 return GNUNET_OK;
549}
550
551/**
552 * Type of a callback that will be called for each
553 * data set returned from MySQL.
554 *
555 * @param cls user-defined argument
556 * @param num_values number of elements in values
557 * @param values values returned by MySQL
558 * @return GNUNET_OK to continue iterating, GNUNET_SYSERR to abort
559 */
560typedef int (*GNUNET_MysqlDataProcessor) (void *cls,
561 unsigned int num_values,
562 MYSQL_BIND * values);
563
564
565/**
566 * Run a prepared SELECT statement.
567 *
568 * @param result_size number of elements in results array
569 * @param results pointer to already initialized MYSQL_BIND
570 * array (of sufficient size) for passing results
571 * @param processor function to call on each result
572 * @param processor_cls extra argument to processor
573 * @param ... pairs and triplets of "MYSQL_TYPE_XXX" keys and their respective
574 * values (size + buffer-reference for pointers); terminated
575 * with "-1"
576 * @return GNUNET_SYSERR on error, otherwise
577 * the number of successfully affected (or queried) rows
578 */
579static int
580prepared_statement_run_select (struct Plugin *plugin,
581 struct GNUNET_MysqlStatementHandle
582 *s,
583 unsigned int result_size,
584 MYSQL_BIND * results,
585 GNUNET_MysqlDataProcessor
586 processor, void *processor_cls,
587 ...)
588{
589 va_list ap;
590 int ret;
591 unsigned int rsize;
592 int total;
593
594 if (GNUNET_OK != prepare_statement (plugin, s))
595 {
596 GNUNET_break (0);
597 return GNUNET_SYSERR;
598 }
599 va_start (ap, processor_cls);
600 if (GNUNET_OK != init_params (plugin, s, ap))
601 {
602 GNUNET_break (0);
603 va_end (ap);
604 return GNUNET_SYSERR;
605 }
606 va_end (ap);
607 rsize = mysql_stmt_field_count (s->statement);
608 if (rsize > result_size)
609 {
610 GNUNET_break (0);
611 return GNUNET_SYSERR;
612 }
613 if (mysql_stmt_bind_result (s->statement, results))
614 {
615 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
616 _("`%s' failed at %s:%d with error: %s\n"),
617 "mysql_stmt_bind_result",
618 __FILE__, __LINE__, mysql_stmt_error (s->statement));
619 iclose (plugin);
620 return GNUNET_SYSERR;
621 }
622
623 total = 0;
624 while (1)
625 {
626 ret = mysql_stmt_fetch (s->statement);
627 if (ret == MYSQL_NO_DATA)
628 break;
629 if (ret != 0)
630 {
631 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
632 _("`%s' failed at %s:%d with error: %s\n"),
633 "mysql_stmt_fetch",
634 __FILE__, __LINE__, mysql_stmt_error (s->statement));
635 iclose (plugin);
636 return GNUNET_SYSERR;
637 }
638 if (processor != NULL)
639 if (GNUNET_OK != processor (processor_cls, rsize, results))
640 break;
641 total++;
642 }
643 mysql_stmt_reset (s->statement);
644 return total;
645}
646
647
648
649/**
650 * Run a prepared statement that does NOT produce results.
651 *
652 * @param ... pairs and triplets of "MYSQL_TYPE_XXX" keys and their respective
653 * values (size + buffer-reference for pointers); terminated
654 * with "-1"
655 * @param insert_id NULL or address where to store the row ID of whatever
656 * was inserted (only for INSERT statements!)
657 * @return GNUNET_SYSERR on error, otherwise
658 * the number of successfully affected rows
659 */
660static int
661prepared_statement_run (struct Plugin *plugin,
662 struct GNUNET_MysqlStatementHandle *s,
663 unsigned long long *insert_id, ...)
664{
665 va_list ap;
666 int affected;
667
668 if (GNUNET_OK != prepare_statement (plugin, s))
669 return GNUNET_SYSERR;
670 va_start (ap, insert_id);
671 if (GNUNET_OK != init_params (plugin, s, ap))
672 {
673 va_end (ap);
674 return GNUNET_SYSERR;
675 }
676 va_end (ap);
677 affected = mysql_stmt_affected_rows (s->statement);
678 if (NULL != insert_id)
679 *insert_id = (unsigned long long) mysql_stmt_insert_id (s->statement);
680 mysql_stmt_reset (s->statement);
681 return affected;
682}
683
684
685static int
686itable (struct Plugin *plugin)
687{
688#define MRUNS(a) (GNUNET_OK != run_statement (plugin, a) )
689 if (MRUNS ("CREATE TEMPORARY TABLE gn080dstore ("
690 " type INT(11) UNSIGNED NOT NULL DEFAULT 0,"
691 " puttime BIGINT UNSIGNED NOT NULL DEFAULT 0,"
692 " expire BIGINT UNSIGNED NOT NULL DEFAULT 0,"
693 " hash BINARY(64) NOT NULL DEFAULT '',"
694 " vhash BINARY(64) NOT NULL DEFAULT '',"
695 " value BLOB NOT NULL DEFAULT '',"
696 " INDEX hashidx (hash(64),type,expire),"
697 " INDEX allidx (hash(64),vhash(64),type),"
698 " INDEX expireidx (puttime)" ") ENGINE=InnoDB") ||
699 MRUNS ("SET AUTOCOMMIT = 1"))
700 return GNUNET_SYSERR;
701#undef MRUNS
702#define PINIT(a,b) (NULL == (a = prepared_statement_create(plugin, b)))
703 if (PINIT (plugin->select_value, SELECT_VALUE_STMT) ||
704 PINIT (plugin->count_value, COUNT_VALUE_STMT) ||
705 PINIT (plugin->select_old_value, SELECT_OLD_VALUE_STMT) ||
706 PINIT (plugin->delete_value, DELETE_VALUE_STMT) ||
707 PINIT (plugin->insert_value, INSERT_VALUE_STMT) ||
708 PINIT (plugin->update_value, UPDATE_VALUE_STMT))
709 return GNUNET_SYSERR;
710#undef PINIT
711 return GNUNET_OK;
712}
713
714
715/**
716 * Store an item in the datastore.
717 *
718 * @param cls closure (our "struct Plugin")
719 * @param key key to store data under
720 * @param size number of bytes in data
721 * @param data data to store
722 * @param type type of the value
723 * @param discard_time when to discard the value in any case
724 * @return 0 on error, number of bytes used otherwise
725 */
726static uint32_t
727mysql_plugin_put (void *cls,
728 const GNUNET_HashCode * key,
729 uint32_t size,
730 const char *data,
731 enum GNUNET_BLOCK_Type type,
732 struct GNUNET_TIME_Absolute discard_time)
733{
734 struct Plugin *plugin = cls;
735 struct GNUNET_TIME_Absolute now;
736 unsigned long k_length;
737 unsigned long h_length;
738 unsigned long v_length;
739 unsigned long long v_now;
740 unsigned long long v_discard_time;
741 unsigned int v_type;
742 GNUNET_HashCode vhash;
743 int ret;
744
745 if (size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
746 return GNUNET_SYSERR;
747 GNUNET_CRYPTO_hash (data, size, &vhash);
748 now = GNUNET_TIME_absolute_get ();
749
750 /* first try UPDATE */
751 h_length = sizeof (GNUNET_HashCode);
752 k_length = sizeof (GNUNET_HashCode);
753 v_length = size;
754 v_type = type;
755 v_now = (unsigned long long) now.value;
756 v_discard_time = (unsigned long long) discard_time.value;
757 if (GNUNET_OK ==
758 prepared_statement_run (plugin,
759 plugin->update_value,
760 NULL,
761 MYSQL_TYPE_LONGLONG,
762 &v_now,
763 GNUNET_YES,
764 MYSQL_TYPE_LONGLONG,
765 &v_discard_time,
766 GNUNET_YES,
767 MYSQL_TYPE_BLOB,
768 key,
769 sizeof (GNUNET_HashCode),
770 &k_length,
771 MYSQL_TYPE_BLOB,
772 &vhash,
773 sizeof (GNUNET_HashCode),
774 &h_length,
775 MYSQL_TYPE_LONG,
776 &v_type,
777 GNUNET_YES, -1))
778 return GNUNET_OK;
779
780 /* now try INSERT */
781 h_length = sizeof (GNUNET_HashCode);
782 k_length = sizeof (GNUNET_HashCode);
783 v_length = size;
784 if (GNUNET_OK !=
785 (ret = prepared_statement_run (plugin,
786 plugin->insert_value,
787 NULL,
788 MYSQL_TYPE_LONG,
789 &type,
790 GNUNET_YES,
791 MYSQL_TYPE_LONGLONG,
792 &v_now,
793 GNUNET_YES,
794 MYSQL_TYPE_LONGLONG,
795 &v_discard_time,
796 GNUNET_YES,
797 MYSQL_TYPE_BLOB,
798 key,
799 sizeof (GNUNET_HashCode),
800 &k_length,
801 MYSQL_TYPE_BLOB,
802 &vhash,
803 sizeof (GNUNET_HashCode),
804 &h_length,
805 MYSQL_TYPE_BLOB,
806 data,
807 (unsigned long) size,
808 &v_length, -1)))
809 {
810 if (ret == GNUNET_SYSERR)
811 itable (plugin);
812 return GNUNET_SYSERR;
813 }
814 return size + OVERHEAD;
815}
816
817
818static int
819return_ok (void *cls, unsigned int num_values, MYSQL_BIND * values)
820{
821 return GNUNET_OK;
822}
823
824
825/**
826 * Iterate over the results for a particular key
827 * in the datastore.
828 *
829 * @param cls closure (our "struct Plugin")
830 * @param key
831 * @param type entries of which type are relevant?
832 * @param iter maybe NULL (to just count)
833 * @param iter_cls closure for iter
834 * @return the number of results found
835 */
836static unsigned int
837mysql_plugin_get (void *cls,
838 const GNUNET_HashCode * key,
839 enum GNUNET_BLOCK_Type type,
840 GNUNET_DATACACHE_Iterator iter,
841 void *iter_cls)
842{
843 struct Plugin *plugin = cls;
844 MYSQL_BIND rbind[3];
845 unsigned long h_length;
846 unsigned long v_length;
847 unsigned long long v_expire;
848 struct GNUNET_TIME_Absolute now;
849 struct GNUNET_TIME_Absolute expire;
850 unsigned int cnt;
851 unsigned long long total;
852 unsigned long long v_now;
853 unsigned int off;
854 unsigned int v_type;
855 int ret;
856 char buffer[GNUNET_SERVER_MAX_MESSAGE_SIZE];
857
858 now = GNUNET_TIME_absolute_get ();
859 h_length = sizeof (GNUNET_HashCode);
860 v_length = sizeof (buffer);
861 total = -1;
862 memset (rbind, 0, sizeof (rbind));
863 rbind[0].buffer_type = MYSQL_TYPE_LONGLONG;
864 rbind[0].buffer = &total;
865 rbind[0].is_unsigned = GNUNET_YES;
866 v_type = type;
867 v_now = (unsigned long long) now.value;
868 if ((GNUNET_OK !=
869 (ret = prepared_statement_run_select (plugin,
870 plugin->count_value,
871 1,
872 rbind,
873 return_ok,
874 NULL,
875 MYSQL_TYPE_BLOB,
876 key,
877 sizeof
878 (GNUNET_HashCode),
879 &h_length,
880 MYSQL_TYPE_LONG,
881 &v_type, GNUNET_YES,
882 MYSQL_TYPE_LONGLONG,
883 &v_now, GNUNET_YES,
884 -1)))
885 || (-1 == total))
886 {
887 if (ret == GNUNET_SYSERR)
888 itable (plugin);
889 return GNUNET_SYSERR;
890 }
891 if ((iter == NULL) || (total == 0))
892 return (int) total;
893
894 off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, total);
895 cnt = 0;
896 while (cnt < total)
897 {
898 memset (rbind, 0, sizeof (rbind));
899 rbind[0].buffer_type = MYSQL_TYPE_BLOB;
900 rbind[0].buffer_length = sizeof (buffer);
901 rbind[0].length = &v_length;
902 rbind[0].buffer = buffer;
903 rbind[1].buffer_type = MYSQL_TYPE_LONGLONG;
904 rbind[1].is_unsigned = 1;
905 rbind[1].buffer = &v_expire;
906 off = (off + 1) % total;
907 if (GNUNET_OK !=
908 (ret = prepared_statement_run_select (plugin,
909 plugin->select_value,
910 2,
911 rbind,
912 return_ok,
913 NULL,
914 MYSQL_TYPE_BLOB,
915 key,
916 sizeof
917 (GNUNET_HashCode),
918 &h_length,
919 MYSQL_TYPE_LONG,
920 &v_type,
921 GNUNET_YES,
922 MYSQL_TYPE_LONGLONG,
923 &v_now,
924 GNUNET_YES,
925 MYSQL_TYPE_LONG,
926 &off,
927 GNUNET_YES,
928 -1)))
929 {
930 if (ret == GNUNET_SYSERR)
931 itable (plugin);
932 return GNUNET_SYSERR;
933 }
934 cnt++;
935 expire.value = v_expire;
936 if (GNUNET_OK != iter (iter_cls,
937 expire,
938 key,
939 v_length, buffer,
940 type))
941 break;
942 }
943 return cnt;
944}
945
946
947/**
948 * Delete the entry with the lowest expiration value
949 * from the datacache right now.
950 *
951 * @param cls closure (our "struct Plugin")
952 * @return GNUNET_OK on success, GNUNET_SYSERR on error
953 */
954static int
955mysql_plugin_del (void *cls)
956{
957 struct Plugin *plugin = cls;
958
959 MYSQL_BIND rbind[5];
960 unsigned int v_type;
961 GNUNET_HashCode v_key;
962 GNUNET_HashCode vhash;
963 unsigned long k_length;
964 unsigned long h_length;
965 unsigned long v_length;
966 int ret;
967 char buffer[GNUNET_SERVER_MAX_MESSAGE_SIZE];
968
969 k_length = sizeof (GNUNET_HashCode);
970 h_length = sizeof (GNUNET_HashCode);
971 v_length = sizeof (buffer);
972 memset (rbind, 0, sizeof (rbind));
973 rbind[0].buffer_type = MYSQL_TYPE_BLOB;
974 rbind[0].buffer_length = sizeof (GNUNET_HashCode);
975 rbind[0].length = &k_length;
976 rbind[0].buffer = &v_key;
977 rbind[1].buffer_type = MYSQL_TYPE_BLOB;
978 rbind[1].buffer_length = sizeof (GNUNET_HashCode);
979 rbind[1].length = &h_length;
980 rbind[1].buffer = &vhash;
981 rbind[2].buffer_type = MYSQL_TYPE_LONG;
982 rbind[2].is_unsigned = 1;
983 rbind[2].buffer = &v_type;
984 rbind[3].buffer_type = MYSQL_TYPE_BLOB;
985 rbind[3].buffer_length = sizeof (buffer);
986 rbind[3].length = &v_length;
987 rbind[3].buffer = buffer;
988 if ((GNUNET_OK !=
989 (ret = prepared_statement_run_select (plugin,
990 plugin->select_old_value,
991 4,
992 rbind,
993 return_ok,
994 NULL,
995 -1))) ||
996 (GNUNET_OK !=
997 (ret = prepared_statement_run (plugin,
998 plugin->delete_value,
999 NULL,
1000 MYSQL_TYPE_BLOB,
1001 &v_key,
1002 sizeof (GNUNET_HashCode),
1003 &k_length,
1004 MYSQL_TYPE_BLOB,
1005 &vhash,
1006 sizeof (GNUNET_HashCode),
1007 &h_length,
1008 MYSQL_TYPE_LONG,
1009 &v_type,
1010 GNUNET_YES,
1011 MYSQL_TYPE_BLOB,
1012 buffer,
1013 (unsigned long)
1014 sizeof (buffer),
1015 &v_length, -1))))
1016 {
1017 if (ret == GNUNET_SYSERR)
1018 itable (plugin);
1019 return GNUNET_SYSERR;
1020 }
1021 plugin->env->delete_notify (plugin->env->cls,
1022 &v_key,
1023 v_length + OVERHEAD);
1024
1025 return GNUNET_OK;
1026}
1027
1028
1029/**
1030 * Entry point for the plugin.
1031 *
1032 * @param cls closure (the "struct GNUNET_DATACACHE_PluginEnvironmnet")
1033 * @return the plugin's closure (our "struct Plugin")
1034 */
1035void *
1036libgnunet_plugin_datacache_mysql_init (void *cls)
1037{
1038 struct GNUNET_DATACACHE_PluginEnvironment *env = cls;
1039 struct GNUNET_DATACACHE_PluginFunctions *api;
1040 struct Plugin *plugin;
1041
1042 plugin = GNUNET_malloc (sizeof (struct Plugin));
1043 plugin->env = env;
1044 plugin->cnffile = get_my_cnf_path (env->cfg);
1045 if (GNUNET_OK !=
1046 iopen (plugin))
1047 {
1048 GNUNET_free_non_null (plugin->cnffile);
1049 GNUNET_free (plugin);
1050 return NULL;
1051 }
1052 if (GNUNET_OK !=
1053 itable (plugin))
1054 {
1055 iclose (plugin);
1056 GNUNET_free_non_null (plugin->cnffile);
1057 GNUNET_free (plugin);
1058 return NULL;
1059 }
1060 api = GNUNET_malloc (sizeof (struct GNUNET_DATACACHE_PluginFunctions));
1061 api->cls = plugin;
1062 api->get = &mysql_plugin_get;
1063 api->put = &mysql_plugin_put;
1064 api->del = &mysql_plugin_del;
1065 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO,
1066 "mysql", _("MySQL datacache running\n"));
1067 return api;
1068}
1069
1070
1071/**
1072 * Exit point from the plugin.
1073 *
1074 * @param cls closure (our "struct Plugin")
1075 * @return NULL
1076 */
1077void *
1078libgnunet_plugin_datacache_mysql_done (void *cls)
1079{
1080 struct GNUNET_DATACACHE_PluginFunctions *api = cls;
1081 struct Plugin *plugin = api->cls;
1082
1083 iclose (plugin);
1084 GNUNET_free_non_null (plugin->cnffile);
1085 GNUNET_free (plugin);
1086 GNUNET_free (api);
1087 mysql_library_end ();
1088 return NULL;
1089}
1090
1091
1092/* end of plugin_datacache_mysql.c */
diff --git a/src/datacache/test_datacache.c b/src/datacache/test_datacache.c
index 8e09a7692..c5acf365a 100644
--- a/src/datacache/test_datacache.c
+++ b/src/datacache/test_datacache.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 (C) 2006, 2009 Christian Grothoff (and other contributing authors) 3 (C) 2006, 2009, 2010 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -32,6 +32,11 @@
32 32
33static int ok; 33static int ok;
34 34
35/**
36 * Name of plugin under test.
37 */
38static const char *plugin_name;
39
35 40
36static int 41static int
37checkIt (void *cls, 42checkIt (void *cls,
@@ -120,12 +125,15 @@ FAILURE:
120} 125}
121 126
122 127
123static int 128int
124check () 129main (int argc, char *argv[])
125{ 130{
126 char *const argv[] = { "test-datacache-api", 131 const char *pos;
132 char cfg_name[128];
133 char *const xargv[] = {
134 "test-datacache",
127 "-c", 135 "-c",
128 "test_datacache_data.conf", 136 cfg_name,
129#if VERBOSE 137#if VERBOSE
130 "-L", "DEBUG", 138 "-L", "DEBUG",
131#endif 139#endif
@@ -134,30 +142,28 @@ check ()
134 struct GNUNET_GETOPT_CommandLineOption options[] = { 142 struct GNUNET_GETOPT_CommandLineOption options[] = {
135 GNUNET_GETOPT_OPTION_END 143 GNUNET_GETOPT_OPTION_END
136 }; 144 };
137 GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1,
138 argv, "test-datacache-api", "nohelp",
139 options, &run, NULL);
140 if (ok != 0)
141 fprintf (stderr, "Missed some testcases: %d\n", ok);
142 return ok;
143}
144 145
145 146 GNUNET_log_setup ("test-datacache",
146int
147main (int argc, char *argv[])
148{
149 int ret;
150
151 GNUNET_log_setup ("test-datacache-api",
152#if VERBOSE 147#if VERBOSE
153 "DEBUG", 148 "DEBUG",
154#else 149#else
155 "WARNING", 150 "WARNING",
156#endif 151#endif
157 NULL); 152 NULL);
158 ret = check (); 153 /* determine name of plugin to use */
159 154 plugin_name = argv[0];
160 return ret; 155 while (NULL != (pos = strstr(plugin_name, "_")))
156 plugin_name = pos+1;
157 GNUNET_snprintf (cfg_name,
158 sizeof (cfg_name),
159 "test_datacache_data_%s.conf",
160 plugin_name);
161 GNUNET_PROGRAM_run ((sizeof (xargv) / sizeof (char *)) - 1,
162 xargv, "test-datacache", "nohelp",
163 options, &run, NULL);
164 if (ok != 0)
165 fprintf (stderr, "Missed some testcases: %d\n", ok);
166 return ok;
161} 167}
162 168
163/* end of test_datacache.c */ 169/* end of test_datacache.c */
diff --git a/src/datacache/test_datacache_data_mysql.conf b/src/datacache/test_datacache_data_mysql.conf
new file mode 100644
index 000000000..3086497df
--- /dev/null
+++ b/src/datacache/test_datacache_data_mysql.conf
@@ -0,0 +1,12 @@
1
2[testcache]
3QUOTA = 1000000
4DATABASE = mysql
5
6[datacache-mysql]
7DATABASE = gnunetcheck
8# CONFIG = ~/.my.cnf
9# USER =
10# PASSWORD =
11# HOST =
12# PORT = \ No newline at end of file
diff --git a/src/datacache/test_datacache_data.conf b/src/datacache/test_datacache_data_sqlite.conf
index 2e8606682..2e8606682 100644
--- a/src/datacache/test_datacache_data.conf
+++ b/src/datacache/test_datacache_data_sqlite.conf
diff --git a/src/datacache/test_datacache_quota.c b/src/datacache/test_datacache_quota.c
index f4686b6a3..9028196bd 100644
--- a/src/datacache/test_datacache_quota.c
+++ b/src/datacache/test_datacache_quota.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 (C) 2006, 2009 Christian Grothoff (and other contributing authors) 3 (C) 2006, 2009, 2010 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -33,6 +33,11 @@
33static int ok; 33static int ok;
34 34
35/** 35/**
36 * Name of plugin under test.
37 */
38static const char *plugin_name;
39
40/**
36 * Quota is 1 MB. Each iteration of the test puts in about 1 MB of 41 * Quota is 1 MB. Each iteration of the test puts in about 1 MB of
37 * data. We do 10 iterations. Afterwards we check that the data from 42 * data. We do 10 iterations. Afterwards we check that the data from
38 * the first 5 iterations has all been discarded and that at least 43 * the first 5 iterations has all been discarded and that at least
@@ -110,12 +115,15 @@ FAILURE:
110} 115}
111 116
112 117
113static int 118int
114check () 119main (int argc, char *argv[])
115{ 120{
116 char *const argv[] = { "test-datacache-quota", 121 const char *pos;
122 char cfg_name[128];
123 char *const xargv[] = {
124 "test-datacache-quota",
117 "-c", 125 "-c",
118 "test_datacache_data.conf", 126 cfg_name,
119#if VERBOSE 127#if VERBOSE
120 "-L", "DEBUG", 128 "-L", "DEBUG",
121#endif 129#endif
@@ -124,20 +132,7 @@ check ()
124 struct GNUNET_GETOPT_CommandLineOption options[] = { 132 struct GNUNET_GETOPT_CommandLineOption options[] = {
125 GNUNET_GETOPT_OPTION_END 133 GNUNET_GETOPT_OPTION_END
126 }; 134 };
127 GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, 135
128 argv, "test-datacache-quota", "nohelp",
129 options, &run, NULL);
130 if (ok != 0)
131 fprintf (stderr, "Missed some testcases: %d\n", ok);
132 return ok;
133}
134
135
136int
137main (int argc, char *argv[])
138{
139 int ret;
140
141 GNUNET_log_setup ("test-datacache-quota", 136 GNUNET_log_setup ("test-datacache-quota",
142#if VERBOSE 137#if VERBOSE
143 "DEBUG", 138 "DEBUG",
@@ -145,9 +140,20 @@ main (int argc, char *argv[])
145 "WARNING", 140 "WARNING",
146#endif 141#endif
147 NULL); 142 NULL);
148 ret = check (); 143 /* determine name of plugin to use */
149 144 plugin_name = argv[0];
150 return ret; 145 while (NULL != (pos = strstr(plugin_name, "_")))
146 plugin_name = pos+1;
147 GNUNET_snprintf (cfg_name,
148 sizeof (cfg_name),
149 "test_datacache_data_%s.conf",
150 plugin_name);
151 GNUNET_PROGRAM_run ((sizeof (xargv) / sizeof (char *)) - 1,
152 xargv, "test-datacache-quota", "nohelp",
153 options, &run, NULL);
154 if (ok != 0)
155 fprintf (stderr, "Missed some testcases: %d\n", ok);
156 return ok;
151} 157}
152 158
153/* end of test_datacache_quota.c */ 159/* end of test_datacache_quota.c */
diff --git a/src/datastore/Makefile.am b/src/datastore/Makefile.am
index a96e22d4c..3c687e8ce 100644
--- a/src/datastore/Makefile.am
+++ b/src/datastore/Makefile.am
@@ -71,10 +71,10 @@ libgnunet_plugin_datastore_mysql_la_SOURCES = \
71 plugin_datastore_mysql.c 71 plugin_datastore_mysql.c
72libgnunet_plugin_datastore_mysql_la_LIBADD = \ 72libgnunet_plugin_datastore_mysql_la_LIBADD = \
73 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 73 $(top_builddir)/src/statistics/libgnunetstatistics.la \
74 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lz -lsqlite3 74 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lz -lmysqlclient
75libgnunet_plugin_datastore_mysql_la_LDFLAGS = \ 75libgnunet_plugin_datastore_mysql_la_LDFLAGS = \
76 $(GN_PLUGIN_LDFLAGS) $(MYSQL_LDFLAGS) -lmysqlclient 76 $(GN_PLUGIN_LDFLAGS) $(MYSQL_LDFLAGS) -lmysqlclient
77libgnunet_plugin_datastore_sqlite_la_CPFLAGS = \ 77libgnunet_plugin_datastore_mysql_la_CPPFLAGS = \
78 $(MYSQL_CPPFLAGS) 78 $(MYSQL_CPPFLAGS)
79 79
80 80
diff --git a/src/datastore/plugin_datastore_mysql.c b/src/datastore/plugin_datastore_mysql.c
index 98c6c4ab3..c216e989c 100644
--- a/src/datastore/plugin_datastore_mysql.c
+++ b/src/datastore/plugin_datastore_mysql.c
@@ -572,46 +572,6 @@ run_statement (struct Plugin *plugin,
572} 572}
573 573
574 574
575#if 0
576/**
577 * Run the given MySQL SELECT statement. The statement
578 * must have only a single result (one column, one row).
579 *
580 * @return result on success, NULL on error
581 */
582static char *
583run_statement_select (struct Plugin *plugin,
584 const char *statement)
585{
586 MYSQL_RES *sql_res;
587 MYSQL_ROW sql_row;
588 char *ret;
589
590 if ((NULL == plugin->dbf) && (GNUNET_OK != iopen (plugin)))
591 return NULL;
592 mysql_query (plugin->dbf, statement);
593 if ((mysql_error (plugin->dbf)[0]) ||
594 (!(sql_res = mysql_use_result (plugin->dbf))) ||
595 (!(sql_row = mysql_fetch_row (sql_res))))
596 {
597 LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR,
598 "mysql_query", plugin);
599 return NULL;
600 }
601 if ((mysql_num_fields (sql_res) != 1) || (sql_row[0] == NULL))
602 {
603 GNUNET_break (mysql_num_fields (sql_res) == 1);
604 if (sql_res != NULL)
605 mysql_free_result (sql_res);
606 return NULL;
607 }
608 ret = GNUNET_strdup (sql_row[0]);
609 mysql_free_result (sql_res);
610 return ret;
611}
612#endif
613
614
615/** 575/**
616 * Create a prepared statement. 576 * Create a prepared statement.
617 * 577 *